From 15abcc92d32a552cd686820e0d35a73489a69c51 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Fri, 16 May 2025 19:06:07 -0500 Subject: [PATCH] Add indoc and indexing to grammar. --- Cargo.lock | 7 +++ Cargo.toml | 1 + src/parser/deimos.pest | 19 ++++++-- src/parser/mod.rs | 108 ++++++++++++++++++----------------------- 4 files changed, 70 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d21f4a3..29092f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,6 +148,7 @@ version = "0.1.0" dependencies = [ "clap", "codespan-reporting", + "indoc", "log", "pest", "pest_derive", @@ -179,6 +180,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "indoc" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" + [[package]] name = "is_terminal_polyfill" version = "1.70.1" diff --git a/Cargo.toml b/Cargo.toml index e4ebad0..9d3a400 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,4 @@ clap = { version = "4.5.23", features = ["derive"] } pest_derive = "2.7.14" codespan-reporting = "0.12.0" log = "0.4.27" +indoc = "2.0.6" diff --git a/src/parser/deimos.pest b/src/parser/deimos.pest index 4c1ca9d..cc08a00 100644 --- a/src/parser/deimos.pest +++ b/src/parser/deimos.pest @@ -95,6 +95,7 @@ Borrow = { "&" } Star = { "*" } LeftShift = { "<<" } RightShift = { ">>" } +Index = { "[]" } Operator = { Or @@ -118,6 +119,9 @@ Operator = { | Spread | Borrow | Star + | LeftShift + | RightShift + | Index } // Names @@ -429,9 +433,9 @@ FunctionModifier = { } FunctionBody = { - FunctionEqualsBody + FunctionAliasBody + | FunctionEqualsBody | BlockStatement - | FunctionAliasBody } FunctionEqualsBody = { @@ -652,9 +656,18 @@ ParenthesizedExpression = { } ObjectAccess = { + ( ObjectProperty | ObjectIndex )+ +} + +ObjectProperty = { "." ~ Identifier - ~ ( "." ~ Identifier )* +} + +ObjectIndex = { + "[" + ~ Expression + ~ "]" } // Calls diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 4d20567..f941658 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -7,8 +7,8 @@ pub struct DeimosParser; #[cfg(test)] mod deimos_parser_tests { use crate::parser::{DeimosParser, Rule}; - use pest::iterators::Pair; - use pest::{Parser}; + use indoc::indoc; + use pest::Parser; macro_rules! fail_rule { ($pair: expr; $rule:path) => {{ @@ -28,81 +28,65 @@ mod deimos_parser_tests { }}; } - macro_rules! match_inner_rules { - ($pair:expr; $rule:path; $handle_last:expr) => {{ - if let $rule = $pair.as_rule() { - $handle_last($pair); - } else { - fail_rule!($pair; $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 { - let pair = DeimosParser::parse(rule, input) - .expect("Parsing failed.") - .next() - .unwrap(); - dbg!(&pair); - pair + fn parses_to(rule: Rule, input: &str) { + let parse_result = DeimosParser::parse(rule, input); + if let Err(e) = parse_result { + panic!("Parsing failed.\n{}", e); + } else { + let mut pairs = parse_result.unwrap(); + let first = pairs.next().unwrap(); + match_rule!(first; rule) + } } #[test] fn hex_int() { - let pair = parse(Rule::IntLiteral, "0x1234abcd"); - match_inner_rules!(pair; Rule::IntLiteral, Rule::NumberBase, Rule::HexadecimalBase; |hexadecimal_base: Pair| { - assert_eq!(hexadecimal_base.as_str(), "0x1234abcd") - }); + parses_to(Rule::IntLiteral, "0x1234abcd"); } #[test] fn hex_long() { - let pair = parse(Rule::LongLiteral, "0x123456789abcdefL"); - match_inner_rules!(pair; Rule::LongLiteral, Rule::NumberBase, Rule::HexadecimalBase; |hexadecimal_base: Pair| { - assert_eq!(hexadecimal_base.as_str(), "0x123456789abcdef") - }) + parses_to(Rule::LongLiteral, "0x123456789abcdefL"); } #[test] - fn identifier_call_as_expression() { - parse(Rule::Expression, "foo()"); + fn suffix_expression_call_single_identifier() { + parses_to(Rule::SuffixExpression, "foo()"); } - mod smoke_screen_tests { - use crate::parser::deimos_parser_tests::parse; - use crate::parser::Rule; + #[test] + fn simple_interface() { + parses_to(Rule::CompilationUnit, "pub int Simple { fn foo() -> Void }"); + } - #[test] - fn simple_interface() { - parse(Rule::CompilationUnit, "pub int Simple { fn foo() -> Void }"); - } + #[test] + fn interface_with_op() { + parses_to( + Rule::CompilationUnit, + "pub int Callable { op () () -> Void }", + ); + } - #[test] - fn interface_with_op() { - parse( - Rule::CompilationUnit, - "pub int Callable { op () () -> Void }", - ); - } + #[test] + fn interface_with_alias() { + parses_to( + Rule::CompilationUnit, + indoc! {" + pub int Callable { + fn call() -> Void + def op () () -> Void alias call + } + "}, + ); + } - #[test] - fn interface_with_alias() { - parse( - Rule::CompilationUnit, - "pub int Callable {\n fn call() -> Void\n op () () -> Void alias call\n}", - ); - } + #[test] + fn index_identifier() { + parses_to(Rule::SuffixExpression, "foo[0]"); + } + + #[test] + fn chained_index_call_on_identifier() { + parses_to(Rule::SuffixExpression, "foo[0]()"); } }