Work on object access and number literal grammar; basic parser testing.

This commit is contained in:
Jesse Brault 2025-04-20 14:11:03 -05:00
parent 815168603c
commit 90a3c40ac3
2 changed files with 78 additions and 6 deletions

View File

@ -67,25 +67,38 @@ Statement = { VariableDeclaration | CallExpression | AssignmentExpression }
VariableDeclaration = { "let" ~ Mutable? ~ Identifier ~ TypeAnnotation? ~ ( "=" ~ Expression )? }
// Expressions
Expression = { CallExpression | AssignmentExpression | Literal | FullyQualifiedName }
Expression = { CallExpression | AssignmentExpression | Literal | ObjectAccess }
ExpressionList = { Expression ~ ( "," ~ Expression )* }
// Calls
CallExpression = { FullyQualifiedName ~ GenericArguments ~ CallArguments }
CallExpression = { ObjectAccess ~ GenericArguments? ~ CallArguments }
CallArguments = {
( "(" ~ ExpressionList? ~")")
| ExpressionList
}
// Assignment
AssignmentExpression = { FullyQualifiedName ~ "=" ~ Expression }
AssignmentExpression = { ObjectAccess ~ "=" ~ Expression }
// Object
ObjectAccess = { FullyQualifiedName ~ ( "." ~ Identifier )* }
// Literals
Literal = { NumberLiteral | StringLiteral | BooleanLiteral | NullLiteral }
NumberLiteral = { IntLiteral }
IntLiteral = { '0'..'9'+ }
LongLiteral = { '0'..'9'+ ~ "L" }
NumberLiteral = { LongLiteral | IntLiteral }
IntLiteral = { NumberBase }
LongLiteral = ${ NumberBase ~ "L" }
NumberBase = { DecimalBase | BinaryBase | HexadecimalBase }
DecimalBase = @{ DecimalStartDigit ~ Digit* }
BinaryBase = @{ "0b" ~ Digit* }
DecimalStartDigit = { '1'..'9' }
Digit = { '0'..'9'+ }
HexadecimalBase = @{ "0x" ~ HexadecimalDigit+ }
HexadecimalDigit = { '0'..'9' | 'a'..'f' }
StringLiteral = ${ "\"" ~ StringInner ~ "\"" }
StringInner = @{ StringChar* }

View File

@ -3,3 +3,62 @@ use pest_derive::Parser;
#[derive(Parser)]
#[grammar = "parser/deimos.pest"]
pub struct DeimosParser;
#[cfg(test)]
mod deimos_parser_tests {
use crate::parser::{DeimosParser, Rule};
use pest::iterators::Pair;
use pest::Parser;
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()
)
}
}};
($pair:expr; $head_rule:path $(, $tail_rules:path )* ; $handle_last:expr) => {{
if let $head_rule = $pair.as_rule() {
let inner = $pair.into_inner().next().unwrap();
match_inner_rules!(
inner;
$( $tail_rules ),*;
$handle_last
);
} else {
panic!(
"Expected {} but found {:?}",
stringify!($head_rule),
$pair.as_rule()
)
}
}};
}
fn parse(rule: Rule, input: &str) -> Pair<Rule> {
let pair = DeimosParser::parse(rule, input).unwrap().next().unwrap();
dbg!(&pair);
pair
}
#[test]
fn hex_int() {
let pair = parse(Rule::IntLiteral, "0x1234abcd");
match_inner_rules!(pair; Rule::IntLiteral, Rule::NumberBase, Rule::HexadecimalBase; |hexadecimal_base: Pair<Rule>| {
assert_eq!(hexadecimal_base.as_str(), "0x1234abcd")
});
}
#[test]
fn hex_long() {
let pair = parse(Rule::LongLiteral, "0x123456789abcdefL");
match_inner_rules!(pair; Rule::LongLiteral, Rule::NumberBase, Rule::HexadecimalBase; |hexadecimal_base: Pair<Rule>| {
assert_eq!(hexadecimal_base.as_str(), "0x123456789abcdef")
})
}
}