Add indoc and indexing to grammar.

This commit is contained in:
Jesse Brault 2025-05-16 19:06:07 -05:00
parent f5a82c414c
commit 15abcc92d3
4 changed files with 70 additions and 65 deletions

7
Cargo.lock generated
View File

@ -148,6 +148,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"codespan-reporting", "codespan-reporting",
"indoc",
"log", "log",
"pest", "pest",
"pest_derive", "pest_derive",
@ -179,6 +180,12 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "indoc"
version = "2.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
[[package]] [[package]]
name = "is_terminal_polyfill" name = "is_terminal_polyfill"
version = "1.70.1" version = "1.70.1"

View File

@ -17,3 +17,4 @@ clap = { version = "4.5.23", features = ["derive"] }
pest_derive = "2.7.14" pest_derive = "2.7.14"
codespan-reporting = "0.12.0" codespan-reporting = "0.12.0"
log = "0.4.27" log = "0.4.27"
indoc = "2.0.6"

View File

@ -95,6 +95,7 @@ Borrow = { "&" }
Star = { "*" } Star = { "*" }
LeftShift = { "<<" } LeftShift = { "<<" }
RightShift = { ">>" } RightShift = { ">>" }
Index = { "[]" }
Operator = { Operator = {
Or Or
@ -118,6 +119,9 @@ Operator = {
| Spread | Spread
| Borrow | Borrow
| Star | Star
| LeftShift
| RightShift
| Index
} }
// Names // Names
@ -429,9 +433,9 @@ FunctionModifier = {
} }
FunctionBody = { FunctionBody = {
FunctionEqualsBody FunctionAliasBody
| FunctionEqualsBody
| BlockStatement | BlockStatement
| FunctionAliasBody
} }
FunctionEqualsBody = { FunctionEqualsBody = {
@ -652,9 +656,18 @@ ParenthesizedExpression = {
} }
ObjectAccess = { ObjectAccess = {
( ObjectProperty | ObjectIndex )+
}
ObjectProperty = {
"." "."
~ Identifier ~ Identifier
~ ( "." ~ Identifier )* }
ObjectIndex = {
"["
~ Expression
~ "]"
} }
// Calls // Calls

View File

@ -7,8 +7,8 @@ pub struct DeimosParser;
#[cfg(test)] #[cfg(test)]
mod deimos_parser_tests { mod deimos_parser_tests {
use crate::parser::{DeimosParser, Rule}; use crate::parser::{DeimosParser, Rule};
use pest::iterators::Pair; use indoc::indoc;
use pest::{Parser}; use pest::Parser;
macro_rules! fail_rule { macro_rules! fail_rule {
($pair: expr; $rule:path) => {{ ($pair: expr; $rule:path) => {{
@ -28,81 +28,65 @@ mod deimos_parser_tests {
}}; }};
} }
macro_rules! match_inner_rules { fn parses_to(rule: Rule, input: &str) {
($pair:expr; $rule:path; $handle_last:expr) => {{ let parse_result = DeimosParser::parse(rule, input);
if let $rule = $pair.as_rule() { if let Err(e) = parse_result {
$handle_last($pair); panic!("Parsing failed.\n{}", e);
} else { } else {
fail_rule!($pair; $rule); let mut pairs = parse_result.unwrap();
} let first = pairs.next().unwrap();
}}; match_rule!(first; 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 {
fail_rule!($pair; $head_rule);
}
}};
}
fn parse(rule: Rule, input: &str) -> Pair<Rule> {
let pair = DeimosParser::parse(rule, input)
.expect("Parsing failed.")
.next()
.unwrap();
dbg!(&pair);
pair
} }
#[test] #[test]
fn hex_int() { fn hex_int() {
let pair = parse(Rule::IntLiteral, "0x1234abcd"); parses_to(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] #[test]
fn hex_long() { fn hex_long() {
let pair = parse(Rule::LongLiteral, "0x123456789abcdefL"); parses_to(Rule::LongLiteral, "0x123456789abcdefL");
match_inner_rules!(pair; Rule::LongLiteral, Rule::NumberBase, Rule::HexadecimalBase; |hexadecimal_base: Pair<Rule>| {
assert_eq!(hexadecimal_base.as_str(), "0x123456789abcdef")
})
} }
#[test] #[test]
fn identifier_call_as_expression() { fn suffix_expression_call_single_identifier() {
parse(Rule::Expression, "foo()"); parses_to(Rule::SuffixExpression, "foo()");
} }
mod smoke_screen_tests { #[test]
use crate::parser::deimos_parser_tests::parse; fn simple_interface() {
use crate::parser::Rule; parses_to(Rule::CompilationUnit, "pub int Simple { fn foo() -> Void }");
}
#[test] #[test]
fn simple_interface() { fn interface_with_op() {
parse(Rule::CompilationUnit, "pub int Simple { fn foo() -> Void }"); parses_to(
} Rule::CompilationUnit,
"pub int Callable { op () () -> Void }",
);
}
#[test] #[test]
fn interface_with_op() { fn interface_with_alias() {
parse( parses_to(
Rule::CompilationUnit, Rule::CompilationUnit,
"pub int Callable { op () () -> Void }", indoc! {"
); pub int Callable {
} fn call() -> Void
def op () () -> Void alias call
}
"},
);
}
#[test] #[test]
fn interface_with_alias() { fn index_identifier() {
parse( parses_to(Rule::SuffixExpression, "foo[0]");
Rule::CompilationUnit, }
"pub int Callable {\n fn call() -> Void\n op () () -> Void alias call\n}",
); #[test]
} fn chained_index_call_on_identifier() {
parses_to(Rule::SuffixExpression, "foo[0]()");
} }
} }