/**
 *
 */
options {
  MULTI=true;
  VISITOR=true;
  NODE_DEFAULT_VOID=true;
  STATIC=false;
}

PARSER_BEGIN(PointcutExpressionParser)
package org.jboss.aop.pointcut.ast;

import java.lang.reflect.Modifier;

public class PointcutExpressionParser {
  public static void main(String args[]) {
    System.out.println("Reading from standard input...");
    PointcutExpressionParser t = new PointcutExpressionParser(System.in);
    try {
      ASTStart n = t.Start();
      //PointcutExpressionParserVisitor v = new PointcutExpressionDumpVisitor();
      //n.jjtAccept(v, null);
    } catch (Exception e) {
      System.out.println("Oops.");
      System.out.println(e.getMessage());
      e.printStackTrace();
    }
  }
}

PARSER_END(PointcutExpressionParser)


SKIP :
{
  " "
| "\t"
}

TOKEN : /* IDENTIFIERS */
{
< AND: ["A","a"]["N","n"]["D","d"] >
| < OR:  ["O","o"]["R","r"] >
| < CALL: "call(" > : BEHAVIOR
| < ALL: "all(" >  : FIELD_DECLARATION
| < EXECUTION: "execution(" > : BEHAVIOR
| < CONSTRUCTION: "construction(" > : BEHAVIOR
| < HAS: "has(" > : BEHAVIOR
| < HAS_FIELD: "hasfield(" > : FIELD_DECLARATION
| < GET: "get(" > : FIELD_DECLARATION
| < SET: "set(" > : FIELD_DECLARATION
| < FIELD: "field(" > : FIELD_DECLARATION
| < WITHIN: "within(" > : FIELD_DECLARATION
| < WITHINCODE: "withincode(" > : BEHAVIOR
| < POINTCUT: <POINTCUT_IDENTIFIER> (<POINTCUT_DOT> <POINTCUT_IDENTIFIER>)*>
| < POINTCUT_IDENTIFIER: (<POINTCUT_WILD_LETTER>)+ >
|
  < #POINTCUT_WILD_LETTER: ["_","a"-"z","A"-"Z","0"-"9"] >
|
  < #POINTCUT_DOT: ["."] >
| <NOT: "!">
}

<PARAMS> SKIP :
{
  " "
| "\t"
}

<PARAMS> TOKEN:
{
  < ALL_PARAMS: ".." >
|
  < PARAM_CLASS: <PARAM_IDENTIFIER> (<PARAM_DOT> <PARAM_IDENTIFIER>)+ (<PARAM_ARRAY>)*>
|
  < PARAM_ARRAY_CLASS: <PARAM_IDENTIFIER> (<PARAM_ARRAY>)+>
|
  < PARAM_ANNOTATION: "@" <PARAM_IDENTIFIER> (<PARAM_DOT> <PARAM_IDENTIFIER>)* >
|
  < PARAM_INSTANCEOF: "$instanceof{" (<PARAM_IDENTIFIER> | <PARAM_CLASS> | <PARAM_ANNOTATION>) "}">
|
  < PARAM_TYPEDEF: "$typedef{" <POINTCUT> "}">
|
  < PARAM_IDENTIFIER: (<PARAM_WILD_LETTER>)+ >
|
  < COMMA: "," >
|
  < #PARAM_WILD_LETTER: ["$", "*","_","a"-"z","A"-"Z","0"-"9"] >
|
  < #PARAM_DOT: ["."] >
|
  < #PARAM_ARRAY: "[]" >
| <PARAMS_CLOSE: ")"> : BEHAVIOR
}


<BEHAVIOR> SKIP :
{
  " "
| "\t"
}

<BEHAVIOR> TOKEN : /* IDENTIFIERS */
{
  < ABSTRACT: "abstract" >
| < FINAL: "final" >
| < PRIVATE: "private" >
| < PROTECTED: "protected" >
| < PUBLIC: "public" >
| < STATIC: "static" >
| < NATIVE: "native" >
| < SYNCHRONIZED: "synchronized" >
| < NEW: "new" >
| < THROWS: "throws" >
|
  < INSTANCEOF: "$instanceof{" (<IDENTIFIER> | <CLASS> | <ANNOTATION>) "}">
|
  < TYPEDEF: "$typedef{" <POINTCUT> "}">
|
  < CLASS: <IDENTIFIER> (<DOT> <IDENTIFIER>)+ (<ARRAY>)*>
| 
  < PACKAGE: <IDENTIFIER> (<DOT> <IDENTIFIER>)* <DOT><DOT>>
| 
  < EXCEPTION_SEPERATOR: "," >
|
  < ARRAY_CLASS: <IDENTIFIER> (<ARRAY>)+>
|
  < ANNOTATION: "@" <IDENTIFIER> (<DOT> <IDENTIFIER>)*>
|
  <IMPLEMENTS: "$implements{" (<IDENTIFIER> | <CLASS> | <ANNOTATION>) "}">
|
  <IMPLEMENTING: "$implementing{" (<IDENTIFIER> | <CLASS> | <ANNOTATION>) "}">
|
  < IDENTIFIER: (<WILD_LETTER>)+ >
|
  < #WILD_LETTER: ["$","*","_","a"-"z","A"-"Z","0"-"9"] >
|
  < #DOT: ["."] >
|
  < #ARRAY: "[]" >
| < SEPARATOR: "->" >
| <BEHAVIOR_NOT: "!">
| < PARAMS_OPEN: "("> : PARAMS
| <BEHAVIOR_CLOSE: ")"> : DEFAULT
}

