diff --git a/parser-ng/src/parser/cst/syntax_kind.rs b/parser-ng/src/parser/cst/syntax_kind.rs index 3491ff779..6587ef01c 100644 --- a/parser-ng/src/parser/cst/syntax_kind.rs +++ b/parser-ng/src/parser/cst/syntax_kind.rs @@ -61,6 +61,7 @@ pub enum SyntaxKind { // Punctuation AMPERSAND, ASTERISK, + CARET, COLON, COMMA, BACKSLASH, @@ -98,7 +99,13 @@ pub enum SyntaxKind { PATTERNS_BLK, PATTERN_MODS, PATTERN_MOD, + RANGE, REGEXP, + TERM, + EXPR, + INDEXING_EXPR, + PRIMARY_EXPR, + FUNC_CALL_EXPR, META_DEF, META_BLK, SOURCE_FILE, @@ -186,6 +193,7 @@ impl From<&Token> for SyntaxKind { Token::AMPERSAND(_) => SyntaxKind::AMPERSAND, Token::ASTERISK(_) => SyntaxKind::ASTERISK, Token::BACKSLASH(_) => SyntaxKind::BACKSLASH, + Token::CARET(_) => SyntaxKind::CARET, Token::COLON(_) => SyntaxKind::COLON, Token::COMMA(_) => SyntaxKind::COMMA, Token::DOT(_) => SyntaxKind::DOT, diff --git a/parser-ng/src/parser/mod.rs b/parser-ng/src/parser/mod.rs index 5e3927190..521db3eee 100644 --- a/parser-ng/src/parser/mod.rs +++ b/parser-ng/src/parser/mod.rs @@ -1134,25 +1134,96 @@ impl<'src> InternalParser<'src> { /// /// ```text /// BOOLEAN_TERM := ( - /// TRUE_KW | - /// FALSE_KW + /// `true` | + /// `false` | + /// `not` BOOLEAN_TERM | + /// `defined` BOOLEAN_TERM | + /// `(` BOOLEAN_EXPR `)` /// ) /// `` fn boolean_term(&mut self) -> &mut Self { self.begin(SyntaxKind::BOOLEAN_TERM) .begin_alt() - .alt(|p| p.expect(t!(TRUE_KW))) - .alt(|p| p.expect(t!(FALSE_KW))) + .alt(|p| { + p.expect(t!(PATTERN_IDENT)) + .if_found(t!(AT_KW), |p| { + p.expect(t!(AT_KW)).then(|p| p.expr()) + }) + .if_found(t!(IN_KW), |p| { + p.expect(t!(IN_KW)).then(|p| p.range()) + }) + }) + .alt(|p| p.expect(t!(TRUE_KW | FALSE_KW))) + .alt(|p| p.expect(t!(NOT_KW)).then(|p| p.boolean_term())) + .alt(|p| p.expect(t!(DEFINED_KW)).then(|p| p.boolean_term())) + .alt(|p| { + p.expect(t!(L_PAREN)) + .then(|p| p.boolean_expr()) + .expect(t!(R_PAREN)) + }) .end_alt() .end() } fn expr(&mut self) -> &mut Self { - todo!() + self.begin(SyntaxKind::EXPR) + .then(|p| p.term()) + .zero_or_more(|p| { + p.expect(t!(PLUS + | HYPEN + | ASTERISK + | BACKSLASH + | PERCENT + | SHL + | SHR + | AMPERSAND + | PIPE + | TILDE + | DOT)) + .then(|p| p.term()) + }) + .end() } fn term(&mut self) -> &mut Self { - todo!() + self.begin(SyntaxKind::TERM) + .begin_alt() + .alt(|p| p.indexing_expr()) + .alt(|p| p.func_call_expr()) + .alt(|p| p.primary_expr()) + .end_alt() + .end() + } + + /// Parses a range. + /// + /// ```text + /// RANGE := `(` EXPR `.` `.` EXPR `)` + /// `` + fn range(&mut self) -> &mut Self { + self.begin(SyntaxKind::RANGE) + .expect(t!(L_PAREN)) + .then(|p| p.expr()) + .expect(t!(DOT)) + .expect(t!(DOT)) + .then(|p| p.expr()) + .expect(t!(R_PAREN)) + .end() + } + + fn indexing_expr(&mut self) -> &mut Self { + // TODO + self + } + + fn func_call_expr(&mut self) -> &mut Self { + // TODO + self + } + + fn primary_expr(&mut self) -> &mut Self { + // TODO + self } } diff --git a/parser-ng/src/parser/tests/testdata/basic-4.in b/parser-ng/src/parser/tests/testdata/basic-4.in new file mode 100644 index 000000000..4d92f8e50 --- /dev/null +++ b/parser-ng/src/parser/tests/testdata/basic-4.in @@ -0,0 +1,4 @@ +rule test { + condition: + true and not false or (false or true) +} diff --git a/parser-ng/src/parser/tests/testdata/basic-4.out b/parser-ng/src/parser/tests/testdata/basic-4.out new file mode 100644 index 000000000..28e2d2bfb --- /dev/null +++ b/parser-ng/src/parser/tests/testdata/basic-4.out @@ -0,0 +1,42 @@ +SOURCE_FILE@0..66 + RULE_DECL@0..65 + RULE_KW@0..4 "rule" + WHITESPACE@4..5 " " + IDENT@5..9 "test" + WHITESPACE@9..10 " " + L_BRACE@10..11 "{" + NEWLINE@11..12 "\n" + WHITESPACE@12..13 "\t" + CONDITION_BLK@13..63 + CONDITION_KW@13..22 "condition" + COLON@22..23 ":" + NEWLINE@23..24 "\n" + WHITESPACE@24..26 "\t\t" + BOOLEAN_EXPR@26..63 + BOOLEAN_TERM@26..30 + TRUE_KW@26..30 "true" + WHITESPACE@30..31 " " + AND_KW@31..34 "and" + WHITESPACE@34..35 " " + BOOLEAN_TERM@35..44 + NOT_KW@35..38 "not" + WHITESPACE@38..39 " " + BOOLEAN_TERM@39..44 + FALSE_KW@39..44 "false" + WHITESPACE@44..45 " " + OR_KW@45..47 "or" + WHITESPACE@47..48 " " + BOOLEAN_TERM@48..63 + L_PAREN@48..49 "(" + BOOLEAN_EXPR@49..62 + BOOLEAN_TERM@49..54 + FALSE_KW@49..54 "false" + WHITESPACE@54..55 " " + OR_KW@55..57 "or" + WHITESPACE@57..58 " " + BOOLEAN_TERM@58..62 + TRUE_KW@58..62 "true" + R_PAREN@62..63 ")" + NEWLINE@63..64 "\n" + R_BRACE@64..65 "}" + NEWLINE@65..66 "\n" diff --git a/parser-ng/src/parser/tests/testdata/hex-patterns-1.in b/parser-ng/src/parser/tests/testdata/hex-patterns-1.in index dcb30f22c..af5adcc2a 100644 --- a/parser-ng/src/parser/tests/testdata/hex-patterns-1.in +++ b/parser-ng/src/parser/tests/testdata/hex-patterns-1.in @@ -2,5 +2,5 @@ rule test { strings: $a = { 00 11 AA ?? B? ?2 ~02 11223344 } condition: - true + $a } \ No newline at end of file diff --git a/parser-ng/src/parser/tests/testdata/hex-patterns-1.out b/parser-ng/src/parser/tests/testdata/hex-patterns-1.out index e5bed384b..139104302 100644 --- a/parser-ng/src/parser/tests/testdata/hex-patterns-1.out +++ b/parser-ng/src/parser/tests/testdata/hex-patterns-1.out @@ -1,5 +1,5 @@ -SOURCE_FILE@0..87 - RULE_DECL@0..87 +SOURCE_FILE@0..85 + RULE_DECL@0..85 RULE_KW@0..4 "rule" WHITESPACE@4..5 " " IDENT@5..9 "test" @@ -43,13 +43,13 @@ SOURCE_FILE@0..87 R_BRACE@63..64 "}" NEWLINE@64..65 "\n" WHITESPACE@65..67 " " - CONDITION_BLK@67..85 + CONDITION_BLK@67..83 CONDITION_KW@67..76 "condition" COLON@76..77 ":" NEWLINE@77..78 "\n" WHITESPACE@78..81 "\t " - BOOLEAN_EXPR@81..85 - BOOLEAN_TERM@81..85 - TRUE_KW@81..85 "true" - NEWLINE@85..86 "\n" - R_BRACE@86..87 "}" + BOOLEAN_EXPR@81..83 + BOOLEAN_TERM@81..83 + PATTERN_IDENT@81..83 "$a" + NEWLINE@83..84 "\n" + R_BRACE@84..85 "}" diff --git a/parser-ng/src/parser/tests/testdata/hex-patterns-2.in b/parser-ng/src/parser/tests/testdata/hex-patterns-2.in index 9556bc0a6..fac9eb58c 100644 --- a/parser-ng/src/parser/tests/testdata/hex-patterns-2.in +++ b/parser-ng/src/parser/tests/testdata/hex-patterns-2.in @@ -2,5 +2,5 @@ rule test { strings: $a = { 11 ( 22 | 33 ) 44 } condition: - true + $a } \ No newline at end of file diff --git a/parser-ng/src/parser/tests/testdata/hex-patterns-2.out b/parser-ng/src/parser/tests/testdata/hex-patterns-2.out index b015c8d7a..f18787174 100644 --- a/parser-ng/src/parser/tests/testdata/hex-patterns-2.out +++ b/parser-ng/src/parser/tests/testdata/hex-patterns-2.out @@ -1,5 +1,5 @@ -SOURCE_FILE@0..74 - RULE_DECL@0..74 +SOURCE_FILE@0..72 + RULE_DECL@0..72 RULE_KW@0..4 "rule" WHITESPACE@4..5 " " IDENT@5..9 "test" @@ -41,13 +41,13 @@ SOURCE_FILE@0..74 R_BRACE@50..51 "}" NEWLINE@51..52 "\n" WHITESPACE@52..54 " " - CONDITION_BLK@54..72 + CONDITION_BLK@54..70 CONDITION_KW@54..63 "condition" COLON@63..64 ":" NEWLINE@64..65 "\n" WHITESPACE@65..68 "\t " - BOOLEAN_EXPR@68..72 - BOOLEAN_TERM@68..72 - TRUE_KW@68..72 "true" - NEWLINE@72..73 "\n" - R_BRACE@73..74 "}" + BOOLEAN_EXPR@68..70 + BOOLEAN_TERM@68..70 + PATTERN_IDENT@68..70 "$a" + NEWLINE@70..71 "\n" + R_BRACE@71..72 "}" diff --git a/parser-ng/src/tokenizer/mod.rs b/parser-ng/src/tokenizer/mod.rs index fc046ef4c..3dd705688 100644 --- a/parser-ng/src/tokenizer/mod.rs +++ b/parser-ng/src/tokenizer/mod.rs @@ -293,6 +293,8 @@ enum NormalToken<'src> { Percent, #[token("|")] Pipe, + #[token("^")] + Caret, #[token("~")] Tilde, @@ -545,6 +547,7 @@ fn convert_normal_token(token: NormalToken, span: Span) -> Token { NormalToken::Ampersand => Token::AMPERSAND(span), NormalToken::Asterisk => Token::ASTERISK(span), NormalToken::Backslash => Token::BACKSLASH(span), + NormalToken::Caret => Token::CARET(span), NormalToken::Colon => Token::COLON(span), NormalToken::Dot => Token::DOT(span), NormalToken::Equal => Token::EQUAL(span), diff --git a/parser-ng/src/tokenizer/tokens.rs b/parser-ng/src/tokenizer/tokens.rs index e1e68ab91..bc4542867 100644 --- a/parser-ng/src/tokenizer/tokens.rs +++ b/parser-ng/src/tokenizer/tokens.rs @@ -70,6 +70,7 @@ pub enum Token { AMPERSAND(Span), ASTERISK(Span), BACKSLASH(Span), + CARET(Span), COLON(Span), COMMA(Span), DOT(Span), @@ -173,19 +174,20 @@ impl Token { | Token::GE(span) // Punctuation. - | Token::PLUS(span) + | Token::AMPERSAND(span) | Token::ASTERISK(span) | Token::BACKSLASH(span) - | Token::AMPERSAND(span) + | Token::CARET(span) | Token::COLON(span) | Token::COMMA(span) | Token::DOT(span) + | Token::EQUAL(span) | Token::HYPEN(span) | Token::PERCENT(span) | Token::PIPE(span) + | Token::PLUS(span) | Token::TILDE(span) - | Token::EQUAL(span) | Token::L_BRACE(span) | Token::R_BRACE(span) | Token::L_BRACKET(span) @@ -272,6 +274,7 @@ impl Token { Token::AMPERSAND(_) => "&", Token::ASTERISK(_) => "`*`", Token::BACKSLASH(_) => "`\\`", + Token::CARET(_) => "`^`", Token::COLON(_) => "`:`", Token::COMMA(_) => "`,`", Token::DOT(_) => "`.`",