/* I know that haing some of these options on one line is rude but 
 * if we don't do that the line number reported from javacc are off
 * which, trust me, is far more annoying.  --tcarroll@bea.com
 */
options {
  JAVA_UNICODE_ESCAPE = false;
  UNICODE_INPUT = true;
  STATIC = false;
  OPTIMIZE_TOKEN_MANAGER = true; MULTI = true; VISITOR = true; NODE_PACKAGE = "org.eclipse.jst.jsp.core.internal.java.jspel"; NODE_SCOPE_HOOK = true;
}

PARSER_BEGIN(JSPELParser)

package org.eclipse.jst.jsp.core.internal.java.jspel;

public class JSPELParser {
  
  void jjtreeOpenNodeScope(Node n)
  {
          ((SimpleNode)n).setFirstToken(getToken(1));
  }

  void jjtreeCloseNodeScope(Node n)
  {
    ((SimpleNode)n).setLastToken(getToken(0));
  }
  
  public static JSPELParser createParser(java.lang.String input) {
          java.io.StringReader reader = new java.io.StringReader(input);
          return new JSPELParser(reader);
  }
  
  public void ReInit(java.lang.String input) {
           java.io.StringReader reader = new java.io.StringReader(input);
           ReInit(reader);
  }
  
}

PARSER_END(JSPELParser)

SKIP :
{
  " "
| "\t"
| "\n"
| "\r"
}

TOKEN :
{
/* Literals */
  < INTEGER_LITERAL: ["0"-"9"] (["0"-"9"])* >
|
  < FLOATING_POINT_LITERAL:
        (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)?
      | "." (["0"-"9"])+ (<EXPONENT>)?
      | (["0"-"9"])+ <EXPONENT>
  >
|
  < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
|
  < STRING_LITERAL:
      ("\"" ((~["\"","\\"]) | ("\\" ( ["\\","\""] )))* "\"") |
      ("\'" ((~["\'","\\"]) | ("\\" ( ["\\","\'"] )))* "\'")
  >
|
  < BADLY_ESCAPED_STRING_LITERAL:
      ("\"" (~["\"","\\"])* ("\\" ( ~["\\","\""] ))) |
      ("\'" (~["\'","\\"])* ("\\" ( ~["\\","\'"] )))
  >

/* Reserved Words and Symbols */
| < TRUE: "true" >
| < FALSE: "false" >
| < NULL: "null" >
| < DOT: "." >
| < GT1: ">" >
| < GT2: "gt" >
| < LT1: "<" >
| < LT2: "lt" >
| < EQ1: "==" >
| < EQ2: "eq" >
| < LE1: "<=" >
| < LE2: "le" >
| < GE1: ">=" >
| < GE2: "ge" >
| < NEQ1: "!=" >
| < NEQ2: "ne" >
| < LPAREN: "(" >
| < RPAREN: ")" >
| < COMMA: "," >
| < COLON: ":" >
| < LBRACKET: "[" >
| < RBRACKET: "]" >
| < PLUS: "+" >
| < MINUS: "-" >
| < MULTIPLY: "*" >
| < DIVIDE1: "/" >
| < DIVIDE2: "div" >
| < MODULUS1: "%" >
| < MODULUS2: "mod" >
| < NOT1: "not" >
| < NOT2: "!" >
| < AND1: "and" >
| < AND2: "&&" >
| < OR1: "or" >
| < OR2: "||" >
| < EMPTY: "empty" >
| < COND: "?" >

/* Identifiers */

| < IDENTIFIER: (<LETTER>|<IMPL_OBJ_START>) (<LETTER>|<DIGIT>)* >
| < #IMPL_OBJ_START: "#" >
|
  < #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"
      ]
  >
}

ASTExpression Expression() : {}
{
        (LOOKAHEAD("?") ChoiceExpression() | OrExpression()) { return jjtThis; }
}

void OrExpression() #OrExpression(>1) : 
{
        Token t;
}
{
        AndExpression() ((t = <OR1> | t = <OR2>) { jjtThis.addOperatorToken(t); }
        AndExpression())*
}

void AndExpression() #AndExpression(>1) : 
{
        Token t;
}
{
        EqualityExpression() ((t = <AND1> | t = <AND2>) { jjtThis.addOperatorToken(t); }
        EqualityExpression())*        
}

void EqualityExpression() #EqualityExpression(>1) : 
{
        Token t;
}
{
        RelationalExpression() 
        ((t = <EQ1> | t = <EQ2> | t = <NEQ1> | t = <NEQ2>) { jjtThis.addOperatorToken(t); }
        RelationalExpression())*
}

void RelationalExpression() #RelationalExpression(>1) :
{
        Token t;
}
{
        AddExpression() 
        (
                (t = <LT1> | t = <LT2> | t = <GT1> | t = <GT2> | t = <GE1> | t = <GE2> | t = <LE1> | t = <LE2>)  { jjtThis.addOperatorToken(t); }
                AddExpression()
        )*
}

void AddExpression() #AddExpression(>1) : 
{
        Token t;
}
{
        MultiplyExpression() ((t = <PLUS> | t = <MINUS>) { jjtThis.addOperatorToken(t); }
        MultiplyExpression())*
}

void MultiplyExpression() #MultiplyExpression(>1) : 
{
        Token t;
}
{
        UnaryExpression() (
                ( t = <MULTIPLY> | t = <DIVIDE1> | t = <DIVIDE2> | t = <MODULUS1> | t = <MODULUS2>) { jjtThis.addOperatorToken(t); }
                UnaryExpression()        
        )*
}

void ChoiceExpression() : {}
{
        OrExpression() <COND> OrExpression() <COLON> OrExpression()
}

void UnaryExpression() : {}
{
        ((<NOT1> | <NOT2> | <MINUS> | <EMPTY>) UnaryExpression())
        | Value()
        
}

void Value() : {}
{
        ValuePrefix() (ValueSuffix())*
}

void ValuePrefix() : {}
{
    Literal() | (<LPAREN> Expression() <RPAREN>) | LOOKAHEAD(3) FunctionInvocation() | <IDENTIFIER> 
}

void ValueSuffix() : 
{
        Token t = null;
}
{
        (<DOT> (t = <IDENTIFIER>)?) { jjtThis.setPropertyNameToken(t); }
        | (<LBRACKET> Expression() <RBRACKET>)
}

void FunctionInvocation() : 
{
        Token prefix = null, name = null;
}
{
    (prefix = <IDENTIFIER> <COLON>) { jjtThis.setFullFunctionName(prefix.image + ":"); }
        (name = <IDENTIFIER>)? {
            if(null != prefix && null != name)
                    jjtThis.setFullFunctionName(prefix.image + ":" + (null == name ? "" : name.image));
            else if(null != name)
                    jjtThis.setFullFunctionName(name.image);
        }
        (<LPAREN> Expression() (<COMMA> Expression())* try  { (<RPAREN>) } catch (Exception e) {} )?
}

void Literal() : {}
{
        <TRUE> | <FALSE> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> | <STRING_LITERAL> | <NULL>
}