<FIELD_DECLARATION> SKIP :
{
  " "
| "\t"
}

<FIELD_DECLARATION> TOKEN : /* IDENTIFIERS */
{
  < FIELD_ABSTRACT: "abstract" >
| < FIELD_FINAL: "final" >
| < FIELD_PRIVATE: "private" >
| < FIELD_PROTECTED: "protected" >
| < FIELD_PUBLIC: "public" >
| < FIELD_STATIC: "static" >
| < FIELD_TRANSIENT: "transient" >
| < FIELD_NATIVE: "native" >
| < FIELD_SYNCHRONIZED: "synchronized" >
|
  < FIELD_INSTANCEOF: "$instanceof{" (<FIELD_IDENTIFIER> | <FIELD_CLASS> | <FIELD_ANNOTATION>) "}">
|
  < FIELD_TYPEDEF: "$typedef{" <POINTCUT> "}">
|
  < FIELD_CLASS: <FIELD_IDENTIFIER> (<FIELD_DOT> <FIELD_IDENTIFIER>)+ (<FIELD_ARRAY>)*>
| 
  < FIELD_PACKAGE: <FIELD_IDENTIFIER> (<FIELD_DOT> <FIELD_IDENTIFIER>)* <FIELD_DOT><FIELD_DOT>>
|
  < FIELD_ARRAY_CLASS: <FIELD_IDENTIFIER> (<FIELD_ARRAY>)+>
|
  < FIELD_ANNOTATION: "@" <FIELD_IDENTIFIER> (<FIELD_DOT> <FIELD_IDENTIFIER>)* >
|
  < FIELD_IDENTIFIER: (<FIELD_WILD_LETTER>)+ >
|
  < #FIELD_WILD_LETTER: ["$","*","_","a"-"z","A"-"Z","0"-"9"] >
|
  < #FIELD_DOT: ["."] >
|
  < #FIELD_ARRAY: "[]" >
| < FIELD_SEPARATOR: "->" >
| < FIELD_NOT: "!" >
| <FIELD_CLOSE: ")"> : DEFAULT
}

ASTStart Start() #Start : {}
{
  Expression() <EOF>
  { return jjtThis; }
}

ASTExecution execution() #ExecutionOnly : {}
{
  Execution() <EOF>
  { return (ASTExecution)jjtThis.jjtGetChild(0); }
}

void Expression() #void : {}
{
  LOOKAHEAD(234234234) BooleanExpression() | Concrete() |  Not()
}

void BooleanExpression() #Boolean : {}
{
   LOOKAHEAD(3) SubExpression() | LOOKAHEAD(3) CompositeExpression()
}

void CompositeExpression() #Composite : {}
{
   "(" SubExpression() ")"
}

void Not() #Not : {}
{
   <NOT> (LOOKAHEAD(3) ConcreteExpression() | LOOKAHEAD(3) CompositeExpression())
}

void SubExpression() #Sub : {}
{
  (LOOKAHEAD(3) Not() | LOOKAHEAD(3) ConcreteExpression() | LOOKAHEAD(3) CompositeExpression() ) ( And() | Or())+
}

void And() #And : {}
{
  <AND> (LOOKAHEAD(3) ConcreteExpression() | LOOKAHEAD(3) CompositeExpression() | LOOKAHEAD(3) Not())
}

void Or() #Or : {}
{
  <OR> (LOOKAHEAD(3) ConcreteExpression() | LOOKAHEAD(3) CompositeExpression() | LOOKAHEAD(3) Not())
}

ASTCFlowExpression CFlowExpression() #CFlowExpression : {}
{
  (LOOKAHEAD(3) CFlowBoolean() | LOOKAHEAD(3) CFlow() |  LOOKAHEAD(3) NotCFlow()) <EOF>
  { return jjtThis; }
}

void CFlowBoolean() #CFlowBoolean : {}
{
   CompositeCFlow()
}

