Nous avons apporté quelques corrections à la donnée de la partie 1 du projet. Ce
document énumère ces corrections et fournit également quelques
éclaircissements supplémentaires.
Corrections
Grammaires lexicale et syntaxique
Dans la version originale de la donnée, nous utilisions les termes
syntaxe lexicale et syntaxe pour désigner les deux
grammaires décrites dans ce document. Le
second terme peut prêter à confusion car il peut aussi bien désigner la
première grammaire que la seconde. Nous avons donc remplacé ces deux
termes par les termes grammaire lexicale et grammaire
syntaxique respectivement.
Définition de token
La définitions de token dans la grammaire lexicale
a été légérement augmentée afin de correspondre à la classe Tokens que nous vous avons
fournie.
Gestion de la fin de fichier
Dans la version originale de la donnée, on indiquait que pour
traiter la fin du fichier source, on modifiait la grammaire syntaxique
comme suit :
Program = { Declaration ";" } Expression EOF.
EOF = EOF_CH
Ceci est incorrect car cela signifierait que EOF est
un non-terminal de la grammaire syntaxique, ce qui est faux. Voilà
comment il faut modifier la grammaire :
Program = { Declaration ";" } Expression EOF_CH.
La grammaire syntaxique contient ainsi un terminal
EOF_CH auquel correspond la classe de lexèmes
EOF définie dans Tokens . On dit que
EOF_CH définit un pseudo-lexème car, dans la grammaire
lexicale, EOF_CH apparaît dans la définition de
input et non comme une alternative de token
comme c'est le cas pour tout vrai lexème.
Eclaircissements
Méthodes nextToken et readToken
Dans la classe Scanner que
nous vous avons fournie, une partie du travail de la méthode
nextToken est délégué à la méthode
readToken . Cette dernière étant privée (donc inaccessible
depuis n'importe quelle autre classe), vous pouvez en faire ce que
vous voulez et par exemple décider de la supprimer et d'implanter
toute l'analyse dans nextToken .
Plus généralement, vous pouvez toujours supprimer ou modifier des
méthodes privées que nous vous fournissons du moment que vous adaptez
aussi le code des méthodes qui les utilisaient. Par contre, vous ne
devriez pas toucher aux méthodes non privées car celles-ci risquent
d'être utilisées par des classes que vous n'avez pas encore
reçues. Bien sûr, vous pouvez aussi, si vous le désirez, ajouter de
nouvelles méthodes aux classes que nous vous fournissons. Ces méthodes
peuvent elles être aussi bien privées que publiques.
Méthodes nextCh
La classe Scanner définit
deux méthodes nextCh . La première simplement appelle la
seconde et retourne la valeur passée en argument. Sa seule utilité est
de simplifier votre code. Par exemple, au lieu d'écrire
if (<cond>) {
nextCh();
return <token1>;
} else {
return <token2>;
}
vous pouvez écrire
return <cond> ? nextCh(<token1>) : <token2>;
Méthodes fatal
Les méthodes fatal de la classe Global ne retournent jamais (elles
lèvent toujours une exception pour stopper l'exécution), mais elles
sont tout de même déclarées avec un type de retour de la classe
Error . Cela permet de placer l'appel à l'intérieur d'une
instruction throw :
throw global.fatal(pos, "erreur fatale");
Cela est parfois très utile. Par exemple lorsque l'on doit appeler
cette méthode dans une fonction dont le type de retour n'est pas
void . Dans ce cas, si on écrit un simple appel à la
méthode fatal , le compilateur Java sera incapable de
déterminer que cette méthode ne retourne jamais et il vous obligera de
placer une instruction return quelque part après votre
appel à fatal . L'utilisation du throw permet
d'éviter cela.
|