options {
  STATIC = false;
  JAVA_UNICODE_ESCAPE = true;
}

PARSER_BEGIN(Parser)
import edu.neu.ccs.demeter.*;
public class Parser { 
  // oit is uugly.  Why isn't there a Character.valueOf(String)? 
  static char unescapifyChar(String s) { 
    char c = s.charAt(0); 
    if (c == '\\') { 
      switch (s.charAt(1)) { 
      case 'n': c = '\n'; break; 
      case 't': c = '\t'; break; 
      case 'b': c = '\b'; break; 
      case 'r': c = '\r'; break; 
      case 'f': c = '\f'; break; 
      case '\\': c = '\\'; break; 
      case '\'': c = '\''; break; 
      case '\"': c = '\"'; break; 
      default: 
       c = (char) Integer.parseInt(s.substring(1, s.length()), 8); 
       break; 
      } 
    } 
    return c; 
  } 
  // Even uglier... 
  static String unescapify(String s) { 
    char str[] = new char[s.length()]; 
    int i = 0, o = 0; 
    while (i < s.length()) { 
      char c = s.charAt(i++); 
      if (c == '\\') { 
       int j = i + 1; 
       while (j < s.length() && 
              Character.digit(s.charAt(j), 8) != -1) { 
         j++; 
       } 
       c = unescapifyChar(s.substring(i-1, j)); 
       i = j; 
      } 
      str[o++] = c; 
    } 
    return String.valueOf(str, 0, o); 
  } 
} 

PARSER_END(Parser)

Main _Main() : {
  Main it = null;
} {
  { it=new Main(); }
  { return it; }
}

MAX_CSP_Products _MAX_CSP_Products() : {
  MAX_CSP_Products it = null;
  MAX_CSP_List _max_csp_list;
} {
  { it=new MAX_CSP_Products(); }
  _max_csp_list=_MAX_CSP_List() { it.set_max_csp_list(_max_csp_list); }
  <EOF>
  { return it; }
}

MAX_CSP _MAX_CSP() : {
  MAX_CSP it = null;
  TransitionRules _transitionrules;
  TransitionManager _transitionmanager;
} {
  { it=new MAX_CSP(); }
  "MAX-CSP"  _transitionrules=_TransitionRules() { it.set_transitionrules(_transitionrules); }
  _transitionmanager=_TransitionManager() { it.set_transitionmanager(_transitionmanager); }
  { return it; }
}

TransitionRules _TransitionRules() : {
  TransitionRules it = null;
  Decide _decide;
  UP _up;
  Reduce _reduce;
  SSR _ssr;
  Restart _restart;
  Finale _finale;
  Update _update;
} {
  { it=new TransitionRules(); }
  _decide=_Decide() { it.set_decide(_decide); }
  _up=_UP() { it.set_up(_up); }
  _reduce=_Reduce() { it.set_reduce(_reduce); }
  [  _ssr=_SSR() { it.set_ssr(_ssr); }  ]
  _restart=_Restart() { it.set_restart(_restart); }
  _finale=_Finale() { it.set_finale(_finale); }
  _update=_Update() { it.set_update(_update); }
  { return it; }
}

Decide _Decide() : {
  Decide it = null;
  Order _order;
} {
  { it=new Decide(); }
  "decide"  _order=_Order() { it.set_order(_order); }
  { return it; }
}

Order _Order() : {
  Order it = null;
} {
  ( it=_ValueOrder() | it=_VariableOrder() )
  { return it; }
}

void common_Order(Order it) : {
} {
  { }
}

ValueOrder _ValueOrder() : {
  ValueOrder it = null;
  VOKind _kind;
} {
  { it=new ValueOrder(); }
  "valueOrder"  _kind=_VOKind() { it.set_kind(_kind); }
  common_Order(it)
  { return it; }
}

VOKind _VOKind() : {
  VOKind it = null;
} {
  ( it=_Random() | it=_LookAheadPolynomial() )
  { return it; }
}

void common_VOKind(VOKind it) : {
} {
  { }
}

VariableOrder _VariableOrder() : {
  VariableOrder it = null;
  LookAheadPolynomial _lookaheadpolynomial;
} {
  { it=new VariableOrder(); }
  "variableOrder"  _lookaheadpolynomial=_LookAheadPolynomial() { it.set_lookaheadpolynomial(_lookaheadpolynomial); }
  common_Order(it)
  { return it; }
}

LookAheadPolynomial _LookAheadPolynomial() : {
  LookAheadPolynomial it = null;
} {
  { it=new LookAheadPolynomial(); }
  "look-ahead"  common_VOKind(it)
  { return it; }
}

Random _Random() : {
  Random it = null;
} {
  { it=new Random(); }
  "random"  common_VOKind(it)
  { return it; }
}

