/*@bgen(jjtree) Generated By:JJTree: Do not edit this line. ft.jj */
/*@egen*//**
* JJTree file
*  NODE_PACKAGE = "eu.dnetlib.data.collective.transformation.rulelanguage.node";
*/

options {
  STATIC=false;
               
                 
  JDK_VERSION = "1.6";
}

PARSER_BEGIN(FtScript) 

package eu.dnetlib.data.collective.transformation.rulelanguage.parser;
import eu.dnetlib.data.collective.transformation.rulelanguage.Rules;
public class FtScript/*@bgen(jjtree)*/implements FtScriptTreeConstants/*@egen*/ {/*@bgen(jjtree)*/
  protected JJTFtScriptState jjtree = new JJTFtScriptState();

/*@egen*/
}

PARSER_END(FtScript)

SKIP :
{
  " "
| "\t"
| "\n"
| "\r"
| <"//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>
| <"/*" (~["*"])* "*" (~["/"] (~["*"])* "*")* "/">
}

MORE :
{
  "//" : IN_SINGLE_LINE_COMMENT
}

< IN_SINGLE_LINE_COMMENT >
SPECIAL_TOKEN :
{
  <SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" > : DEFAULT
}

/* RESERVED WORDS AND LITERALS */
// KEYWORDS
TOKEN : {	< IMPORT:            "import" > }
TOKEN : {	< TRANS:             "trans" > }
TOKEN : {	< IF:                "if" > }
TOKEN : {	< ELSE:              "else" > }
TOKEN : {	< END:               "end" > }
TOKEN : {   < EXTRACT:           "Extract" > }
TOKEN : {   < IDENTIFIEREXTRACT: "identifierExtract" > }
TOKEN : {	< CONVERT:           "Convert" > }
TOKEN : {	< REGEXPR:           "RegExpr" > }
TOKEN : {	< GETVALUE:	         "getValue" > }
TOKEN : {   < COPY:              "copy" > }
TOKEN : {   < DECLARE_NAMESPACE: "declare_ns" > }
TOKEN : {   < DECLARE_SCRIPT:    "declare_script" > }
TOKEN : {   < DECLARE_SUBSCRIPT: "declare_subscript" > }
TOKEN : {   < PREPROCESS:        "preprocess" > }
TOKEN : {   < SET:               "set" > }
TOKEN : {   < SKIPRECORD:        "skipRecord" > }
TOKEN : {   < SPLIT:             "split" > }
TOKEN : {   < STATIC:            "static" > }
TOKEN : {   < XPATH_SCHEME:      "xpath:" > }
TOKEN : {   < APPLY:             "apply" > }
TOKEN : {   < EMPTY:             "empty" > }
TOKEN : {   < DBLOOKUP:          "dblookup" > }
TOKEN : {   < BLACKLIST:         "blacklist" > }
TOKEN : {   < LOOKUP:            "lookup" > }
TOKEN : {   < CONCAT:            "concat" > }

// SPEC. CHARS
TOKEN : { < SEMICOLON: ";" > }
TOKEN : { < RBRACKET: "]" > }
TOKEN : { < LBRACE: "{" > }
TOKEN : { < RBRACE: "}" > }
TOKEN : { < COMMA: "," > }
TOKEN : { < RPAREN: ")" > }
TOKEN : { < QUOTE: "'" > }

TOKEN :
{

  < EQUAL:   "="      > |
  < NOTEQUAL:   "!="      > |
  < GT:    " &gt; "  | ">"    > |
  < LT:    " &lt; "  | "<"    > |
  < GTE:   " &gt;= " | ">="    > |
  < LTE:   " &lt;= " | "<="    > |
  < PLUS:   "+"      > |
  < VBAR:   "|"      > |
//  < SLASH_SLASH:  "//"      > |
  < SLASH:   "/"      > |

  < DOT_DOT:      ".."      > |
  //< DOT:     "."      > |

  < AT:     "@"      > |

  < LPAREN: "(" > |
  < LBRACKET: "[" > |
  < DOLLAR_QNAME: "$" <IDENTIFIER>     >  |
  < PERCENT_QNAME: "%" < IDENTIFIER > >

}

