Adding most operators

This commit is contained in:
Anthony Debucquoy 2025-03-20 13:27:57 +01:00
parent 4db6081fc8
commit 5d21e611f0
Signed by: tonitch
GPG Key ID: A78D6421F083D42E
6 changed files with 126 additions and 28 deletions

17
examples/arithmetic.spf Normal file
View File

@ -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;

View File

@ -7,4 +7,4 @@ tant que nombre > 0 faire {
nombre = nombre - 1;
}
afficher "La factorielle vaut", factorielle;
afficher "La factorielle vaut", factorielle;

View File

@ -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;

View File

@ -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)

View File

@ -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"

85
spf.py
View File

@ -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)