L3/TL — TP 2 Expressions arithmétiques et arbres syntaxiques

L3/TL — TP 2
Expressions arithm´etiques et arbres syntaxiques
L’objectif de ce TP est de continuer `a se familiariser avec l’outil d’analyse syntaxique JavaCC
et d’aborder l’utilisation de l’outil JJTree. Les fichiers que vous aurez `a modifier ou compl´eter au
cours de ce TP sont disponibles `a l’adresse suivante :
http://circe.univ-fcomte.fr/Jerome-Voinot/TL/TP2/
1 Expressions arithm´etiques
Le fichier Arith.jj, fourni et reproduit dans la figure 1, contient des r`egles lexicales et
syntaxiques permettant de reconnaˆıtre des expressions arithm´etiques constitu´ees de constantes
(nombres), du symbole binaire + et du symbole n-aire .
Exercice 1.1
1. Compiler le fichier Arith.jj afin de g´en´erer les sources de l’analyseur correspondant.
2. D´efinir une classe Java permettant de lancer l’analyseur d’expressions arithm´etiques que
vous venez de compiler (Indication : s’inspirer du TP pr´ec´edent).
3. Compiler l’ensemble des sources Java (analyseur et lanceur).
4. Ex´ecuter l’analyseur sur des exemples tels que 4 3+25, 4 + 5 3 ou encore 4 + 5 3+2
et en d´eduire l’ensemble des expressions arithm´etiques reconnues par cet analyseur.
Exercice 1.2
1. Copier le fichier Arith.jj dans un autre dossier, en le renommant Arith2.jj.
2. Ajouter et/ou modifier, dans le fichier Arith2.jj, les r`egles lexicales et syntaxiques pour
reconnaˆıtre le symbole unaire de n´egation, en plus de ceux d´ej`a reconnus.
3. Compiler le fichier Arith2.jj.
4. D´efinir une nouvelle classe Java permettant de lancer l’analyseur g´en´er´e `a partir du fichier
Arith2.jj et compiler l’ensemble des sources Java.
5. Ex´ecuter l’analyseur afin de v´erifier qu’il reconnaˆıt bien des expressions telles que 4 3 + 2
mais pas les expressions telles que 4 3.
Exercice 1.3
1. Remplacer dans le fichier Arith2.jj la r`egle syntaxique unElement par celle donn´ee dans
la figure 2.
2. Ajouter aux autres r`egles syntaxiques les instructions Java n´ecessaires `a l’affichage de chaque
op´erateur au moment o`u celui-ci est reconnu.
3. V´erifier que l’on obtient bien le bon affichage pour diff´erentes expressions arithm´etiques
constitu´ees de constantes (nombres), du symbole unaire , du symbole binaire + et du
symbole n-aire .
1
/** Fichier Arith.jj
*
* Copyright (c) 2004-06 Universite de Franche-Comte
* Auteurs : A. Giorgetti, J. Julliand, P.-A. Masson, J. Voinot
*/
PARSER_BEGIN(Arith)
public class Arith {
}
PARSER_END(Arith)
/* ----------------- Regles lexicales ------------------------ */
SKIP: {
" " | "\r" | "\n" | "\t"
}
TOKEN: {
< CONSTANT: ( <DIGIT> )+ >
| < DIGIT: ["0"-"9"] >
}
TOKEN: { /* OPERATEURS */
< PLUS: "+" >
| < MULT: "*" >
}
/* ---------------- Regles syntaxiques ---------------------- */
void axiome() : {} {
unTerme() <EOL>
}
void unTerme() : {} {
unProduit() [ <PLUS> unTerme() ]
}
void unProduit() : {} {
unElement()
( <MULT> unElement() )*
}
void unElement() : {} {
<CONSTANT>
}
Fig. 1 – Fichier Arith.jj
void unElement() : { int x = 0; }{
<CONSTANT> {
try {
x = Integer.parseInt(token.image);
} catch (NumberFormatException ee) {
System.err.println("Error: "
+ token.image + " is not a number.");
x = 0;
}
System.out.println(x);
}
}
Fig. 2 – R`egle syntaxique unElement()
2
2 Arbres syntaxiques
Dans cette partie du TP, nous allons aborder `a travers diff´erents exercices l’utilisation de
l’outil JJTree. Cet outil prend en entr´ee des fichiers contenant la description d’une grammaire
pour JavaCC, des annotations de construction d’arbres et ´eventuellement d’autres actions. Dans le
cas du fichier Aritha.jjt, fourni et reproduit dans la figure 3, l’ex´ecution du pr´eprocesseur JJTree,
par la commande jjtree Aritha.jjt, g´en`ere un fichier .jj dont la traduction par JavaCC en`ere
un traducteur Java d’expressions arithm´etiques en arbres syntaxiques.
Exercice 2.1
1. Dans le fichier Aritha.jjt, ajouter et/ou modifier les r`egles lexicales et syntaxiques pour
reconnaˆıtre aussi le symbole unaire de n´egation.
2. Ex´ecuter le pr´eprocesseur JJTree sur le fichier Aritha.jjt ainsi modifi´e.
3. Ex´ecuter JavaCC sur le fichier Aritha.jj produit par JJTree.
4. Remplacer le fichier ASTunElement.java par celui qui est fourni, reproduit dans la figure 5.
5. Ajouter le fichier Launcher.java, fourni et reproduit dans la figure 4. Il sert `a lancer l’ana-
lyseur g´en´er´e `a partir du fichier Aritha.jjt et `a afficher l’arbre produit.
6. Construire l’ex´ecutable Launcher.class et l’ex´ecuter sur quelques exemples afin de com-
prendre son fonctionnement.
Indications sur le fonctionnement de JJTree
JJTree cr´ee un nœud d’arbre par non-terminal en partie gauche d’une r`egle syntaxique, sauf
si le nom de ce non-terminal est suivi de l’annotation #void.
JJTree cr´ee un arbre avec n fils pour chaque non-terminal suivi d’une annotation #NonTermin (n),
o`u NonTermin est le nom de ce non-terminal. Par exemple, dans la r`egle unTerme,JJTree
cr´ee un arbre de classe ASTAdd avec 2 fils, qui seront les 2 arbres construits par les 2 non-
terminaux unProduit() et unTerme() en partie droite de r`egle.
La variable jjtThis est une r´ef´erence sur le nœud courant.
3
/** Fichier Aritha.jjt
* Copyright (c) 2004-06 Departement Informatique UFR ST
* Auteurs : A. Giorgetti, J. Julliand, P.-A. Masson, J. Voinot
*
* Ce fichier decrit un petit analyseur syntaxique qui produit
* une representation sous forme d’arbre de syntaxe abstraite (ASA)
* d’une expression arithmetique en entree.
*
* L’option MULTI permet de typer les arbres par ASTNomArbre.
* Par exemple, l’arbre annote’ avec #Add est de type ASTAdd.
* Cette classe est creee automatiquement par JJTree
* et est modifiable. Elle herite de la classe SimpleNode.
**/
options {
MULTI=true;
}
PARSER_BEGIN(Aritha)
public class Aritha {}
PARSER_END(Aritha)
/** ----------------- Regles lexicales ------------------------ */
SKIP : { " " | "\r" | "\n" | "\t" }
TOKEN : {
< CONSTANT: ( <DIGIT> )+ >
| < DIGIT: ["0"-"9"] >
/* OPERATEURS */
| < PLUS: "+" >
| < MULT: "*" >
}
/** ---------------- Regles syntaxiques --------------------- */
void axiome() #Exp() : {
/* #Exp indique que l’analyse d’un axiome construit
un ASA de classe ASTExp qui aura autant de fils que
de non-terminaux en partie droite de regle. */
} { /* [ X ] abrege (epsilon | X) */
[unTerme()] <EOF>
}
void unTerme() #void : {} {
unProduit() [ <PLUS> unTerme() #Add(2) ]
}
void unProduit() #Mul() : {} {
unElement()
( <MULT> unElement() )*
}
void unElement() :
/* La reconnaissance d’un non terminal unElement construit un ASA
pr´ed´efini, de classe ASTunElement. On modifie la d´efinition de la
classe pr´ed´efinie ASTunElement en lui ajoutant une m´ethode qui
permet de stocker la valeur du nombre reconnu. Voir le fichier
ASTunElement.java fourni. */
{ int x = 0; } {
<CONSTANT>
{
try { x = Integer.parseInt(token.image);
} catch (NumberFormatException ee) {
System.err.println("Error: "
+ token.image + " is not a number.");
x = 0;
}
jjtThis.setValeur(x);
}
}
Fig. 3 – Fichier Aritha.jjt
4
/** Fichier Launcher.java
*
* Copyright (c) 2006 Universite de Franche-Comte
* Auteurs : A. Giorgetti
*/
public class Launcher {
public static void main(String args[]) throws Exception {
Aritha parser = new Aritha(System.in);
parser.Axiome();
System.out.println("Debut arbre");
Node racine = parser.jjtree.rootNode();
((SimpleNode) racine).dump(" > ");
System.out.println("Fin arbre");
}
}
Fig. 4 – Fichier Launcher.java
Exercice 2.2
1. Ajouter dans les fichiers AST*.java et SimpleNode.java une m´ethode public int eval()
qui ´evalue une expression.
2. Ajouter dans Launcher un appel `a cette m´ethode et faire afficher son r´esultat. Par exemple,
l’expression 4 + 3 devra produire l’affichage :
Valeur de l’expression : 7
Indications pour l’exercice 2.2 Chaque nœud construit h´erite de toutes les m´ethodes d´efinies
dans l’interface Node et implant´ees dans la classe SimpleNode (voir le fichier SimpleNode.java ou
sa documentation). Parmi ces m´ethodes, utiliser :
int jjtGetNumChildren() qui retourne le nombre de fils d’un nœud.
Node jjtGetChild(i) qui retourne le (i+ 1)efils d’un nœud, les fils ´etant num´erot´es de 0
`a jjtGetNumChildren() 1.
Exercice 2.3
1. Ajouter dans les fichiers AST*.java,SimpleNode.java et Launcher.java une m´ethode
commut() de transformation des arbres en arbres commut´es, selon les r`egles suivantes :
commut(Entier : n) = Entier : n
commut(Mul x1 ... xn) = Mul commut(xn) ... commut(x1)
commut(Add x y) = Add commut(y) commut(x)
commut(Sub x) = Sub commut(x)
Indications pour l’exercice 2.3
La m´ethode void jjtAddChild(Node n, int i) de la classe SimpleNode ajoute le fils nen
position i, les fils ´etant num´erot´es `a partir de 0.
Les constructeurs d’arbres
ASTMul(ArithTreeConstants.JJTMUL) et
ASTAdd(ArithTreeConstants.JJTADD)
cr´eent respectivement un arbre de classe ASTMul et ASTAdd.
Les constantes statiques JJTMUL et JJTADD sont d´efinies dans le fichier ArithTreeConstants.java.
5
1 / 6 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !