/**  file: StrInExp: trasforma Stringhe in EXP (nella R.Interna) */

import java.io.*;
import java.util.*;
import java.awt.*;
import java.lang.Exception;

/** ================
      IL TOKENIZER 
    ================ */
/** Il "TOKENIZER" e' un oggetto a cui viene data una stringa e
    che rende (facendo chiamate successive) la stringa 
    spezzettata in "token", cioe' disgregata nei sui "componenti"
    (ridefinibili tramite opportuni metodi) */
class ExpTokenizer extends StreamTokenizer {  // trasforma STR in TOKEN
  TextArea msgOut;
    
  /** Costruttore del disgregatore di espressioni */
  ExpTokenizer (InputStream I) throws Exception {
    super (I);
    parseNumbers ();
    eolIsSignificant (true);
    ordinaryChar ('(');
    ordinaryChar (')');
    ordinaryChar ('+');
    ordinaryChar ('*');
    ordinaryChar ('-');
    ordinaryChar ('/');
    ordinaryChar ('=');
    ordinaryChar ('X');
    ordinaryChar ('Y');
    ordinaryChar ('A');
    ordinaryChar ('B');
    quoteChar('"');
    slashStarComments (false);
  }
  ExpTokenizer (String s, TextArea AreaOut) throws Exception {
    this (new StringBufferInputStream(s)); // chiama costruttore di sopra!
    msgOut = AreaOut;
    msgOut.appendText ("ExpTokenizer - inizializzato con "+ s +"\n");
  }
  
  /** Rimette dentro il "tokenizer" l'ultimo "token" prelevato.
      Si annulla l'ultima operazione "next". */
  public void pushBack () {
    if (ttype != TT_EOF) {
      msgOut.appendText ("Tokenizer - 'pushBack' di '");
      switch (ttype) {
        case   TT_WORD: msgOut.appendText (sval+"'\n"); break;
        case TT_NUMBER: msgOut.appendText (nval+"'\n"); break;
               default: msgOut.appendText ((char)ttype +"'\n");
      }//switch
      super.pushBack();
    }
  }

  /** Rende il prossimo "token" */
  public Token next() throws Exception {
    Token T;   // Token da rendere
    int TType = nextToken();  // Prende il nuovo valore dal Tokenizer
    msgOut.appendText ("Tokenizer - 'next' rende token '");
    switch (TType) {
      case   TT_WORD: msgOut.appendText (sval+"'\n"); break;
      case TT_NUMBER: msgOut.appendText (nval+"'\n"); break;
      case    TT_EOF: msgOut.appendText ("EOTok'\n"); break;
             default: msgOut.appendText ((char)TType +"'\n");
    }//switch
    switch (TType) {        // Controlla il token preso
      case   TT_WORD: { // IDENTIFICATORE composto o operatore (letterale)
                         if ((sval.compareTo("sqr") == 0) ||
                             (sval.compareTo("sqrt")== 0) ||
                             (sval.compareTo("inv") == 0))
                           T = new Token(sval, 'O');
                         else
                           T = new Token(sval, 'I');
                         break;
                       }
      case TT_NUMBER: T = new Token(""+nval, 'N'); break; // NUMERO
      case       '(':
      case       ')':
      case       '=':
      case       '+':
      case       '-':
      case       '*':
      case       '/': T = new Token((char)TType+"", 'O'); break;
      case       'X':
      case       'Y':
      case       'A':
      case       'B': T = new Token((char)TType+"", 'I'); break;
      case    TT_EOF: T = new Token("FINE",'$');          break;
      case    TT_EOL: T = next();                         break;
             default: T = new Token((char)TType+"");
   } //switch
   return T;  // rende oggetto (token) creato
  } //next
} //ExpTokenizer

/** =======================================
      LE CLASSI TOKEN (rese dal TOKENIZER)
    ======================================= */
class Token {
  String  MyInfo;
  char    MyTipo;  // 'N' per NUM, 'I' per ID,
                   // 'O' per operatore  o '$' per nullo
  
  public Token (String Informaz, char Tipo) {
    MyInfo = Informaz; 
    MyTipo = Tipo;
  }
  public Token (String Informaz) {
    this (Informaz, 'O');
  }
 
  public String  Info()         { return MyInfo;          }
  public String  toString()     { return MyInfo+" ["+MyTipo+"]"; }
  public boolean Contiene(String EQuesto) {
    return (MyInfo.compareTo(EQuesto) == 0);
  }
  public boolean ENumero()      { return (MyTipo == 'N'); }
  public boolean EIdentific()   { return (MyTipo == 'I'); }
  public boolean EOperatore()   { return (MyTipo == 'O'); }
  public boolean NoPiuToken()   { return (MyTipo == '$'); }
}

   
/** =============
      IL PARSER
    ============= */
class StrParser {  // Legge la sequenza di token e rende la R.I. (in Exp)
  //Nota: in ingresso riceve il Tokenizer
  ExpTokenizer  ETokeniz;
  TextArea      msgOut;
    
  StrParser (ExpTokenizer ETokz, TextArea AreaOut) throws Exception {
    ETokeniz = ETokz;
    msgOut = AreaOut;
    msgOut.appendText ("Parser    - inizializzato\n");
  }
 // Insieme delle produzioni per le TRE NOTAZIONI:
 // Notazione PREfissa (pre)     INfissa (in)     POSTfissa (post)
 //             E::= + E E         E::= E + T       E::= E E +
 //             E::= - E E         E::= E - T       E::= E E -
 //             E::= = ID E        E::= ID = E      E::= ID E =
 //                                E::= T
 //             E::= * E E         T::= T * F       E::= E E *
 //             E::= / E E         T::= T / F       E::= E E /
 //             E::= F             T::= F           E::= F
 //                                F::= ( E )
 //             E::= sqr E         F::= sqr F       F::= E sqr
 //             E::= sqrt E        F::= sqrt F      F::= E sqrt
 //             E::= inv E         F::= inv F       F::= E inv
 //             F::= NUM           F::= NUM         F::= NUM
 //             F::= ID            F::= ID          F::= ID
 //    Nota: SOLO la notazione INfissa ha bisogno delle parentesi!
 // Ora tolgo la RICORSIONE SINISTRA dalle ultime due!
 // Notazione PREfissa (pre)     INfissa (in)     POSTfissa (post)
 //             E::= + E E         E ::= T RE       E ::= F UN RE
 //             E::= - E E         E ::= ID = E     RE::= §
 //             E::= = ID E        RE::= + T RE     RE::= F UN RO RE
 //                                RE::= - T RE     RO::= + UN
 //                                RE::= §          RO::= - UN
 //                                T ::= F RT       RO::= * UN
 //             E::= * E E         RT::= * F RT     RO::= / UN
 //             E::= / E E         RT::= / F RT     RO::= =
 //             E::= F             RT::= §          RO::= F UN RO RO
 //                                F ::= ( E )      UN::= §
 //             E::= sqr E         F ::= sqr F      UN::= sqr UN
 //             E::= sqrt E        F ::= sqrt F     UN::= sqrt UN
 //             E::= inv E         F ::= inv F      UN::= inv UN
 //             F::= NUM           F ::= NUM        F ::= NUM
 //             F::= ID            F ::= ID         F ::= ID
 // E quindi CODIFICO ogni NON TERMINALE con una PROCEDURA
 

/** ====================
      NOTAZIONE INFISSA
    ==================== */
  public Exp RendiExpDaNotazInfissa () throws Exception {
    msgOut.appendText ("INIZIO LA COSTRUZIONE STR-->R.I.\n"
                       +"(*) Elaboro in Notazione INFISSA\n");
    Exp ExpResa = ExpIN();             // RENDE R.I.
    Token NuoTok= ETokeniz.next();     // prendo prossimo token
    if (NuoTok.NoPiuToken())     // (dovrebbe verificarsi cio')
      return ExpResa;    // tutto ok, stringa totalmente consumata
    else
      throw new Exception("NON HO CONSUMATO L'INTERA STRINGA!"); // errore
  }//RendiExpDaNotazInfissa
  
  protected Exp ExpIN() throws Exception {
    // E ::= T RE
    msgOut.appendText ("RendiExpIN   inizio  E=T\n");
    Exp Term = TermIN();
    Exp ExpDaRendere = RestExpIN(Term);
    msgOut.appendText ("RendiExpIN   fine di E=T\n");
    return ExpDaRendere;
  }//ExpIN
  
  protected Exp RestExpIN(Exp Stato) throws Exception {
    // E ::= ID = E   (messo qui per verificare che sia ID)
    // RE::= + T RE
    // RE::= - T RE
    // RE::= §
    Exp ExpDaRendere;
    msgOut.appendText ("RendiExpIN   inizio  RE=+T|-T|null\n");
    Token NuovoToken = ETokeniz.next (); // prendo prossimo token
    if (NuovoToken.NoPiuToken()) {        // Token finiti
      msgOut.appendText ("RendiExpIN no piu' token\n");
      ExpDaRendere = Stato;    // Rendo la RI avuta in ingresso
    }
    else
      if (NuovoToken.Contiene("+")) {              // Trovo un "+"
           msgOut.appendText ("RendiExpIN riconosc. +T\n");
           Exp Term = TermIN();
           Exp NuovoStato = new PiuExp (Stato, Term);
           ExpDaRendere = RestExpIN (NuovoStato);
      }
      else
        if (NuovoToken.Contiene("-")) {            // Trovo un "-"
             msgOut.appendText ("RendiExpIN riconosc. -T\n");
             Exp Term = TermIN();
             Exp NuovoStato = new MenExp (Stato, Term);
             ExpDaRendere = RestExpIN (NuovoStato);
        }
        else
          if (NuovoToken.Contiene("=")) {          // Trovo un "="
            msgOut.appendText ("RendiExpIN riconosc. ID=E\n");
            if (!(Stato instanceof IdentRefExp))
              throw new Exception("IL PRIMO ARG. DI '=' DEV'ESSERE UN SIMBOLO"); // errore
            Exp LValue = new IdentExp (((IdentRefExp)Stato).Val()); // l-value!
            Exp RValue = ExpIN();
            ExpDaRendere = new AssignExp (LValue, RValue);
          }
          else {
            msgOut.appendText ("RendiExpIN   pushback in RE\n");
            ETokeniz.pushBack();    // ri-inserisco l'operat.non elaborato
            ExpDaRendere = Stato;   // Rendo la RI avuta in ingresso
          }
    msgOut.appendText ("RendiExpIN     fine  RE=+T|-T|null\n");
    return ExpDaRendere;
  }//RestExpIN

  protected Exp TermIN() throws Exception {
    // T ::= F RT
    msgOut.appendText ("RendiExpIN   inizio  T=F\n");
    Exp Fact = FactIN();
    Exp ExpDaRendere = RestTermIN(Fact);
    msgOut.appendText ("RendiExpIN     fine  T=F\n");
    return ExpDaRendere;
  }//TermIN
  