UP _UP() : {
  UP it = null;
  ImplicationGraph _implicationgraph;
} {
  { it=new UP(); }
  "up"  [  _implicationgraph=_ImplicationGraph() { it.set_implicationgraph(_implicationgraph); }  ]
  { return it; }
}

SSR _SSR() : {
  SSR it = null;
  ImplicationGraph _implicationgraph;
} {
  { it=new SSR(); }
  "ssr"  [  _implicationgraph=_ImplicationGraph() { it.set_implicationgraph(_implicationgraph); }  ]
  { return it; }
}

ImplicationGraph _ImplicationGraph() : {
  ImplicationGraph it = null;
} {
  { it=new ImplicationGraph(); }
  "implicationGraph"  { return it; }
}

Reduce _Reduce() : {
  Reduce it = null;
} {
  { it=new Reduce(); }
  "reduce"  { return it; }
}

Restart _Restart() : {
  Restart it = null;
} {
  { it=new Restart(); }
  "restart"  { return it; }
}

Finale _Finale() : {
  Finale it = null;
} {
  { it=new Finale(); }
  "finale"  { return it; }
}

Update _Update() : {
  Update it = null;
} {
  { it=new Update(); }
  "update"  { return it; }
}

TransitionManager _TransitionManager() : {
  TransitionManager it = null;
} {
  { it=new TransitionManager(); }
  "transitionManager"  { return it; }
}

MAX_CSP_List _MAX_CSP_List() : {
  MAX_CSP_List it = null;
  Nonempty_MAX_CSP_List _first;
} {
  { it=new MAX_CSP_List(); }
  [  _first=_Nonempty_MAX_CSP_List() { it.set_first(_first); }  ]
  { return it; }
}

Nonempty_MAX_CSP_List _Nonempty_MAX_CSP_List() : {
  Nonempty_MAX_CSP_List it = null;
  MAX_CSP _it;
  Nonempty_MAX_CSP_List _next;
} {
  { it=new Nonempty_MAX_CSP_List(); }
  _it=_MAX_CSP() { it.set_it(_it); }
  [  _next=_Nonempty_MAX_CSP_List() { it.set_next(_next); }  ]
  { return it; }
}


boolean _boolean() : { Token t; }{
  ( t=<TRUE> { return true; }
  | t=<FALSE> { return false; }
  )
}

char _char() : { Token t; } {
    t=<CHARACTER_LITERAL> { 
       String s = t.image; 
       return unescapifyChar(s.substring(1, s.length()-1)); 
    } 
} 

byte _byte() : { int i; } 
{ i=_int() { return (byte) i; } } 

short _short() : { int i; } 
{ i=_int() { return (short) i; } } 

int _int() : { Number num; } 
{ num=_Number() { return num.intValue(); } } 

long _long() : { Number num; } 
{ num=_Number() { return num.longValue(); } } 

float _float() : { Number num; } 
{ num=_Number() { return num.floatValue(); } } 

double _double() : { Number num; } 
{ num=_Number() { return num.doubleValue(); } } 

Boolean _Boolean() : { Token t; }{
  ( t=<TRUE> { return Boolean.TRUE; }
  | t=<FALSE> { return Boolean.FALSE; }
  )
}

Character _Character() : { char c; } 
{ c=_char() { return new Character(c); } }

Integer _Integer() : { int i; } 
{ i = _int() { return new Integer(i); } }

Long _Long() : { long l; } 
{ l=_long() { return new Long(l); } } 

Float _Float() : { float f; } 
{ f=_float() { return new Float(f); } } 

Double _Double() : { double d; } 
{ d=_double() { return new Double(d); } } 

Number _Number() : 
{
    Token t; 
    String s = null; 
    int radix = 0; 
    Number num = null; 
} {
  ( 
    ( t=<DECIMAL_LITERAL> { 
       s = t.image; 
       radix = 10; 
      } 
    | t=<HEX_LITERAL> { 
       // Strip off the "0x". 
       s = t.image.substring(2, t.image.length()); 
       radix = 16; 
      } 
    | t=<OCTAL_LITERAL> { 
       s = t.image; 
       radix = 8; 
      } 
    ) { 
       switch (s.charAt(s.length()-1)) { 
       case 'l': case 'L': 
         s = s.substring(0, s.length()-1);
         num = new Long(new java.math.BigInteger(s, radix).longValue());
         break; 
       default: 
         num = new Integer(new java.math.BigInteger(s, radix).intValue());
         break; 
       } 
    } 
  | t=<FLOATING_POINT_LITERAL> { 
       s = t.image; 
       switch (s.charAt(s.length()-1)) { 
       case 'd': case 'D': 
           num = Double.valueOf(s.substring(0, s.length()-1)); 
           break; 
       case 'f': case 'F': 
           num = Float.valueOf(s.substring(0, s.length()-1)); 
           break; 
       default: 
           num = Float.valueOf(s); 
           break; 
       } 
    } 
  ) { return num; } 
} 

