添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
For more technical information about the JEXL Grammar, you can find the JavaCC grammar for JEXL here: Parser.jjt

Language Elements

Specified using ## or // and extend to the end of line, e.g. ## This is a comment Also specified using // , e.g. // This is a comment Multiple lines comments are specified using /*...*/ , e.g. /* This is a multi-line comment */ NOTE: JEXL does not support variables with hyphens in them, e.g. commons-logging // invalid variable name (hyphenated) is not a valid variable, but instead is treated as a subtraction of the variable logging from the variable commons JEXL also supports ant-style variables, the following is a valid variable name: my.dotted.var N.B. the following keywords are reserved, and cannot be used as a variable name or property when using the dot operator: or and eq ne lt gt le ge div mod not null true false new var do while break continue function return For example, the following is invalid: my.new.dotted.var // invalid ('new' is keyword) In such cases, quoted identifiers or the [ ] operator can be used, for example: my.'new'.dotted.var my['new'].dotted.var A script in JEXL is made up of zero or more statements, optionally enclosed in a function definition block. Scripts can include one or more pragmas. Scripts can be read from a String, File or URL. Scripts can be created with named parameters which allow a later evaluation to be performed with arguments. By default, in the absence of an explicit return statement, scripts return the value of the last evaluated statement. Using the return keyword, a script will return the expression that follows (or null). Declares a pragma, a method to communicate information from a script to its execution environment, e.g. #pragma execution.option 42 will declare a pragma named execution.option with a value of 42 .

Pragma keys can be identifiers or antish names, pragma values can be literals (boolean, integer, real, string, null, NaN) and antish names

Although pragmas are statements, they are not evaluated at runtime; they are constants associated to the script after parsing. It is expected that user code accesses the pragma map from scripts to alter some functions behavior.

There are 3 built-in pragmas:

