1. On peut introduire un nouveau non-terminal L pour la construction de liaison. Les opération binaires sont « plus prioritaires » que la liaison.
    SL
     
    Llet id = L in L          LE
     
    EP          EE + P          EE - P
     
    PF          PP * F          PP / F
     
    Fint          F( L )
    Et il ne faut pas oublier que la construction let... peut apparaître dans les parenthèses.

  2. Au minimum, pour que l'on puisse faire quelque chose des objets de la classe Instit il faut exposer au monde extérieur le constructeur Instit et la méthode parse, ils pourront être qualifiés par public si on souhaite exposer ces fonctionalités au delà du package courant (nous y reviendront à la question suivante).

    Toutes les autres méthodes et tous les champs devraient être privés (qualifiés par private). Cela s'applique indiscutablement aux champs tok et à la méthode step, afin de contrôler strictement l'usage du tampon de un lexème.

    Le champ lexer doit aussi logiquement être privé, mais ici la protection est plus illusoire, car rien n'empêche le monde extérieur de lire un lexème (le Lexer provient du monde extérieur).

    Le cas des méthodes parseF, parseP et parseE est également discutable, on peut concevoir un usage risqué de l'analyseur par le monde extérieur (par exemple analyser une liste de facteurs...). Sans autre information, autant cacher ces méthodes (mot-clé private).

    En résumé, un usage raisonnable de notre classe est d'exporter le constructeur et la méthode parse, et de cacher tout le reste. Mais ce n'est pas si simple.

  3. Pour constituer notre petit vérificateur en package, il faut. Alors, on peut écrire la classe Main suivante qui exploite les méthodes publiques du package expr.
    import java.io.* ;
    import expr.* ; // « importer » toutes les classes publiques du package expr


    class Main {
      
    public static void main(String [] argv) {
        
    Lexer lexer = new Lexer (new StringReader (argv[0])) ;
        
    Instit i = new Instit (lexer) ;
        i.parse() ;
      }
    }
    La seconde déclaration import permet de désigner les classes Lexer et Instit par leurs noms abrégés (autrement, il faudrait les qualifier complètement expr.Lexer et expr.Instit).

  4. La grammaire indique clairement comment procéder. Il faut modifier légèrement parseF, ajouter une nouvelle méthode parseL et modifier parse pour l'apeller.
       void parseF() {
        
    switch (tok.nature) {
        
    case Token.OPAR:
          step() ;
          parseL() ;
          
    if (tok.nature != Token.CPAR) error(")", tok) ;
          step() ;
          
    return ;
        
    case Token.ID: case Token.INT:
          step() ;
          
    return  ;
        
    default:
          error("entier ou identificateur", tok) ;
          
    return ; // Not Reached
        }
      }

      … 
    // parseP et parseE inchangées 

      
    void parseL() {
        
    if (tok.nature == Token.LET) {
          step() ;
          
    if (tok.nature != Token.ID) error("identificateur", tok) ;
          step() ;
          
    if (tok.nature != Token.EQ) error("=", tok) ;
          step() ;
          parseL() ;
          
    if (tok.nature != Token.IN) error("in", tok) ;
          step() ;
          parseL() ;
        } 
    else {
          parseE() ;
        }
      }

      
    void parse() {
        parseL() ;
        
    if (tok.nature != Token.EOF) error("EOF", tok) ;
      }