String _String() : { Token t; } {
    t=<STRING_LITERAL> { 
       String s = t.image; 
       return unescapify(s.substring(1, s.length()-1)); 
    } 
} 

StringBuffer _StringBuffer() : { String s; } 
{ s=_String() { return new StringBuffer(s); } }

Ident _Ident() : { Token t; } {
    t=<IDENTIFIER> { 
       return new Ident(t.image); 
    } 
} 

Text _Text() : { Token t; } {
    t=<TEXT_LITERAL> { 
       String s = t.image; 
       return new Text(s.substring(2, s.length()-2)); 
    } 
} 

Line _Line() : { Token t; } {
    { token_source.SwitchTo(1); } 
    t=<LINE> { 
       return new Line(t.image); 
    } 
} 

Word _Word() : { Token t; } {
    { token_source.SwitchTo(2); } 
    t=<WORD> { 
       return new Word(t.image); 
    } 
} 

// Lexical specification (largely taken from Java.jack): 

SKIP : {
  " " 
| "\t" 
| "\n" 
| "\r" 
| <"//" (~["\n","\r"])* ("\n"|"\r\n")> 
| <"/*" (~["*"])* "*" (~["/"] (~["*"])* "*")* "/"> 
} 
 
TOKEN : { /* LITERALS */
  < DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* (["l","L"])? > 
| 
  < HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ (["l","L"])? > 
| 
  < OCTAL_LITERAL: "0" (["0"-"7"])* (["l","L"])? > 
| 
  < FLOATING_POINT_LITERAL: 
        (["0"-"9"])+ "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])? 
      | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])? 
      | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])? 
      | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"] 
  > 
| 
  < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > 
| 
  < CHARACTER_LITERAL: 
      "'" 
      (   (~["\'","\\","\n","\r"]) 
        | ("\\" 
            ( ["n","t","b","r","f","\\","\'","\""] 
            | ["0"-"7"] ( ["0"-"7"] )? 
            | ["0"-"3"] ["0"-"7"] ["0"-"7"] 
            ) 
          ) 
      ) 
      "'" 
  >   
| 
  < STRING_LITERAL: 
      "\"" 
      (   (~["\"","\\","\n","\r"]) 
        | ("\\" 
            ( ["n","t","b","r","f","\\","\'","\""] 
            | ["0"-"7"] ( ["0"-"7"] )? 
            | ["0"-"3"] ["0"-"7"] ["0"-"7"] 
            ) 
          ) 
      )* 
      "\"" 
  > 
| 
  < TEXT_LITERAL: 
     ( "(@" 
           (~["@"])* 
           ( "@" ~[")"] 
             (~["@"])* 
           )* 
      "@)" ) 
    | ( "{{" 
           (~["}"])* 
           ( "}" ~["}"] 
             (~["}"])* 
           )* 
      "}}" ) 
  > 
| 
  < TRUE: "true" >
| 
  < FALSE: "false" >
} 

TOKEN : { /* IDENTIFIERS */ 
  < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* >
|
  < #LETTER:
      [
       "\u0024",
       "\u0041"-"\u005a",
       "\u005f",
       "\u0061"-"\u007a",
       "\u00c0"-"\u00d6",
       "\u00d8"-"\u00f6",
       "\u00f8"-"\u00ff",
       "\u0100"-"\u1fff",
       "\u3040"-"\u318f",
       "\u3300"-"\u337f",
       "\u3400"-"\u3d2d",
       "\u4e00"-"\u9fff",
       "\uf900"-"\ufaff"
      ]
  >
|
  < #DIGIT:
      [
       "\u0030"-"\u0039",
       "\u0660"-"\u0669",
       "\u06f0"-"\u06f9",
       "\u0966"-"\u096f",
       "\u09e6"-"\u09ef",
       "\u0a66"-"\u0a6f",
       "\u0ae6"-"\u0aef",
       "\u0b66"-"\u0b6f",
       "\u0be7"-"\u0bef",
       "\u0c66"-"\u0c6f",
       "\u0ce6"-"\u0cef",
       "\u0d66"-"\u0d6f",
       "\u0e50"-"\u0e59",
       "\u0ed0"-"\u0ed9",
       "\u1040"-"\u1049"
      ]
  >
}

<Line> TOKEN : {
  < LINE: (~["\n","\r"])* > : DEFAULT
}

<Word> SKIP :  { " " | "\t" | "\n" | "\r" }
<Word> TOKEN : {
  < WORD: (~[" ","\t","\n","\r"])* > : DEFAULT
}