jexl.options overrides the evaluation options using the option-flags syntax. #pragma jexl.options "+strict -safe +lexical +lexicalShade" will let the script run with the options strict being true, safe false, lexical true and lexical shade true. jexl.namespace. ns_prefix declares a namespace valid for the script execution lifetime, the value being the fully-qualified namespace class-name. #pragma jexl.namespace.str java.lang.String declare 'str' as the namespace using the String class. jexl.import works in conjunction with the 'new' operator. It declares the packages that a new ClassIdentifier(...) will visit - in declaration order - to resolve the class name into a fully-qualified class-name. #pragma jexl.import java.net will allow executing let url = new URL("https://commons.apache.org"); , the URL class name being solved as the java.net.URL fully-qualified class-name. A statement can be the empty statement, the semicolon ( ; ), block, conditional, variable declaration or an expression. Statements are optionally terminated with a semicolon. A single statement or a statement block can be annotated.
  • let declares a local variable (or a parameter) with a lexical block scope. The variable can only be accessed within its definition block and any nested sub-block. This also forbids variable redeclaration within that scope. Note: This emulates Java behavior which differs from ECMAScript.
  • const behaves as let but will prevent the variable from being reassigned by any side effect operator.
  • var declares a variable whose scope is the whole script and allows redefinition. This behavior is altered by the JexlFeature#setLexical(true) that will enforce a lexical scope for all variables akin to let declaration.
  • Invalid declaration: var x.y;
  • Local variables they take precedence in resolution over contextual variables. When scripts are created with named parameters, those behave as local variables. Local variables can not use ant-style naming, only one identifier. An expression can be the literal, variable, assignment, access operator, function definition, function call, method call or an evaluation operator. Assigns the value of a variable ( my.var = 'a value' ) using a JexlContext as initial resolver. Both beans and ant-ish variables assignment are supported. Defines a function within the script, usually associated with a local variable assignment. var fun = function(x, y) { x + y } The following syntaxes are also supported:
  • var fun = (x, y) -> { x + y }
  • var fun = (let x, let y) -> { x + y }
  • const fun = (const x, const y) -> { x + y }
  • function fun(const x, const y) { x + y }
  • If the function has only one argument the parentheses may be omitted var fun = x -> { x * x } . Functions with an expression as body can forego the curly brackets as in: var fun = x -> x * x .

    Note that functions can use local variables and parameters from their declaring script. Those variables values are bound to the function environment at definition time.

    var t = 20; var s = function(x, y) {x + y + t}; t = 54; s(15, 7) The function closure captures 't' when defined; the result of the evaluation will lead to 15 + 7 + 20 = 42 . Calling a function follows the usual convention, e.g. fun(17, 25) will call the fun function with arguments 17 and 25 Calls a method of an object, e.g. "hello world".hashCode() will call the hashCode method of the "hello world" String.

    In case of multiple arguments and overloading, JEXL will make the best effort to find the most appropriate non ambiguous method to call.

    Allows to evaluate a property of an object, a value of the collection or an array by using either square brackets or a dotted numeral, e.g. foo.bar will access the bar property of the foo Object. arr1[0] will access the first element of the arr1 array.

    The safe-access operator foo?.bar shortcuts any null or non-existent references along the navigation path, allowing a safe-navigation free of errors. In the previous expression, if 'foo' is null, the whole expression will evaluate as null. This is an efficient shortcut to defensive expressions such as x?.y?.z that would otherwise be expressed as x? (x.y? (x.y.z ?: null) :null) : null .

    Properties can also be quoted as in foo.'b a r' and can be dynamic back-quoted interpolation strings as in cal.`${dd.year}-${dd.month}-${dd.day}` . These syntaxes are mixable with safe-access as in foo.'b a r'?.quux or foo?.`${bar}`.quux .

    The safe-access array operator (as in foo?[bar] ) provides the same behavior as the safe-access operator and shortcuts any null or non-existent references along the navigation path, allowing a safe-navigation free of errors. In the previous expression, if 'foo' is null, the whole expression will evaluate as null. Note that this can also be used in a chain as in x?[y]?[z] .

    Access operators can be overloaded in JexlArithmetic , so that the operator behavior will differ depending on the type of the operator arguments

    Performs computational, logical or comparative action between one, two or three arguments whose values are expressions, e.g. 40 + 2 will call the add operator between two integer literals.

    All operators, except when stated otherwise, can be overloaded in JexlArithmetic , so that the action taken will differ depending on the type of the operator arguments

    Annotations in JEXL are 'meta-statements'; they allow to wrap the execution of the JEXL statement in a user provided caller; typical example would be: @synchronized(x) x.someMethod(); Annotations may be declared with zero or more parameters; @lenient x.someMethod(); @synchronized(x) x.someMethod(); @parallel(pool, 8) x.someMethod(); They also can be chained as in: @lenient @silent x.someMethod(); Annotation processing is implemented by providing a JexlContext.AnnotationProcessor; its processAnnotation method will call the annotated statement encapsulated in a Callable. Annotation arguments are evaluated and passed as arguments to processAnnotation. 1 or more digits from 0 to 9 , followed by a decimal point and then one or more digits from 0 to 9 , optionally followed by f or F , eg 42.0 or 42.0f . 1 or more digits from 0 to 9 , followed by a decimal point and then one or more digits from 0 to 9 suffixed with d or D , eg 42.0d . A special literal NaN can be used to denote Double.NaN constant 1 or more digits from 0 to 9 , followed by a decimal point and then one or more digits from 0 to 9 suffixed with b or B ) , eg 42.0b . Natural numbers (i.e. Integer, Long, BigInteger) can also be expressed as octal or hexadecimal using the same format as Java. i.e. prefix the number with 0 for octal, and prefix with 0x or 0X for hexadecimal. For example 010 or 0x10 . Real numbers (i.e. Float, Double, BigDecimal) can also be expressed using standard Java exponent notation. i.e. suffix the number with e or E followed by the sign + or - followed by one or more decimal digits. For example 42.0E-1D or 42.0E+3B . Can start and end with either ' or " delimiters, e.g. "Hello world" and 'Hello world' are equivalent.

    The escape character is \ (backslash). Unicode characters can be used in string literals;