From 5f0f1147b18895e512dc41739979b0fcea21850c Mon Sep 17 00:00:00 2001 From: Reid 'arrdem' McKenzie Date: Sat, 21 Aug 2021 17:14:57 -0600 Subject: [PATCH] Get arrays and mappings working --- projects/lilith/src/python/lilith/grammar.lark | 15 ++++++++++++--- projects/lilith/src/python/lilith/parser.py | 14 ++++++++++---- projects/lilith/src/python/lilith/repl.py | 6 ++++-- projects/lilith/test/python/conftest.py | 5 +++++ projects/lilith/test/python/test_parser.py | 15 +++++++++++++++ 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/projects/lilith/src/python/lilith/grammar.lark b/projects/lilith/src/python/lilith/grammar.lark index 3d88fa1..c6245bc 100644 --- a/projects/lilith/src/python/lilith/grammar.lark +++ b/projects/lilith/src/python/lilith/grammar.lark @@ -10,9 +10,18 @@ STRING: /""".*?"""/ | /".*?"/ int: INT float: FLOAT number: int | float -word: WORD ("." WORD)* +word: "nil" -> nil + | "true" -> true + | "false" -> false + | WORD ("." WORD)* -> word string: STRING -atom: number | word | string + +list: "[" (expr ("," expr)*)? "]" + +pair: expr ":" expr +dict: "{" (pair ("," pair)*)? "}" + +atom: number | word | string | list | dict application: word "[" arguments? "]" @@ -20,7 +29,7 @@ expr: application | atom args: expr ("," args)? -kwargs: expr ":" expr ("," kwargs)? +kwargs: pair ("," kwargs)* a_args_kwargs: args ";" kwargs a_args: args diff --git a/projects/lilith/src/python/lilith/parser.py b/projects/lilith/src/python/lilith/parser.py index fb48391..c6d2e97 100644 --- a/projects/lilith/src/python/lilith/parser.py +++ b/projects/lilith/src/python/lilith/parser.py @@ -54,13 +54,16 @@ class TreeToTuples(Transformer): def string(self, s): return s[1:-1].replace('\\"', '"') - null = lambda self, _: None + nil = lambda self, _: None true = lambda self, _: True false = lambda self, _: False int = v_args(inline=True)(lambda self, x: int(x)) float = v_args(inline=True)(lambda self, x: float(x)) number = v_args(inline=True)(lambda self, x: x) + list = list + dict = dict + def word(self, args): """args: ['a'] ['a' ['b', 'c', 'd']]""" return Symbol(".".join(a.value for a in args)) @@ -82,11 +85,14 @@ class TreeToTuples(Transformer): _args = _args + args[1] return _args + def pair(self, args): + return (args[0], args[1]) + def kwargs(self, args): d = {} - key, val = args[0:2] - if len(args) == 3: - d.update(args[2]) + key, val = args[0] + if len(args) == 2: + d.update(args[1]) d[key] = val return d diff --git a/projects/lilith/src/python/lilith/repl.py b/projects/lilith/src/python/lilith/repl.py index bb4ff66..8680146 100644 --- a/projects/lilith/src/python/lilith/repl.py +++ b/projects/lilith/src/python/lilith/repl.py @@ -1,5 +1,7 @@ """A simple Lilith shell.""" +import traceback + from lilith.interpreter import Bindings, eval, Runtime from lilith.parser import Apply, Args, parse_expr from lilith.reader import Module @@ -49,12 +51,12 @@ if __name__ == "__main__": try: expr = parse_expr(line) except Exception as e: - print(e) + traceback.print_exc() continue try: result = eval(runtime, module, Bindings("__root__", None), expr) print_([("class:result", f"⇒ {result!r}")], style=STYLE) except Exception as e: - print(e) + traceback.print_exc() continue diff --git a/projects/lilith/test/python/conftest.py b/projects/lilith/test/python/conftest.py index 7be6349..6723c47 100644 --- a/projects/lilith/test/python/conftest.py +++ b/projects/lilith/test/python/conftest.py @@ -22,6 +22,11 @@ def arguments_grammar(): return parser_with_transformer(GRAMMAR, "arguments") +@pytest.fixture +def expr_grammar(): + return parser_with_transformer(GRAMMAR, "expr") + + @pytest.fixture def header_grammar(): return parser_with_transformer(GRAMMAR, "header") diff --git a/projects/lilith/test/python/test_parser.py b/projects/lilith/test/python/test_parser.py index 0ceca97..3b13657 100644 --- a/projects/lilith/test/python/test_parser.py +++ b/projects/lilith/test/python/test_parser.py @@ -60,6 +60,21 @@ def test_parse_arguments(arguments_grammar, example, expected): assert arguments_grammar.parse(example) == expected +@pytest.mark.parametrize( + "example, expected", + [ + ("1", 1), + ("[1, 2, 3]", [1, 2, 3]), + ('{"a": 1}', {"a": 1}), + ("true", True), + ("false", False), + ("nil", None), + ], +) +def test_parse_expr(expr_grammar, example, expected): + assert expr_grammar.parse(example) == expected + + @pytest.mark.parametrize( "example, expected", [