:: Enseignements :: ESIPE :: E4INFO :: 2008-2009 :: Compilation :: Tutoriel Tatoo ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | Implantation d'un analyseur sémantique en une passe |
Principe
Un analyseur en une passe est basé sur un parseur couplé à un lexeur.
On peut utiliser le script EBNF pour typer les tokens lus et les non-terminaux de la grammaire.
Lors de la construction de l'analyseur, il est alors possible de passer deux objets en paramètres :
- un TerminalEvaluator qui permet de donner la valeur de chaque token typé lu.
- un GrammarEvaluator qui permet, à chaque réduction donnée, d'effectuer certaines opérations et, quand le non-terminal résultant est typé, de construire la valeur de non-terminal, en fonction des valeurs, fournies par le TerminalEvaluator, des terminaux et des valeurs, fournies par le GrammarEvaluator (donc this), des non-terminaux présents dans le membre droit de la production.
Le TerminalEvaluator contient une méthode tok(B data) pour chaque token typé tok.
L'argument data est le buffer contenant le token reconnu.
Le GrammarEvaluator contient, pour chaque production p,
une méthode p(...) appelée lorsqu'il y a une réduction par p.
Ses arguments sont les valeurs des différents terminaux et non-terminaux typés de la partie droite de p.
Sa valeur de retour est du type du non-terminal résultant de la réduction, s'il est typé.
Evaluation simple d'expressions arithmétiques
Soit l'exemple simple d'EBNF ci-dessous :
Le parseur décrit reconnaît des expressions arithmétiques.
On note que l'on associe au token value et au non-terminal expr, le type de base int.
Dans le fichier EvaluationAnalyzer.java qui implémente l'analyseur, un TerminalEvaluator et un GrammarEvaluator sont instanciés.
Ils sont passés en paramètre lors de la construction de l'analyseur comme montré ci-dessous.
L'analyseur affiche la valeur de l'expression arithmétique tapée en entrée standard.
Traduction d'expressions arithmétiques
L'exemple ci-dessous montre un analyseur qui convertit une expression arithmétique sous une autre forme et affiche son résultat.
Vous trouverez son code dans l'exemple
translation.
Par exemple, l'expression
12 + 34 - 6 est analysée comme:
Translation is: - + 12 34 6
Result is: 40
Le parseur décrit reconnaît des expressions arithmétiques.
On note que l'on associe au token/terminal value, le type de base int.
On observe aussi que l'on type un non-terminal expr par un ExprContent, classe Java qui est importée dans la section imports.
Un ExprContent est formé d'un string (traduction) et d'un entier (valeur).
L'analyseur est codé dans la classe TranslationAnalyzer.java:
Comme indiqué dans la description du format EBNF, il est possible de séparer la partie syntaxique de la partie sémantique en écrivant deux fichiers EBNF.
La génération des classes de base de l'analyseur est configurée dans le
build.xml (fichier
build2.xml exemple
translation)
EBNF pour la syntaxe
EBNF pour la sémantique
build.xml
Génération automatique de l'AST
Lorsque que l'on souhaite avoir un analyseur en plusieurs passes, on peut générer automatiquement l'AST
puis le parcourir à l'aide de visiteurs.
Pour cela, il faut ajouter l'attribut
generateast="true" de l'élément
ebnf dans le
build.xml (cf exemple ci-dessous).
A la génération des classes de base de l'analyseur, tatoo génère un
ASTGrammarEvaluator qui est un
GrammarEvaluator chargé de construire l'AST de l'expression analysée.
Les noeuds de l'AST sont des instances de classes qui correspondent aux productions de la grammaire.
Ces classes sont générées automatiquement. Leurs noms correspondent aux noms des productions associées.
Les fils de ces noeuds sont excessibles à l'aide de getters des éléments pertinents de la partie droite de la production associée:
terminaux typés et non-terminaux.
Elles sont visitables par leur méthode
accept.
Cette méthode prend en argument un
Visitor<R,P,E> qui contient une méthode
visit par noeud de l'AST.
R, P et E sont respectivement les types de retour, des paramètres (deuxième argument) et des exceptions levées dans ces méthodes.
L'exemple ci-dessous correspond à un analyseur qui évalue des expressions arithmétiques entières à l'aide d'un visiteur.
Il instancie un
ASTGrammarEvaluator (pour créer l'AST) et un
TerminalEvaluator (pour évaluer les terminaux) qui sont utilisés dans l'analyseur (méthode
Analyszer.run).
La racine de l'AST est récupérée grâce à la méthode
getStart() de l'
ASTGrammarEvaluator, une fois l'analyse terminée.
Il s'agit ensuite d'écrire un visiteur et de l'utiliser pour parcourir l'AST en fonction de la tâche que l'on a à effectuer.
EBNF
build.xml
Visiteur pour l'évaluation d'une expression arithmétique
Analyseur
© Université de Marne-la-Vallée