From 52c7d7234ca5451467a68d025f8862e232e2abf5 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 21 Jul 2024 16:40:28 +0200 Subject: [PATCH] Add block expression parsing --- src/grammar.pest | 16 ++++++--- src/test/expressions.rs | 17 ++++++++++ src/test/statements.rs | 74 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 100 insertions(+), 7 deletions(-) diff --git a/src/grammar.pest b/src/grammar.pest index 2adcb19..384338f 100644 --- a/src/grammar.pest +++ b/src/grammar.pest @@ -1,10 +1,12 @@ file = { "hello world" } -statement = { decl } -decl = { "let" ~ #name = ident ~ #args = (ident)* ~ "=" ~ expr } +block = { "{" ~ MLF ~ block_line ~ MLF ~ "}" } +block_line = _{ expr | (statement ~ MLF)* } +statement = { (decl | expr) ~ TERMINATE } +decl = { "let" ~ #name = ident ~ #args = (ident)* ~ "=" ~ expr } expr = { infix_expr | call_expr | term } -term = _{ ident | literal | "(" ~ expr ~ ")" } +term = _{ ident | literal | "(" ~ MLF ~ expr ~ MLF ~ ")" | block } call_expr = { #name = ident ~ #args = (term)+ } @@ -14,7 +16,7 @@ infix_expr = { operator = { "+" | "-" | "*" | "/" | "&&" | "||" | "<" | ">" | "==" | "!=" } -ident = @{ ALPHABETIC ~ (ALPHABETIC | NUMBER | "_")* | quoted_indent } +ident = @{ !KEYWORD ~ ALPHABETIC ~ (ALPHABETIC | NUMBER | "_")* | quoted_indent } quoted_indent = _{ "`" ~ (!"`" ~ ANY)+ ~ "`" } literal = { string | number | boolean | char } @@ -29,4 +31,8 @@ float = @{ byte = @{ "0x" ~ ASCII_HEX_DIGIT{1, 2} | "0b" ~ ASCII_BIN_DIGIT{0, 8} } boolean = @{ "true" | "false" } -WHITESPACE = _{ " " | "\t" | "\r" | "\n" } +WHITESPACE = _{ " " | "\t" } +KEYWORD = _{ "let" } +TERMINATE = _{ LF | EOI | ";" } +MLF = _{ (LF)* } +LF = _{ "\n" | "\r" } diff --git a/src/test/expressions.rs b/src/test/expressions.rs index dc67956..86708b4 100644 --- a/src/test/expressions.rs +++ b/src/test/expressions.rs @@ -21,6 +21,23 @@ fn it_parses_addition() { ]); } +#[test] +fn it_parses_plain_values() { + parses_to!(parser: SnekParser, input: "10", rule: Rule::expr, tokens: [ + expr(0, 2, [ + literal(0, 2, [ + integer(0, 2) + ]), + ]) + ]); + + parses_to!(parser: SnekParser, input: "test", rule: Rule::expr, tokens: [ + expr(0, 4, [ + ident(0, 4), + ]) + ]); +} + #[test] fn it_parses_addition_with_variables() { parses_to!(parser: SnekParser, input: "first + second", rule: Rule::expr, tokens: [ diff --git a/src/test/statements.rs b/src/test/statements.rs index 8ca3469..e2d63e9 100644 --- a/src/test/statements.rs +++ b/src/test/statements.rs @@ -13,7 +13,8 @@ fn it_parses_plain_assignments() { integer(8, 9) ]), ]) - ]) + ]), + EOI(9, 9) ]) ]); } @@ -36,7 +37,76 @@ fn it_parses_assignments_with_args() { ]) ]) ]) - ]) + ]), + EOI(17, 17) + ]), + ]); +} + +#[test] +fn it_parses_blocks() { + parses_to!(parser: SnekParser, input: "let a = { 1 + 1 }", rule: Rule::statement, tokens: [ + statement(0, 17, [ + decl(0, 17, [ + ident(4, 5), + expr(8, 17, [ + block(8, 17, [ + expr(10, 15, [ + infix_expr(10, 15, [ + literal(10, 11, [ + integer(10, 11) + ]), + operator(12, 13), + expr(14, 15, [ + literal(14, 15, [ + integer(14, 15) + ]) + ]) + ]) + ]) + ]) + ]) + ]), + EOI(17, 17) + ]) + ]); +} + +#[test] +fn it_parses_multiline_blocks() { + parses_to!(parser: SnekParser, input: "let a = {\nlet b = 1 + 1\nb\n}", rule: Rule::statement, tokens: [ + statement(0, 27, [ + decl(0, 27, [ + ident(4, 5), + expr(8, 27, [ + block(8, 27, [ + statement(10, 24, [ + decl(10, 23, [ + ident(14, 15), + expr(18, 23, [ + infix_expr(18, 23, [ + literal(18, 19, [ + integer(18, 19) + ]), + operator(20, 21), + expr(22, 23, [ + literal(22, 23, [ + integer(22, 23) + ]) + ]) + ]) + ]) + ]), + ]), + statement(24, 26, [ + expr(24, 25, [ + ident(24, 25) + ]) + ]) + ]) + ]) + ]), + EOI(27, 27) ]) ]); }