From 07fa61ef6c2afd007df7eeedd3c236e52f7ef94e Mon Sep 17 00:00:00 2001 From: Anthony Debucquoy Date: Sat, 22 Mar 2025 23:07:00 +0100 Subject: [PATCH] Refactoring operators to include priority --- spf.lark | 65 ++++++++++--------- spf.py | 188 +++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 162 insertions(+), 91 deletions(-) diff --git a/spf.lark b/spf.lark index e41353a..f2c6b20 100644 --- a/spf.lark +++ b/spf.lark @@ -6,36 +6,41 @@ instruction: declaration ";" | ADD_KW expression "dans" VARIABLE ";" -> append | controls -expression: expressionleft // TODO: priorité des operator certainement fausse - | operator +// rule finishing by u are "UnambigiousED" +expression: logical -expressionleft: literal - | list - | range - | VARIABLE -> variable - | "(" expression ")" +logical: comparison logicalu? +logicalu: AND_OP logical + | OR_OP logical -//any -> bool -operator: expressionleft SAME_OP expression -> equal - | expressionleft DIFF_OP expression -> unequal -//bool -> bool - | expressionleft AND_OP expression -> and_op - | expressionleft OR_OP expression -> or_op - | NOT_OP expression -> not_op -//int -> bool - | 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 -> plus - | expressionleft MINUS_OP expression -> minus - | expressionleft TIMES_OP expression -> time - | expressionleft DIVIDE_OP expression -> divide - | NEG_OP expression -> neg -// string/list -> string/list - | SIZE_OP expression -> sizeof - | expressionleft "[" expression "]" -> list_get +comparison: sumterm comparisonu? +comparisonu: SAME_OP comparison + | DIFF_OP comparison + | LT_OP comparison + | LE_OP comparison + | GT_OP comparison + | GE_OP comparison + +sumterm: multterm sumtermu? +sumtermu: PLUS_OP sumterm + | MINUS_OP sumterm + +multterm: priority multtermu? +multtermu: TIMES_OP multterm + | DIVIDE_OP multterm + +priority: finalterm + | finalterm "[" expression "]" -> list_get + | SIZE_OP finalterm + | NEG_OP finalterm + | NOT_OP finalterm + + +finalterm: "(" expression ")" + | literal + | list + | range + | VARIABLE -> variable ?type: BOOL_TYPE | INT_TYPE @@ -64,7 +69,7 @@ test: "si" expression "alors" "{" instruction_seq "}" ("sinon" "{" instruction_s instruction_seq: (instruction*) ?booleen: TRUE_KW -> true - | FALSE_KW -> false + | FALSE_KW -> false TERMINAL: ";" @@ -101,6 +106,8 @@ GE_OP: ">=" CONC_OP: "+" SIZE_OP: "taille" +LBRAC: "[" +RBRAC: "]" ADD_KW: "ajouter" SHOW_KW: "afficher" diff --git a/spf.py b/spf.py index 2a3d98c..31725d1 100755 --- a/spf.py +++ b/spf.py @@ -52,72 +52,136 @@ 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 list_get(self, el): - (left, right) = self.visit_children(el) - return left[right-1] - + # 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 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 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 + # + # sizeof = lambda self, el:len(self.visit_children(el)[1]) + # neg = lambda self, el:-self.visit_children(el)[1] + # + # def not_op(self, el): + # (sign, right) = self.visit_children(el) + # return not right + # + # + # def list_get(self, el): + # (left, right) = self.visit_children(el) + # return left[right-1] def expression(self, el): return self.visit_children(el)[0] - def expressionleft(self, el): + def logical(self, el): + result = self.visit_children(el) + if len(result) < 2: + return result[0] + if result[1][0].type == "AND_OP": + return result[0] and result[1][1] + elif result[1][0].type == "OR_OP": + return result[0] or result[1][1] + assert "Unreachable" + + def comparison(self, el): + result = self.visit_children(el) + if len(result) < 2: + return result[0] + if result[1][0].type == "SAME_OP": + return result[0] == result[1][1] + elif result[1][0].type == "DIFF_OP": + return result[0] != result[1][1] + elif result[1][0].type == "LT_OP": + return result[0] < result[1][1] + elif result[1][0].type == "LE_OP": + return result[0] <= result[1][1] + elif result[1][0].type == "GT_OP": + return result[0] > result[1][1] + elif result[1][0].type == "GE_OP": + return result[0] >= result[1][1] + assert "Unreachable" + + def sumterm(self, el): + result = self.visit_children(el) + if len(result) < 2: + return result[0] + if result[1][0].type == "PLUS_OP": + return result[0] + result[1][1] + elif result[1][0].type == "MINUS_OP": + return result[0] - result[1][1] + assert "Unreachable" + + def multterm(self, el): + result = self.visit_children(el) + if len(result) < 2: + return result[0] + if result[1][0].type == "TIMES_OP": + return result[0] * result[1][1] + elif result[1][0].type == "DIVIDE_OP": + return result[0] / result[1][1] + assert "Unreachable" + + def priority(self, el): + result = self.visit_children(el) + print(result) + if len(result) < 2: + return result[0] + elif result[0].type == "SIZE_OP": + return len(result[1]) + elif result[0].type == "NEG_OP": + return -result[1] + elif result[0].type == "NOT_OP": + return not result[1] + + def list_get(self, el): + result = self.visit_children(el) + return result[0][result[1] - 1] # Index start at 1 (like lua) + + def finalterm(self, el): return self.visit_children(el)[0] def variable(self, el):