  protected Exp RestTermIN(Exp Stato) throws Exception {
    // RT::= * F RT
    // RT::= / F RT
    // RT::= §
    Exp ExpDaRendere;
    msgOut.appendText ("RendiExpIN   inizio  RT=*F|/F|null\n");
    Token NuovoToken = ETokeniz.next ();  // Prendo prossimo token
    if (NuovoToken.NoPiuToken()) {        // Token finiti
      msgOut.appendText ("RendiExpIN no piu' token\n");
      ExpDaRendere = Stato;    // Rendo la RI avuta in ingresso
    }
    else
      if (NuovoToken.Contiene("*")) {              // Trovo un "*"
           msgOut.appendText ("RendiExpIN riconosc. *F\n");
           Exp Fact = FactIN();
           Exp NuovoStato = new PerExp (Stato, Fact);
           ExpDaRendere = RestTermIN (NuovoStato);
      }
      else
        if (NuovoToken.Contiene("/")) {            // Trovo un "/"
             msgOut.appendText ("RendiExpIN riconosc. /F\n");
             Exp Fact = FactIN();
             Exp NuovoStato = new DivExp (Stato, Fact);
             ExpDaRendere = RestTermIN (NuovoStato);
        }
        else {
          msgOut.appendText ("RendiExpIN   pushback in RT\n");
          ETokeniz.pushBack();    // ri-inserisco l'operat.non elaborato
          ExpDaRendere = Stato;    // Rendo la RI avuta in ingresso
        }
    msgOut.appendText ("RendiExpIN     fine  RT=*F|/F|null\n");
    return ExpDaRendere;
  }//RestTermIN
  
  protected Exp FactIN() throws Exception {
    // F ::= ( E )
    // F ::= sqr F
    // F ::= sqrt F
    // F ::= inv F
    Exp ExpDaRendere;
    msgOut.appendText ("RendiExpIN   inizio  F=(E)\n");
    Token NuovoToken = ETokeniz.next ();  // prendo prossimo token
    if (NuovoToken.Contiene("(")) {               // Trovo una "("
      msgOut.appendText ("RendiExpIN riconosc. TONDA APERTA\n");
      ExpDaRendere = ExpIN();
      NuovoToken = ETokeniz.next ();      // prendo prossimo token
      if (!(NuovoToken.Contiene(")")))
        throw new Exception("MANCA UNA TONDA CHIUSA"); // errore
    }
    else
      if (NuovoToken.Contiene("sqr")) {          // Trovo un "sqr"
        msgOut.appendText ("RendiExpIN riconosc. SQR\n");
        Exp EspInt = FactIN();
        ExpDaRendere = new SqrExp (EspInt);
      }
      else
        if (NuovoToken.Contiene("sqrt")) {       // Trovo un"sqrt"
          msgOut.appendText ("RendiExpIN riconosc. SQRT\n");
          Exp EspInt = FactIN();
          ExpDaRendere = new SqrtExp (EspInt);
        }
        else
          if (NuovoToken.Contiene("inv")) {      // Trovo un "inv"
            msgOut.appendText ("RendiExpIN riconosc. INV\n");
            Exp EspInt = FactIN();
            ExpDaRendere = new InvExp (EspInt);
          }
          else
            ExpDaRendere = FactNumIdALL(NuovoToken);
    msgOut.appendText ("RendiExpIN     fine  F=(E)\n");
    return ExpDaRendere;
  }//FactIN
  
