options { 
  IGNORE_CASE = true; // ignore upper/lower case
  STATIC = true; // generate static methods
  UNICODE_INPUT = true; // support Unicode in input
}

PARSER_BEGIN(FridgeParser)

package javakurs.uebung04;

/**
 * {@link FridgeParser} is the natural language interface to the FCM (fridge
 * content management) system in class {@link Fridge}.
 * 
 * @author Ulrich Schaefer, DFKI
 * @version $Id$
 */
public class FridgeParser {

  /**
   * Contains the FCM object.
   */
  private static Fridge fridge = null;
  
  /**
   * Contains flag to indicate end of program.
   */
  private static boolean quit = false;


  /**
   * Start method for running the natural language I/O to and from the
   * fridge via stdin/stdout. The for loop is executed forever; exit through
   * the 'Ende' command calling fridge.finish() -> System.exit()
   *
   * @param args not used
   */
  public static void main(String[] args) {

    FridgeParser parser = new FridgeParser(System.in);
    fridge = new Fridge();
    while (true) {
      // loop forever - until break is executed  
      try {
        // start symbol/rule
        Input();
        if (quit) {
          break;
        }
      } catch (ParseException pe) {
        String tstring = pe.currentToken.image;
        // in the ParserException context, Token is always set,
        // but its image may be null
        if (tstring == null) {
          tstring = "";
        }
        else {
          tstring = tstring + " ";
        }
        String parserMessage =
        "Ich habe Deine Eingabe nur bis zu '" + tstring + "' verstanden.";
        fridge.message(parserMessage);  
        // needed by JavaCC-generated static code:
        ReInit(System.in); 
      }
    }
    // shutdown fridge
    fridge.finish(); 
  }
}

PARSER_END(FridgeParser)


// Lexer definition
SKIP :
{
  " "
| "\r"
| "\t"
}

TOKEN :
{ // fixed tokens (reserved words)
  < AUF : "auf" >
| < BERECHNE :
    "berechne"
  | "berechnen" >
| < BESTAND :
    "bestand"
  | "inhalt" >
| < DOT : "." >
| < EINKAUFSLISTE : "einkaufsliste" >
| < ENDE :
    "schluss"
  | "aus"
  | "ende"
  | "beenden"
  | "beende"
  | "tsch\u00fcss" >
| < ES : "es" >
| < IST : "ist" >
| < LF : "\n" >
| < MINUS : "-" >
| < PLUS : "+" >
| < QM : "?" >
| < SPAET : "sp\u00e4t" >
| < WIE : "wie" >
| < WIEDERSEHEN : "wiedersehen" >
| < WIEVIEL : "wieviel" >
// preterminal symbols
|  < PRODUKT : (<LETTER>)+ >
| < NUM :
    (< DIGIT >)+
    (
      ( "." | "," ) (< DIGIT >)+
    )? >
// open class for letters in product names
|  < #LETTER : ["a"-"z", "A"-"Z", "\u00c0"-"\u00ff"] >
|  < #DIGIT : ["0"-"9"] >
}


void Input() :
/* parses [Command_or_Question() (?|.)] <LF> */
{ // variable initialization
}
{ // RHS
  (
    (
      Command_or_Question()
      (
        < DOT >
      | < QM >
      )?
      < LF >
    )+
  | 
    ( // special handling of exit commands:
      < ENDE >
    | < AUF > < WIEDERSEHEN >
    | < EOF >
    )
    {
      quit = true;
    }
  )
  { // post action 
    if (quit) {
      return;
    }
  }
}


void Command_or_Question() :
{
  Token prod = null;
}
{
 (   
     ( < WIE > < SPAET > < IST > < ES > )
  {
    fridge.printTime();
  }
 
  |  ( < BERECHNE > Expr() )
  |  ( < BESTAND > [ prod = < PRODUKT > ] )
  {
    // TODO fertig implementieren
    fridge.listStock(prod);
  }
    /* TODO weitere Eingabemuster hier einfuegen (s. Tabelle Uebungsblatt)
       ggf. Regelstruktur wegen gemeinsamer Praefix-Tokens wie z.B. "Wieviel"
       Achtung: spezielle Regel fuer alle Fragen, die mit wieviel beginnen.
       Praefix muss eindeutig sein, sonst generiert JavaCC eine Fehlermeldung,
       Konflikt.
    */
 )
}


void Expr() :  
/* chain calculation rule; parse <NUM> ( (+|-) <NUM> )* */
{ // variable initialization
}
{ // RHS
    <NUM>  // TODO fertig implementieren
  } 



// ggf. weitere Regeln implementieren
 