Write expressions grammar, basic testing.

This commit is contained in:
Jesse Brault 2025-04-21 09:11:02 -05:00
parent 90a3c40ac3
commit 084ed4a00b
2 changed files with 81 additions and 15 deletions

View File

@ -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
}

View File

@ -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<Rule>| {
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);
}
}