void NotCFlow() #NotCFlow : {}
{
   <NOT> (LOOKAHEAD(3) CFlow() | LOOKAHEAD(3) CompositeCFlow())
}

void CompositeCFlow() #CompositeCFlow : {}
{
   "(" SubCFlow() ")"
}

void SubCFlow() #SubCFlow : {}
{
   (LOOKAHEAD(3) NotCFlow() | LOOKAHEAD(3) CFlow()) ( AndCFlow() | OrCFlow())+
}

void AndCFlow() #AndCFlow : {}
{
  <AND> (LOOKAHEAD(3) CFlow() | LOOKAHEAD(3) CompositeCFlow())
}

void OrCFlow() #OrCFlow : {}
{
  <OR> (LOOKAHEAD(3) CFlow() | LOOKAHEAD(3) CompositeCFlow())
}

void ConcreteExpression() #void : {}
{
  Concrete()
}

void Concrete() #void : {}
{
   ( LOOKAHEAD(4) Call() | LOOKAHEAD(4) Within() | LOOKAHEAD(4) Withincode() | LOOKAHEAD(4) Execution() | LOOKAHEAD(4) Construction() | LOOKAHEAD(4) Set() | LOOKAHEAD(4) Get() | LOOKAHEAD(4) FieldExecution() | LOOKAHEAD(4) Pointcut() | LOOKAHEAD(4) All()| LOOKAHEAD(4) Has()| LOOKAHEAD(4) HasField())
}

void Pointcut() #Pointcut :
{
  Token pointcut;
}
{
   pointcut=<POINTCUT>
   {
      jjtThis.setPointcutName(pointcut.image);
   }
}

void CFlow() #CFlow :
{
  Token pointcut;
}
{
   pointcut=<POINTCUT>
   {
      jjtThis.setPointcutName(pointcut.image);
   }
}

void All() #All :
{
  Token pointcut;
}
{
   <ALL>

   (pointcut=<FIELD_CLASS>|pointcut=<FIELD_PACKAGE>|pointcut=<FIELD_IDENTIFIER>|pointcut=<FIELD_ANNOTATION>|pointcut=<FIELD_INSTANCEOF>|pointcut=<FIELD_TYPEDEF>)
   {
      jjtThis.setClassExpression(pointcut.image);
   }

   <FIELD_CLOSE>
}

void Call() #Call : {}
{
   <CALL> (LOOKAHEAD(4) Method() | LOOKAHEAD(4) Constructor()) <BEHAVIOR_CLOSE>
}

void Within() #Within :
{
   Token clazz;
}
{
  <WITHIN>
  (clazz=<FIELD_CLASS> | clazz=<FIELD_PACKAGE> | clazz=<FIELD_IDENTIFIER> | clazz=<FIELD_ANNOTATION> | clazz=<FIELD_INSTANCEOF>| clazz=<FIELD_TYPEDEF>)
  <FIELD_CLOSE>
   { jjtThis.setClassExpression(clazz.image); }
}

void Withincode() #Withincode : {}
{
   <WITHINCODE> (LOOKAHEAD(3) Method() | LOOKAHEAD(3) Constructor()) <BEHAVIOR_CLOSE>
}

void Execution() #Execution : {}
{
   <EXECUTION> (LOOKAHEAD(3) Method() | LOOKAHEAD(3) Constructor()) <BEHAVIOR_CLOSE>
}

void Construction() #Construction : {}
{
   <CONSTRUCTION> (Constructor()) <BEHAVIOR_CLOSE>
}

void Has() #Has : {}
{
   <HAS> (LOOKAHEAD(4) Method() | LOOKAHEAD(4) Constructor()) <BEHAVIOR_CLOSE>
}

void HasField() #HasField : {}
{
   <HAS_FIELD> Field() <FIELD_CLOSE>
}

void Get() #Get : {}
{
   <GET> Field() <FIELD_CLOSE>
}

void Set() #Set : {}
{
   <SET> Field() <FIELD_CLOSE>
}

void FieldExecution() #FieldExecution : {}
{
   <FIELD> Field() <FIELD_CLOSE>
}


void Method() #Method :
{
  Token ret, clazz, body;
}
{
  (Attribute())* (ret=<CLASS>|ret=<IDENTIFIER>|ret=<ANNOTATION>|ret=<ARRAY_CLASS>|ret=<INSTANCEOF>|ret=<TYPEDEF>) (clazz=<CLASS>|clazz=<PACKAGE>|clazz=<IDENTIFIER>|clazz=<ANNOTATION>|clazz=<INSTANCEOF>|clazz=<TYPEDEF>) <SEPARATOR> (body=<IDENTIFIER>|body=<ANNOTATION>|body=<IMPLEMENTS>|body=<IMPLEMENTING>) Parameters() Throws()
  {
    jjtThis.setReturnTypeExpression(ret.image);
    jjtThis.setClassExpression(clazz.image);
    jjtThis.setMethodExpression(body.image);
  }
}

