diff --git a/src/parser/deimos.pest b/src/parser/deimos.pest index 3fc0dc5..137a88a 100644 --- a/src/parser/deimos.pest +++ b/src/parser/deimos.pest @@ -67,13 +67,46 @@ Statement = { VariableDeclaration | CallExpression | AssignmentExpression } VariableDeclaration = { "let" ~ Mutable? ~ Identifier ~ TypeAnnotation? ~ ( "=" ~ Expression )? } // Expressions -Expression = { CallExpression | AssignmentExpression | Literal | ObjectAccess } -ExpressionList = { Expression ~ ( "," ~ Expression )* } +Expression = { OrExpression } -// Calls -CallExpression = { ObjectAccess ~ GenericArguments? ~ CallArguments } +OrExpression = { AndExpression ~ ( "||" ~ AndExpression )* } +AndExpression = { EqualityExpression ~ ( "&&" ~ EqualityExpression )* } + +EqualityExpression = { ComparisonExpression ~ ( ( EqualTo | NotEqualTo ) ~ ComparisonExpression )* } +EqualTo = { "==" } +NotEqualTo = { "!=" } + +ComparisonExpression = { AdditiveExpression ~ ( ( Greater | Less | GreaterEqual | LessEqual ) ~ AdditiveExpression )* } +Greater = { ">" } +Less = { "<" } +GreaterEqual = { ">=" } +LessEqual = { "<=" } + +AdditiveExpression = { MultiplicativeExpression ~ ( ( Add | Subtract ) ~ MultiplicativeExpression )* } +Add = { "+" } +Subtract = { "-" } + +MultiplicativeExpression = { UnaryExpression ~ ( ( Multiply | Divide | Modulo ) ~ UnaryExpression )* } +Multiply = { "*" } +Divide = { "/" } +Modulo = { "%" } + +UnaryExpression = { ( Not | Negative )* ~ PrimaryExpression ~ ( Call | ( PlusPlus | MinusMinus ) )* } +Not = { "!" } +Negative = { "-" } +PlusPlus = { "++" } +MinusMinus = { "--" } + +PrimaryExpression = { Literal | ObjectAccess | ParenthesizedExpression } +ParenthesizedExpression = { "(" ~ Expression ~ ")" } + + +// Call +CallExpression = { PrimaryExpression ~ Call+ } +Call = { GenericArguments? ~ CallArguments } +ExpressionList = { Expression ~ ( "," ~ Expression )* } CallArguments = { - ( "(" ~ ExpressionList? ~")") + ( "(" ~ ExpressionList? ~ ")" ) | ExpressionList } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 3f8af4b..d341bda 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -10,16 +10,30 @@ mod deimos_parser_tests { use pest::iterators::Pair; use pest::Parser; + macro_rules! fail_rule { + ($pair: expr; $rule:path) => {{ + panic!( + "Expected {} but found {:?}", + stringify!($rule), + $pair.as_rule() + ) + }}; + } + + macro_rules! match_rule { + ($pair:expr; $rule:path) => {{ + if $rule != $pair.as_rule() { + fail_rule!($pair; $rule); + } + }}; + } + macro_rules! match_inner_rules { ($pair:expr; $rule:path; $handle_last:expr) => {{ if let $rule = $pair.as_rule() { $handle_last($pair); } else { - panic!( - "Expected {} but found {:?}", - stringify!($rule), - $pair.as_rule() - ) + fail_rule!($pair; $rule); } }}; ($pair:expr; $head_rule:path $(, $tail_rules:path )* ; $handle_last:expr) => {{ @@ -31,11 +45,7 @@ mod deimos_parser_tests { $handle_last ); } else { - panic!( - "Expected {} but found {:?}", - stringify!($head_rule), - $pair.as_rule() - ) + fail_rule!($pair; $head_rule); } }}; } @@ -61,4 +71,27 @@ mod deimos_parser_tests { assert_eq!(hexadecimal_base.as_str(), "0x123456789abcdef") }) } + + #[test] + fn identifier_call_as_expression() { + let pair = parse(Rule::Expression, "foo()"); + match_inner_rules!(pair; Rule::Expression, Rule::OrExpression, Rule::AndExpression, Rule::EqualityExpression, Rule::ComparisonExpression, Rule::AdditiveExpression, Rule::MultiplicativeExpression, Rule::UnaryExpression; |unary_expression: Pair| { + let mut unary_pairs = unary_expression.into_inner(); + let primary_expression = unary_pairs.next().unwrap(); + match_rule!(primary_expression; Rule::PrimaryExpression); + let call = unary_pairs.next().unwrap(); + match_rule!(call; Rule::Call); + }); + } + + #[test] + fn identifier_call_as_call_expression() { + let pair = parse(Rule::CallExpression, "foo()"); + match_rule!(pair; Rule::CallExpression); + let mut call_expression_pairs = pair.into_inner(); + let primary_expression = call_expression_pairs.next().unwrap(); + match_rule!(primary_expression; Rule::PrimaryExpression); + let call = call_expression_pairs.next().unwrap(); + match_rule!(call; Rule::Call); + } }