TOKEN :
{
  < XPATH:
     < XPATH_SCHEME > <QUOTED_STRING >
  > 
}

TOKEN :
{
  < JOBCONST:
     < JOBCONST_PREFIX > <LETTER_OR_DIGIT> (<LETTER_OR_DIGIT>)* >
|  < #JOBCONST_PREFIX: "$job." >
}

TOKEN:
{
  < QUOTED_STRING: "\""
  (~["\""]
  )+ "\"" >
}

TOKEN:
{
  < SINGLE_QUOTE: "'"
  (~["'"]
  )+ "'" >
}

TOKEN : /* STRING LITERALS*/
{
  < 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"]
           )
        )
    )*
    "\""
  >
}


TOKEN :
{
  < URI:
    < IDENTIFIER > "://" <IDENTIFIER >
    ( "/" < IDENTIFIER > )*  ( "/" )?
  >
}



TOKEN : /* IDENTIFIERS */
{
  < IDENTIFIER:
   ( < AT >|<LETTER_OR_DIGIT>) (<LETTER_OR_DIGIT>|<MINUS>|< DOT >|< COLON >|< AT >)* >
|  < #LETTER_OR_DIGIT: ["_","a"-"z","A"-"Z","0"-"9"] >
|  < #MINUS: "-" >
|  < #DOT: "." >
|  < #COLON: ":" >
//|  < #AT: "@" >
}



ASTStart Start() :{/*@bgen(jjtree) Start */
  ASTStart jjtn000 = new ASTStart(JJTSTART);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) Start */
  try {
/*@egen*/	
  (script())/*@bgen(jjtree)*/
  {
    jjtree.closeNodeScope(jjtn000, true);
    jjtc000 = false;
  }
/*@egen*/
  { return jjtn000; }/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
  }
/*@egen*/
}

/**
 * id = value
 */
void assign(Rules r)           : {/*@bgen(jjtree) MyAssign */
                                  ASTMyAssign jjtn000 = new ASTMyAssign(JJTMYASSIGN);
                                  boolean jjtc000 = true;
                                  jjtree.openNodeScope(jjtn000);
/*@egen*/String value = ""; Token t;}
{/*@bgen(jjtree) MyAssign */
                                                          try {
/*@egen*/
	                                                  {jjtn000.setRule(r);}
         (t = inputField()/*@bgen(jjtree)*/
                                                      {
                                                        jjtree.closeNodeScope(jjtn000, true);
                                                        jjtc000 = false;
                                                      }
/*@egen*/                            {jjtn000.setFieldExpression(t.image);}        
         |value = quotedString()/*@bgen(jjtree)*/
                                                      {
                                                        jjtree.closeNodeScope(jjtn000, true);
                                                        jjtc000 = false;
                                                      }
/*@egen*/                      {jjtn000.setAttribute(value);}
         )/*@bgen(jjtree)*/
                                                          } catch (Throwable jjte000) {
                                                            if (jjtc000) {
                                                              jjtree.clearNodeScope(jjtn000);
                                                              jjtc000 = false;
                                                            } else {
                                                              jjtree.popNode();
                                                            }
                                                            if (jjte000 instanceof RuntimeException) {
                                                              throw (RuntimeException)jjte000;
                                                            }
                                                            if (jjte000 instanceof ParseException) {
                                                              throw (ParseException)jjte000;
                                                            }
                                                            throw (Error)jjte000;
                                                          } finally {
                                                            if (jjtc000) {
                                                              jjtree.closeNodeScope(jjtn000, true);
                                                            }
                                                          }
/*@egen*/
}

void attrib_list()       : {}
{
	<LBRACKET>
	  (attribute())*
	<RBRACKET>
}


void attribute()              : {/*@bgen(jjtree) MyAttribute */
                                 ASTMyAttribute jjtn000 = new ASTMyAttribute(JJTMYATTRIBUTE);
                                 boolean jjtc000 = true;
                                 jjtree.openNodeScope(jjtn000);
/*@egen*/String value; Token t=null;}
{/*@bgen(jjtree) MyAttribute */
        try {
/*@egen*/
	(value = identifier() { jjtn000.setAttributeValue(value);}
	|t = inputField()
	{ value = t.image;
	  jjtn000.setAttributeInputField(value);
	}
	)
	[<COMMA>]/*@bgen(jjtree)*/
        } catch (Throwable jjte000) {
          if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            throw (RuntimeException)jjte000;
          }
          if (jjte000 instanceof ParseException) {
            throw (ParseException)jjte000;
          }
          throw (Error)jjte000;
        } finally {
          if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
          }
        }
