-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from LBF38:TP5
TP5 - Checker
- Loading branch information
Showing
6 changed files
with
153 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,8 @@ | |
"merge", | ||
"TP3", | ||
"TP4", | ||
"compiler" | ||
"compiler", | ||
"TP5" | ||
], | ||
"python.testing.pytestArgs": [ | ||
"." | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# TP5 | ||
|
||
Elaboration d'un visiteur plus complexe : le Checker. | ||
|
||
L'objectif de ce visiteur est de vérifier que toutes les variables utilisées dans leur contexte sont bien déclarées. | ||
Ainsi, une variable doit soit être déclaré dans le contexte global du programme, soit dans l'un des contextes locaux englobant son utilisation. | ||
Pour mettre en place cela, on peut créer par exemple un dictionnaire contenant l'ensemble des variables déclarées dans le contexte courant. | ||
Chaque dictionnaire représente donc le contexte d'un bloc de code. | ||
S'il on veut vérifier la définition d'une variable ou son utilisation, il nous suffit de vérifier que la variable fait partie de l'un des dictionnaires accessibles à partir du contexte d'utilisation. | ||
|
||
**Notes :** | ||
|
||
- Visiteur : | ||
- Quand on définit un visiteur, chaque méthode contient la logique de visite de l'élément correspondant. | ||
- Penser que l'on peut créer autant de visiteurs que l'on souhaite. | ||
- Penser également à séparer les responsabilités en créant, par exemple, une classe qui va gérer la mise en forme du code. (indentation, ajout de lignes, blocs, etc.) | ||
|
||
## Question 7 - Définitions des règles du langage étudié | ||
|
||
Ces règles permettent de définir la syntaxe du langage et de rejeter ce que l'on ne souhaite pas. | ||
|
||
- **`circuit`** *identifier* | ||
- **`input`** *identifier* (`,` *identifier*)$*$ | ||
- **`output`** *identifier* (`,` *identifier*)$*$ | ||
- *body* | ||
- **`end`** | ||
- *body* := *out_statement* (`\n` *out_statement*)$*$ | ||
- *out_statement* := *output* *operator* *in_statement* | ||
- *in_statement* := *input* (*operator* *input*)? | ||
- *operator* := `+` | `-` | `*` | `/` | `^` |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
"""Abstract Syntax Definition | ||
This file defines the abstract syntax of the language. | ||
""" | ||
|
||
|
||
from typing import List | ||
|
||
|
||
class AstNode: | ||
def accept(self, visitor, args=None): | ||
name = self.__class__.__name__ | ||
return getattr(visitor, 'visit' + name)(self, args) | ||
|
||
|
||
class Circuit(AstNode): | ||
def __init__(self, identifier, input, output, body) -> None: | ||
self.identifier: Identifier = identifier | ||
self.input: Input = input | ||
self.output: Output = output | ||
self.body: Body = body | ||
|
||
|
||
class Input(AstNode): | ||
def __init__(self, parameters) -> None: | ||
self.parameters: List[Parameter] = parameters | ||
|
||
|
||
class Output(AstNode): | ||
def __init__(self, parameters) -> None: | ||
self.parameters = parameters | ||
|
||
|
||
class Identifier(AstNode): | ||
def __init__(self, name: str) -> None: | ||
self.name: str = name | ||
|
||
|
||
class Body(AstNode): | ||
def __init__(self, expressions) -> None: | ||
self.expressions = expressions | ||
|
||
|
||
class Operator(AstNode): | ||
def __init__(self, name) -> None: | ||
self.name: str = name | ||
|
||
|
||
class Expression(AstNode): | ||
def __init__(self, left, operator: Operator, right) -> None: | ||
self.left = left | ||
self.operator = operator | ||
self.right = right | ||
|
||
|
||
class Parameter(AstNode): | ||
def __init__(self, identifier: Identifier) -> None: | ||
self.identifier = identifier | ||
|
||
|
||
if __name__ == '__main__': | ||
from visitor_tp5 import SimpleVisitor | ||
|
||
print(f"test of {__name__}") | ||
ast = Circuit(Identifier("half_adder"), Input([Identifier("a"), Identifier("b")]), Output([Identifier( | ||
"sum"), Identifier("carry")]), Body([Expression(Identifier("sum"), Operator("="), Expression(Identifier("a"), Operator("XOR"), Identifier("b"))), Expression(Identifier("carry"), Operator("="), Expression(Identifier("a"), Operator("AND"), Identifier("b")))])) | ||
visitor = SimpleVisitor() | ||
print(visitor.visit(ast)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
|
||
from abstract_syntax import (AstNode,Circuit,Identifier,Body,Input,Output,Expression,Operator,Parameter) | ||
|
||
|
||
class Visitor: | ||
def visit(self, node: AstNode): | ||
return node.accept(self) | ||
|
||
class SimpleVisitor(Visitor): | ||
def visitCircuit(self, circuit:Circuit,args): | ||
code_string=f"circuit {circuit.identifier.accept(self)}\n" | ||
code_string+=f"\t{circuit.input.accept(self,args)}\n" | ||
code_string+=f"\t{circuit.output.accept(self)}\n" | ||
code_string+=f"\t{circuit.body.accept(self)}\n" | ||
code_string+="end" | ||
return code_string | ||
|
||
def visitIdentifier(self,identifier:Identifier,args): | ||
return identifier.name | ||
|
||
def visitInput(self,input:Input,args): | ||
input_string="input " | ||
for parameter in input.parameters: | ||
input_string+=parameter.accept(self) | ||
input_string+=", " | ||
input_string=input_string[:-2] | ||
return input_string | ||
|
||
def visitOutput(self,output:Output,args): | ||
output_string="output " | ||
for parameter in output.parameters: | ||
output_string+=parameter.accept(self) | ||
output_string+=", " | ||
output_string=output_string[:-2] | ||
return output_string | ||
|
||
def visitBody(self, body:Body,args): | ||
body_string="" | ||
for expression in body.expressions[:-1]: | ||
body_string+=expression.accept(self)+"\n\t" | ||
body_string+=body.expressions[-1].accept(self) | ||
return body_string | ||
|
||
def visitExpression(self,expression:Expression,args): | ||
return f"{expression.left.accept(self)} {expression.operator.accept(self)} {expression.right.accept(self)}" | ||
|
||
def visitOperator(self,operator:Operator,args): | ||
return operator.name | ||
|
||
def visitParameter(self,parameter:Parameter,args): | ||
return parameter.identifier.accept(self) | ||
|