1. Deux méthodes auxiliaires.
      String readInt() {
        
    if (tok.nature != Token.INT) error("entier", tok) ;
        
    String r = Integer.toString(tok.asInt) ;
        step() ;
        
    return r ;
      }

      
    String echo(String i1, Token tok, String i2) {
        
    switch (tok.nature) {
        
    case Token.ADD: case Token.SUB:
        
    case Token.MUL: case Token.DIV:
          
    return "(" + i1 + tok + i2 + ")" ;
        }
        error("Impossible !!!", tok) ;
        
    return "" ;
      }
  2. Samir.
      String samir() {
        
    String i1 = readInt() ;
        
    switch (tok.nature) {
        
    case Token.ADD: case Token.SUB:
        
    case Token.MUL: case Token.DIV:
          
    Token op = tok ;
          step() ;
          
    return echo(i1, op, samir()) ;
        
    case Token.EOF :
          
    return i1 ;
        
    default:
          error("opérateur", tok) ;
          
    return "" ; // Not Reached
        }
      }
  3. Pour Oscar on ne peut plus s'inspirer des règles, car alors on écrirait un programme ne terminant jamais, la méthode oscar se rappelant immédiatement elle-même.

    Le truc est de procéder à l'analyse comme pour Samir, mais de produire un résultat différent. Dans une production EE op int le E du membre droit représente le préfixe déjà vu du mot en cours de reconnaissance.
      String doOscar(String dejavu) {
        
    switch (tok.nature) {
        
    case Token.ADD: case Token.SUB:
        
    case Token.MUL: case Token.DIV:
          
    Token op = tok ;
          step() ;
          
    int i2 = readInt() ;
          
    return doOscar(echo(dejavu, op, i2))
        
    case Token.EOF :
          
    return r ;
        
    default:
          error("opérateur", tok) ;
          
    return "" ; // Not Reached
        }
      }

      
    String oscar() {
        
    return doOscar(readInt()) ;
      }
    On notera que la nécessité de disposer d'un dejavu non-vide conduit à modifier un peu la grammaire « à la Samir ».
    Sint E eof          Eop int E          E → ε

    En pratique, on peut remplacer la récursion (terminale) par une boucle while.
      String oscar() {
        
    String r = readInt() ;
        
    while (tok.nature != Token.EOF) {
          
    switch (tok.nature) {
          
    case Token.ADD: case Token.SUB:
          
    case Token.MUL: case Token.DIV:
            
    Token op = tok ;
            step() ;
            
    String i = readInt() ;
            r = echo(r, op, i) ;
            
    break;
          
    default:
            error("opérateur", tok) ;
          }
        }
        
    return r ;
      }
  4. Pour l'instituteur, on suit les règles de la grammaire, en se débrouillant pour faire pencher les expressions à gauche comme pour Oscar.
      private String parseF() {
        
    return readInt() ;
      }

      
    private String parseP() {
        
    String r = parseF() ;
        
    while (tok.nature == Token.MUL || tok.nature == Token.DIV) {
          
    Token op = tok ;
          step() ;
          
    String f = parseF() ;
          r = echo(r,op,f) ;
        }
        
    return r ;
      }

      
    private String parseE() {
        
    String r = parseP() ;
        
    while (tok.nature == Token.ADD || tok.nature == Token.SUB) {
          
    Token op = tok ;
          step() ;
          
    String p = parseP() ;
          r = echo(r,op,p) ;
        }
        
    return r ;
      }

      
    String instit() {
        
    String r = parseE() ;
        
    if (tok.nature != Token.EOF) error("EOF", tok) ;
        
    return r ;
      }


  5. Pour réaliser les calculs selon la méthode universelle il faut procéder à l'analyse syntaxique des expressions bien parenthésées revoyées par les trois methodes samir, etc.

    Mais la méthode universel utilisera une méthode  calc qui effectue les calculs, là où les autres analyseurs employaient echo.
      int calc(int i1, Token tok, int i2) {
        
    switch (tok.nature) {
        
    case Token.ADD: return i1+i2 ;
        
    case Token.SUB: return i1-i2 ;
        
    case Token.MUL: return i1*i2 ;
        
    case Token.DIV: return i1/i2 ;
        }
        error("Impossible !!!",  tok) ;
        
    return 0 ;
      }

    Ensuite on pourra par exemple écrire :
      String pretty = new Translate(lexer).instit() ;
      
    int r = new Translate(new Lexer (new StringReader (pretty))).universel() ;

    L'écriture de la méthode universel est facile, les parenthèses levant absolument toutes les ambiguïtés.
      int doUniversel() {
        
    if (tok.nature == Token.OPAR) {
          step() ;
          
    int i1 = doUniversel() ;
          
    Token op = null ;
          
    switch (tok.nature) {
          
    case Token.ADD: case Token.SUB:
          
    case Token.MUL: case Token.DIV:
            op = tok ;
            
    break ;
          
    default:
            error("opérateur", tok) ;
          }
          step() ;
          
    int i2 = doUniversel() ;
          
    if (tok.nature != Token.CPAR) error("parenthèse fermante", tok) ;
          step() ;
          
    return calc(i1, op, i2) ;
        } 
    else if (tok.nature == Token.INT) {
          
    int i = tok.asInt ;
          step() ;
          
    return i ;
        } 
    else {
          error("entier ou parenthèse ouvrante", tok) ;
          
    return 0 ; // Not Reached
        }
      }

      
    int universel () {
        
    int r = doUniversel() ;
        
    if (tok.nature != Token.EOF) error("EOF", tok) ;
        
    return r ;
      }
    Note : la grammaire des expressions complètement parenthésées est très semblable à celle des arbres de l'amphi.
    SE eof          Eint          E( E op E )
    L'écriture de l'analyseur est ici particulièrement évidente, le premier non-terminal d'un mot déterminant la production à appliquer.

  6. Il serait évidemment plus direct de procéder aux calculs dès la première analyse en remplaçant les appels à echo par des appels à calc dans les trois méthodes oscar, etc.

    Il serait plus informatique d'éviter une nouvelle analyse en remplaçant echo par une méthode construisant des abres binaires.