/*@egen*/
	
}

/**
 *  a conditional Rule, which contains the condition, the Rule on which the condition holds and the alternative rule
 */
void conditionalStmt()              : {/*@bgen(jjtree) MyCondition */
                                       ASTMyCondition jjtn000 = new ASTMyCondition(JJTMYCONDITION);
                                       boolean jjtc000 = true;
                                       jjtree.openNodeScope(jjtn000);
/*@egen*/Rules r1 = new Rules(); Rules r2 = new Rules(); Token cond; Token apply;}
{/*@bgen(jjtree) MyCondition */
  try {
/*@egen*/
  [< APPLY > apply = inputField()
  {
    jjtn000.setApplyExpression(apply.image);
  } ]
   < IF > cond = inputField() { jjtn000.setConditionalExpression(cond.image); jjtn000.setPrimaryRule(r1); jjtn000.setSecondaryRule(r2); }
    rule(r1)
  < ELSE >
    rule(r2)/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
  }
/*@egen*/
}

void empty(Rules r)          : {/*@bgen(jjtree) MyEmpty */
  ASTMyEmpty jjtn000 = new ASTMyEmpty(JJTMYEMPTY);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) MyEmpty */
                                             try {
/*@egen*/
                                             {jjtn000.setRule(r);}
        < EMPTY >/*@bgen(jjtree)*/
                                             {
                                               jjtree.closeNodeScope(jjtn000, true);
                                               jjtc000 = false;
                                             }
/*@egen*/                            {jjtn000.setEmpty(true);}/*@bgen(jjtree)*/
                                             } finally {
                                               if (jjtc000) {
                                                 jjtree.closeNodeScope(jjtn000, true);
                                               }
                                             }
/*@egen*/        
}

String identifier()       : {Token t;}
{
  t = <IDENTIFIER> {return t.image;}
}

void importDeclaration()           :
{/*@bgen(jjtree) MyImport */
 ASTMyImport jjtn000 = new ASTMyImport(JJTMYIMPORT);
 boolean jjtc000 = true;
 jjtree.openNodeScope(jjtn000);
/*@egen*/String scriptName;}
{/*@bgen(jjtree) MyImport */
  try {
/*@egen*/
  <IMPORT> <LPAREN> scriptName = identifier() <RPAREN> ";"/*@bgen(jjtree)*/
                                                           {
                                                             jjtree.closeNodeScope(jjtn000, true);
                                                             jjtc000 = false;
                                                           }
/*@egen*/ { jjtn000.setScriptName(scriptName); }/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
  }
/*@egen*/
}

Token anyExpression()       : { Token t; }
{
  t = < IDENTIFIER >
  {
    return t;
  }
}

Token inputField()       :{ Token t; }
{
  t =  < XPATH >
  {
    return t;
  }
  | t = < JOBCONST >
  {
    return t;
  }
  | t = < DOLLAR_QNAME >
  {
    return t;
  }
}


/*
 * becomes obsolete
 */
String key()       : {String key;}
{
   key = identifier()                     
   <EQUAL>
   {return key;}
}

void literal()       :
{}
{
  < CHARACTER_LITERAL > | < STRING_LITERAL >
}

void nsDeclaration()       :
{/*@bgen(jjtree) MyNs */
 ASTMyNs jjtn000 = new ASTMyNs(JJTMYNS);
 boolean jjtc000 = true;
 jjtree.openNodeScope(jjtn000);
/*@egen*/String nsPrefix; String nsUri;}
{/*@bgen(jjtree) MyNs */
        try {
/*@egen*/
	< DECLARE_NAMESPACE > nsPrefix = identifier() < EQUAL > nsUri = quotedString() < SEMICOLON >/*@bgen(jjtree)*/
        {
          jjtree.closeNodeScope(jjtn000, true);
          jjtc000 = false;
        }
/*@egen*/
	{
	  jjtn000.setNsDeclaration(nsPrefix, nsUri);
	}/*@bgen(jjtree)*/
        } catch (Throwable jjte000) {
          if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            throw (RuntimeException)jjte000;
          }
          if (jjte000 instanceof ParseException) {
            throw (ParseException)jjte000;
          }
          throw (Error)jjte000;
        } finally {
          if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
          }
        }
