588 lines
12 KiB
Plaintext
588 lines
12 KiB
Plaintext
/*
|
|
* 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.
|
|
*/
|
|
|
|
/*
|
|
Author: Jacob Hookom
|
|
Email: jacob at hookom.net
|
|
*/
|
|
|
|
/* == Option Declaration == */
|
|
options
|
|
{
|
|
STATIC=false;
|
|
NODE_PREFIX="Ast";
|
|
VISITOR_EXCEPTION="javax.el.ELException";
|
|
VISITOR=false;
|
|
MULTI=true;
|
|
NODE_DEFAULT_VOID=true;
|
|
JAVA_UNICODE_ESCAPE=false;
|
|
UNICODE_INPUT=true;
|
|
BUILD_NODE_FILES=true;
|
|
}
|
|
|
|
/* == Parser Declaration == */
|
|
PARSER_BEGIN( ELParser )
|
|
package org.apache.el.parser;
|
|
import java.io.StringReader;
|
|
import javax.el.ELException;
|
|
public class ELParser {
|
|
|
|
public static Node parse(String ref) throws ELException {
|
|
try {
|
|
return new ELParser(new StringReader(ref)).CompositeExpression();
|
|
} catch (ParseException pe) {
|
|
throw new ELException(pe.getMessage());
|
|
}
|
|
}
|
|
}
|
|
PARSER_END( ELParser )
|
|
|
|
/*
|
|
* CompositeExpression
|
|
* Allow most flexible parsing, restrict by examining
|
|
* type of returned node
|
|
*/
|
|
AstCompositeExpression CompositeExpression() #CompositeExpression : {}
|
|
{
|
|
(DeferredExpression() |
|
|
DynamicExpression() |
|
|
LiteralExpression())* <EOF> { return jjtThis; }
|
|
}
|
|
|
|
/*
|
|
* LiteralExpression
|
|
* Non-EL Expression blocks
|
|
*/
|
|
void LiteralExpression() #LiteralExpression : { Token t = null; }
|
|
{
|
|
t=<LITERAL_EXPRESSION> { jjtThis.setImage(t.image); }
|
|
}
|
|
|
|
/*
|
|
* DeferredExpression
|
|
* #{...} Expressions
|
|
*/
|
|
void DeferredExpression() #DeferredExpression : {}
|
|
{
|
|
<START_DEFERRED_EXPRESSION> Expression() <RBRACE>
|
|
}
|
|
|
|
/*
|
|
* DynamicExpression
|
|
* ${...} Expressions
|
|
*/
|
|
void DynamicExpression() #DynamicExpression : {}
|
|
{
|
|
<START_DYNAMIC_EXPRESSION> Expression() <RBRACE>
|
|
}
|
|
|
|
/*
|
|
* Expression
|
|
* EL Expression Language Root
|
|
*/
|
|
void Expression() : {}
|
|
{
|
|
Semicolon()
|
|
}
|
|
|
|
/*
|
|
* Semicolon
|
|
*/
|
|
void Semicolon() : {}
|
|
{
|
|
Assignment() ( <SEMICOLON> Assignment() #Semicolon(2) )*
|
|
}
|
|
|
|
/*
|
|
* Assignment
|
|
*/
|
|
void Assignment() : {}
|
|
{
|
|
LOOKAHEAD(4) LambdaExpression() |
|
|
Choice() ( LOOKAHEAD(2) <ASSIGN> Assignment() #Assign(2) )*
|
|
}
|
|
|
|
/*
|
|
* Lambda expression
|
|
*/
|
|
void LambdaExpression() #LambdaExpression : {}
|
|
{
|
|
LambdaParameters() <ARROW> ( LOOKAHEAD(3) LambdaExpression() | Choice() )
|
|
}
|
|
|
|
/*
|
|
* Lambda parameters
|
|
*/
|
|
void LambdaParameters() #LambdaParameters : {}
|
|
{
|
|
Identifier() | <LPAREN> ( Identifier() ( <COMMA> Identifier() )* )? <RPAREN>
|
|
}
|
|
|
|
/*
|
|
* Possible invocation of lambda expression. Invocations must be bracketed but
|
|
* being bracketed does not mean it is an invocation.
|
|
*/
|
|
void LambdaExpressionOrInvocation() #LambdaExpression : {}
|
|
{
|
|
<LPAREN>
|
|
LambdaParameters()
|
|
<ARROW>
|
|
( LOOKAHEAD(3) LambdaExpression() | Choice() )
|
|
<RPAREN>
|
|
( MethodParameters() )*
|
|
}
|
|
|
|
/*
|
|
* Choice
|
|
* For Choice markup a ? b : c, then Or
|
|
*/
|
|
void Choice() : {}
|
|
{
|
|
Or() (LOOKAHEAD(3) <QUESTIONMARK> Choice() <COLON> Choice() #Choice(3))*
|
|
}
|
|
|
|
/*
|
|
* Or
|
|
* For 'or' '||', then And
|
|
*/
|
|
void Or() : {}
|
|
{
|
|
And() ((<OR0>|<OR1>) And() #Or(2))*
|
|
}
|
|
|
|
/*
|
|
* And
|
|
* For 'and' '&&', then Equality
|
|
*/
|
|
void And() : {}
|
|
{
|
|
Equality() ((<AND0>|<AND1>) Equality() #And(2))*
|
|
}
|
|
|
|
/*
|
|
* Equality
|
|
* For '==' 'eq' '!=' 'ne', then Compare
|
|
*/
|
|
void Equality() : {}
|
|
{
|
|
Compare()
|
|
(
|
|
((<EQ0>|<EQ1>) Compare() #Equal(2))
|
|
|
|
|
((<NE0>|<NE1>) Compare() #NotEqual(2))
|
|
)*
|
|
}
|
|
|
|
/*
|
|
* Compare
|
|
* For a bunch of them, then +=
|
|
*/
|
|
void Compare() : {}
|
|
{
|
|
Concatenation()
|
|
(
|
|
((<LT0>|<LT1>) Concatenation() #LessThan(2))
|
|
|
|
|
((<GT0>|<GT1>) Concatenation() #GreaterThan(2))
|
|
|
|
|
((<LE0>|<LE1>) Concatenation() #LessThanEqual(2))
|
|
|
|
|
((<GE0>|<GE1>) Concatenation() #GreaterThanEqual(2))
|
|
)*
|
|
}
|
|
|
|
/*
|
|
* Concatenation
|
|
* For +=, then Math
|
|
*
|
|
*/
|
|
void Concatenation() : {}
|
|
{
|
|
Math()
|
|
(
|
|
<CONCAT> Math() #Concatenation(2)
|
|
)*
|
|
}
|
|
|
|
/*
|
|
* Math
|
|
* For '+' '-', then Multiplication
|
|
*/
|
|
void Math() : {}
|
|
{
|
|
Multiplication()
|
|
(
|
|
(<PLUS> Multiplication() #Plus(2))
|
|
|
|
|
(<MINUS> Multiplication() #Minus(2))
|
|
)*
|
|
}
|
|
|
|
/*
|
|
* Multiplication
|
|
* For a bunch of them, then Unary
|
|
*/
|
|
void Multiplication() : {}
|
|
{
|
|
Unary()
|
|
(
|
|
(<MULT> Unary() #Mult(2))
|
|
|
|
|
((<DIV0>|<DIV1>) Unary() #Div(2))
|
|
|
|
|
((<MOD0>|<MOD1>) Unary() #Mod(2))
|
|
)*
|
|
}
|
|
|
|
/*
|
|
* Unary
|
|
* For '-' '!' 'not' 'empty', then Value
|
|
*/
|
|
void Unary() : {}
|
|
{
|
|
<MINUS> Unary() #Negative
|
|
|
|
|
(<NOT0>|<NOT1>) Unary() #Not
|
|
|
|
|
<EMPTY> Unary() #Empty
|
|
|
|
|
Value()
|
|
}
|
|
|
|
/*
|
|
* Value
|
|
* Defines Prefix plus zero or more Suffixes
|
|
*/
|
|
void Value() : {}
|
|
{
|
|
(ValuePrefix() (ValueSuffix())*) #Value(>1)
|
|
}
|
|
|
|
/*
|
|
* ValuePrefix
|
|
* For Literals, Variables, and Functions
|
|
*/
|
|
void ValuePrefix() : {}
|
|
{
|
|
Literal()
|
|
| NonLiteral()
|
|
}
|
|
|
|
/*
|
|
* ValueSuffix
|
|
* Either dot or bracket notation
|
|
*/
|
|
void ValueSuffix() : {}
|
|
{
|
|
( DotSuffix() | BracketSuffix() ) ( MethodParameters())?
|
|
}
|
|
|
|
/*
|
|
* DotSuffix
|
|
* Dot Property
|
|
*/
|
|
void DotSuffix() #DotSuffix : { Token t = null; }
|
|
{
|
|
<DOT> t=<IDENTIFIER> { jjtThis.setImage(t.image); }
|
|
}
|
|
|
|
/*
|
|
* BracketSuffix
|
|
* Sub Expression Suffix
|
|
*/
|
|
void BracketSuffix() #BracketSuffix : {}
|
|
{
|
|
<LBRACK> Expression() <RBRACK>
|
|
}
|
|
|
|
/*
|
|
* MethodParameters
|
|
*/
|
|
void MethodParameters() #MethodParameters : {}
|
|
{
|
|
<LPAREN> ( Expression() ( <COMMA> Expression())* )? <RPAREN>
|
|
}
|
|
|
|
/*
|
|
* NonLiteral
|
|
* For Grouped Operations, Identifiers, and Functions
|
|
*/
|
|
void NonLiteral() : {}
|
|
{
|
|
LOOKAHEAD(5) LambdaExpressionOrInvocation()
|
|
| <LPAREN> Expression() <RPAREN>
|
|
| LOOKAHEAD((<IDENTIFIER> <COLON>)? <IDENTIFIER> <LPAREN>) Function()
|
|
| Identifier()
|
|
| LOOKAHEAD(3)SetData()
|
|
| ListData()
|
|
| MapData()
|
|
}
|
|
|
|
/*
|
|
* Note that both an empty Set and an empty Map are represented by {}. The
|
|
* parser will always parse {} as an empty Set and special handling is required
|
|
* to convert it to an empty Map when appropriate.
|
|
*/
|
|
void SetData() #SetData: {}
|
|
{
|
|
<START_SET_OR_MAP>
|
|
( Expression() ( <COMMA> Expression() )* )?
|
|
<RBRACE>
|
|
}
|
|
|
|
void ListData() #ListData: {}
|
|
{
|
|
<LBRACK>
|
|
( Expression() ( <COMMA> Expression() )* )?
|
|
<RBRACK>
|
|
}
|
|
|
|
/*
|
|
* Note that both an empty Set and an empty Map are represented by {}. The
|
|
* parser will always parse {} as an empty Set and special handling is required
|
|
* to convert it to an empty Map when appropriate.
|
|
*/
|
|
void MapData() #MapData: {}
|
|
{
|
|
<START_SET_OR_MAP>
|
|
( MapEntry() ( <COMMA> MapEntry() )* )?
|
|
<RBRACE>
|
|
}
|
|
|
|
void MapEntry() #MapEntry: {}
|
|
{
|
|
Expression() <COLON> Expression()
|
|
}
|
|
|
|
/*
|
|
* Identifier
|
|
* Java Language Identifier
|
|
*/
|
|
void Identifier() #Identifier : { Token t = null; }
|
|
{
|
|
t=<IDENTIFIER> { jjtThis.setImage(t.image); }
|
|
}
|
|
|
|
/*
|
|
* Function
|
|
* Namespace:Name(a,b,c)
|
|
*/
|
|
void Function() #Function :
|
|
{
|
|
Token t0 = null;
|
|
Token t1 = null;
|
|
}
|
|
{
|
|
t0=<IDENTIFIER> ( <COLON> t1=<IDENTIFIER> )?
|
|
{
|
|
if (t1 != null) {
|
|
jjtThis.setPrefix(t0.image);
|
|
jjtThis.setLocalName(t1.image);
|
|
} else {
|
|
jjtThis.setLocalName(t0.image);
|
|
}
|
|
}
|
|
( MethodParameters() )+
|
|
}
|
|
|
|
/*
|
|
* Literal
|
|
* Reserved Keywords
|
|
*/
|
|
void Literal() : {}
|
|
{
|
|
Boolean()
|
|
| FloatingPoint()
|
|
| Integer()
|
|
| String()
|
|
| Null()
|
|
}
|
|
|
|
/*
|
|
* Boolean
|
|
* For 'true' 'false'
|
|
*/
|
|
void Boolean() : {}
|
|
{
|
|
<TRUE> #True
|
|
| <FALSE> #False
|
|
}
|
|
|
|
/*
|
|
* FloatingPoint
|
|
* For Decimal and Floating Point Literals
|
|
*/
|
|
void FloatingPoint() #FloatingPoint : { Token t = null; }
|
|
{
|
|
t=<FLOATING_POINT_LITERAL> { jjtThis.setImage(t.image); }
|
|
}
|
|
|
|
/*
|
|
* Integer
|
|
* For Simple Numeric Literals
|
|
*/
|
|
void Integer() #Integer : { Token t = null; }
|
|
{
|
|
t=<INTEGER_LITERAL> { jjtThis.setImage(t.image); }
|
|
}
|
|
|
|
/*
|
|
* String
|
|
* For Quoted Literals
|
|
*/
|
|
void String() #String : { Token t = null; }
|
|
{
|
|
t=<STRING_LITERAL> { jjtThis.setImage(t.image); }
|
|
}
|
|
|
|
/*
|
|
* Null
|
|
* For 'null'
|
|
*/
|
|
void Null() #Null : {}
|
|
{
|
|
<NULL>
|
|
}
|
|
|
|
|
|
/* ========================================================================== */
|
|
TOKEN_MGR_DECLS:
|
|
{
|
|
java.util.Deque<Integer> deque = new java.util.ArrayDeque<Integer>();
|
|
}
|
|
<DEFAULT> TOKEN :
|
|
{
|
|
/*
|
|
* The following definition uses + rather than * in two places to prevent
|
|
* LITERAL_EXPRESSION matching the empty string that could result in the
|
|
* Parser entering an infinite loop.
|
|
*/
|
|
< LITERAL_EXPRESSION:
|
|
( (~["$", "#", "\\"])* "\\" (["$", "#"])?
|
|
| (~["$", "#"])* (["$", "#"] ~["{", "$", "#", "\\"])
|
|
| (~["$", "#"])+
|
|
)+
|
|
| "$"
|
|
| "#"
|
|
>
|
|
|
|
|
< START_DYNAMIC_EXPRESSION: "${" > {deque.push(DEFAULT);}: IN_EXPRESSION
|
|
|
|
|
< START_DEFERRED_EXPRESSION: "#{" > {deque.push(DEFAULT);}: IN_EXPRESSION
|
|
}
|
|
|
|
<IN_EXPRESSION, IN_SET_OR_MAP> SKIP : { " " | "\t" | "\n" | "\r" }
|
|
|
|
<IN_EXPRESSION, IN_SET_OR_MAP> TOKEN :
|
|
{
|
|
< START_SET_OR_MAP : "{" > {deque.push(curLexState);}: IN_SET_OR_MAP
|
|
| < RBRACE: "}" > {SwitchTo(deque.pop());}
|
|
| < 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: ("\"" ((~["\"","\\"])
|
|
| ("\\" ( ["\\","\"","\'"] )))* "\"")
|
|
| ("\'" ((~["\'","\\"])
|
|
| ("\\" ( ["\\","\"","\'"] )))* "\'")
|
|
>
|
|
| < TRUE : "true" >
|
|
| < FALSE : "false" >
|
|
| < NULL : "null" >
|
|
| < DOT : "." >
|
|
| < LPAREN : "(" >
|
|
| < RPAREN : ")" >
|
|
| < LBRACK : "[" >
|
|
| < RBRACK : "]" >
|
|
| < COLON : ":" >
|
|
| < SEMICOLON : ";" >
|
|
| < COMMA : "," >
|
|
| < GT0 : ">" >
|
|
| < GT1 : "gt" >
|
|
| < LT0 : "<" >
|
|
| < LT1 : "lt" >
|
|
| < GE0 : ">=" >
|
|
| < GE1 : "ge" >
|
|
| < LE0 : "<=" >
|
|
| < LE1 : "le" >
|
|
| < EQ0 : "==" >
|
|
| < EQ1 : "eq" >
|
|
| < NE0 : "!=" >
|
|
| < NE1 : "ne" >
|
|
| < NOT0 : "!" >
|
|
| < NOT1 : "not" >
|
|
| < AND0 : "&&" >
|
|
| < AND1 : "and" >
|
|
| < OR0 : "||" >
|
|
| < OR1 : "or" >
|
|
| < EMPTY : "empty" >
|
|
| < INSTANCEOF : "instanceof" >
|
|
| < MULT : "*" >
|
|
| < PLUS : "+" >
|
|
| < MINUS : "-" >
|
|
| < QUESTIONMARK : "?" >
|
|
| < DIV0 : "/" >
|
|
| < DIV1 : "div" >
|
|
| < MOD0 : "%" >
|
|
| < MOD1 : "mod" >
|
|
| < CONCAT : "+=" >
|
|
| < ASSIGN : "=" >
|
|
| < ARROW : "->" >
|
|
| < IDENTIFIER : (<LETTER>|<IMPL_OBJ_START>) (<LETTER>|<DIGIT>)* >
|
|
| < FUNCTIONSUFFIX : (<IDENTIFIER>) >
|
|
| < #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"
|
|
]
|
|
>
|
|
| < ILLEGAL_CHARACTER: (~[]) >
|
|
}
|