  protected Exp FactNumIdALL (Token NuovoToken) throws Exception {
    // F::= NUM
    // F::= ID
    Exp ExpDaRendere;
    msgOut.appendText ("RendiExpXX   inizio  F=NUM|ID\n");
    if (NuovoToken.Contiene("-")) {      // Controllo "-NUM"
      NuovoToken = ETokeniz.next();      // prendo prossimo token
      if (NuovoToken.ENumero()) {        // Trovo un NUMERO
        msgOut.appendText ("RendiExpXX riconosc. -NUMERO\n");
        NuovoToken = new Token ("-"+NuovoToken.Info(),'N');
        // questo nuovo token verra' usato tra poco:
      }
    }
    if (NuovoToken.ENumero()) {         // Trovo un NUMERO
      msgOut.appendText ("RendiExpXX riconosc. NUMERO "+NuovoToken+"\n");
      double Valore = (new Double(NuovoToken.Info())).doubleValue();
      ExpDaRendere = new NumExp (Valore);
    }
    else
      if (NuovoToken.EIdentific()) {    // Trovo IDENTIFICAT.
        msgOut.appendText ("RendiExpXX riconosc. IDENTIF. "+NuovoToken+"\n");
        ExpDaRendere = new IdentRefExp (NuovoToken.Info()); // r-value!
      }
      else
        throw new Exception("ESPRESSIONE NON RAPPRESENTABILE"); // errore
    msgOut.appendText ("RendiExpXX     fine  F=NUM|ID\n");
    return ExpDaRendere;
  }//FactNumIdALL

   
/** =====================
      NOTAZIONE PREFISSA
    ===================== */  
  public Exp RendiExpDaNotazPrefissa () throws Exception {
    msgOut.appendText ("INIZIO LA COSTRUZIONE STR-->R.I.\n"
                      +"(*) Elaboro in Notazione PREFISSA\n");
    Exp ExpResa = ExpPRE();            // RENDE R.I.
    Token NuoTok= ETokeniz.next();     // prendo prossimo token
    if (NuoTok.NoPiuToken())     // (dovrebbe verificarsi cio')
      return ExpResa;    // tutto ok, stringa totalmente consumata
    else
      throw new Exception("NON HO CONSUMATO L'INTERA STRINGA!"); // errore
  }        
  
  protected Exp ExpPRE() throws Exception {
    // E::= + E E
    // E::= - E E
    // E::= = ID E
    // E::= * E E
    // E::= / E E
    // E::= sqr E
    // E::= sqrt E
    // E::= inv E
    // E::= F
    Exp ExpDaRendere;
    msgOut.appendText ("RendiExpPRE   inizio  RT=+ E E|* E E|..\n");
    Token NuovoToken = ETokeniz.next ();  // prendo prossimo token
    if (NuovoToken.Contiene("+")) {                // Trovo un "+"
      msgOut.appendText ("RendiExpPRE riconosc. + F F\n");
      Exp Arg1 = ExpPRE();
      Exp Arg2 = ExpPRE();
      ExpDaRendere = new PiuExp (Arg1, Arg2);
    }
    else
      if (NuovoToken.Contiene("-")) {              // Trovo un "-"
        msgOut.appendText ("RendiExpPRE riconosc. - F F\n");
        Exp Arg1 = ExpPRE();
        Exp Arg2 = ExpPRE();
        ExpDaRendere = new MenExp (Arg1, Arg2);
      }
      else
        if (NuovoToken.Contiene("*")) {            // Trovo un "*"
          msgOut.appendText ("RendiExpPRE riconosc. * F F\n");
          Exp Arg1 = ExpPRE();
          Exp Arg2 = ExpPRE();
          ExpDaRendere = new PerExp (Arg1, Arg2);
        }
        else
          if (NuovoToken.Contiene("/")) {          // Trovo un "/"
            msgOut.appendText ("RendiExpPRE riconosc. / F F\n");
            Exp Arg1 = ExpPRE();
            Exp Arg2 = ExpPRE();
            ExpDaRendere = new DivExp (Arg1, Arg2);
          }
          else
            if (NuovoToken.Contiene("=")) {        // Trovo un "="
              msgOut.appendText ("RendiExpPRE riconosc. = ID E\n");
              Exp ID = FactNumIdALL (NuovoToken);
              if (!(ID instanceof IdentRefExp))
                throw new Exception("IL PRIMO ARG. DI '=' DEV'ESSERE UN SIMBOLO"); // errore
              Exp LValue = new IdentExp (((IdentRefExp)ID).Val()); // l-value!
              Exp RValue = ExpPRE();
              ExpDaRendere = new AssignExp (LValue, RValue);
            }
            else
              if ((NuovoToken.Contiene("(")) ||
                  (NuovoToken.Contiene(")")))   // Trovo "(" o" )"
                throw new Exception("NON SI DEVONO USARE LE PARENTESI!");
              else
                if (NuovoToken.Contiene("sqr")) {   // Trovo "sqr"
                  msgOut.appendText ("RendiExpIN riconosc. SQR\n");
                  Exp EspInterna = ExpPRE();
                  ExpDaRendere = new SqrExp (EspInterna);
                }
                else
                  if (NuovoToken.Contiene("sqrt")) { //Trovo "sqrt"
                    msgOut.appendText ("RendiExpIN riconosc. SQRT\n");
                    Exp EspInterna = ExpPRE();
                    ExpDaRendere = new SqrtExp (EspInterna);
                  }
                  else
                    if (NuovoToken.Contiene("inv")) { //Trovo"inv"
                      msgOut.appendText ("RendiExpIN riconosc. INV\n");
                      Exp EspInterna = ExpPRE();
                      ExpDaRendere = new InvExp (EspInterna);
                    }
                    else
                      ExpDaRendere = FactNumIdALL (NuovoToken);
                // nota: richiamo il riconoscimento di NUM o ID o errore
    msgOut.appendText ("RendiExpPRE     fine  RT=+ E E|* E E|..\n");
    return ExpDaRendere;
  }//ExpPRE


/** ======================
      NOTAZIONE POSTFISSA
    ====================== */
  public Exp RendiExpDaNotazPostfissa () throws Exception {
    
    msgOut.appendText ("INIZIO LA COSTRUZIONE STR-->R.I.\n"
                       +"(*) Elaboro in Notazione POSTFISSA\n");
    Exp ExpResa = ExpPOST();           // RENDE R.I.
    Token NuoTok= ETokeniz.next();     // prendo prossimo token
    if (NuoTok.NoPiuToken())     // (dovrebbe verificarsi cio')
      return ExpResa;    // tutto ok, stringa totalmente consumata
    else
      throw new Exception("NON HO CONSUMATO L'INTERA STRINGA!"); // errore
  }//RendiExpDaNotazPostfissa
  
