import tokeniterator.*;
import java.util.*;

public class EspressioneUtil {

  public static String espressione2string(Espressione e) {
    if (e instanceof Atomo) 
      return ((Atomo)e).variabile();
    else if (e instanceof Not)
      return "!" +
        espressione2string(((Not)e).operando());
    else if (e instanceof And) 
      return "(" + 
        espressione2string(((And)e).operando1()) + 
        " & " +
        espressione2string(((And)e).operando2()) + ")";
    else // e instanceof Or)
      return "(" +
        espressione2string(((Or)e).operando1()) + 
        " | " +
        espressione2string(((Or)e).operando2()) + ")";
  }

  public static Set variabili(Espressione e) {
    Set vars = new HashSet();
    aggiungivariabili(e,vars);
    return vars;
  }

  private static void aggiungivariabili(Espressione e, Set vars) {
    if (e instanceof Atomo) 
      vars.add(((Atomo)e).variabile());
    else if (e instanceof Not)
      aggiungivariabili(((Not)e).operando(),vars);
    else if (e instanceof And) {
      aggiungivariabili(((And)e).operando1(),vars);
      aggiungivariabili(((And)e).operando2(),vars);
    }
    else {//(e instanceof Or)
      aggiungivariabili(((Or)e).operando1(),vars);
      aggiungivariabili(((Or)e).operando2(),vars);
    }  
  }


  public static Espressione string2espressione(String s) {
    // E ->  EE  |  EE & EE  |   EE | EE
    // EE ->  !EE | EEE 
    // EEE -> ( E ) | atom
    TokenIterator ti = new TokenIterator(s,"()&|!"," ");
    return E(ti);
  }
    
  private static Espressione E(TokenIterator ti) {
    Espressione e1 = EE(ti);
    if (ti.hasNext()&&(ti.peek().equals("&")||ti.peek().equals("|"))) {
      String tk = ti.next(); //tk == "&" oppure  "|"
      Espressione e2 = EE(ti);
      if (tk.equals("&")) 
        return new And(e1,e2);
      else // tk.equals("|")
        return new Or(e1,e2);
    }
    else return e1;
  }


  private static Espressione EE(TokenIterator ti) {
    if (ti.peek().equals("!")) { //guarda se tk corrente e' "!"
      ti.next(); // "ho letto "!"
      Espressione e = EE(ti);
      return new Not(e);
    } 
    else return EEE(ti);
  }

  private static Espressione EEE(TokenIterator ti) {
    String tk = ti.next();
    if (tk.equals("(")) {
      Espressione e = E(ti);
      ti.next(); //ho letto ")"
      return e;
    } 
    else  //tk e' una variabile
      return new Atomo(tk);
  }
}
    

  
