From a824ff273d1fce93b866c3a8169f95ba94df43a8 Mon Sep 17 00:00:00 2001 From: PaddiM8 Date: Thu, 10 Oct 2024 22:52:10 +0200 Subject: [PATCH] Use parser example for integration tests --- examples/parser/ast.elk | 4 +++- examples/parser/evaluator.elk | 5 +++++ examples/parser/lexer.elk | 2 +- examples/parser/parser.elk | 15 +++++++++++++++ examples/parser/tests.elk | 7 +++++++ tests/IntegrationTests.cs | 1 + 6 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 examples/parser/tests.elk diff --git a/examples/parser/ast.elk b/examples/parser/ast.elk index 475920e..3fad007 100644 --- a/examples/parser/ast.elk +++ b/examples/parser/ast.elk @@ -2,4 +2,6 @@ pub struct Token(kind, value) pub struct BinaryExpr(left, op, right) -pub struct LiteralExpr(value) \ No newline at end of file +pub struct LiteralExpr(value) + +pub struct GroupExpr(value) \ No newline at end of file diff --git a/examples/parser/evaluator.elk b/examples/parser/evaluator.elk index f630fd8..5f2be28 100644 --- a/examples/parser/evaluator.elk +++ b/examples/parser/evaluator.elk @@ -7,6 +7,7 @@ pub fn evaluate(ast) { fn next(expr) { return nextBinary(expr) if expr | isType(BinaryExpr) return nextLiteral(expr) if expr | isType(LiteralExpr) + return nextGroup(expr) if expr | isType(GroupExpr) } fn nextBinary(expr) { @@ -21,4 +22,8 @@ fn nextBinary(expr) { fn nextLiteral(expr) { expr->value->value | into::float +} + +fn nextGroup(expr) { + expr->value | next } \ No newline at end of file diff --git a/examples/parser/lexer.elk b/examples/parser/lexer.elk index 918be60..261b436 100644 --- a/examples/parser/lexer.elk +++ b/examples/parser/lexer.elk @@ -30,7 +30,7 @@ fn next() { return nil if c == nil - if c in ["+", "-", "*", "/"] { + if c in ["+", "-", "*", "/", "(", ")"] { advance return new Token(c, c) } diff --git a/examples/parser/parser.elk b/examples/parser/parser.elk index 6647893..5d8db43 100644 --- a/examples/parser/parser.elk +++ b/examples/parser/parser.elk @@ -8,6 +8,7 @@ let index = 0 pub fn parse(input) { tokens = lexer::lex(input) index = 0 + return nil if len(tokens) == 0 expr() } @@ -28,6 +29,13 @@ fn match(kinds...) { kinds | iter::anyOf => kind { kind == current()->kind } } +fn expect(kind) { + return advance() if match(kind) + + throw new ParseError("Expected '${kind}'") if current() == nil + throw new ParseError("Expected '${kind}' but got '${current()->kind}'") +} + fn expr() { additive() } @@ -61,6 +69,13 @@ fn primary() { return new LiteralExpr(advance()) } + if match("(") { + advance() + let group = new GroupExpr(expr()) + expect(")") + return group + } + throw new ParseError("Unexpected end of expression") if current() != nil throw new ParseError("Unexpected token: '${current()->kind}'") } diff --git a/examples/parser/tests.elk b/examples/parser/tests.elk new file mode 100644 index 0000000..9339311 --- /dev/null +++ b/examples/parser/tests.elk @@ -0,0 +1,7 @@ +with parse from ./parser +with evaluate from ./evaluator + +parse("2 + 3 * 4") | evaluate | assertEqual(14) +parse("(3 + 3 * 4) / 3") | evaluate | assertEqual(5) +parse("2") | evaluate | assertEqual(2) +parse("") | evaluate | assertEqual(nil) \ No newline at end of file diff --git a/tests/IntegrationTests.cs b/tests/IntegrationTests.cs index d585988..9345276 100644 --- a/tests/IntegrationTests.cs +++ b/tests/IntegrationTests.cs @@ -46,6 +46,7 @@ public static IEnumerable ElkFiles() Directory.GetFiles(dataPath, "*.elk", SearchOption.AllDirectories), Directory.GetFiles(Path.Combine(examplesPath, "advent-of-code-2022"), "*.elk", SearchOption.AllDirectories), Directory.GetFiles(Path.Combine(examplesPath, "advent-of-code-2023"), "*.elk", SearchOption.AllDirectories), + Directory.GetFiles(Path.Combine(examplesPath, "parser"), "*.elk", SearchOption.AllDirectories), }.SelectMany(x => x); } } \ No newline at end of file