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 = [
"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"

View File

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

View File

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

View File

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