/* classe Pila implementata con Lista semplice di valori interi
   Si inseriscono e prelevano i nodi SOLO DALLA TESTA della lista.
   Il meccanismo è il seguente:
     Push()    -> inserisce un nodo in TESTA alla lista
     Pop()     -> elimina un nodo dalla TESTA della lista
     Clear()   -> elimina tutti i nodi (usa eccezione)
     TopElem() -> riavvolge e preleva il valore dal primo nodo della lista
*/
public class LLPila {
  private Lista elem;
    
  //costruttore  
  public LLPila() {
    elem = new Lista();
  }
  
  //metodi "canonici"  
  public boolean IsEmpty() {
    return elem.IsEmpty();
  }
  
  public void Clear() {
    //svuota lista
    try {
      while(true)
        elem.DeleteHead();
    } catch (EmptyListException e) {}
  }

  public void Push(int val) {
    elem.InsertHead(val);
  }
  
  public int Pop() {
    if (IsEmpty())
      throw new StackEmptyException();
    return elem.DeleteHead();
  }
  
  public int TopElem() {
    if (IsEmpty())
      throw new StackEmptyException();
    //Si posiziona alla testa della lista e preleva il valore
    elem.rewind();
    return elem.getNextElem();
  }
    
}

//Eccezioni personalizzate per la classe Pila.
class StackEmptyException extends RuntimeException {
  public StackEmptyException() {
    super("Pila vuota!!");
  }
  public StackEmptyException(String msg) {
    super(msg);
  }
}

class StackFullException extends RuntimeException {
  public StackFullException() {
    super("Pila piena!!");
  }
  public StackFullException(String msg) {
    super(msg);
  }
}