Computer Science Department
Programming Methods Laboratory
(LAMP)
Ecole Polytechnique Federale de Lausanne
Programmation Avancée et Compilation     semestre d'été 2000

Projet - Séance 4 (14.04.2000)

Analyseur syntaxique
Erreurs et omissions
Nouveaux fichiers
Arbre syntaxique
Pretty printer
Actions sémantiques
Tests
Lors de cette séance, il vous faut, si ce n'est pas encore le cas, terminer votre analyseur syntaxique, puis compléter l'arbre syntaxique, le pretty printer et rajouter des actions sémantiques à votre analyseur syntaxique.

Analyseur syntaxique

Ci-dessous quelques fichiers qui vous permettrons de tester votre analyseur syntaxique. Le premier fichier couvre une large partie de la grammaire. Ainsi, si votre programme l'analyse correctement, il y a de forte chance qu'il en fera de même pour tous les programmes corrects. Le deuxième et le troisième fichier contiennent une erreur de syntaxe à la deuxième ligne due au fait que les opérateurs ==, !=, <, <=, > et >= ne sont pas associatifs. Si votre analyseur ne signale pas ces erreurs, vérifiez que votre/vos déclaration(s) de précédence pour ces opérateurs spécifient une associativité du type nonassoc et non pas left ou right.

Erreurs et omissions

Nous avons constaté que la grammaire que nous vous avons fournies pour Jex contient quelques erreurs et omissions. Elles sont énumérées ci-dessous.
  • Les mots clés true et false, tout comme en Java, ne commencent pas par une majuscule mais par une minuscule.
  • Les paramètres dans l'expression new sont optionnels. La production corrects pour le new est donc:
      Expr = "new" Type "(" [ Exprs ] ")"
  • Il manque les productions pour les expressions parenthèsées et la valeur null:
      Expr = "(" Expr ")"
           | null
Il vous faudra tenir compte des deux premiers points dans votre programme. En effet, nos fichiers de tests supposent que ceux-ci ont été corrigés. Par contre, ils ne feront pas appel aux deux productions supplémentaires du dernier point. Vous êtes donc libre de les implémenter ou pas.

Nouveaux fichiers

Voici les nouveaux fichiers dont vous aurez besoin pour la suite du projet:

Arbre syntaxique

L'arbre syntaxique est décrit dans le fichier Tree.java. Un certain nombre de noeuds ont déjà été réalisés. Il ne vous reste plus qu'à implémenter les noeuds suivants:
  • Assign      (ASSIGN Expr Expr)
  • If          (IF Expr Statement Statement)
  • Block       (BLOCK { Statement | Formal })
  • Return      (RETURN Expr)
  • StringLit   (STRINGLIT String)
  • BooleanLit  (BOOLEANLIT boolean)
  • Ident       (IDENT ident)
  • MethodCall  (METHODCALL Expr ident { Expr })
  • FieldAccess (FIELDACCESS Expr ident)
  • New         (NEW Type { Expr })
  • BooleanTp   (BOOLEANTP)
Pour chaque noeud, vous devez déclarer une nouvelle sous-classe de Tree et y implémenter un constructeur ainsi que la méthode void apply(Visitor v). Vous devez aussi compléter l'interface Visitor (à la fin du fichier Tree.java).

Pretty printer

Le pretty printer est implémenté par la classe Printer. Vous devez la compléter en ajoutant une nouvelle méthode case pour chacun des noeuds que vous avez ajouté à l'arbre syntaxique.

Actions sémantiques

Pour que l'analyseur syntaxique construise un arbre syntaxique, il faut ajouter une action sémantique à chacune des productions. Ci-dessous, les premières productions complétées avec des actions sémantiques.
Program     ::= DefList:p
                {: RESULT = new DefList(pleft, p.toArray()); :}
            ;

DefList     ::= /* empty */
                {: RESULT = new TreeArrayBuffer(); :}
            |   DefList:p Statement:s
                {: RESULT = p.append(s); :}
            |   DefList:p Definition:d
                {: RESULT = p.append(d); :}
            ;

Definition  ::= Formal:f SEMI
                {: RESULT = f; :}
            |   FunDef:f
                {: RESULT = f; :}
            |   Import:f
                {: RESULT = f; :}
            ;

Import      ::= IMPORT:i Package:p TIMES SEMI
                {: RESULT = new Import(ileft, p.toArray(), true); :}
            |   IMPORT:i Package:p IDENT:id SEMI
                {: RESULT = new Import(ileft, p.append(id).toArray(),false); :}
            ;
Afin de pouvoir compiler le code ci-dessus, vous devez rajouter la déclaration suivante au début de votre fichier.
import jex.Tree.*;
Vous devez également compléter la déclaration des non-terminaux afin d'y spécifier leur type:
non terminal Tree              Program;
non terminal TreeArrayBuffer   DefList;
non terminal Tree              Definition;
non terminal Tree              Import;
non terminal StringArrayBuffer Package;
non terminal Tree              FunDef;
non terminal TreeArrayBuffer   Formals;
non terminal Tree              Formal;
non terminal Tree              Type;
non terminal Tree              Statement;
À vous de rajouter les actions sémantiques aux autres productions et de spécifier un type pour les non-terminaux restants. Pensez à utilisez les classes TreeArrayBuffer et StringArrayBuffer lorsque vous devez créer des tableaux d'arbres ou de chaînes de caractères.

Tests

Pour vérifier que l'arbre généré correspond bien au fichier analysé, utilisez le programme PrinterTest. Celui-ci génère un arbre syntaxique puis l'imprime avec le pretty printer. Pour lancer le programme, utilisez la commande suivante:
  gmake run.jex.PrinterTest < examples/syntax-1.jex
ou, sans utiliser gmake:
  java jex.PrinterTest < examples/syntax-1.jex
Vérifiez notamment que l'ordre d'évaluation des expressions est correct et que dans les instructions if imbriquées les else sont correctement associés aux if. Vous pouvez aussi comparer vos résultats avec ceux fourni par notre programme: Notez bien que vous n'êtes pas obligé d'obtenir exactement les mêmes résultats. Le but du pretty printer est simplement de permettre l'affichage des arbres syntaxiques. La syntaxe de cette affichage est libre.


Teaching
LAMP homepage
Last modified: 14.04.2000, Philippe Altherr <philippe.altherr@epfl.ch>