/*@egen*/
}

void preprocess()               :{/*@bgen(jjtree) MyPreprocess */
                                  ASTMyPreprocess jjtn000 = new ASTMyPreprocess(JJTMYPREPROCESS);
                                  boolean jjtc000 = true;
                                  jjtree.openNodeScope(jjtn000);
/*@egen*/String preprocessId;}
{/*@bgen(jjtree) MyPreprocess */
  try {
/*@egen*/
  (
    < PREPROCESS >
   preprocessId = identifier() < EQUAL >
   < DBLOOKUP >
    < LPAREN >                     { String sqlExpr; }
      sqlExpr = quotedString()
    < RPAREN >                     { jjtn000.preprocess(preprocessId, "dblookup", sqlExpr); }
  < SEMICOLON >
  ) |
 (
   < BLACKLIST >
   < LPAREN > { String blacklistDataSourceId; }
      blacklistDataSourceId = quotedString()
   < RPAREN >
   { jjtn000.preprocess("blacklist", blacklistDataSourceId); }
   < SEMICOLON >
 )/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
  }
/*@egen*/
}

void set(Rules r)        : {/*@bgen(jjtree) MySet */
                            ASTMySet jjtn000 = new ASTMySet(JJTMYSET);
                            boolean jjtc000 = true;
                            jjtree.openNodeScope(jjtn000);
/*@egen*/Token expr; String value = "";}
{/*@bgen(jjtree) MySet */
  try {
/*@egen*/
  {    jjtn000.setRule(r);  }

  < SET >
        < LPAREN >
        (
          
        expr = inputField()        { jjtn000.setValueExpression(expr.image); }
      | value = quotedString()     { jjtn000.setAttribute(value); }
        )
        (
          < COMMA >
		     {
		       r = new Rules();
		     }
		     rule(r)
		     {
			   jjtn000.addAttributeRule(r);  
			 }
          
        )*
        < RPAREN >/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
  }
/*@egen*/
}

void skip(Rules r)         :{/*@bgen(jjtree) MySkip */
  ASTMySkip jjtn000 = new ASTMySkip(JJTMYSKIP);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) MySkip */
  try {
/*@egen*/
  { jjtn000.setRule(r);  }
	< SKIPRECORD >	                {jjtn000.skipRecord();}
	   < LPAREN >
	   < RPAREN >/*@bgen(jjtree)*/
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
  }
/*@egen*/  
}

void copy(Rules r)         : {/*@bgen(jjtree) MyCopy */
  ASTMyCopy jjtn000 = new ASTMyCopy(JJTMYCOPY);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) MyCopy */
  try {
/*@egen*/
  {    jjtn000.setRule(r);  }
  	   < COPY >
	      < LPAREN >         	        { String templateMatchExpression; String applyTemplateSelectExpression; String copySelectExpression; }
	       templateMatchExpression = quotedString()
	       < COMMA >
	       applyTemplateSelectExpression = quotedString()
	       <  COMMA >
	       copySelectExpression = quotedString()
	      < RPAREN >/*@bgen(jjtree)*/
                                                {
                                                  jjtree.closeNodeScope(jjtn000, true);
                                                  jjtc000 = false;
                                                }
/*@egen*/	                { jjtn000.copy(templateMatchExpression, applyTemplateSelectExpression, copySelectExpression); }/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
  }
/*@egen*/

}

