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 | #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 lark | ||||||
| import sys | import sys | ||||||
| from enum import Enum | from enum import Enum | ||||||
|  | from modules.Variables import Variables | ||||||
| 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}" |  | ||||||
|  |  | ||||||
| class SPFInterpreter(lark.visitors.Interpreter): | class SPFInterpreter(lark.visitors.Interpreter): | ||||||
|  |     def __init__(self, trace=False): | ||||||
|  |         super().__init__() | ||||||
|  |         self.variables = Variables(trace) | ||||||
|  |  | ||||||
|     def afficher(self, el): |     def afficher(self, el): | ||||||
|         for toprint in el.children[1:]: |         for toprint in el.children[1:]: | ||||||
|             print(self.visit_children(toprint)[0]) |             print(self.visit_children(toprint)[0]) | ||||||
| @ -41,26 +22,20 @@ class SPFInterpreter(lark.visitors.Interpreter): | |||||||
|     def declaration(self, el): |     def declaration(self, el): | ||||||
|         type = el.children[0].value |         type = el.children[0].value | ||||||
|         name = el.children[1].value |         name = el.children[1].value | ||||||
|         assert el.children[2].value == "=", "Unexpected" |         value = self.visit_children(el.children[3])[0] if el.children[2].value == "=" else None | ||||||
|         assert el.children[3].data == "expression", "Unexpected" |         self.variables.declare(type, name, value) | ||||||
|         value = self.visit_children(el.children[3])[0] |  | ||||||
|         variables[name] = Variable(type, value) |  | ||||||
|  |  | ||||||
|     def assignation(self, el): |     def assignation(self, el): | ||||||
|         name = el.children[0].value |         name = el.children[0].value | ||||||
|         assert name in variables, f"Unknown variable : {el.children[0].value} not in {variables}" |         assert el.children[1].value == "=" and el.children[2].data == "expression", "Unexpected" | ||||||
|         assert el.children[1].value == "=", "Unexpected" |  | ||||||
|         assert el.children[2].data == "expression", "Unexpected" |  | ||||||
|         value = self.visit_children(el.children[2])[0] |         value = self.visit_children(el.children[2])[0] | ||||||
|         variables[name] = value #TODO: vérifier type |         self.variables.assign(name, value) | ||||||
|  |  | ||||||
|     def expressionleft(self, el): |     def expressionleft(self, el): | ||||||
|         return self.visit_children(el)[0] |         return self.visit_children(el)[0] | ||||||
|  |  | ||||||
|  |  | ||||||
|     def variable(self, el): |     def variable(self, el): | ||||||
|         assert el.children[0].value in variables, f"Unknown variable : {el.children[0].value} not in {variables}" |         return self.variables.get(el.children[0].value) | ||||||
|         return variables[el.children[0].value] |  | ||||||
|  |  | ||||||
|     # Literals |     # Literals | ||||||
|     string = lambda self, el: el.children[0][1:-1] |     string = lambda self, el: el.children[0][1:-1] | ||||||
| @ -68,6 +43,9 @@ class SPFInterpreter(lark.visitors.Interpreter): | |||||||
|     true = lambda self, _: True |     true = lambda self, _: True | ||||||
|     false = lambda self, _: False |     false = lambda self, _: False | ||||||
|  |  | ||||||
|  |     def dump(self): | ||||||
|  |         self.variables.dump() | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def main(): | def main(): | ||||||
| @ -81,9 +59,6 @@ def main(): | |||||||
|                         action="store_true") |                         action="store_true") | ||||||
|     args = arg_parser.parse_args() |     args = arg_parser.parse_args() | ||||||
|  |  | ||||||
|     if args.trace: |  | ||||||
|         print("Trace activated (TODO)", file=sys.stderr) |  | ||||||
|  |  | ||||||
|     with open("spf.lark") as grammar: |     with open("spf.lark") as grammar: | ||||||
|         spf_parser = lark.Lark(grammar, parser="lalr", strict=True, debug=True) |         spf_parser = lark.Lark(grammar, parser="lalr", strict=True, debug=True) | ||||||
|  |  | ||||||
| @ -91,11 +66,11 @@ def main(): | |||||||
|         program = spf_input.read() |         program = spf_input.read() | ||||||
|         parsed = spf_parser.parse(program) |         parsed = spf_parser.parse(program) | ||||||
|  |  | ||||||
|     interpreter = SPFInterpreter() |     interpreter = SPFInterpreter(args.trace) | ||||||
|     interpreted = interpreter.visit(parsed) |     interpreted = interpreter.visit(parsed) | ||||||
|  |  | ||||||
|     if args.dump: |     if args.dump: | ||||||
|         print(variables, file=sys.stderr) |         interpreted.dump() | ||||||
|  |  | ||||||
|  |  | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user