Full ast parsing
This commit is contained in:
parent
b7b4e75f01
commit
7a8ab3d571
@ -79,6 +79,22 @@ fn statement_delimiter(input: Span) -> ParseResult<()> {
|
|||||||
tok(alt((value((), line_ending), value((), char(';')))))(input)
|
tok(alt((value((), line_ending), value((), char(';')))))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn program(input: Span) -> ParseResult<AST> {
|
||||||
|
let id = fresh_id(&input);
|
||||||
|
//TODO `rest` should be empty
|
||||||
|
let (rest, statements) = context("AST",
|
||||||
|
map(
|
||||||
|
tuple((
|
||||||
|
many0(statement_delimiter),
|
||||||
|
separated_list0(statement_delimiter, statement),
|
||||||
|
many0(statement_delimiter),
|
||||||
|
)), |(_, items, _)| items.into())
|
||||||
|
)(input)?;
|
||||||
|
|
||||||
|
let ast = AST { id, statements };
|
||||||
|
Ok((rest, ast))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn block(input: Span) -> ParseResult<Block> {
|
pub fn block(input: Span) -> ParseResult<Block> {
|
||||||
context(
|
context(
|
||||||
"block",
|
"block",
|
||||||
@ -97,16 +113,33 @@ pub fn block(input: Span) -> ParseResult<Block> {
|
|||||||
|
|
||||||
fn statement(input: Span) -> ParseResult<Statement> {
|
fn statement(input: Span) -> ParseResult<Statement> {
|
||||||
let (input, pos) = position(input)?;
|
let (input, pos) = position(input)?;
|
||||||
let pos: usize = pos.location_offset();
|
let location = pos.location_offset().into();
|
||||||
let id = fresh_id(&input);
|
let id = fresh_id(&input);
|
||||||
context(
|
let (rest, kind) = context(
|
||||||
"Parsing-statement",
|
"Parsing-statement",
|
||||||
map(expression, move |expr| Statement {
|
alt((
|
||||||
id,
|
map(expression, StatementKind::Expression),
|
||||||
location: pos.into(),
|
map(declaration, StatementKind::Declaration),
|
||||||
kind: StatementKind::Expression(expr),
|
))
|
||||||
}),
|
)(input)?;
|
||||||
)(input)
|
Ok((rest, Statement { id, location, kind }))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declaration(input: Span) -> ParseResult<Declaration> {
|
||||||
|
alt((binding, module))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn binding(input: Span) -> ParseResult<Declaration> {
|
||||||
|
let parser =
|
||||||
|
tuple((kw("let"), opt(kw("mut")), tok(identifier), opt(type_anno), tok(char('=')), expression));
|
||||||
|
map(parser, |(_, maybe_mut, ident, type_anno, _, expr)|
|
||||||
|
Declaration::Binding { name: rc_string(ident.fragment()), constant: maybe_mut.is_none(),
|
||||||
|
type_anno, expr })(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn module(input: Span) -> ParseResult<Declaration> {
|
||||||
|
map(tuple((kw("module"), tok(identifier), block)),
|
||||||
|
|(_, name, items)| Declaration::Module { name: rc_string(name.fragment()), items })(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expression(input: Span) -> ParseResult<Expression> {
|
pub fn expression(input: Span) -> ParseResult<Expression> {
|
||||||
|
@ -28,6 +28,12 @@ impl Parser {
|
|||||||
peg_parser::schala_parser::program(input, self).map_err(ParseError::from_peg)
|
peg_parser::schala_parser::program(input, self).map_err(ParseError::from_peg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parse_comb(&mut self, input: &str) -> Result<AST, ParseError> {
|
||||||
|
let id_store: IdStore<ASTItem> = IdStore::new();
|
||||||
|
let span = Span::new_extra(input, Rc::new(RefCell::new(id_store)));
|
||||||
|
combinator::program(span).map_err(|err| convert_err(input, err)).map(|(_, output)| output)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn expression(&mut self, input: &str) -> Result<Expression, ParseError> {
|
fn expression(&mut self, input: &str) -> Result<Expression, ParseError> {
|
||||||
peg_parser::schala_parser::expression(input, self).map_err(ParseError::from_peg)
|
peg_parser::schala_parser::expression(input, self).map_err(ParseError::from_peg)
|
||||||
|
@ -98,6 +98,20 @@ macro_rules! assert_ast {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
macro_rules! assert_ast_comb {
|
||||||
|
($input:expr, $statements:expr) => {
|
||||||
|
let mut parser = Parser::new();
|
||||||
|
let ast = parser.parse_comb($input);
|
||||||
|
let expected = AST { id: Default::default(), statements: $statements.into() };
|
||||||
|
if ast.is_err() {
|
||||||
|
println!("Parse error: {}", ast.unwrap_err().msg);
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
assert_eq!(ast.unwrap(), expected);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! assert_fail {
|
macro_rules! assert_fail {
|
||||||
($input:expr, $failure:expr) => {
|
($input:expr, $failure:expr) => {
|
||||||
let mut parser = Parser::new();
|
let mut parser = Parser::new();
|
||||||
@ -180,7 +194,7 @@ fn binexps() {
|
|||||||
use StatementKind::Expression;
|
use StatementKind::Expression;
|
||||||
|
|
||||||
assert_expr_comb!("0xf_f+1", binop("+", expr(NatLiteral(255)), expr(NatLiteral(1))));
|
assert_expr_comb!("0xf_f+1", binop("+", expr(NatLiteral(255)), expr(NatLiteral(1))));
|
||||||
assert_ast!(
|
assert_ast_comb!(
|
||||||
"3; 4; 4.3",
|
"3; 4; 4.3",
|
||||||
vec![
|
vec![
|
||||||
stmt(Expression(expr(NatLiteral(3)))),
|
stmt(Expression(expr(NatLiteral(3)))),
|
||||||
@ -1315,7 +1329,7 @@ fn blocks() {
|
|||||||
|
|
||||||
let mut parser = Parser::new();
|
let mut parser = Parser::new();
|
||||||
for case in cases.iter() {
|
for case in cases.iter() {
|
||||||
let block = parser.block(case);
|
let block = parser.block_comb(case);
|
||||||
assert_eq!(block.unwrap(), vec![exst(Value(qn!(a)))].into());
|
assert_eq!(block.unwrap(), vec![exst(Value(qn!(a)))].into());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1397,7 +1411,7 @@ fn comments() {
|
|||||||
assert_fail_expr!(source, binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))));
|
assert_fail_expr!(source, binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))));
|
||||||
|
|
||||||
let source = "5//no man\n";
|
let source = "5//no man\n";
|
||||||
assert_ast!(source, vec![exst(NatLiteral(5))]);
|
assert_ast_comb!(source, vec![exst(NatLiteral(5))]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO support backtick operators like this
|
//TODO support backtick operators like this
|
||||||
|
Loading…
Reference in New Issue
Block a user