From 1a793bebe725be37cb09247008867b9d5c7815a2 Mon Sep 17 00:00:00 2001 From: Nikolaj Gade Date: Fri, 23 Feb 2024 15:00:52 +0100 Subject: [PATCH] :sparkles: --- documentation/plthy.pdf | Bin 22678 -> 20709 bytes documentation/plthy.tex | 3 ++ plthy_impl/ast_nodes.py | 21 ++++++++++--- plthy_impl/lexer.py | 6 ++-- plthy_impl/parser.py | 9 +++--- tests/20_highest-integer.expected | 1 + tests/20_highest-integer.plthy | 11 +++++++ tests/21_fizzbuzz.expected | 50 ++++++++++++++++++++++++++++++ tests/21_fizzbuzz.plthy | 23 ++++++++++++++ 9 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 tests/20_highest-integer.expected create mode 100644 tests/20_highest-integer.plthy create mode 100644 tests/21_fizzbuzz.expected create mode 100644 tests/21_fizzbuzz.plthy diff --git a/documentation/plthy.pdf b/documentation/plthy.pdf index e1b48560767fe9bc5f0751a50bc5c51a7be6832f..c0ac042daaef455ec25f4e8dde9d58ab521ae87f 100644 GIT binary patch delta 7572 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 Gk^TccFlA2w diff --git a/documentation/plthy.tex b/documentation/plthy.tex index 556dfcb..e446aee 100644 --- a/documentation/plthy.tex +++ b/documentation/plthy.tex @@ -7,7 +7,10 @@ \ifnum#1<10 0\fi \number#1} +\pagestyle{empty} + \begin{document} + \section{Grammar} \begin{center} \begin{tabular}{|lcl|} \hline diff --git a/plthy_impl/ast_nodes.py b/plthy_impl/ast_nodes.py index a6955bd..4dd155a 100644 --- a/plthy_impl/ast_nodes.py +++ b/plthy_impl/ast_nodes.py @@ -6,7 +6,8 @@ from rply.token import BaseBox BUILTIN_ARGS = { "print": "*", "input" : "*", - "random": 2 + "random": 2, + "len": 1 } def rep_join(l): @@ -70,13 +71,19 @@ class ExpABinop(Exp): if r1.isdigit(): r1 = int(r1) else: - r1 = float(r1) + try: + r1 = float(r1) + except ValueError: + pass vtable, ftable, r2 = self.exp2.eval(vtable, ftable) if isinstance(r2,str): if r2.isdigit(): r2 = int(r2) else: - r2 = float(r2) + try: + r2 = float(r2) + except ValueError: + pass if self.op == "+": return vtable, ftable, r1+r2 elif self.op == "-": @@ -91,6 +98,8 @@ class ExpABinop(Exp): return vtable, ftable, r1 > r2 elif self.op == "<": return vtable, ftable, r1 < r2 + elif self.op == "mod": + return vtable, ftable, r1 % r2 else: raise Exception(f"Unknown binop {self.op}") @@ -149,7 +158,7 @@ class Command(BaseBox): class Builtin(Command): def __init__(self, builtin, args: list[Exp]): - self.builtin = builtin.value + self.builtin = builtin.value[:-1] self.args = args self.position = builtin.source_pos.lineno expected_args = BUILTIN_ARGS[self.builtin] @@ -191,6 +200,10 @@ class Builtin(Command): r = random.randint(r1, r2) return vtable, ftable, r + elif self.builtin == "len": + vtable, ftable, result = self.args[0].eval(vtable,ftable) + + return vtable, ftable, len(result) else: raise Exception(f"Unknown builtin {self.builtin}") diff --git a/plthy_impl/lexer.py b/plthy_impl/lexer.py index d5a5ddc..6774483 100644 --- a/plthy_impl/lexer.py +++ b/plthy_impl/lexer.py @@ -21,10 +21,11 @@ KEYWORD_TOKENS = [("KEYWORD_"+i.upper(), i) for i in [ "else" ]] -BUILTIN_TOKENS = [("BUILTIN", i) for i in [ +BUILTIN_TOKENS = [("BUILTIN", i+"<") for i in [ "print", "input", - "random" + "random", + "len" ]] DATA_TOKENS = [ @@ -56,6 +57,7 @@ SYMBOL_TOKENS = [ ("SYMBOL_LT", r"\<"), ("SYMBOL_GT", r"\>"), ("SYMBOL_EQUALS", r"\="), + ("SYMBOL_MOD", r"mod") # ("SYMBOL_DOLLAR", r"\$") ] diff --git a/plthy_impl/parser.py b/plthy_impl/parser.py index 14826ae..12c771c 100644 --- a/plthy_impl/parser.py +++ b/plthy_impl/parser.py @@ -8,12 +8,12 @@ class Parser(): self.pg = ParserGenerator( [i[0] for i in ALL_TOKENS], precedence=[ - ('left', ["KEYWORD_SET", "SYMBOL_SET", "KEYWORD_IF", "KEYWORD_MAYBE", "KEYWORD_RETURN"]), + ('left', ["KEYWORD_SET","KEYWORD_IF", "KEYWORD_MAYBE", "KEYWORD_RETURN"]), ('left', [ "KEYWORD_BECAUSE", "KEYWORD_UNTIL", "KEYWORD_DEFINE", "KEYWORD_AS"]), ('left', ["KEYWORD_DO", "BUILTIN"]), ('left', ["SYMBOL_EQUALS", "SYMBOL_LT","SYMBOL_GT"]), ('left', ["SYMBOL_PLUS", "SYMBOL_MINUS", "SYMBOL_OR", "SYMBOL_AND"]), - ('left', ["SYMBOL_TIMES", "SYMBOL_DIVIDE", "SYMBOL_TILDE"]) + ('left', ["SYMBOL_LCURL", "SYMBOL_TIMES", "SYMBOL_DIVIDE", "SYMBOL_TILDE", "SYMBOL_MOD", "ID"]) ] ) @@ -78,9 +78,9 @@ class Parser(): def command_until(tokens): return ast_nodes.CommandUntil(tokens[0],tokens[2]) - @self.pg.production('command : BUILTIN SYMBOL_LT expressions SYMBOL_GT') + @self.pg.production('command : BUILTIN expressions SYMBOL_GT') def command_builtin(tokens): - return ast_nodes.Builtin(tokens[0], tokens[2]) + return ast_nodes.Builtin(tokens[0], tokens[1]) @self.pg.production('command : SYMBOL_QUOTE ID SYMBOL_QUOTE SYMBOL_LT expressions SYMBOL_GT') def command_call(tokens): @@ -129,6 +129,7 @@ class Parser(): @self.pg.production('expression : expression SYMBOL_EQUALS expression') @self.pg.production('expression : expression SYMBOL_LT expression') @self.pg.production('expression : expression SYMBOL_GT expression') + @self.pg.production('expression : expression SYMBOL_MOD expression') def exp_a_binop(tokens): return ast_nodes.ExpABinop(tokens[1].value,tokens[0],tokens[2]) diff --git a/tests/20_highest-integer.expected b/tests/20_highest-integer.expected new file mode 100644 index 0000000..871727d --- /dev/null +++ b/tests/20_highest-integer.expected @@ -0,0 +1 @@ +84 diff --git a/tests/20_highest-integer.plthy b/tests/20_highest-integer.plthy new file mode 100644 index 0000000..2aa1da4 --- /dev/null +++ b/tests/20_highest-integer.plthy @@ -0,0 +1,11 @@ +hello| +set {5;3;8;9;55;1;34;84;6;} -> list| +set 0 -> i| +set 0 -> highest| +skip| +do [ + do set variable list{variable i} -> highest if variable list{variable i} > variable highest| + set variable i+1 -> i| +] until variable i = do len| +do print| +goodbye| \ No newline at end of file diff --git a/tests/21_fizzbuzz.expected b/tests/21_fizzbuzz.expected new file mode 100644 index 0000000..956e30e --- /dev/null +++ b/tests/21_fizzbuzz.expected @@ -0,0 +1,50 @@ +1 +2 +fizz +4 +buzz +fizz +7 +8 +fizz +buzz +11 +fizz +13 +14 +fizzbuzz +16 +17 +fizz +19 +buzz +fizz +22 +23 +fizz +buzz +26 +fizz +28 +29 +fizzbuzz +31 +32 +fizz +34 +buzz +fizz +37 +38 +fizz +buzz +41 +fizz +43 +44 +fizzbuzz +46 +47 +fizz +49 +buzz diff --git a/tests/21_fizzbuzz.plthy b/tests/21_fizzbuzz.plthy new file mode 100644 index 0000000..b4a92cd --- /dev/null +++ b/tests/21_fizzbuzz.plthy @@ -0,0 +1,23 @@ +hello| +set 3 -> f| +set 5 -> b| +set 50 -> max| +set 0 -> i| +do [ + set variable i + 1 -> i| + set '' -> print_string| + do + set variable print_string + 'fizz' -> print_string + if variable i mod variable f = 0| + + do + set variable print_string + 'buzz' -> print_string + if variable i mod variable b = 0| + + do + do print + else + do print + if variable print_string = ''| +] until variable i = variable max| +goodbye| \ No newline at end of file