From e7eca3b46d1d0a9c0c2c0e1cc93c831310fed029 Mon Sep 17 00:00:00 2001 From: tonitch Date: Thu, 20 Mar 2025 00:17:50 +0100 Subject: [PATCH] Implementing Variables class + dump and trace --- examples/simple.spf | 4 +- modules/Variables.py | 68 ++++++++++++++++++ modules/__pycache__/Variables.cpython-313.pyc | Bin 0 -> 4379 bytes spf.py | 55 ++++---------- 4 files changed, 85 insertions(+), 42 deletions(-) create mode 100644 modules/Variables.py create mode 100644 modules/__pycache__/Variables.cpython-313.pyc diff --git a/examples/simple.spf b/examples/simple.spf index 06138d2..61f4245 100644 --- a/examples/simple.spf +++ b/examples/simple.spf @@ -8,6 +8,6 @@ afficher nom, age, majeur; #TODO: Ces lignes devraient donner une erreur -majeur = 42; +# majeur = 42; -afficher majeur; +# afficher majeur; diff --git a/modules/Variables.py b/modules/Variables.py new file mode 100644 index 0000000..08a073c --- /dev/null +++ b/modules/Variables.py @@ -0,0 +1,68 @@ +import sys + +trace_format = '\033[1m -> ' +reset_format = '\033[0m' + +class Variables: + + class Variable: + types = { "entier": int, + "texte": str, + "booléen": bool, + "liste": list } + + def __init__(self, typ, value = None): + assert typ in self.types.keys(), "Ce type de variable est inconnu" + self.type = typ + assert self.checkType(value, typ), "Le type n'est pas équivalent" + self.value = value if (value is not None) else self.default(typ) + + def set(self, value): + assert self.checkType(value, self.type), "Le type n'est pas équivalent" + self.value = value + + def __str__(self): + if self.type == "booléen": + return "Vrai" if self.value else "Faux" + return f"{self.value}" + + def __repr__(self): + if self.type == "texte": + return f"\"{self.value}\"" + return f"{self.value}" + + + def checkType(self, value, typ) -> bool: + return type(value) == self.types[typ] + + def default(self, typ): + if typ == "entier": + return 0 + if typ == "texte": + return "" + if typ == "booléen": + return False + if typ == "liste": + return [] + + def __init__(self, trace=False): + self.variables = {} + self.trace = trace + + def get(self, name): + 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.stdout) + return self.variables[name] + + def declare(self, typ, name, value=None): + assert name not in self.variables, "la variable {name} existe déjà" + self.variables[name] = self.Variable(typ, value) + if self.trace: + print(f"{trace_format}déclare {name} = {value}{reset_format}", file=sys.stdout) + + def assign(self, name, value): + assert name in self.variables, "la variable n'éxiste pas" + self.variables[name].set(value) + if self.trace: + print(f"{trace_format}modifie {name} = {value}{reset_format}", file=sys.stdout) diff --git a/modules/__pycache__/Variables.cpython-313.pyc b/modules/__pycache__/Variables.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b7acd230a9dba80cb82deb0ab7fc64efd3597cf9 GIT binary patch literal 4379 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 UmuTSm&SJ+H!}y5-M1m~=0KyAe-v9sr literal 0 HcmV?d00001 diff --git a/spf.py b/spf.py index 0b1da1b..d076365 100755 --- a/spf.py +++ b/spf.py @@ -7,32 +7,13 @@ import argparse import lark import sys from enum import Enum - -variables = {} - -class VariableType(Enum): - boolean = 1 - integer = 2 - string = 3 - list = 4 - - -class Variable(): - def __init__(self, type, value): - self.type = type - self.value = value - - def __str__(self): - if self.type == "booléen": - return "Vrai" if self.value else "Faux" - return f"{self.value}" - - def __repr__(self): - if self.type == "texte": - return f"\"{self.value}\"" - return f"{self.value}" +from modules.Variables import Variables class SPFInterpreter(lark.visitors.Interpreter): + def __init__(self, trace=False): + super().__init__() + self.variables = Variables(trace) + def afficher(self, el): for toprint in el.children[1:]: print(self.visit_children(toprint)[0]) @@ -41,26 +22,20 @@ class SPFInterpreter(lark.visitors.Interpreter): def declaration(self, el): type = el.children[0].value name = el.children[1].value - assert el.children[2].value == "=", "Unexpected" - assert el.children[3].data == "expression", "Unexpected" - value = self.visit_children(el.children[3])[0] - variables[name] = Variable(type, value) + value = self.visit_children(el.children[3])[0] if el.children[2].value == "=" else None + self.variables.declare(type, name, value) def assignation(self, el): name = el.children[0].value - assert name in variables, f"Unknown variable : {el.children[0].value} not in {variables}" - assert el.children[1].value == "=", "Unexpected" - assert el.children[2].data == "expression", "Unexpected" + assert el.children[1].value == "=" and el.children[2].data == "expression", "Unexpected" value = self.visit_children(el.children[2])[0] - variables[name] = value #TODO: vérifier type + self.variables.assign(name, value) def expressionleft(self, el): return self.visit_children(el)[0] - def variable(self, el): - assert el.children[0].value in variables, f"Unknown variable : {el.children[0].value} not in {variables}" - return variables[el.children[0].value] + return self.variables.get(el.children[0].value) # Literals string = lambda self, el: el.children[0][1:-1] @@ -68,6 +43,9 @@ class SPFInterpreter(lark.visitors.Interpreter): true = lambda self, _: True false = lambda self, _: False + def dump(self): + self.variables.dump() + def main(): @@ -81,9 +59,6 @@ def main(): action="store_true") args = arg_parser.parse_args() - if args.trace: - print("Trace activated (TODO)", file=sys.stderr) - with open("spf.lark") as grammar: spf_parser = lark.Lark(grammar, parser="lalr", strict=True, debug=True) @@ -91,11 +66,11 @@ def main(): program = spf_input.read() parsed = spf_parser.parse(program) - interpreter = SPFInterpreter() + interpreter = SPFInterpreter(args.trace) interpreted = interpreter.visit(parsed) if args.dump: - print(variables, file=sys.stderr) + interpreted.dump() if __name__ == "__main__":