| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| options |
| { |
| MULTI=true; |
| STATIC=false; |
| JAVA_TEMPLATE_TYPE="modern"; |
| VISITOR=true; |
| NODE_SCOPE_HOOK=true; |
| NODE_CLASS="JexlNode"; |
| UNICODE_INPUT=true; |
| KEEP_LINE_COLUMN=true; |
| TRACK_TOKENS=true; |
| CACHE_TOKENS=true; |
| ERROR_REPORTING=false; |
| // DEBUG_PARSER=true; |
| // DEBUG_TOKEN_MANAGER=true; |
| } |
| |
| PARSER_BEGIN(Parser) |
| |
| package org.apache.commons.jexl3.parser; |
| |
| import java.util.Collections; |
| import java.util.LinkedList; |
| |
| import org.apache.commons.jexl3.JexlInfo; |
| import org.apache.commons.jexl3.JexlFeatures; |
| import org.apache.commons.jexl3.JexlException; |
| import org.apache.commons.jexl3.internal.Scope; |
| |
| public final class Parser extends JexlParser |
| { |
| public ASTJexlScript parse(JexlInfo jexlInfo, JexlFeatures jexlFeatures, String jexlSrc, Scope jexlScope) { |
| JexlFeatures previous = getFeatures(); |
| try { |
| setFeatures(jexlFeatures); |
| // lets do the 'Unique Init' in here to be safe - it's a pain to remember |
| info = jexlInfo != null? jexlInfo : new JexlInfo(); |
| source = jexlSrc; |
| pragmas = null; |
| this.scope = jexlScope; |
| token_source.comparatorNames = jexlFeatures.supportsComparatorNames(); |
| ReInit(jexlSrc); |
| ASTJexlScript script = jexlFeatures.supportsScript()? JexlScript(jexlScope) : JexlExpression(jexlScope); |
| script.jjtSetValue(info.detach()); |
| script.setFeatures(jexlFeatures); |
| script.setPragmas(pragmas != null |
| ? Collections.unmodifiableMap(pragmas) |
| : Collections.emptyMap()); |
| return script; |
| } catch (TokenMgrException xtme) { |
| throw new JexlException.Tokenization(info, xtme).clean(); |
| } catch (ParseException xparse) { |
| Token errortok = errorToken(jj_lastpos, jj_scanpos, token.next, token); |
| throw new JexlException.Parsing(info.at(errortok.beginLine, errortok.beginColumn), errortok.image).clean(); |
| } finally { |
| token_source.defaultLexState = DEFAULT; |
| cleanup(previous); |
| jjtree.reset(); |
| } |
| } |
| } |
| |
| PARSER_END(Parser) |
| |
| TOKEN_MGR_DECLS : { |
| boolean comparatorNames = false; |
| boolean jexl331 = true; |
| } |
| |
| /*************************************** |
| * Skip & Number literal tokens |
| ***************************************/ |
| |
| <*> SKIP : /* WHITE SPACE */ |
| { |
| " " |
| | "\t" |
| | "\n" |
| | "\r" |
| | "\f" |
| | <"##" (~["\n","\r"])* ("\n" | "\r" | "\r\n")? > |
| | <"/*" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/"> |
| | <"//" (~["\n","\r"])* ("\n" | "\r" | "\r\n")? > |
| } |
| |
| <*> TOKEN : { /* SEPARATORS */ |
| < LPAREN : "("> |
| | < RPAREN : ")"> |
| | < LCURLY : "{" > |
| | < RCURLY : "}" > |
| | < LBRACKET : "[" > |
| | < QLBRACKET : "?[" > |
| | < RBRACKET : "]" > |
| | < SEMICOL : ";" > |
| | < COLON : ":" > |
| | < COMMA : "," > |
| | < DOT : "." > : DOT_ID |
| | < QDOT : "?." > : DOT_ID |
| | < ELIPSIS : "..." > |
| } |
| |
| <*> TOKEN : { /* CONDITIONALS */ |
| < QMARK : "?" > |
| | < ELVIS : "?:" > |
| | < NULLP : "??" > |
| | < AND : "&&" > |
| | < OR : "||" > |
| } |
| |
| <DEFAULT> TOKEN : { /* CONDITIONALS */ |
| < _AND : "and" > |
| | < _OR: "or" > |
| } |
| |
| <*> TOKEN : { /* COMPARISONS */ |
| < eq : "==" > |
| | < ne : "!=" > |
| | < gt : ">" > |
| | < ge : ">=" > |
| | < lt : "<" > |
| | < le : "<=" > |
| | < req : "=~" > // regexp equal |
| | < rne : "!~" > // regexp not equal |
| | < seq : "=^" > // starts equal |
| | < eeq : "=$" > // ends equal |
| | < sne : "!^" > // start not equal |
| | < ene : "!$" > // ends not equal |
| } |
| |
| <NEVER> TOKEN : { /* COMPARISONS */ |
| < EQ : "eq" > |
| | < NE : "ne" > |
| | < GT : "gt" > |
| | < GE : "ge" > |
| | < LT : "lt" > |
| | < LE : "le" > |
| } |
| |
| <*> TOKEN : { /* OPERATORS */ |
| < plus_assign : "+=" > |
| | < minus_assign : "-=" > |
| | < mult_assign : "*=" > |
| | < div_assign : "/=" > |
| | < mod_assign : "%=" > |
| | < and_assign : "&=" > |
| | < or_assign : "|=" > |
| | < xor_assign : "^=" > |
| | < lshift_assign : "<<=" > |
| | < rshiftu_assign : ">>>=" > |
| | < rshift_assign : ">>=" > |
| |
| | < assign : "=" > |
| | < plus : "+" > |
| | < plusplus : "++" > |
| | < minus : "-" > |
| | < minusminus : "--" > |
| | < mult : "*" > |
| | < div : "/" > |
| | < mod : "%" > |
| | < not : "!" > |
| | < and : "&" > |
| | < or : "|" > |
| | < xor : "^" > |
| | < lshift : "<<" > |
| | < rshiftu : ">>>" > |
| | < rshift : ">>" > |
| |
| | < tilda : "~" > |
| | < range : ".." > |
| } |
| |
| <DEFAULT> TOKEN : { /* OPERATORS */ |
| < NOT : "not" > |
| | < DIV : "div" > |
| | < MOD : "mod" > |
| } |
| |
| <*> TOKEN : /* KEYWORDS */ |
| { |
| < LAMBDA : "->" > |
| | < FATARROW : "=>" > |
| | < PRAGMA : "#pragma" > |
| } |
| |
| <DEFAULT> TOKEN : /* KEYWORDS */ |
| { |
| < IF : "if" > |
| | < ELSE : "else" > |
| | < DO : "do" > |
| | < WHILE : "while" > |
| | < FOR : "for" > |
| | < BREAK : "break" > |
| | < CONTINUE : "continue" > |
| | < FUNCTION : "function" > |
| | < RETURN : "return" > |
| | < NEW : "new" > |
| | < SIZE : "size" > |
| | < EMPTY : "empty" > |
| | < VAR : "var" > |
| | < LET : "let" > |
| | < CONST : "const" > |
| | < NULL : "null" > |
| | < TRUE : "true" > |
| | < FALSE : "false" > |
| } |
| |
| <NEVER> TOKEN : /* Exception handling. */ |
| { |
| < THROW : "throw" > |
| | < TRY : "try" > |
| | < CATCH : "catch" > |
| | < FINALLY : "finally" > |
| } |
| |
| /*************************************** |
| * Identifier & String tokens |
| ***************************************/ |
| <DEFAULT> TOKEN : /* NaN */ |
| { |
| < NAN_LITERAL : "NaN" > |
| } |
| |
| <DEFAULT> TOKEN : /* ANNOTATION */ |
| { |
| < ANNOTATION: "@" ( [ "0"-"9", "a"-"z", "A"-"Z", "_", "$" ])+ > |
| } |
| |
| <DOT_ID> TOKEN : /* IDENTIFIERS */ |
| { |
| < DOT_IDENTIFIER: ( [ "0"-"9", "a"-"z", "A"-"Z", "_", "$", "@" ])+ > : DEFAULT |
| } |
| |
| <DEFAULT> TOKEN : /* IDENTIFIERS */ |
| { |
| < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>|<ESCAPE>)* > |
| { |
| matchedToken.image = StringParser.unescapeIdentifier(matchedToken.image); |
| final int length = matchedToken.image.length(); |
| if (comparatorNames && length == 2) { |
| switch (matchedToken.image) { |
| case "ne" : matchedToken.kind = NE; break; |
| case "eq" : matchedToken.kind = EQ; break; |
| case "lt" : matchedToken.kind = LT; break; |
| case "le" : matchedToken.kind = LE; break; |
| case "gt" : matchedToken.kind = GT; break; |
| case "ge" : matchedToken.kind = GE; break; |
| } |
| } else if (jexl331 && length >= 3 && length <= 7) { |
| switch (matchedToken.image) { |
| case "try" : matchedToken.kind = TRY; break; |
| case "catch" : matchedToken.kind = CATCH; break; |
| case "finally" : matchedToken.kind = FINALLY; break; |
| case "throw" : matchedToken.kind = THROW; break; |
| } |
| } |
| } |
| | |
| < #LETTER: [ "a"-"z", "A"-"Z", "_", "$", "@" ] > |
| | |
| < #DIGIT: [ "0"-"9"] > |
| | |
| < #ESCAPE: "\\" [" ", "'", "\"", "\\"] > |
| } |
| |
| <DEFAULT> TOKEN : |
| { |
| < REGISTER: "#" (["0"-"9"])+ > |
| } |
| |
| <DEFAULT> TOKEN : /* LITERALS */ |
| { |
| <INTEGER_LITERAL: |
| <DECIMAL_LITERAL> (<INT_SFX>)? |
| | <HEX_LITERAL> (<INT_SFX>)? |
| | <OCTAL_LITERAL> (<INT_SFX>)? |
| > |
| | <#DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])*> |
| | <#HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+> |
| | <#OCTAL_LITERAL: "0" (["0"-"7"])*> |
| | <#INT_SFX : ["l","L","h","H"]> |
| | |
| <FLOAT_LITERAL: |
| (["0"-"9"])+ "." (["0"-"9"])+ (<FLT_SFX>)? |
| | (["0"-"9"])+ (".")? (<FLT_SFX>) |
| | "." (["0"-"9"])+ (<FLT_SFX>) |
| | "#NaN" |
| > |
| | <#EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+> |
| | <#FLT_CLS : ["f","F","d","D","b","B"]> |
| | <#FLT_SFX : <EXPONENT> (<FLT_CLS>)? | <FLT_CLS> > |
| } |
| |
| <*> TOKEN : |
| { |
| < STRING_LITERAL: |
| "\"" (~["\"","\\","\n","\r","\u2028","\u2029"] | "\\" ~["\n","\r","\u2028","\u2029"])* "\"" |
| | |
| "'" (~["'","\\","\n","\r","\u2028","\u2029"] | "\\" ~["\n","\r","\u2028","\u2029"])* "'" |
| > : DEFAULT |
| } |
| |
| <*> TOKEN : |
| { |
| < JXLT_LITERAL: |
| "`" (~["`","\\"] | "\\" ~["\u0000"])* "`" |
| > : DEFAULT |
| } |
| |
| <DEFAULT> TOKEN : |
| { |
| < REGEX_LITERAL: |
| "~" "/" (~["/","\n","\r","\t","\f","\b","\u2028","\u2029"] | "\\" "/" )* "/" |
| > |
| } |
| |
| /*************************************** |
| * Statements |
| ***************************************/ |
| |
| ASTJexlScript JexlScript(Scope frame) : { |
| jjtThis.setScope(frame); |
| } |
| { |
| { |
| pushUnit(jjtThis); |
| } |
| ( LOOKAHEAD(<PRAGMA>) Pragma() | { controlPragmaAnywhere(); } Statement() )* <EOF> |
| { |
| popUnit(jjtThis); |
| return jjtThis.script(); |
| } |
| } |
| |
| ASTJexlScript JexlExpression(Scope frame) #JexlScript : { |
| jjtThis.setScope(frame); |
| } |
| { |
| { |
| pushUnit(jjtThis); |
| } |
| ( Pragma() )* { controlPragmaAnywhere(); } ( Expression() )? <EOF> |
| { |
| popUnit(jjtThis); |
| return jjtThis.script(); |
| } |
| } |
| |
| void Annotation() #Annotation : |
| { |
| Token t; |
| } |
| { |
| t=<ANNOTATION> { jjtThis.setName(t.image); } (LOOKAHEAD(<LPAREN>) Arguments() )? |
| } |
| |
| void AnnotatedStatement() #AnnotatedStatement : {} |
| { |
| (LOOKAHEAD(<ANNOTATION>) Annotation())+ (LOOKAHEAD(1) Block() | Statement()) |
| } |
| |
| void Statement() #void : {} |
| { |
| LOOKAHEAD(<LET>|<CONST>|<VAR>) Var() |
| | |
| LOOKAHEAD(<FUNCTION> <IDENTIFIER>) FunctionStatement() |
| | |
| StatementNoVar() |
| } |
| |
| void StatementNoVar() #void : {} |
| { |
| <SEMICOL> |
| | LOOKAHEAD(<ANNOTATION>) AnnotatedStatement() |
| | LOOKAHEAD(<IF>) IfStatement() |
| | LOOKAHEAD(<FOR>) ForeachStatement() |
| | LOOKAHEAD(<WHILE>) WhileStatement() |
| | LOOKAHEAD(<DO>) DoWhileStatement() |
| | LOOKAHEAD(<RETURN>) ReturnStatement() |
| | LOOKAHEAD(<CONTINUE>) Continue() |
| | LOOKAHEAD(<BREAK>) Break() |
| | LOOKAHEAD(<THROW>) ThrowStatement() |
| | LOOKAHEAD(<TRY>) TryStatement() |
| | LOOKAHEAD(Expression()) ExpressionStatement() |
| | Block() |
| | LOOKAHEAD(<VAR>, {!getFeatures().isLexical()} ) Var() |
| } |
| |
| void Block() #Block : {} |
| { |
| <LCURLY> { pushUnit(jjtThis); } ( LOOKAHEAD(<PRAGMA>) Pragma() | Statement() )* { popUnit(jjtThis); } <RCURLY> |
| } |
| |
| void FunctionStatement() #JexlLambda : {} |
| { |
| <FUNCTION> DeclareFunction() { pushScope(); pushUnit(jjtThis); } Parameters() ( LOOKAHEAD(3) Block() | Expression()) { popUnit(jjtThis); popScope(); } |
| } |
| |
| void ExpressionStatement() #void : {} |
| { |
| Expression() (LOOKAHEAD(Expression()) Expression() #Ambiguous(1))* (LOOKAHEAD(1) <SEMICOL>)? |
| } |
| |
| |
| void IfStatement() : {} |
| { |
| <IF> <LPAREN> Expression() <RPAREN> (LOOKAHEAD(1) Block() | StatementNoVar()) |
| ( LOOKAHEAD(2) <ELSE> <IF> <LPAREN> Expression() <RPAREN> (LOOKAHEAD(1) Block() | StatementNoVar()) )* |
| ( LOOKAHEAD(1) <ELSE> (LOOKAHEAD(1) Block() | StatementNoVar()) )? |
| } |
| |
| void TryStatement() : { |
| int tryForm = 0; |
| } |
| { |
| <TRY> (LOOKAHEAD(1) (TryResources() ) | Block()) |
| (LOOKAHEAD(1) <CATCH> <LPAREN> InlineVar() <RPAREN> Block() { tryForm |= 1; })? |
| (LOOKAHEAD(1) <FINALLY> Block() { tryForm |= 2; })? |
| { |
| jjtThis.setTryForm(tryForm); |
| } |
| } |
| |
| void TryResources() : {} |
| { |
| { |
| pushUnit(jjtThis); |
| } |
| <LPAREN> |
| TryResource() ( LOOKAHEAD(2) <SEMICOL> TryResource() )* (<SEMICOL>)? |
| <RPAREN> |
| Block() |
| { |
| popUnit(jjtThis); |
| } |
| } |
| |
| void TryResource() #void : {} |
| { |
| (LOOKAHEAD(2) Var() | Identifier(true)) |
| } |
| |
| void WhileStatement() : {} |
| { |
| <WHILE> <LPAREN> Expression() <RPAREN> { loopCount += 1; } (LOOKAHEAD(1) Block() | StatementNoVar()) { loopCount -= 1; } |
| } |
| |
| void DoWhileStatement() : {} |
| { |
| <DO> { loopCount += 1; } (LOOKAHEAD(1) Block() | StatementNoVar()) <WHILE> <LPAREN> Expression() <RPAREN> { loopCount -= 1; } |
| } |
| |
| void ReturnStatement() : {} |
| { |
| <RETURN> (LOOKAHEAD(2) ExpressionStatement() )? |
| } |
| |
| void ThrowStatement() : {} |
| { |
| <THROW> (LOOKAHEAD(2) ExpressionStatement() )? |
| } |
| |
| void Continue() #Continue : { |
| Token t; |
| } |
| { |
| t=<CONTINUE> { if (loopCount == 0) { throwParsingException(t); } } |
| } |
| |
| void Break() #Break : { |
| Token t; |
| } |
| { |
| t=<BREAK> { if (loopCount == 0) { throwParsingException(t); } } |
| } |
| |
| void ForeachStatement() : { |
| int loopForm = 0; |
| } |
| { |
| { |
| pushUnit(jjtThis); |
| } |
| <FOR> <LPAREN> |
| ( |
| LOOKAHEAD(3) InlineVar() <COLON> Expression() { loopForm = 0; } |
| | |
| ((LOOKAHEAD(1) Var() | Expression()) { loopForm = 1; })? <SEMICOL> |
| (Expression() { loopForm |= 2; })? <SEMICOL> |
| (Expression() { loopForm |= 4; })? { loopForm |= 8; } |
| ) |
| <RPAREN> |
| { |
| loopCount += 1; |
| } |
| (LOOKAHEAD(1) Block() | StatementNoVar() ) |
| { |
| loopCount -= 1; |
| jjtThis.setLoopForm(loopForm); |
| popUnit(jjtThis); |
| } |
| } |
| |
| void InlineVar() #Reference : {} |
| { |
| <VAR> DeclareVar(false, false) |
| | |
| <LET> DeclareVar(true, false) |
| | |
| <CONST> DeclareVar(true, true) |
| | |
| Identifier(true) |
| } |
| |
| void Var() #void : {} |
| { |
| (<VAR> DefineVar() (<COMMA> DefineVar())*) #DefineVars(>1) |
| | |
| (<LET> DefineLet() (<COMMA> DefineLet())*) #DefineVars(>1) |
| | |
| (<CONST> DefineConst() (<COMMA> DefineConst())*) #DefineVars(>1) |
| } |
| |
| void DefineVar() #void : {} |
| { |
| DeclareVar(false, false) (LOOKAHEAD(1) <assign> Expression() #Assignment(2))? |
| } |
| |
| void DefineLet() #void : {} |
| { |
| DeclareVar(true, false) (LOOKAHEAD(1) <assign> Expression() #Assignment(2))? |
| } |
| |
| void DefineConst() #void : {} |
| { |
| DeclareVar(true, true) <assign> Expression() #Assignment(2) |
| } |
| |
| void DeclareVar(boolean lexical, boolean constant) #Var : |
| { |
| Token t; |
| } |
| { |
| t=<IDENTIFIER> { declareVariable(jjtThis, t, lexical, constant); } |
| } |
| void DeclareFunction() #Var : |
| { |
| Token t; |
| } |
| { |
| t=<IDENTIFIER> { declareFunction(jjtThis, t); } |
| } |
| |
| void Pragma() #void : |
| { |
| LinkedList<String> lstr = new LinkedList<String>(); |
| Object value; |
| } |
| { |
| <PRAGMA> pragmaKey(lstr) value=pragmaValue() { declarePragma(stringify(lstr), value); } |
| } |
| |
| void pragmaKey(LinkedList<String> lstr) #void : |
| { |
| Token t; |
| } |
| { |
| t=<IDENTIFIER> { lstr.add(t.image); } ( LOOKAHEAD(<DOT>) pragmaKey(lstr) )* |
| | |
| <DOT> t=<DOT_IDENTIFIER> { lstr.add(t.image); } |
| } |
| |
| Object pragmaValue() #void : |
| { |
| Token s = null; |
| Token v; |
| LinkedList<String> lstr = new LinkedList<String>(); |
| Object result; |
| } |
| { |
| ( |
| LOOKAHEAD(2) (s=<plus>|s=<minus>)? v=<INTEGER_LITERAL> { result = NumberParser.parseInteger(s, v); } |
| | LOOKAHEAD(2) (s=<plus>|s=<minus>)? v=<FLOAT_LITERAL> { result = NumberParser.parseDouble(s, v); } |
| | LOOKAHEAD(1) v=<STRING_LITERAL> { result = Parser.buildString(v.image, true); } |
| | LOOKAHEAD(1) pragmaKey(lstr) { result = stringify(lstr); } |
| | LOOKAHEAD(1) <TRUE> { result = true; } |
| | LOOKAHEAD(1) <FALSE> { result = false; } |
| | LOOKAHEAD(1) <NULL> { result = null; } |
| | LOOKAHEAD(1) <NAN_LITERAL> { result = Double.NaN; } |
| ) |
| { |
| return result; |
| } |
| } |
| |
| |
| /*************************************** |
| * Expression syntax |
| ***************************************/ |
| |
| void Expression() #void : {} |
| { |
| AssignmentExpression() |
| } |
| |
| void AssignmentExpression() #void : {} |
| { |
| ConditionalExpression() |
| ( LOOKAHEAD(2) ( |
| <plus_assign> Expression() #SetAddNode(2) |
| | |
| <mult_assign> Expression() #SetMultNode(2) |
| | |
| <div_assign> Expression() #SetDivNode(2) |
| | |
| <mod_assign> Expression() #SetModNode(2) |
| | |
| <and_assign> Expression() #SetAndNode(2) |
| | |
| <or_assign> Expression() #SetOrNode(2) |
| | |
| <xor_assign> Expression() #SetXorNode(2) |
| | |
| <minus_assign> Expression() #SetSubNode(2) |
| | |
| <lshift_assign> Expression() #SetShiftLeftNode(2) |
| | |
| <rshift_assign> Expression() #SetShiftRightNode(2) |
| | |
| <rshiftu_assign> Expression() #SetShiftRightUnsignedNode(2) |
| | |
| <assign> Expression() #Assignment(2) |
| ) )? |
| } |
| |
| /*************************************** |
| * Conditional & relational |
| ***************************************/ |
| |
| void ConditionalExpression() #void : {} |
| { |
| ConditionalOrExpression() |
| ( LOOKAHEAD(2) ( |
| <QMARK> Expression() <COLON> Expression() #TernaryNode(3) |
| | |
| <ELVIS> Expression() #TernaryNode(2) |
| | |
| <NULLP> Expression() #NullpNode(2) |
| ) )? |
| } |
| |
| void ConditionalOrExpression() #void : {} |
| { |
| ConditionalAndExpression() |
| ( LOOKAHEAD(2) ( (<OR>|<_OR>) ConditionalAndExpression() #OrNode(2) ) )* |
| } |
| |
| void ConditionalAndExpression() #void : {} |
| { |
| InclusiveOrExpression() |
| ( LOOKAHEAD(2) ( (<AND>|<_AND>) InclusiveOrExpression() #AndNode(2) ) )* |
| } |
| |
| void InclusiveOrExpression() #void : {} |
| { |
| ExclusiveOrExpression() |
| ( LOOKAHEAD(2) ( <or> ExclusiveOrExpression() #BitwiseOrNode(2) ) )* |
| } |
| |
| void ExclusiveOrExpression() #void : {} |
| { |
| AndExpression() |
| ( LOOKAHEAD(2) ( <xor> AndExpression() #BitwiseXorNode(2) ) )* |
| } |
| |
| void AndExpression() #void : {} |
| { |
| EqualityExpression() |
| ( LOOKAHEAD(2) (<and> EqualityExpression() #BitwiseAndNode(2) ) )* |
| } |
| |
| void EqualityExpression() #void : {} |
| { |
| RelationalExpression() |
| ( LOOKAHEAD(2) ( |
| (<eq> | <EQ>) RelationalExpression() #EQNode(2) |
| | |
| (<ne> | <NE>) RelationalExpression() #NENode(2) |
| | |
| <range> RelationalExpression() #RangeNode(2) // range |
| ) )? |
| } |
| |
| void RelationalExpression() #void : {} |
| { |
| ShiftExpression() |
| ( LOOKAHEAD(2) ( |
| (<lt> |<LT>) ShiftExpression() #LTNode(2) |
| | |
| (<gt> | <GT>) ShiftExpression() #GTNode(2) |
| | |
| (<le> | <LE>) ShiftExpression() #LENode(2) |
| | |
| (<ge> | <GE>) ShiftExpression() #GENode(2) |
| | |
| <req> ShiftExpression() #ERNode(2) // equals regexp |
| | |
| <rne> ShiftExpression() #NRNode(2) // not equals regexp |
| | |
| <seq> ShiftExpression() #SWNode(2) // starts with |
| | |
| <sne> ShiftExpression() #NSWNode(2) // not starts with |
| | |
| <eeq> ShiftExpression() #EWNode(2) // ends with |
| | |
| <ene> ShiftExpression() #NEWNode(2) // not ends with |
| ) )? |
| } |
| |
| /*************************************** |
| * Arithmetic |
| ***************************************/ |
| void ShiftExpression() #void : {} |
| { |
| AdditiveExpression() |
| ( LOOKAHEAD(2) ( |
| <lshift> AdditiveExpression() #ShiftLeftNode(2) // left shift |
| | |
| <rshift> AdditiveExpression() #ShiftRightNode(2) // right shift |
| | |
| <rshiftu> AdditiveExpression() #ShiftRightUnsignedNode(2) // right shift unsigned |
| ) )* |
| } |
| |
| void AdditiveExpression() #void : {} |
| { |
| MultiplicativeExpression() |
| ( LOOKAHEAD(2) ( |
| <plus> MultiplicativeExpression() #AddNode(2) |
| | |
| <minus> MultiplicativeExpression() #SubNode(2) |
| ) )* |
| } |
| |
| void MultiplicativeExpression() #void : {} |
| { |
| UnaryExpression() |
| ( LOOKAHEAD(2) ( |
| <mult> UnaryExpression() #MulNode(2) |
| | |
| (<div>|<DIV>) UnaryExpression() #DivNode(2) |
| | |
| (<mod>|<MOD>) UnaryExpression() #ModNode(2) |
| ) )* |
| } |
| |
| void UnaryExpression() #void : {} |
| { |
| <minus> UnaryExpression() #UnaryMinusNode(1) |
| | |
| <plus> UnaryExpression() #UnaryPlusNode(1) |
| | |
| <tilda> UnaryExpression() #BitwiseComplNode(1) |
| | |
| (<not>|<NOT>) UnaryExpression() #NotNode(1) |
| | |
| <EMPTY> UnaryExpression() #EmptyFunction(1) |
| | |
| <SIZE> UnaryExpression() #SizeFunction(1) |
| | |
| <minusminus> UnaryExpression() #DecrementGetNode(1) |
| | |
| <plusplus> UnaryExpression() #IncrementGetNode(1) |
| | |
| PostfixExpression() |
| } |
| |
| void PostfixOperator() #void : {} |
| { |
| <plusplus> #GetIncrementNode(1) |
| | |
| <minusminus> #GetDecrementNode(1) |
| } |
| |
| void PostfixExpression() #void : {} |
| { |
| ValueExpression() [ LOOKAHEAD(1) PostfixOperator() ] |
| } |
| |
| /*************************************** |
| * Identifier & Literals |
| ***************************************/ |
| |
| void Identifier(boolean top) : |
| { |
| Token t; |
| } |
| { |
| t=<IDENTIFIER> { jjtThis.setSymbol(top? checkVariable(jjtThis, t.image) : t.image); } |
| | |
| t=<REGISTER> { if (!getFeatures().supportsRegister()) throwParsingException(t); jjtThis.setSymbol(t.image); } |
| } |
| |
| |
| void NamespaceIdentifier() #NamespaceIdentifier : |
| { |
| Token ns; |
| Token id; |
| } |
| { |
| ns=<IDENTIFIER> <COLON> id=<IDENTIFIER> { jjtThis.setNamespace(ns.image, id.image); } |
| } |
| |
| void Literal() #void : |
| { |
| Token t; |
| } |
| { |
| IntegerLiteral() |
| | |
| FloatLiteral() |
| | |
| BooleanLiteral() |
| | |
| JxltLiteral() |
| | |
| StringLiteral() |
| | |
| RegexLiteral() |
| | |
| NullLiteral() |
| | |
| NaNLiteral() |
| } |
| |
| void NaNLiteral() #NumberLiteral : |
| {} |
| { |
| <NAN_LITERAL> { jjtThis.setReal("NaN"); } |
| } |
| |
| void NullLiteral() : {} |
| { |
| <NULL> |
| } |
| |
| void BooleanLiteral() #void : |
| {} |
| { |
| <TRUE> #TrueNode |
| | |
| <FALSE> #FalseNode |
| } |
| |
| void IntegerLiteral() #NumberLiteral : |
| { |
| Token t; |
| } |
| { |
| t=<INTEGER_LITERAL> |
| { jjtThis.setNatural(t.image); } |
| } |
| |
| |
| void FloatLiteral() #NumberLiteral: |
| { |
| Token t; |
| } |
| { |
| t=<FLOAT_LITERAL> |
| { jjtThis.setReal(t.image); } |
| } |
| |
| void StringLiteral() : |
| { |
| Token t; |
| } |
| { |
| t=<STRING_LITERAL> |
| { jjtThis.setLiteral(Parser.buildString(t.image, true)); } |
| } |
| |
| |
| void JxltLiteral() #JxltLiteral : |
| { |
| Token t; |
| } |
| { |
| t=<JXLT_LITERAL> |
| { jjtThis.setLiteral(Parser.buildString(t.image, true)); } |
| } |
| |
| void RegexLiteral() : |
| { |
| Token t; |
| } |
| { |
| t=<REGEX_LITERAL> |
| { jjtThis.setLiteral(Parser.buildRegex(t.image)); } |
| } |
| |
| |
| void ExtendedLiteral() #ExtendedLiteral : {} |
| { |
| <ELIPSIS> |
| } |
| |
| void ArrayLiteral() : {} |
| { |
| <LBRACKET> |
| ( |
| (<COMMA>)? ExtendedLiteral() |
| | |
| (Expression() (LOOKAHEAD(2) <COMMA> Expression())* |
| (<COMMA> (ExtendedLiteral() { jjtThis.setExtended(true); })? )? )? |
| ) |
| <RBRACKET> |
| } |
| |
| void MapLiteral() : {} |
| { |
| <LCURLY> |
| ( |
| MapEntry() (LOOKAHEAD(2) <COMMA> MapEntry() )* |
| (<COMMA> (ExtendedLiteral(){ jjtThis.setExtended(true); })? )? |
| | |
| <COLON> |
| ) <RCURLY> |
| } |
| |
| void MapEntry() : {} |
| { |
| LOOKAHEAD(2) Identifier(true) <COLON> Expression() |
| | |
| Expression() <COLON> Expression() |
| } |
| |
| void SetLiteral() : {} |
| { |
| <LCURLY> |
| ( |
| Expression() (LOOKAHEAD(2) <COMMA> Expression())* |
| (<COMMA> (ExtendedLiteral() { jjtThis.setExtended(true); } )? )? |
| )? <RCURLY> |
| } |
| |
| |
| /*************************************** |
| * Functions & Methods |
| ***************************************/ |
| |
| void Arguments() #Arguments : {} |
| { |
| <LPAREN> (Expression() (<COMMA> Expression())* )? <RPAREN> |
| } |
| |
| void FunctionCallLookahead() #void : {} |
| { |
| LOOKAHEAD(4, <IDENTIFIER> <COLON> <IDENTIFIER> <LPAREN>, { isNamespaceFuncall(getToken(1), getToken(2), getToken(3), getToken(4)) }) <IDENTIFIER> <COLON> <IDENTIFIER> <LPAREN> |
| | |
| LOOKAHEAD(2) <IDENTIFIER> <LPAREN> |
| | |
| LOOKAHEAD(2) <REGISTER> <LPAREN> |
| } |
| |
| void FunctionCall() #void : {} |
| { |
| LOOKAHEAD(4, <IDENTIFIER> <COLON> <IDENTIFIER> <LPAREN>, { isNamespaceFuncall(getToken(1), getToken(2), getToken(3), getToken(4)) }) NamespaceIdentifier() Arguments() #FunctionNode(2) |
| | |
| LOOKAHEAD(<IDENTIFIER> <LPAREN>) Identifier(true) Arguments() #FunctionNode(2) |
| } |
| |
| void QualifiedIdentifier() #QualifiedIdentifier : { |
| LinkedList<String> lstr = new LinkedList<String>(); |
| } |
| { |
| pragmaKey(lstr) { jjtThis.setName(stringify(lstr));} |
| } |
| |
| void Constructor() #ConstructorNode : {} |
| { |
| LOOKAHEAD(2) <NEW> <LPAREN> Expression() ( <COMMA> Expression() )* <RPAREN> |
| | |
| <NEW> QualifiedIdentifier() <LPAREN> [ Expression() ( <COMMA> Expression() )* ] <RPAREN> |
| } |
| |
| void Parameter() #void : |
| { |
| Token t; |
| } |
| { |
| (<VAR>)? t=<IDENTIFIER> { declareParameter(t, false, false); } |
| | |
| <LET> t=<IDENTIFIER> { declareParameter(t, true, false); } |
| | |
| <CONST> t=<IDENTIFIER> { declareParameter(t, true, true); } |
| } |
| |
| void Parameters() #void : {} |
| { |
| <LPAREN> [Parameter() (<COMMA> Parameter())* ] <RPAREN> |
| } |
| |
| void ParametersLookahead() #void : {} |
| { |
| <LPAREN> [(<VAR>|<LET>|<CONST>)? <IDENTIFIER> (<COMMA> ((<VAR>|<LET>|<CONST>)? <IDENTIFIER>))*] <RPAREN> |
| } |
| |
| void LambdaLookahead() #void : {} |
| { |
| <FUNCTION> ParametersLookahead() |
| | |
| ParametersLookahead() (<LAMBDA> | <FATARROW>) |
| | |
| <IDENTIFIER> (<LAMBDA> | <FATARROW>) |
| } |
| |
| void Lambda() #JexlLambda : |
| { |
| Token arrow; |
| Token name; |
| } |
| { |
| <FUNCTION> (LOOKAHEAD(<IDENTIFIER>) DeclareFunction())? { |
| pushScope(); pushUnit(jjtThis); } Parameters() ( LOOKAHEAD(3) Block() | Expression()) { popUnit(jjtThis); popScope(); } |
| | |
| { pushScope(); pushUnit(jjtThis); } Parameters() (arrow=<LAMBDA> | arrow=<FATARROW>) ( LOOKAHEAD(3) Block() | Expression()) { checkLambda(arrow); popUnit(jjtThis); popScope(); } |
| | |
| { pushScope(); pushUnit(jjtThis); } Parameter() (arrow=<LAMBDA> | arrow=<FATARROW>)( LOOKAHEAD(3) Block() | Expression()) { checkLambda(arrow); popUnit(jjtThis); popScope(); } |
| } |
| |
| |
| |
| /*************************************** |
| * References |
| ***************************************/ |
| |
| void IdentifierAccess() #void : |
| { |
| Token t; |
| } |
| { |
| <DOT> ( |
| t=<DOT_IDENTIFIER> { jjtThis.setIdentifier(t.image); } #IdentifierAccess |
| | |
| t=<STRING_LITERAL> { jjtThis.setIdentifier(Parser.buildString(t.image, true)); } #IdentifierAccess |
| | |
| t=<JXLT_LITERAL> { jjtThis.setIdentifier(Parser.buildString(t.image, true)); } #IdentifierAccessJxlt |
| ) |
| | |
| <QDOT> ( |
| t=<DOT_IDENTIFIER> { jjtThis.setIdentifier(t.image); } #IdentifierAccessSafe |
| | |
| t=<STRING_LITERAL> { jjtThis.setIdentifier(Parser.buildString(t.image, true)); } #IdentifierAccessSafe |
| | |
| t=<JXLT_LITERAL> { jjtThis.setIdentifier(Parser.buildString(t.image, true)); } #IdentifierAccessSafeJxlt |
| ) |
| } |
| |
| void ArrayAccess() : { |
| long safe = 0L; |
| int s = 0; |
| } |
| { |
| (LOOKAHEAD(2) (<LBRACKET>|<QLBRACKET> { safe |= (1 << s++); }) Expression() <RBRACKET>)+ { jjtThis.setSafe(safe); } |
| } |
| |
| void MemberAccess() #void : {} |
| { |
| LOOKAHEAD(<LBRACKET>|<QLBRACKET>) ArrayAccess() |
| | |
| LOOKAHEAD(<DOT>) IdentifierAccess() |
| | |
| LOOKAHEAD(<QDOT>) IdentifierAccess() |
| } |
| |
| void ReferenceExpression() #MethodNode(>1) : {} |
| { |
| <LPAREN> Expression() <RPAREN> #ReferenceExpression(1) ( LOOKAHEAD(<LPAREN>) Arguments() )* |
| } |
| |
| void PrimaryExpression() #void : {} |
| { |
| LOOKAHEAD( LambdaLookahead() ) Lambda() |
| | |
| LOOKAHEAD( <LPAREN> ) ReferenceExpression() |
| | |
| LOOKAHEAD( <LCURLY> Expression() <COLON>) MapLiteral() |
| | |
| LOOKAHEAD( <LCURLY> <COLON>) MapLiteral() |
| | |
| LOOKAHEAD( <LCURLY> Expression() (<COMMA> | <RCURLY>)) SetLiteral() |
| | |
| LOOKAHEAD( <LCURLY> <RCURLY> ) SetLiteral() |
| | |
| LOOKAHEAD( <LBRACKET> ) ArrayLiteral() |
| | |
| LOOKAHEAD( <NEW> ) Constructor() |
| | |
| LOOKAHEAD( FunctionCallLookahead() ) FunctionCall() |
| | |
| Identifier(true) |
| | |
| Literal() |
| } |
| |
| void MethodCall() #void : {} |
| { |
| (MemberAccess() (LOOKAHEAD(<LPAREN>) Arguments())+) #MethodNode(>1) |
| } |
| |
| void MemberExpression() #void : {} |
| { |
| LOOKAHEAD(MethodCall()) MethodCall() | MemberAccess() |
| } |
| |
| void ValueExpression() #void : {} |
| { |
| ( PrimaryExpression() ( LOOKAHEAD(2) MemberExpression() )*) #Reference(>1) |
| } |
| |