void Throws() #void : {}
{
   (<THROWS> Exception() (<EXCEPTION_SEPERATOR> Exception())*)?
}

void Exception() #Exception: 
{
   Token ex;
}
{
	(ex=<CLASS> | ex=<IDENTIFIER>)
	{
		jjtThis.setTypeExpression(ex.image);
	}
}

void Attribute() #Attribute :
{
}
{
  [<BEHAVIOR_NOT> { jjtThis.not=true; } ]
  (<PUBLIC> { jjtThis.setValue(Modifier.PUBLIC); } | <PROTECTED> { jjtThis.setValue(Modifier.PROTECTED); } | <PRIVATE> { jjtThis.setValue(Modifier.PRIVATE); } | <STATIC> { jjtThis.setValue(Modifier.STATIC); } | <ABSTRACT> { jjtThis.setValue(Modifier.ABSTRACT); } | <FINAL> { jjtThis.setValue(Modifier.FINAL); } | <NATIVE> { jjtThis.setValue(Modifier.NATIVE); } | <SYNCHRONIZED> { jjtThis.setValue(Modifier.SYNCHRONIZED); })
}

void Constructor() #Constructor :
{
  Token clazz, danew;
}
{
  (ConstructorAttribute())* (clazz=<CLASS> | clazz=<PACKAGE> | clazz=<IDENTIFIER> | clazz=<ANNOTATION> | clazz=<INSTANCEOF> | clazz=<TYPEDEF>)
  {
    jjtThis.setClassExpression(clazz.image);
  }
  <SEPARATOR> (danew=<NEW> | danew=<ANNOTATION>) Parameters() Throws()
  {
    jjtThis.setNewExpression(danew.image);
  }
}

void ConstructorAttribute() #Attribute :
{
}
{
  <PUBLIC> { jjtThis.setValue(Modifier.PUBLIC); } | <PROTECTED> { jjtThis.setValue(Modifier.PROTECTED); } | <PRIVATE> { jjtThis.setValue(Modifier.PRIVATE); }
}

void Parameters() #void :
{
}
{
   (LOOKAHEAD(3) <PARAMS_OPEN> AllParams()<PARAMS_CLOSE> | LOOKAHEAD(3) <PARAMS_OPEN> [Parameter() ( <COMMA> Parameter() )* ] <PARAMS_CLOSE>)
}

void Parameter() #Parameter :
{
  Token t;
}
{
  (t=<ALL_PARAMS> | t=<PARAM_CLASS> | t=<PARAM_IDENTIFIER> | t=<PARAM_ARRAY_CLASS> | t=<PARAM_ANNOTATION> | t=<PARAM_TYPEDEF> | t=<PARAM_INSTANCEOF>)
  {
    jjtThis.setTypeExpression(t.image);
  }
}

void AllParams() #AllParameter :
{
}
{
   <ALL_PARAMS>
}

void Field() #Field :
{
  Token type, clazz, body;
}
{
  (FieldAttribute())*
  (type=<FIELD_CLASS> | type=<FIELD_IDENTIFIER> | type=<FIELD_ANNOTATION> | type=<FIELD_ARRAY_CLASS>| type=<FIELD_INSTANCEOF> | type=<FIELD_TYPEDEF>)
  {
    jjtThis.setTypeExpression(type.image);
  }
  (clazz=<FIELD_CLASS> | clazz=<FIELD_PACKAGE> | clazz=<FIELD_IDENTIFIER> | clazz=<FIELD_ANNOTATION> | clazz=<FIELD_INSTANCEOF> | clazz=<FIELD_TYPEDEF>)
  {
    jjtThis.setClassExpr(clazz.image);
  }
  <FIELD_SEPARATOR>
  (body=<FIELD_IDENTIFIER> | body=<FIELD_ANNOTATION>)
  {
    jjtThis.setFieldExpr(body.image);
  }
}

void FieldAttribute() #Attribute :
{
}
{
  [<FIELD_NOT> { jjtThis.not = true; }]
  (<FIELD_PUBLIC> { jjtThis.setValue(Modifier.PUBLIC); } | <FIELD_PROTECTED> { jjtThis.setValue(Modifier.PROTECTED); } | <FIELD_PRIVATE> { jjtThis.setValue(Modifier.PRIVATE); } | <FIELD_STATIC> { jjtThis.setValue(Modifier.STATIC); } | <FIELD_FINAL> { jjtThis.setValue(Modifier.FINAL); } | <FIELD_TRANSIENT> { jjtThis.setValue(Modifier.TRANSIENT); } )
}




