Compilation : partie 2
À présenter lors de la séance du 29 novembre 2002
Le but de cette partie est d'écrire un analyseur syntaxique pour le langage misc. Votre analyseur doit simplement vérifier que l'entrée est syntaxiquement correcte mais ne doit pas construire l'arbre syntaxique. Si l'entrée est correcte, votre analyseur doit donc simplement s'arrêter, sinon, il doit signaler au moins une erreur.
Votre travail est de réaliser l'analyseur syntaxique en complétant
la classe Parser
. Nous vous
suggérons d'utiliser la technique de la descente
récursive. Avec cette technique, la correspondance entre la
grammaire au format EBNF et le code source de l'analyseur syntaxique
est assez directe : à chaque règle de la grammaire correspond une
méthode de l'analyseur, méthode qui reconnaît les constructions
produites par cette règle; à la répétition ({}
en EBNF)
correspond une boucle; à l'option ([]
en EBNF) correspond
un test; et ainsi de suite. Reportez-vous au cours pour plus
d'informations au sujet de cette technique.
Bien que pour l'instant vous ne deviez pas construire d'arbre
syntaxique, nous vous conseillons de faire en sorte que toutes vos
méthodes d'analyse retournent déjà une valeur de type Tree
ou Tree[]
, car cela simplifiera sa
modification ultérieure. Pour l'instant, retournez simplement un arbre
null
La classe Parser
fournit
deux méthodes error
pour signaler des erreurs. Si
celles-ci ne conviennent pas, vous pouvez aussi directement appeler
les méthodes de la classe Global
.
Pour cette partie, tout comme pour la précédente, vous pouvez vous
contenter de détecter la première erreur. C'est pourquoi, les deux
méthodes error
appellent une méthode fatal
de la classe Global
. Tout
appel à l'une de ces deux méthodes termine donc aussi l'analyse en
cours. Si vous désirez pouvoir signaler plusieurs erreurs, il vous
faudra probablement changer cela et remplacer l'appel à
fatal
par un appel à error
.
Si vous voulez savoir pourquoi les deux méthodes
error
retournent une valeur du type Error
,
lisez le commentaire à propos des méthodes fatal
ici.
Tree.java : Cette classe acueillera,
par la suite, la définition des différents noeuds de l'arbre
syntaxique. Pour l'instant elle est vide et sert uniquement à définir
la classe Tree
afin que les
méthodes de l'analyseur syntaxique puissent être déclarées avec un tel
type de retour.
Parser.java : Cette classe implante l'analyseur syntaxique. A vous d'écrire la partie manquante du code.
ParserTest.java : Cette classe définit un programme qui vous permet de tester votre analyseur syntaxique. Il lit un fichier source et l'analyse. La syntaxe de la ligne de commande est la même que celle de ScannerTest.java, mais, comme il n'y a pas de sortie, le ficher objet ne sert à rien.
Pour pouvoir continuer à utiliser le Makefile, il vous faut y déclarer les nouveaux fichiers. Pour cela, ajoutez y les lignes suivantes :
JC_SOURCES += src/misc/Parser.java JC_SOURCES += src/misc/ParserTest.java JC_SOURCES += src/misc/Tree.java
Pour réaliser le projet en Scala, utilisez les fichiers suivant au lieu de ceux donnés ci-dessus.
Tree.scala : Cette classe acueillera,
par la suite, la définition des différents noeuds de l'arbre
syntaxique. Pour l'instant elle est vide et sert uniquement à définir
la classe Tree
afin que les
méthodes de l'analyseur syntaxique puissent être déclarées avec un tel
type de retour.
Parser.scala : Cette classe implante l'analyseur syntaxique. A vous d'écrire la partie manquante du code.
ParserTest.scala : Cette classe définit un programme qui vous permet de tester votre analyseur syntaxique. Il lit un fichier source et l'analyse. La syntaxe de la ligne de commande est la même que celle de ScannerTest.java, mais, comme il n'y a pas de sortie, le ficher objet ne sert à rien.
Pour pouvoir utiliser ParserTest.scala, il vous faut deux fichiers Java suplémentaires :
ScalaMain.java : Cette classe fourni une base commune pour les programmes Scala.
ScalaMainRunnable.java :
Cette interface est utilisée par la classe ScalaMain
.
Ci-dessous un fichier Makefile
pour compiler les fichier
.java
puis les fichier .scala
.
Makefile : Fichier
Makefile
pour le projet en Scala.
Pour pouvoir utilisez Parser.scala,
vous devez transformer l'interface Tokens
en une classe
abstraite et déclarer tous ses membres public static
final
. Elle devrait donc ressembler à ça. Il vous faut ensuite remplacer le
implements
par un extends
dans la classe Scanner
et dans la classe ScannerTest
, il faut
supprimer le implements Tokens
et remplacer
EOF
par Tokens.EOF
.
Pour lancer le programme de test, vous devez utiliser la commande
java
, mais vous devez inclure dans le classpath
l'archive scala.jar
qui contient les classes du
runtime Scala. Sur les machines en IN3, cette archive se trouve
dans le répertoire suivant :
/home/iclamp/local/packages/scala/lib/
Il vous faut donc lancer une commande qui ressemble à ça :
java -classpath /home/iclamp/local/packages/scala/lib/scala.jar:./classes ParserTest <options> [fichier-source [fichier-objet]]
Pour éviter de devoir à chaque fois spécifier l'option
-classpath
, vous pouvez redéfinir la variable
d'environnement CLASSPATH
afin qu'elle contiennent
l'archive scala.jar
et votre répertoire
classes
.