compilation/spf.py
2025-03-20 21:36:38 +01:00

179 lines
5.0 KiB
Python
Executable File

#!/usr/bin/env python
# Projet de compilation Umons 2025
# Par Debucquoy Anthony (231687)
import argparse
import lark
import sys
from enum import Enum
from modules.Variables import Variables
class SPFInterpreter(lark.visitors.Interpreter):
def __init__(self, trace=False):
super().__init__()
self.variables = Variables(trace)
def while_loop(self, el):
while self.visit_children(el.children[0])[0]:
self.visit_children(el.children[1])
def for_loop(self, el):
type = el.children[0].value
name = el.children[1].value
self.variables.declare(type, name)
target = self.visit_children(el.children[2])[0]
for i in target:
self.variables.assign(name, i)
self.visit_children(el.children[3])
# TODO: delete the variable out of scope
def afficher(self, el):
ligne = ""
for toprint in el.children[1:]:
ligne += str(self.visit_children(toprint)[0]) + " "
print(ligne)
def append(self, el):
(_, toadd, var) = self.visit_children(el);
var_val = self.variables.get(var.value)
var_val.append(toadd)
def declaration(self, el):
type = el.children[0].value
name = el.children[1].value
value = self.visit_children(el.children[3])[0] if len(el.children) >= 3 else None
self.variables.declare(type, name, value)
def assignation(self, el):
name = el.children[0].value
assert el.children[1].value == "=" and el.children[2].data == "expression", "Unexpected"
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 expression(self, el):
return self.visit_children(el)[0]
def expressionleft(self, el):
return self.visit_children(el)[0]
def variable(self, el):
return self.variables.get(el.children[0].value)
def test(self,el):
if self.visit_children(el.children[0])[0]:
self.visit_children(el.children[1])
elif len(el.children) >= 3:
self.visit_children(el.children[2])
# Literals
string = lambda self, el: el.children[0][1:-1]
entier = lambda self, el: int(el.children[0])
true = lambda self, _: True
false = lambda self, _: False
def dump(self):
self.variables.dump()
def main():
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument("spf_file", help="Fichier source à interpréter")
arg_parser.add_argument("-d", "--dump",
help="affichage de la mémoire du programme",
action="store_true")
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:
spf_parser = lark.Lark(grammar, parser="lalr", strict=True, debug=True)
with open(args.spf_file) as spf_input:
program = spf_input.read()
parsed = spf_parser.parse(program)
if args.pretty:
print(parsed.pretty())
return
interpreter = SPFInterpreter(args.trace)
interpreted = interpreter.visit(parsed)
if args.dump:
interpreter.dump()
if __name__ == "__main__":
main()