Algorithmique et Structures de données / Eté 2004 Faculté des Sciences Economiques et Sociales Gilles Falquet & El Mustapha El Atifi Exercices Série 6 (0.5pt.) [TP par binômes A rendre avant le 28-05] Exercice : Écrivez une application Java qui vérifie si un texte est syntaxiquement correct par rapport à la grammaire suivante : instruction ::= affectation | impression affectation ::= variable "=" expression variable ::= lettre { lettre | chiffre } expression ::= [ "-" ] terme { ("+" | "-") terme } terme ::= facteur { ("*" | "/" | "%") facteur } facteur ::= variable | nombre | "(" expression ")" nombre ::= chiffre { chiffre } impression ::= "imprime" expression Méthode : Utilisez la technique de la descente récursive pour écrire votre application (voir les notes de cours). Utilisez un analyseur lexical pour lire les symboles terminaux ou directement formés de terminaux, comme variable et nombre. Vous pouvez reprendre l'analyseur que vous avez écrit pour le TP4 ou bien utiliser l'analyseur AnalyseurLexical défini cidesous, qui est une extension de java.util.StreamTokenizer. L'analyseur s'utilise de la manière suivante : o Au début de l'application mettre : import java.io; o Création d'un analyseur lexical pour la chaîne s : AnalyseurLexical alx = new AnalyseurLexical(s); o Lecture d'un lexème: int lx = alx.next() Le résultat (ici lx) est le type du lexème (voir ci-dessous), l'objet alx contient trois champs dans lesquels sont stockés les caractéristiques du lexème lu : 1. alx.ttype : le type du lexème == alx.TT_EOF si on a atteint la fin du texte == alx.TT_WORD si le lexème est un mot, c'est à dire une lettre suivie de lettres et/ou de chiffres == alx.TT_NUMBER si le lexème est un nombre == '"' si le lexème est une chaine de caractères entre " et " 19.05.2004 == le caractère lu s'il n'appartient à aucun des types ci-dessus (TT_EOF, TT_WORD et TT_NUMBER sont des constantes (champs constants) définies dans la classe StreamTokenizer) 2. alx.sval : si le lexème est un nom (alx.ttype == alx.TT_WORD) ou une chaine alx.ttype == '"', la chaine 3. alx.nval : si le lexème est un nombre (alx.ttype ==alx.TT_WORD), la valeur numérique Voici un petit exemple (on lit une chaine et on imprime les lexèmens: import sio.*; import java.io.*; /** ********** RECOPIEZ TEL-QUEL DEPUIS ICI * * Sous-classe de l'analyseur lexical standard de java.io */ class AnalyseurLexical extends java.io.StreamTokenizer { /* * création d'un analyseur "normal" */ AnalyseurLexical(String s) { super(new StringReader(s)); ordinaryChar('/'); ordinaryChar('-'); ordinaryChar('.'); } /* * lecture d'un lexème (token) */ public int next() { try{ return nextToken(); } catch (IOException e) {System.out.println( "Erreur de lecture"); return TT_EOF;} } } /** ********** JUSQUE LA */ 19.05.2004 class stok { public static void main(String[] args) { term.printLine(); term.printLine(); term.printLine("Test de l'analyseur lexical"); term.printLine(); while (true) { term.print("texte >"); String s1 = term.readLine(); if (s1.equals("")) break; term.printLine(s1); AnalyseurLexical alx = new AnalyseurLexical(s1); while (alx.next() != alx.TT_EOF) { if (alx.ttype == alx.TT_WORD) term.printLine("mot: "+alx.sval); else if (alx.ttype == alx.TT_NUMBER) term.printLine("nombre: "+alx.nval); else if (alx.ttype == '\"' || alx.ttype =='\'') term.printLine("chaine: "+alx.sval); else term.printLine("autre symbole: "+(char)alx.ttype); } } } } Exécution : Test de l'analyseur lexical texte >bo+bo-bo*(a-3*y) bo+bo-bo*(a-3*y) mot: bo autre symbole: + mot: bo autre symbole: mot: bo autre symbole: * autre symbole: ( mot: a autre symbole: nombre: 3.0 autre symbole: * mot: y autre symbole: ) texte > 19.05.2004