JavaCC-Helper.
md 1/30/2023
Java Compiler Compiler (JavaCC) - Guide LOG3210
Comment écrire des règles de production
Nous utiliserons cet exemple dans les diaporamas du cours 2 (p.7)
Nous voulons que notre grammaire accepte cette entrée:
id + id * id
Et nous avons ces règles de production qui définissent notre grammaire:
E → T E'
E' → + T E' | ϵ
T → F T'
T' → * F T' | ϵ
F → ( E ) | id
En Java CC, dans votre [Link], vos id sont représenté par
identifier(): Les variables (ex.: a, b, ma_variable, var, ...)
intValue(): Les nombres entier
realValue(): Les nombres à virgule
et devrait être regroupé par la règle de production BasicExpr()
Puis, vos règles de production sont définies de cette façon:
Exemple: F → ( E ) | id devient
void F(): {}
{
<LPAREN> E() <RPAREN> | <id>
}
Pour les "| ϵ", nous voulons que la règle de production puisse accepter l'absence de symboles. Exemple T'
→ * F T' | ϵ devient:
void TPrime(): {}
{
(<FOIS> F() TPrime())?
}
1/4
[Link] 1/30/2023
ou
void TPrime(): {}
{
[<FOIS> F() TPrime()]
}
Pour vous aider, vous pouvez implémenter votre grammaire avec une grande quantité règles de production
pour décortiquer votre la structure de votre arbre. Par contre, n'oubliez pas de réduire votre arbre avec
#void.
Aussi, vous pouvez identifier des sous-règles directement dans une règle de production et ceux-ci seront
affichées comme des enfants dans l'arbre de parsage. Exemple (Reprenant F → ( E ) | id):
void F(): {}
{
(<LPAREN> E() <RPAREN>)#Parentheses | Expr() #ExpressionSimple
}
Votre arbre de parsage ressemblera à
F
Parentheses
E
...
ou
F
ExpressionSimple
Expr
...
dépendant de l'entrée donnée.
Vous pouvez aussi afficher une règle de production seulement si elle est constitué d'au moins un élément,
par exemple (Reprenant T' → * F T' | ϵ):
void TPrime(): #void {}
{
(<FOIS> F() TPrime())? #TPrime(>1)
}
2/4
[Link] 1/30/2023
Ici, TPrime sera affichez seulement si l'expression * F T' est présente. Notez que la règle de production
contient #void pour ne pas l'afficher initialement.
LOOKAHEAD(n)
Les lookahead peuvent être necessaire pour demander à JavaCC de regarder plus loins que le premier
symbole avant de faire un choix.
Par exemple:
void Input() :
{}
{
"a" ( BC1() | BC2() )
}
void BC1() :
{}
{
"b" "d"
}
void BC2() :
{}
{
"b" "c"
}
Ce code ne compile pas parce que le compilateur ne peut pas choisir entre BC1() et BC2(). En effet, les
deux règles de production commencent avec le même symbole "b". Pour régler ce problème, il existe 2
solutions:
1. Vous pouvez utiliser un LOOKAHEAD(n) qui spécifie au compilateur de vérifier les n prochains
symboles avant de faire le choix. Dans notre cas, un LOOKAHEAD(2) résoudrait le conflit. Vous devez
l'ajouter juste avant votre choix choix1|choix2. Par exemple:
void Input() :
{}
{
"a" ( LOOKAHEAD(2) BC1() | BC2() )
}
void BC1() :
{}
{
"b" "d"
}
void BC2() :
{}
3/4
[Link] 1/30/2023
{
"b" "c"
}
2. Sortir les symboles qui se répètent dans la règle de production parent. Dans notre cas, notre code
deviendrait:
void Input() :
{}
{
"a" "b" ( BC1() | BC2() )
}
void BC1() :
{}
{
"d"
}
void BC2() :
{}
{
"c"
}
4/4