#!/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): old = self.variables.variables.copy() while self.visit_children(el.children[0])[0]: self.visit_children(el.children[1]) self.variables.variables = old.copy() def for_loop(self, el): type = el.children[0].value name = el.children[1].value old = self.variables.variables.copy() 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]) self.variables.variables = old.copy() 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 expression(self, el): return self.visit_children(el)[0] 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": # Division entière car nous ne gérons pas les flotants 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): return self.variables.get(el.children[0].value) def test(self,el): old = self.variables.variables.copy() 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]) self.variables.variables = old.copy() # 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 range(self, el): (left, right) = self.visit_children(el) return list(range(left, right+1)) 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()