void op(Rules r)       : {/*@bgen(jjtree) MyOp */
                          ASTMyOp jjtn000 = new ASTMyOp(JJTMYOP);
                          boolean jjtc000 = true;
                          jjtree.openNodeScope(jjtn000);
/*@egen*/String functionName = ""; Token expr; Token expr2; Token vocab; String defaultPattern = ""; String function = ""; String elementName = ""; String regExpr; Token feature;}
{/*@bgen(jjtree) MyOp */
                                            try {
/*@egen*/
	                                    {jjtn000.setRule(r);}
	( (<GETVALUE> 
	 <LPAREN>
	   functionName = identifier() <COMMA> attrib_list()
	 <RPAREN>/*@bgen(jjtree)*/
                                            {
                                              jjtree.closeNodeScope(jjtn000, true);
                                              jjtc000 = false;
                                            }
/*@egen*/                           {jjtn000.getValue(functionName);}
	 )	 
	| (<CONVERT> 
	  <LPAREN>
	    expr = inputField()
	    <COMMA>
	    vocab = <IDENTIFIER>
	    (
	      <COMMA>
	      defaultPattern = quotedString()
	      <COMMA>
	      function = quotedString()
	    )*
	  <RPAREN>/*@bgen(jjtree)*/
                                            {
                                              jjtree.closeNodeScope(jjtn000, true);
                                              jjtc000 = false;
                                            }
/*@egen*/                          {jjtn000.convert(expr.image, vocab.image, defaultPattern, function);} 
	  )
	| (< EXTRACT >
	   < LPAREN >
	    feature = < IDENTIFIER >
	   < RPAREN >/*@bgen(jjtree)*/
                                            {
                                              jjtree.closeNodeScope(jjtn000, true);
                                              jjtc000 = false;
                                            }
/*@egen*/                       {jjtn000.extract(feature.image); }
	  )
	| (<REGEXPR>
		<LPAREN>
		expr = inputField()
		<COMMA>
		expr2 = inputField()
		<COMMA>
		regExpr = quotedString()
		<RPAREN>/*@bgen(jjtree)*/
                                                {
                                                  jjtree.closeNodeScope(jjtn000, true);
                                                  jjtc000 = false;
                                                }
/*@egen*/                        {jjtn000.regExpr(expr.image, expr2.image, regExpr);}
	  )
	| (<SPLIT>
	    < LPAREN >
	     expr = inputField()
	     < COMMA >
	     elementName = quotedString()
	     < COMMA >
	     regExpr = quotedString()
        < RPAREN >/*@bgen(jjtree)*/
                                        {
                                          jjtree.closeNodeScope(jjtn000, true);
                                          jjtc000 = false;
                                        }
/*@egen*/                      {jjtn000.split(expr.image, elementName, regExpr);}
	  )
	| ( < LOOKUP >                    	{ String propertyKey; }
         < LPAREN >                     
           expr = inputField()
           < COMMA >
           propertyKey = quotedString()
         < RPAREN >/*@bgen(jjtree)*/
                                        {
                                          jjtree.closeNodeScope(jjtn000, true);
                                          jjtc000 = false;
                                        }
/*@egen*/                     { jjtn000.lookup(expr.image, propertyKey); }
	  )
	| ( < IDENTIFIEREXTRACT >       	{ String xpathExprJsonString; Token xpathExprInputSource; }
	      < LPAREN > 
            // "{//abc, //def }" ?json list of xpath-expr
            // xpath-expr of input source
            // regExpr          
	        xpathExprJsonString = singleQuotedString()
	        < COMMA >
	        xpathExprInputSource = inputField()
	        < COMMA >
	        regExpr = singleQuotedString()            
	      < RPAREN >/*@bgen(jjtree)*/
                                                {
                                                  jjtree.closeNodeScope(jjtn000, true);
                                                  jjtc000 = false;
                                                }
/*@egen*/	                { jjtn000.identifierExtract(xpathExprJsonString, xpathExprInputSource.image, regExpr); }
	  )
	| ( < CONCAT >                    	{ jjtn000.concat();	}
	      < LPAREN >	                { String v; Token t; }
			( v = quotedString() { jjtn000.addConcat(v); }  | t = < DOLLAR_QNAME >			{ jjtn000.addConcat(t.image); }
			)
			(
			  < COMMA >
              (
                v = quotedString() { jjtn000.addConcat(v); } | t = < DOLLAR_QNAME >			{ jjtn000.addConcat(t.image); }
              )
			)*
	      < RPAREN >
	  )
	)/*@bgen(jjtree)*/
                                            } catch (Throwable jjte000) {
                                              if (jjtc000) {
                                                jjtree.clearNodeScope(jjtn000);
                                                jjtc000 = false;
                                              } else {
                                                jjtree.popNode();
                                              }
                                              if (jjte000 instanceof RuntimeException) {
                                                throw (RuntimeException)jjte000;
                                              }
                                              if (jjte000 instanceof ParseException) {
                                                throw (ParseException)jjte000;
                                              }
                                              throw (Error)jjte000;
                                            } finally {
                                              if (jjtc000) {
                                                jjtree.closeNodeScope(jjtn000, true);
                                              }
                                            }
/*@egen*/
}