  protected Exp ExpPOST() throws Exception {
    // E ::= F UN RE
    msgOut.appendText ("RendiExpPOST   inizio  E=F\n");
    Token NuovoToken = ETokeniz.next();   // prendo prossimo token
    Exp Fatt1 = FactNumIdALL (NuovoToken);
    Exp ExpConUnario = UnPOST (Fatt1);
    Exp ExpDaRendere = RestExpPOST (ExpConUnario);
    msgOut.appendText ("RendiExpPOST   fine di E=F RE\n");
    return ExpDaRendere;
  }//ExpPOST
  
  protected Exp RestExpPOST (Exp Fatt1) throws Exception {
    // RE::= §
    // RE::= F UN RO RE
    Exp ExpDaRendere;
    msgOut.appendText ("RendiExpPOST   inizio  RE=F RO RE\n");
    Token NuovoToken = ETokeniz.next (); // prendo prossimo token
    if (NuovoToken.NoPiuToken()) {        // Token finiti
      msgOut.appendText ("RendiExpPOST no piu' token\n");
      ExpDaRendere = Fatt1;      // Rendo la RI avuta in ingresso
    }
    else {
      Exp Fatt2 = FactNumIdALL (NuovoToken);
      Exp ExpUnaria2 = UnPOST (Fatt2);
      Exp ResRO = RestOperPOST (Fatt1, ExpUnaria2);
      ExpDaRendere = RestExpPOST (ResRO);
    }
    msgOut.appendText ("RendiExpPOST     fine  RE=F RO RE\n");
    return ExpDaRendere;
  }//RestExpPOST
  
