From 5d21e611f0191cfb009c4787e3260fdd65963ff1 Mon Sep 17 00:00:00 2001 From: Anthony Debucquoy Date: Thu, 20 Mar 2025 13:27:57 +0100 Subject: [PATCH] Adding most operators --- examples/arithmetic.spf | 17 ++++++++ examples/factorielle.spf | 2 +- examples/simple.spf | 2 +- modules/Variables.py | 5 ++- spf.lark | 43 ++++++++++---------- spf.py | 85 +++++++++++++++++++++++++++++++++++++++- 6 files changed, 126 insertions(+), 28 deletions(-) create mode 100644 examples/arithmetic.spf diff --git a/examples/arithmetic.spf b/examples/arithmetic.spf new file mode 100644 index 0000000..2083c23 --- /dev/null +++ b/examples/arithmetic.spf @@ -0,0 +1,17 @@ +# entier x = 3; +# entier y = 4; +# +liste l = [3, 4, 5]; + +ajouter 3 dans l; + +afficher l; + +# +# afficher x vaut y; +# afficher x ne vaut pas y; +# entier z; +# afficher taille "test"; +# afficher x + 3, 3 + y; +# x = -x; +# afficher x; diff --git a/examples/factorielle.spf b/examples/factorielle.spf index bfc46df..3ea8c48 100644 --- a/examples/factorielle.spf +++ b/examples/factorielle.spf @@ -7,4 +7,4 @@ tant que nombre > 0 faire { nombre = nombre - 1; } -afficher "La factorielle vaut", factorielle; \ No newline at end of file +afficher "La factorielle vaut", factorielle; diff --git a/examples/simple.spf b/examples/simple.spf index 55cecf7..a5eac20 100644 --- a/examples/simple.spf +++ b/examples/simple.spf @@ -9,7 +9,7 @@ majeur = faux; afficher nom, age, majeur; -#TODO: Ces lignes devraient donner une erreur +#Ces lignes devraient donner une erreur # majeur = 42; # afficher majeur; diff --git a/modules/Variables.py b/modules/Variables.py index c3ff847..dd3f7f6 100644 --- a/modules/Variables.py +++ b/modules/Variables.py @@ -31,7 +31,6 @@ class Variables: return f"\"{self.value}\"" return f"{self.value}" - def checkType(self, value, typ) -> bool: return value is None or type(value) == self.types[typ] @@ -53,7 +52,7 @@ class Variables: assert name in self.variables, "la variable {name} n'éxiste pas" if self.trace: print(f"{trace_format}accède {name}{reset_format}", file=sys.stderr) - return self.variables[name] + return self.variables[name].value def declare(self, typ, name, value=None): assert name not in self.variables, "la variable {name} existe déjà" @@ -69,7 +68,9 @@ class Variables: def dump(self): name_len = max(map(len, self.variables.keys())) + name_len = name_len if name_len >= len("name") else len("name") var_len = max(map(len,map(str, self.variables.values()))) + var_len = var_len if var_len >= len("value") else len("value") print(f"┌{'─' * name_len}┬{'─' * var_len}┐", file=sys.stderr) print(f"│{'Name':>{name_len}}│{'Value':<{var_len}}│", file=sys.stderr) print(f"├{'─' * name_len}┼{'─' * var_len}┤", file=sys.stderr) diff --git a/spf.lark b/spf.lark index bc81b28..fce2053 100644 --- a/spf.lark +++ b/spf.lark @@ -3,7 +3,7 @@ start: (instruction)* instruction: declaration ";" | assignation ";" | SHOW_KW expression ("," expression)* ";" -> afficher - | ADD_KW expression "dans" VARIABLE ";" + | ADD_KW expression "dans" VARIABLE ";" -> append | controls expression: expressionleft // TODO: priorité des operator certainement fausse @@ -16,26 +16,25 @@ expressionleft: literal | "(" expression ")" //any -> bool -operator: expressionleft SAME_OP expression - | expressionleft DIFF_OP expression +operator: expressionleft SAME_OP expression -> equal + | expressionleft DIFF_OP expression -> unequal //bool -> bool - | expressionleft AND_OP expression - | expressionleft OR_OP expression - | NOT_OP expression + | expressionleft AND_OP expression -> and_op + | expressionleft OR_OP expression -> or_op + | NOT_OP expression -> not_op //int -> bool - | expressionleft LT_OP expression - | expressionleft LE_OP expression - | expressionleft GT_OP expression - | expressionleft GE_OP expression + | expressionleft LT_OP expression -> lt + | expressionleft LE_OP expression -> le + | expressionleft GT_OP expression -> gt + | expressionleft GE_OP expression -> ge //int -> int - | expressionleft PLUS_OP expression - | expressionleft MINUS_OP expression - | expressionleft TIMES_OP expression - | expressionleft DIVIDE_OP expression - | NEG_OP expression + | expressionleft PLUS_OP expression -> plus + | expressionleft MINUS_OP expression -> minus + | expressionleft TIMES_OP expression -> time + | expressionleft DIVIDE_OP expression -> divide + | NEG_OP expression -> neg // string/list -> string/list - | expressionleft CONC_OP expression - | SIZE_OP expression + | SIZE_OP expression -> sizeof ?type: BOOL_TYPE | INT_TYPE @@ -46,8 +45,8 @@ declaration: type VARIABLE (EQUAL_SIGN expression)? assignation: VARIABLE EQUAL_SIGN expression -loop: /tant que/ expression "faire" "{" (instruction)* "}" - | /pour chaque/ type VARIABLE "dans" expression "faire" "{" (instruction)* "}" +loop: "tant" "que" expression "faire" "{" (instruction)* "}" -> while_loop + | "pour" "chaque" type VARIABLE "dans" expression "faire" "{" (instruction)* "}" -> for_loop ?literal: ENTIER -> entier | booleen @@ -62,6 +61,9 @@ controls: test test: "si" expression "alors" "{" instruction* "}" ("sinon" "{" instruction* "}")? +?booleen: TRUE_KW -> true + | FALSE_KW -> false + TERMINAL: ";" VAR_CHARS: /[a-zA-Zçâêîôûéàèìòùëïü_]/ @@ -71,9 +73,6 @@ EQUAL_SIGN: "=" ENTIER: /0|[1-9][0-9]*/ -?booleen: TRUE_KW -> true - | FALSE_KW -> false - BOOL_TYPE: "booléen" INT_TYPE: "entier" STR_TYPE: "texte" diff --git a/spf.py b/spf.py index 2c877d4..8bed937 100755 --- a/spf.py +++ b/spf.py @@ -14,10 +14,23 @@ class SPFInterpreter(lark.visitors.Interpreter): super().__init__() self.variables = Variables(trace) + def while_loop(self, el): + print("TODO: while") + cond = el.children[0] + instr = el.children[1:] + print(cond.pretty()) + + def for_loop(self, el): + print("TODO: for") + def afficher(self, el): + ligne = "" for toprint in el.children[1:]: - print(self.visit_children(toprint)[0]) - return + ligne += str(self.visit_children(toprint)[0]) + " " + print(ligne) + + # def append(self, el): + # (_, toadd, var) = self.visit_children(el); def declaration(self, el): type = el.children[0].value @@ -31,6 +44,67 @@ class SPFInterpreter(lark.visitors.Interpreter): value = self.visit_children(el.children[2])[0] self.variables.assign(name, value) + def equal(self, el): + (left, sign, right) = self.visit_children(el) + return left == right + + def unequal(self, el): + (left, sign, right) = self.visit_children(el) + return left != right + + def and_op(self, el): + (left, sign, right) = self.visit_children(el) + return left and right + + def or_op(self, el): + (left, sign, right) = self.visit_children(el) + return left or right + + def not_op(self, el): + (sign, right) = self.visit_children(el) + return not right + + def lt(self, el): + (left, sign, right) = self.visit_children(el) + return left < right + + def le(self, el): + (left, sign, right) = self.visit_children(el) + return left <= right + + def gt(self, el): + (left, sign, right) = self.visit_children(el) + return left > right + + def ge(self, el): + (left, sign, right) = self.visit_children(el) + return left >= right + + + def plus(self, el): + (left, sign, right) = self.visit_children(el) + return left + right # Cool ça fonctionne pour les str + + def minus(self, el): + (left, sign, right) = self.visit_children(el) + return left - right + + def time(self, el): + (left, sign, right) = self.visit_children(el) + return left * right + + def divide(self, el): + (left, sign, right) = self.visit_children(el) + return left / right + + neg = lambda self, el:-self.visit_children(el)[1] + + sizeof = lambda self, el:len(self.visit_children(el)[1]) + + + def expression(self, el): + return self.visit_children(el)[0] + def expressionleft(self, el): return self.visit_children(el)[0] @@ -57,6 +131,9 @@ def main(): arg_parser.add_argument("-t", "--trace", help="affichage de la mémoire au cours du programme", action="store_true") + arg_parser.add_argument("-p", "--pretty", + help="affichage de l'arbre et quite", + action="store_true") args = arg_parser.parse_args() with open("spf.lark") as grammar: @@ -66,6 +143,10 @@ def main(): program = spf_input.read() parsed = spf_parser.parse(program) + if args.pretty: + print(parsed.pretty()) + return + interpreter = SPFInterpreter(args.trace) interpreted = interpreter.visit(parsed)