String leftExprOutputField()       :{ String leftExpr; }
{
  leftExpr = identifier() < EQUAL > { return leftExpr; }
}

String leftExprVar()       :{ String leftExpr; }
{
  leftExpr = variable() <  EQUAL >  { return leftExpr; }
}

String leftExprTemplate()       :{ String leftExpr; }
{
  leftExpr = template() < EQUAL >  { return leftExpr;  }
}

String singleQuotedString()       : { Token t;}
{
  t =
    < SINGLE_QUOTE >
    { return t.image; }
}

String quotedString()       : {Token t;}
{
  t =
    < QUOTED_STRING >
     {return t.image;}
}

void rule(Rules r)       : { String ruleDecl; String leftExpr;}
{
	[  ruleDecl = ruleDecl() { r.setRuleDeclaration(ruleDecl);	} ]
	 (
	   leftExpr = leftExprOutputField()
	   {
	     String[] fieldArray = leftExpr.split("@");
	     r.setTargetField(fieldArray[0]);
	     if (fieldArray.length > 1)
	     {
	       r.setAttribute(fieldArray[1]);
	     }
	   }
	 | leftExpr = leftExprVar()	 {	r.setVariable(leftExpr); }
	 | leftExpr = leftExprTemplate()	 { r.setTemplate(leftExpr);	 }
	 )
     (
 	   LOOKAHEAD(2)
       
       assign(r)
     | op(r)
     | set(r)
     | copy(r)
     | empty(r)
     | skip(r)
     ) < SEMICOLON >  
}

String ruleDecl()       : {Token t;}
{
  (
    t = < STATIC >  
  )
  { return t.image;
  }
}

void script()       :{}
{
	   scriptDeclaration()
	  [ importDeclaration() ]
	  (
	     nsDeclaration()
	   )*
	   (
	     preprocess()
	   )*
	  ( stmt() | conditionalStmt() )*
	  ( <END> <EOF> )
}

void scriptDeclaration()           :
{/*@bgen(jjtree) MyScript */
 ASTMyScript jjtn000 = new ASTMyScript(JJTMYSCRIPT);
 boolean jjtc000 = true;
 jjtree.openNodeScope(jjtn000);
/*@egen*/String scriptName; ASTMyScript.SCRIPTTYPE scriptType;}
{/*@bgen(jjtree) MyScript */
        try {
/*@egen*/

  	(
  	  < DECLARE_SCRIPT >
  	  {
  	    jjtn000.setScriptType(ASTMyScript.SCRIPTTYPE.MAINSCRIPT);
  	  }
  	  | < DECLARE_SUBSCRIPT >
  	  {
  	    jjtn000.setScriptType(ASTMyScript.SCRIPTTYPE.SUBSCRIPT);  	    
  	  }
  	) scriptName = quotedString() < SEMICOLON >/*@bgen(jjtree)*/
        {
          jjtree.closeNodeScope(jjtn000, true);
          jjtc000 = false;
        }
/*@egen*/
  	{
  	  jjtn000.setScript(scriptName);
  	}/*@bgen(jjtree)*/
        } catch (Throwable jjte000) {
          if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            throw (RuntimeException)jjte000;
          }
          if (jjte000 instanceof ParseException) {
            throw (ParseException)jjte000;
          }
          throw (Error)jjte000;
        } finally {
          if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
          }
        }
/*@egen*/
}

void stmt()       :{Rules r = new Rules();}
{
  rule(r)
}

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

String variable()       : { Token t; }
{
  t = < DOLLAR_QNAME >  { return t.image;  }
}

String template()       : { Token t; }
{
  t = < PERCENT_QNAME >  { return t.image;  }
}