Skip to content

Commit

Permalink
Merge pull request #7 from LBF38:TP5
Browse files Browse the repository at this point in the history
TP5 - Checker
  • Loading branch information
LBF38 committed May 10, 2023
2 parents 0493282 + 4ff4a4a commit f51fca0
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 2 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"merge",
"TP3",
"TP4",
"compiler"
"compiler",
"TP5"
],
"python.testing.pytestArgs": [
"."
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ Cours de compilation @ ENSTA Bretagne.

## Liens vers les TPs

- [TP1](TPs/TP1/README.md)
- [TP1](TPs/TPs/TP1/README.md)
- [TP2](TPs/TP2/)
- [TP3](TPs/TP3/)
- [TP4](TPs/TP4/README.md)
- [TP5](TPs/TP5/README.md)

## Problèmes rencontrés

Expand Down
30 changes: 30 additions & 0 deletions TPs/TP5/README.md
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 added TPs/TP5/TP_checker.pdf
Binary file not shown.
67 changes: 67 additions & 0 deletions TPs/TP5/abstract_syntax.py
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))
52 changes: 52 additions & 0 deletions TPs/TP5/visitor_tp5.py
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)

0 comments on commit f51fca0

Please sign in to comment.