  protected Exp RestOperPOST (Exp Fatt1, Exp Fatt2) throws Exception {
    // RO::= + UN
    // RO::= - UN
    // RO::= * UN
    // RO::= / UN
    // RO::= =
    // RO::= F UN RO RO
    Exp ExpDaRendere;
    msgOut.appendText ("RendiExpPOST   inizio  RO=+|-|*|..|F RO RO\n");
    Token NuovoToken = ETokeniz.next ();  // prendo prossimo token
    if (NuovoToken.Contiene("+")) {                // Trovo un "+"
      msgOut.appendText ("RendiExpPOST riconosc. F F +\n");
      Exp ExpCalco = new PiuExp (Fatt1, Fatt2);
      ExpDaRendere = UnPOST (ExpCalco);
    }
    else
      if (NuovoToken.Contiene("-")) {              // Trovo un "-"
        msgOut.appendText ("RendiExpPOST riconosc. F F -\n");
        Exp ExpCalco = new MenExp (Fatt1, Fatt2);
        ExpDaRendere = UnPOST (ExpCalco);
      }
      else
        if (NuovoToken.Contiene("*")) {            // Trovo un "*"
          msgOut.appendText ("RendiExpPOST riconosc. F F *\n");
          Exp ExpCalco = new PerExp (Fatt1, Fatt2);
          ExpDaRendere = UnPOST (ExpCalco);
        }
        else
          if (NuovoToken.Contiene("/")) {          // Trovo un "/"
            msgOut.appendText ("RendiExpPOST riconosc. F F /\n");
            Exp ExpCalco = new DivExp (Fatt1, Fatt2);
            ExpDaRendere = UnPOST (ExpCalco);
          }
          else
            if (NuovoToken.Contiene("=")) {        // Trovo un "="
              msgOut.appendText ("RendiExpPOST riconosc. ID E =\n");
              if (!(Fatt1 instanceof IdentRefExp))
                throw new Exception("IL PRIMO ARG. DI '=' DEV'ESSERE UN SIMBOLO"); // errore
              Exp LValue = new IdentExp (((IdentRefExp)Fatt1).Val()); // l-value!
              ExpDaRendere = new AssignExp (LValue, Fatt2);
            }
            else {
              Exp Fatt3 = FactNumIdALL (NuovoToken);
              Exp ExpUnaria3 = UnPOST (Fatt3);
              Exp OpFatt23 = RestOperPOST (Fatt2, ExpUnaria3);
              ExpDaRendere = RestOperPOST (Fatt1, OpFatt23);
            }
    msgOut.appendText ("RendiExpPOST     fine  RO=+|-|*|..|F RO RO\n");
    return ExpDaRendere;
  }//RestOperPOST
  
  protected Exp UnPOST (Exp ExpProbabile) throws Exception {
    // UN::= §
    // UN::= sqr UN
    // UN::= sqrt UN
    // UN::= inv UN
    Exp ExpDaRendere;
    msgOut.appendText ("RendiExpPOST   inizio  UN=null|sqr|..\n");
    Token NuovoToken = ETokeniz.next ();  // prendo prossimo token
    if (NuovoToken.Contiene("sqr")) {               // Trovo "sqr"
      msgOut.appendText ("RendiExpIN riconosc. SQR\n");
      Exp AltraExpProb = new SqrExp (ExpProbabile);
      ExpDaRendere = UnPOST (AltraExpProb);
    }
    else
      if (NuovoToken.Contiene("sqrt")) {            //Trovo "sqrt"
        msgOut.appendText ("RendiExpIN riconosc. SQRT\n");
        Exp AltraExpProb = new SqrtExp (ExpProbabile);
        ExpDaRendere = UnPOST (AltraExpProb);
      }
      else
        if (NuovoToken.Contiene("inv")) {           // Trovo "inv"
          msgOut.appendText ("RendiExpIN riconosc. INV\n");
          Exp AltraExpProb = new InvExp (ExpProbabile);
          ExpDaRendere = UnPOST (AltraExpProb);
        }
        else{
          ETokeniz.pushBack();   // ri-inserisco token non elaborato
          ExpDaRendere = ExpProbabile;
        }
    msgOut.appendText ("RendiExpPOST     fine  UN=null|sqr|..\n");
    return ExpDaRendere;
  }//UnPOST

} //StrParser
//*FINE FILE*