Implementing Variables class + dump and trace
This commit is contained in:
		| @ -8,6 +8,6 @@ afficher nom, age, majeur; | ||||
|  | ||||
|  | ||||
| #TODO: Ces lignes devraient donner une erreur | ||||
| majeur = 42; | ||||
| # majeur = 42; | ||||
|  | ||||
| afficher majeur; | ||||
| # afficher majeur; | ||||
|  | ||||
							
								
								
									
										68
									
								
								modules/Variables.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								modules/Variables.py
									
									
									
									
									
										Normal file
									
								
							| @ -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) | ||||
							
								
								
									
										
											BIN
										
									
								
								modules/__pycache__/Variables.cpython-313.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								modules/__pycache__/Variables.cpython-313.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										55
									
								
								spf.py
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								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__": | ||||
|  | ||||
		Reference in New Issue
	
	Block a user