diff --git a/schala-lang/language/src/parsing/new.rs b/schala-lang/language/src/parsing/new.rs index 9f10244..ac31b1c 100644 --- a/schala-lang/language/src/parsing/new.rs +++ b/schala-lang/language/src/parsing/new.rs @@ -19,7 +19,7 @@ peg::parser! { id: Default::default(), location: Default::default(), kind: StatementKind::Expression(expr) } } - rule block() -> Block = "{" items:(statement() ** delimiter()) "}" { items.into() } + rule block() -> Block = "{" _ items:(statement() ** delimiter()) _ "}" { items.into() } pub rule expression() -> Expression = _ kind:expression_kind() { Expression { id: Default::default(), type_anno: None, kind: kind } } @@ -27,6 +27,9 @@ peg::parser! { rule expression_kind() -> ExpressionKind = precedence_expr() + rule expression_kind_no_struct() -> ExpressionKind = + precedence_expr_no_struct() + rule precedence_expr() -> ExpressionKind = first:prefix_expr() _ next:(precedence_continuation())* { let next = next.into_iter().map(|(sigil, expr)| (BinOp::from_sigil(sigil), expr)).collect(); @@ -36,6 +39,15 @@ peg::parser! { rule precedence_continuation() -> (&'input str, ExpressionKind) = op:operator() _ expr:prefix_expr() _ { (op, expr) } + rule precedence_expr_no_struct() -> ExpressionKind = + first:prefix_expr() _ next:(precedence_continuation_no_struct())* { + let next = next.into_iter().map(|(sigil, expr)| (BinOp::from_sigil(sigil), expr)).collect(); + BinopSequence { first, next }.do_precedence() + } + + rule precedence_continuation_no_struct() -> (&'input str, ExpressionKind) = + op:operator() _ expr:prefix_expr_no_struct() _ { (op, expr) } + rule prefix_expr() -> ExpressionKind = prefix:prefix()? expr:extended_expr() { if let Some(p) = prefix { @@ -47,6 +59,17 @@ peg::parser! { } } + rule prefix_expr_no_struct() -> ExpressionKind = + prefix:prefix()? expr:extended_expr_no_struct() { + if let Some(p) = prefix { + let expr = Expression::new(Default::default(), expr); + let prefix = PrefixOp::from_sigil(p); + ExpressionKind::PrefixExp(prefix, Box::new(expr)) + } else { + expr + } + } + rule prefix() -> &'input str = $(['+' | '-' | '!' ]) @@ -76,6 +99,27 @@ peg::parser! { } } / primary() + #[cache_left_rec] + rule extended_expr_no_struct() -> ExpressionKind = + indexee:extended_expr() indexers:index_part() { + ExpressionKind::Index { + indexee: Box::new(Expression::new(Default::default(), indexee)), + indexers, + } + } / + f:extended_expr() arguments:call_part() { + ExpressionKind::Call { + f: Box::new(Expression::new(Default::default(), f)), + arguments, + } + + } / + expr:extended_expr() "." name:identifier() { ExpressionKind::Access { + name: Rc::new(name.to_string()), + expr: Box::new(Expression::new(Default::default(),expr)), + } } / + primary_no_struct() + rule index_part() -> Vec = "[" indexers:(expression() ++ ",") "]" { indexers } @@ -92,10 +136,23 @@ peg::parser! { _ expr:expression() _ { InvocationArgument::Positional(expr) } + rule primary_no_struct() -> ExpressionKind = + while_expr() / float_literal() / nat_literal() / bool_literal() / string_literal() / paren_expr() / + list_expr() / if_expr() / identifier_expr() + rule primary() -> ExpressionKind = - float_literal() / nat_literal() / bool_literal() / string_literal() / paren_expr() / + while_expr() / float_literal() / nat_literal() / bool_literal() / string_literal() / paren_expr() / list_expr() / if_expr() / named_struct() / identifier_expr() + rule while_expr() -> ExpressionKind = + "while" _ cond:expression_kind_no_struct()? _ body:block() { + ExpressionKind::WhileExpression { + condition: cond.map(|kind| Box::new(Expression::new(Default::default(), kind))), + body, + } + } + + rule identifier_expr() -> ExpressionKind = qn:qualified_identifier() { ExpressionKind::Value(qn) } diff --git a/schala-lang/language/src/parsing/test.rs b/schala-lang/language/src/parsing/test.rs index 166845b..789d9b4 100644 --- a/schala-lang/language/src/parsing/test.rs +++ b/schala-lang/language/src/parsing/test.rs @@ -365,8 +365,8 @@ fn index() { fn while_expression() { use ExpressionKind::*; - assert_expr!("while { }", expr(WhileExpression { condition: None, body: Block::default() })); - assert_expr!( + assert_expr2!("while { }", expr(WhileExpression { condition: None, body: Block::default() })); + assert_expr2!( "while a == b { }", expr(WhileExpression { condition: Some(bx(binop("==", expr(Value(qn!(a))), expr(Value(qn!(b)))))),