<?xml version="1.0"?>
<!--
   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

        https://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.
-->

<document>
    <properties>
        <title>Apache Commons JEXL Syntax</title>
    </properties>

    <body>
        <section name="Overview">
            <p>
                This reference is split up into the following sections:
                <ol>
                    <li>
                        <a href="#Language Elements">Language Elements</a>
                    </li>
                    <li>
                        <a href="#Literals">Literals</a>
                    </li>
                    <li>
                        <a href="#Functions">Functions</a>
                    </li>
                    <li>
                        <a href="#Operators">Operators</a>
                    </li>
                    <li>
                        <a href="#Access">Access</a>
                    </li>
                    <li>
                        <a href="#Conditional">Conditional Statements</a>
                    </li>
                    <li>
                        <a href="#Control Flow">Flow Control</a>
                    </li>
                </ol>
            </p>
            <p>
                For more technical information about the JEXL Grammar, you can find the
                <a href="https://javacc.github.io/javacc">JavaCC</a> grammar for JEXL
                here: <a href="https://gitbox.apache.org/repos/asf?p=commons-jexl.git;a=blob;f=src/main/java/org/apache/commons/jexl3/parser/Parser.jjt">Parser.jjt</a>
            </p>
        </section>
        <section name="Language Elements">
            <table>
                <tr>
                    <th width="15%">Item</th>
                    <th>Description</th>
                </tr>
                <tr>
                    <td>Comments</td>
                    <td>
                        Specified using <code>##</code> or <code>//</code>and extend to the end of line, e.g.
                        <code>## This is a comment</code>
                        Also specified using <code>//</code>, e.g.
                        <code>// This is a comment</code>
                        Multiple lines comments are specified using <code>/*...*/</code>, e.g.
                        <code>/* This is a
                            multi-line comment */</code>
                    </td>
                </tr>
                <tr>
                    <td>Identifiers / variables</td>
                    <td>
                        Must start with <code>a-z</code>, <code>A-Z</code>, <code>_</code> or <code>$</code>.
                        Can then be followed by <code>0-9</code>, <code>a-z</code>, <code>A-Z</code>, <code>_</code> or <code>$</code>.
                        e.g.
                        <ul>
                            <li>Valid: <code>var1</code>,<code>_a99</code>,<code>$1</code></li>
                            <li>Invalid: <code>9v</code>,<code>!a99</code>,<code>1$</code></li>
                        </ul>
                        <p>
                            Variable names are <strong>case-sensitive</strong>, e.g. <code>var1</code> and <code>Var1</code> are different variables.
                        </p>
                        <p>
                            <strong>NOTE:</strong> JEXL does not support variables with hyphens in them, e.g.
                            <code>commons-logging // invalid variable name (hyphenated)</code> is not a valid variable, but instead is treated as a
                            subtraction of the variable <code>logging</code> from the variable <code>commons</code>
                        </p>
                        <p>
                            JEXL also supports <code>ant-style</code> variables, the following is a valid variable name:
                            <code>my.dotted.var</code>
                        </p>
                        <p>
                            <strong>N.B.</strong> the following keywords are reserved, and cannot be used as a variable name or property when using the dot operator:
                            <code>or and eq ne lt gt le ge div mod not null true false new var do while break continue function return</code>
                            For example, the following is invalid:
                            <code>my.new.dotted.var // invalid ('new' is keyword)</code>
                            In such cases, quoted identifiers or the [ ] operator can be used, for example:
                            <code>my.'new'.dotted.var</code>
                            <code>my['new'].dotted.var</code>
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>Scripts</td>
                    <td>
                        <p>
                            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.
                        </p>
                        <p>
                            Scripts can be read from a String, File or URL.
                        </p>
                        <p>
                            Scripts can be created with named parameters which allow a later evaluation to be performed with arguments.
                        </p>
                        <p>
                            By default, in the absence of an explicit <code>return</code> statement, scripts return the value of the
                            last evaluated statement.
                        </p>
                        <p>
                            Using the <code>return</code> keyword, a script will return the expression that follows (or null).
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>#pragma</td>
                    <td>
                        Declares a pragma, a method to communicate information from a script to its execution environment, e.g.
                        <code>#pragma execution.option 42</code> will declare a pragma named <code>execution.option</code> with
                        a value of <code>42</code>.
                        <p>Pragma keys can be identifiers or antish names, pragma values can be literals (boolean, integer,
                            real, string, null, NaN) and antish names</p>
                        <p>Although pragmas are statements, they are <em>not</em> 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.</p>
                        <p>There are 3 built-in pragmas:</p>
                        <p>
                            <b>jexl.options</b> overrides the evaluation options using the option-flags syntax.
                            <code>#pragma jexl.options "+strict -safe +lexical +lexicalShade"</code> will let the script run with
                            the options strict being true, safe false, lexical true and lexical shade true.
                        </p>
                        <p>
                            <b>jexl.namespace.<i>ns_prefix</i></b> declares a namespace valid for the script
                            execution lifetime, the value being the fully-qualified namespace class-name.
                            <code>#pragma jexl.namespace.str java.lang.String</code> declare 'str' as the namespace using
                            the String class.
                        </p>
                        <p>
                            <b>jexl.import</b> works in conjunction with the 'new' operator.
                            It declares the packages that a <code>new ClassIdentifier(...)</code> will visit - in
                            declaration order - to resolve the class name into a fully-qualified class-name.
                            <code>#pragma jexl.import java.net</code> will allow executing <code> let url = new URL("https://commons.apache.org");</code>,
                            the URL class name being solved as the java.net.URL fully-qualified class-name.
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>Statements</td>
                    <td>
                        A statement can be the empty statement, the semicolon (<code>;</code>), block, conditional, variable declaration or an expression.
                        Statements are optionally terminated with a semicolon.
                        A single statement or a statement block can be annotated.
                    </td>
                </tr>
                <tr>
                    <td>Block</td>
                    <td>
                        A block is simply multiple statements inside curly braces (<code>{, }</code>).
                    </td>
                </tr>
                <tr>
                    <td>Local variables</td>
                    <td>Can be defined using the <code>let</code>, <code>const</code> and <code>var</code> keywords;
                        their identifying rules are the same as contextual variables.
                        <ul>
                            <li><code>let</code> 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.</li>
                            <li><code>const</code> behaves as <code>let</code> but will prevent the variable from being
                            reassigned by any side effect operator.</li>
                            <li>
                            <code>var</code> declares a variable whose scope is the whole script and allows redefinition.
                            This behavior is altered by the <code>JexlFeature#setLexical(true)</code> that will enforce a
                            lexical scope for all variables akin to <code>let</code>  declaration.
                            </li>
                        </ul>
                        <ul>
                            <li>Basic declaration: <code>let x;</code></li>
                            <li>Declaration with assignment: <code>const theAnswer = 42;</code></li>
                            <li>Invalid declaration: <code>var x.y;</code></li>
                        </ul>
                        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 <code>ant-style</code> naming, only one identifier.
                    </td>
                </tr>
                <tr>
                    <td>Expression</td>
                    <td>
                        An expression can be the literal, variable, assignment, access operator, function definition, function call, method call or
                        an evaluation operator.
                    </td>
                </tr>
                <tr>
                    <td>Assignment</td>
                    <td>
                        Assigns the value of a variable  (<code>my.var = 'a value'</code>) using a
                        <code>JexlContext</code> as initial resolver. Both <em>beans</em> and <em>ant-ish</em>
                        variables assignment are supported.
                    </td>
                </tr>
                <tr>
                    <td>Function definition</td>
                    <td>
                        Defines a function within the script, usually associated with a local variable assignment.
                        <code>var fun = function(x, y) { x + y }</code>
                        The following syntaxes are also supported:
                        <ul>
                            <li><code>var fun = (x, y) -> { x + y }</code></li>
                            <li><code>var fun = (let x, let y) -> { x + y }</code></li>
                            <li><code>const fun = (const x, const y) -> { x + y }</code></li>
                            <li><code>function fun(const x, const y) { x + y }</code></li>
                        </ul>
                        If the function has only one argument the parentheses may be omitted
                        <code>var fun = x -> { x * x }</code>.
                        Functions with an expression as body can forego the curly brackets as in:
                        <code>var fun = x -> x * x </code>.
                        <p>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.</p>
                        <code>var t = 20; var s = function(x, y) {x + y + t}; t = 54; s(15, 7)</code>
                        The function closure captures 't' when defined; the result of the evaluation will
                        lead to <code>15 + 7 + 20 = 42</code>.
                    </td>
                </tr>
                <tr>
                    <td>Function call</td>
                    <td>
                        Calling a function follows the usual convention, e.g.
                        <code>fun(17, 25)</code> will call the <code>fun</code> function with arguments <code>17</code>
                        and <code>25</code>
                    </td>
                </tr>
                <tr>
                    <td>Method call</td>
                    <td>
                        Calls a method of an object, e.g.
                        <code>"hello world".hashCode()</code> will call the <code>hashCode</code> method
                        of the <code>"hello world"</code> String.
                        <p>In case of multiple arguments and overloading, JEXL will make the best effort to find
                            the most appropriate non ambiguous method to call.</p>
                    </td>
                </tr>
                <tr>
                    <td>Access Operator</td>
                    <td>
                        <p>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.
                        <code>foo.bar</code> will access the <code>bar</code> property
                        of the <code>foo</code> Object.
                        <code>arr1[0]</code> will access the first element of the <code>arr1</code> array.</p>
                        <p>The safe-access operator <code>foo?.bar</code> 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 <code>x?.y?.z</code> that would otherwise be expressed as
                        <code>x? (x.y? (x.y.z ?: null) :null) : null</code>.</p>
                        <p>Properties can also be quoted as in <code>foo.'b a r'</code> and can be dynamic
                        back-quoted interpolation strings as in <code>cal.`${dd.year}-${dd.month}-${dd.day}`</code>.
                        These syntaxes are mixable with safe-access as in <code>foo.'b a r'?.quux</code> or <code>
                            foo?.`${bar}`.quux</code>.</p>
                        <p>The safe-access array operator (as in <code>foo?[bar]</code>) 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 <code>x?[y]?[z]</code>.
                        </p>
                        <p>Access operators can be overloaded in <code>JexlArithmetic</code>, so that
                           the operator behavior will differ depending on the type of the operator arguments</p>
                    </td>
                </tr>
                <tr>
                    <td>Evaluation Operator</td>
                    <td>
                        Performs computational, logical or comparative action between one, two or three arguments
                        whose values are expressions, e.g.
                        <code>40 + 2</code> will call the <code>add</code> operator
                        between two integer literals.
                        <p>All operators, except when stated otherwise, can be overloaded in <code>JexlArithmetic</code>, so that the action taken
                           will differ depending on the type of the operator arguments</p>
                    </td>
                </tr>
                <tr>
                    <td>@annotation</td>
                    <td>
                        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: <code>@synchronized(x) x.someMethod();</code>
                        <p>
                            Annotations may be declared with zero or more parameters;
                            <code>@lenient x.someMethod();</code>
                            <code>@synchronized(x) x.someMethod();</code>
                            <code>@parallel(pool, 8) x.someMethod();</code>
                        </p>
                        <p>
                            They also can be chained as in:
                            <code>@lenient @silent x.someMethod();</code>
                        </p>
                        <p>
                        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.
                        </p>
                    </td>
                </tr>
            </table>
        </section>
        <section name="Literals">
            <table>
                <tr>
                    <th width="15%">Item</th>
                    <th>Description</th>
                </tr>
                <tr>
                    <td>Integer Literals</td>
                    <td>1 or more digits from <code>0</code> to <code>9</code>, eg <code>42</code>.
                    </td>
                </tr>
                <tr>
                    <td>Float Literals</td>
                    <td>
                        1 or more digits from <code>0</code> to <code>9</code>, followed
                        by a decimal point and then one or more digits from
                        <code>0</code> to <code>9</code>,
                        optionally followed by <code>f</code> or <code>F</code>,
                        eg <code>42.0</code> or <code>42.0f</code>.
                    </td>
                </tr>
                <tr>
                    <td>Long Literals</td>
                    <td>1 or more digits from <code>0</code> to <code>9</code> suffixed with <code>l</code> or <code>L</code>
                        , eg <code>42l</code>.
                    </td>
                </tr>
                <tr>
                    <td>Double Literals</td>
                    <td>
                        1 or more digits from <code>0</code> to <code>9</code>, followed
                        by a decimal point and then one or more digits from
                        <code>0</code> to <code>9</code> suffixed with <code>d</code> or <code>D</code>
                        , eg <code>42.0d</code>.
                        A special literal <code>NaN</code> can be used to denote <code>Double.NaN</code> constant
                    </td>
                </tr>
                <tr>
                    <td>BigInteger Literals</td>
                    <td>1 or more digits from <code>0</code> to <code>9</code> suffixed with <code>h</code> or <code>H</code>
                        (for Huge ala OGNL, "does not interfere with hexa-decimal digits"), eg <code>42h</code>.
                    </td>
                </tr>
                <tr>
                    <td>BigDecimal Literals</td>
                    <td>
                        1 or more digits from <code>0</code> to <code>9</code>, followed
                        by a decimal point and then one or more digits from
                        <code>0</code> to <code>9</code> suffixed with <code>b</code> or <code>B</code>)
                        , eg <code>42.0b</code>.
                    </td>
                </tr>
                <tr>
                    <td>Natural literals - octal and hex support</td>
                    <td>
                        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 <code>0</code> for octal, and prefix with <code>0x</code> or <code>0X</code> for hexadecimal.
                        For example <code>010</code> or <code>0x10</code>.
                    </td>
                </tr>
                <tr>
                    <td>Real literals - exponent support</td>
                    <td>
                        Real numbers (i.e. Float, Double, BigDecimal) can also be expressed using standard Java exponent notation.
                        i.e. suffix the number with <code>e</code> or <code>E</code> followed by the sign <code>+</code> or <code>-</code>
                        followed by one or more decimal digits.
                        For example <code>42.0E-1D</code> or <code>42.0E+3B</code>.
                    </td>
                </tr>
                <tr>
                    <td>String literals</td>
                    <td>
                        Can start and end with either <code>'</code> or <code>"</code> delimiters, e.g.
                        <code>"Hello world"</code> and
                        <code>'Hello world'</code> are equivalent.
                        <p>The escape character is <code>\</code> (backslash).
                        Unicode characters can be used in string literals;
                            <ul>Unicode escape sequences consist of:
                                <li> a backslash '\' </li>
                                <li>a 'u' </li>
                                <li>4 hexadecimal digits ([0-9],[A-H],[a-h]).</li>
                            </ul>
                            Such sequences represent the UTF-16 encoding of a Unicode character,
                            for example, <code>'a'</code> is equivalent to <code>'\u0061'</code>.
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>Multiline format literals</td>
                    <td>
                        Start and end with <code>`</code> delimiter - back-quote -, e.g. <code>`Hello world`</code>
                        <p>The escape character is <code>\</code> (backslash); Unicode escape sequences can also be used.</p>
                        These format literals can span multiple lines and allow Unified JEXL expressions (JSTL like expressions)
                        to be interpolated. If a variable <code>user</code> valued <code>JEXL</code>is present in the environment - whether
                        as a local or global variable -, the format <code>`Hello ${user}`</code> will evaluate as <code>Hello JEXL</code>.
                    </td>
                </tr>
                <tr>
                    <td>Regular expression (regex) literals</td>
                    <td>
                        Start with <code>~/</code> and ends with <code>/</code> delimiters, e.g.
                        <code>~/ABC.*/</code>
                        <p>The escape character is <code>\</code> (backslash); it only escapes the string delimiter <code>\</code> (slash)</p>
                    </td>
                </tr>
                <tr>
                    <td>Boolean literals</td>
                    <td>
                        The literals <code>true</code> and <code>false</code> can be used, e.g.
                        <code>val1 == true</code>
                    </td>
                </tr>
                <tr>
                    <td>Null literal</td>
                    <td>
                        The null value is represented as in java using the literal <code>null</code>, e.g.
                        <code>val1 == null</code>
                    </td>
                </tr>
                <tr>
                    <td>Array literal</td>
                    <td>
                        A <code>[</code> followed by zero or more expressions separated by <code>,</code> and ending
                        with <code>]</code>, e.g.
                        <code>[ 1, 2, "three" ]</code>
                        <p>This syntax creates an <code>Object[]</code>.</p>
                        <p>Empty array literal can be specified as <code>[]</code> with result of creating <code>Object[]</code></p>
                        <p>
                            JEXL will attempt to strongly type the array; if all entries are of the same class or if all
                            entries are Number instance, the array literal will be an <code>MyClass[]</code> in the former
                            case, a <code>Number[]</code> in the latter case.</p>
                        <p>Furthermore, if all entries in the array literal are of the same class
                            and that class has an equivalent primitive type, the array returned will be a primitive array. e.g.
                            <code>[1, 2, 3]</code> will be interpreted as <code>int[]</code>.</p>
                    </td>
                </tr>
                <tr>
                    <td>List literal</td>
                    <td>
                        A <code>[</code> followed by zero or more expressions separated by <code>,</code> and ending
                        with <code>,...]</code>, e.g.
                        <code>[ 1, 2, "three",...]</code>
                        <p>This syntax creates an <code>ArrayList&lt;Object&gt;</code>.</p>
                        <p>Empty list literal can be specified as <code>[...]</code></p>
                    </td>
                </tr>
                <tr>
                    <td>Set literal</td>
                    <td>
                        A <code>{</code> followed by zero or more expressions separated by <code>,</code> and ending
                        with <code>}</code>, e.g.
                        <code>{ "one" , 2, "more"}</code>
                        <p>This syntax creates a <code>HashSet&lt;Object&gt;</code>.</p>
                        <p>Empty set literal can be specified as <code>{}</code></p>
                    </td>
                </tr>
                <tr>
                    <td>Map literal</td>
                    <td>
                        A <code>{</code> followed by zero or more sets of <code>key : value</code> pairs separated by <code>,</code> and ending
                        with <code>}</code>, e.g.
                        <code>{ "one" : 1, "two" : 2, "three" : 3, "more": "many more" }</code>
                        <p>This syntax creates a <code>HashMap&lt;Object,Object&gt;</code>.</p>
                        <p>Empty map literal can be specified as <code>{:}</code></p>
                    </td>
                </tr>

                <tr>
                    <td>Range literal</td>
                    <td>
                        A value followed by <code>..</code> and ending with other value, e.g.
                        <code>1 .. 42</code>
                        <p>This syntax creates a 'range' object in the form of a java iterable which can be used in for statement, e.g.
                           <code>for (i : 1..42) a = a + b[i]</code></p>
                    </td>
                </tr>

            </table>
        </section>
        <section name="Functions">
            <table>
                <tr>
                    <th width="15%">Function</th>
                    <th>Description</th>
                </tr>
                <tr>
                    <td>empty</td>
                    <td>
                        Evaluates whether an expression if 'empty'.
                        This is true when the argument is:
                        <ol>
                            <li>
                                <code>null</code>
                            </li>
                            <li>An instance of class C and the derived JexlArithmetic overloads a method 'public boolean empty(C arg)'
                                that returns true when the argument is considered empty</li>
                            <li>An empty string</li>
                            <li>An array of length zero</li>
                            <li>A collection of size zero</li>
                            <li>An empty map</li>
                            <li>Defining a method 'public boolean isEmpty()'
                                that returns true when the instance is considered empty</li>
                        </ol>
                        This is false in other cases (besides errors).
                        <code>empty(arg)</code>
                    </td>
                </tr>
                <tr>
                    <td>size</td>
                    <td>
                        Evaluates the 'size' of an expression.
                        This returns:
                        <ol>
                            <li>0 if the argument is null</li>
                            <li>The result of calling a method from a derived JexlArithmetic overload 'public int size(C arg)',
                                C being the class of the argument</li>
                            <li>Length of an array</li>
                            <li>Length of a string</li>
                            <li>Size of a Collection</li>
                            <li>Size of a Map</li>
                            <li>The result of calling a method 'public int size()' defined by the argument class</li>
                        </ol>
                        This returns 0 in other cases (besides errors).
                        <code>size("Hello")</code> returns 5.
                    </td>
                </tr>
                <tr>
                    <td>new</td>
                    <td>
                        Creates a new instance using a fully-qualified class name or Class:
                        <code>new("java.lang.Double", 10)</code> returns 10.0.
                        <p>Note that the first argument of <code>new</code> can be a variable or any
                            expression evaluating as a String or Class; the rest of the arguments are used
                            as arguments to the constructor for the class considered.</p>
                        <p>In case of multiple constructors, JEXL will make the best effort to find
                            the most appropriate non ambiguous constructor to call.</p>
                        <p>
                        Alternatively, using <code>#pragma jexl.import java.lang</code>code>, one can use the
                        following syntax: <code>new Double(10)</code>.
                        </p>
                    </td>
                </tr>
                <tr>
                    <td>Top level function</td>
                    <td>
                        Top level function is a function which can be invoked without specifying a namespace.
                        <p>Top level function can be defined by the function definition method inside the script</p>
                        <p>A <code>JexlContext</code> can define methods which can be invoked as top level functions.
                        This can allow expressions like:
                        <code>string(23.0)</code></p>
                        <p>Another way to define top level function is to register to <code>JexlEngine</code> objects or classes
                           with null namespace.</p>

                    </td>
                </tr>
                <tr>
                    <td>ns:function</td>
                    <td>
                        A <code>JexlEngine</code> can register objects or classes used as function namespaces.
                        This can allow expressions like:
                        <code>math:cosinus(23.0)</code>
                    </td>
                </tr>
            </table>
        </section>
        <section name="Operators">
            <table>
                <tr>
                    <th width="15%">Operator</th>
                    <th>Description</th>
                </tr>
                <tr>
                    <td>Boolean <code>and</code></td>
                    <td>
                        <p>The usual <code>&amp;&amp;</code> operator can be used as well as the word <code>and</code>, e.g.
                        <code>cond1 and cond2</code> and
                        <code>cond1 &amp;&amp; cond2</code> are equivalent.</p>
                        <p>Note that this operator can not be overloaded</p>
                    </td>
                </tr>
                <tr>
                    <td>Boolean <code>or</code></td>
                    <td>
                        <p>The usual <code>||</code> operator can be used as well as the word <code>or</code>, e.g.
                        <code>cond1 or cond2</code> and
                        <code>cond1 || cond2</code> are equivalent.</p>
                        <p>Note that this operator can not be overloaded</p>
                    </td>
                </tr>
                <tr>
                    <td>Boolean <code>not</code></td>
                    <td>
                        <p>The usual <code>!</code> operator can be used as well as the word <code>not</code>, e.g.
                        <code>!cond1</code> and
                        <code>not cond1</code> are equivalent.</p>
                        <p>Note that this operator can not be overloaded</p>
                    </td>
                </tr>
                <tr>
                    <td>Bitwise <code>and</code></td>
                    <td>
                        The usual <code>&amp;</code> operator is used, e.g.
                        <code>33 &amp; 4</code>, 0010 0001 &amp; 0000 0100 = 0.
                    </td>
                </tr>
                <tr>
                    <td>Bitwise <code>or</code></td>
                    <td>
                        The usual <code>|</code> operator is used, e.g.
                        <code>33 | 4</code>, 0010 0001 | 0000 0100 = 0010 0101 = 37.
                    </td>
                </tr>
                <tr>
                    <td>Bitwise <code>xor</code></td>
                    <td>
                        The usual <code>^</code> operator is used, e.g.
                        <code>33 ^ 4</code>, 0010 0001 ^ 0000 0100 = 0010 0100 = 37.
                    </td>
                </tr>
                <tr>
                    <td>Bitwise <code>complement</code></td>
                    <td>
                        The usual <code>~</code> operator is used, e.g.
                        <code>~33</code>, ~0010 0001 = 1101 1110 = -34.
                    </td>
                </tr>
                <tr>
                    <td>Left-shift <code>&lt;&lt;</code></td>
                    <td>
                    The left shift operator (&lt;&lt;) shifts the first operand the specified number of bits to the left.
                        <code>1 &lt;&lt; 2</code> = 4
                    </td>
                </tr>
                <tr>
                    <td>Right-shift <code>&gt;&gt;</code></td>
                    <td>
                        The right shift operator (>>) shifts the first operand the specified number of bits to the right.
                        <code>4 &gt;&gt; 2</code> = 1
                    </td>
                </tr>
                <tr>
                    <td>Unsigned Right-shift <code>&gt;&gt;&gt;</code></td>
                    <td>
                    (zero-fill right shift) shifts the first operand the specified number of bits to the right.
                    The sign bit becomes 0, so the result is always non-negative.
                    </td>
                </tr>
                <tr>
                    <td>Ternary conditional <code>?:</code> </td>
                    <td>
                        The usual ternary conditional operator <code>condition ? if_true : if_false</code> operator can be
                        used as well as the abbreviation <code>value ?: if_false</code> which returns the <code>value</code> if
                        its evaluation is defined, non-null and non-false, e.g.
                        <code>val1 ? val1 : val2</code> and
                        <code>val1 ?: val2 </code> are equivalent.
                        <p>
                            <strong>NOTE:</strong> The condition will evaluate to <code>false</code> when it
                            refers to an undefined variable or <code>null</code> for all <code>JexlEngine</code>
                            flag combinations. This allows explicit syntactic leniency and treats the condition
                            'if undefined or null or false' the same way in all cases.
                        </p>
                        <p>Note that this operator can not be overloaded</p>
                    </td>
                </tr>
                <tr>
                    <td>Null coalescing operator <code>??</code> </td>
                    <td>
                        The null coalescing operator returns the result of its first operand if it is defined and is not null.
                        <p>When <code>x</code>and<code>y</code>are null or undefined,
                            <code>x ?? 'unknown or null x'</code> evaluates as  <code>'unknown or null x'</code>
                            <code>y ?? "default"</code> evaluates as  <code>"default"</code>.
                        </p>
                        <p>
                            When <code>var x = 42</code> and  <code>var y = "forty-two"</code>,<code>x??"other"</code>
                            evaluates as <code>42</code> and <code>y??"other"</code> evaluates as <code>"forty-two"</code>.
                        </p>
                        <p>
                            <strong>NOTE:</strong> this operator does not behave like the ternary conditional since it
                            does not coerce the first argument to a boolean to evaluate the condition.
                            When <code>var x = false</code> and  <code>var y = 0</code>,<code>x??true</code>
                            evaluates as <code>false</code> and <code>y??1</code> evaluates as <code>0</code>.
                        </p>
                        <p>Note that this operator can not be overloaded</p>
                    </td>
                </tr>
                <tr>
                    <td>Equality</td>
                    <td>
                        The equality <code>==</code> operator checks whether its two operands are equal, returning a
                        Boolean result. Unlike the strict equality operator, it attempts to convert and compare
                        operands that are of different types.
                        <ol>
                            <li>
                                <code>null</code> is only ever equal to null, that is if you compare null
                                to any non-null value, the result is false.
                            </li>
                            <li>Equality uses the java <code>equals</code> method</li>
                        </ol>
                    </td>
                </tr>
                <tr>
                    <td>Inequality</td>
                    <td>
                        The inequality <code>!=</code> operator checks whether its two operands are not equal,
                        returning a Boolean result. Unlike the strict inequality operator, it attempts to convert and
                        compare operands that are of different types.
                    </td>
                </tr>
                <tr>
                    <td>Strict-Equality</td>
                    <td>The strict equality <code>===</code> operator checks whether its two operands are equal,
                        returning a Boolean result. Unlike the equality operator, the strict equality operator always
                        considers operands of different types to be different.
                    </td>
                </tr>
                <tr>
                    <td>Strict Inequality</td>
                    <td>
                        The strict inequality <code>!==</code> operator checks whether its two operands are not equal,
                        returning a Boolean result. Unlike the inequality operator, the strict inequality operator
                        always considers operands of different types to be different
                    </td>
                </tr>
                <tr>
                    <td>Less Than</td>
                    <td>
                        The usual <code>&lt;</code> operator can be used as well as the abbreviation <code>lt</code>.
                        For example
                        <code>val1 &lt; val2</code> and
                        <code>val1 lt val2</code> are equivalent.
                    </td>
                </tr>
                <tr>
                    <td>Less Than Or Equal To</td>
                    <td>
                        The usual <code>&lt;=</code> operator can be used as well as the abbreviation <code>le</code>.
                        For example
                        <code>val1 &lt;= val2</code> and
                        <code>val1 le val2</code> are equivalent.
                    </td>
                </tr>
                <tr>
                    <td>Greater Than</td>
                    <td>
                        The usual <code>&gt;</code> operator can be used as well as the abbreviation <code>gt</code>.
                        For example
                        <code>val1 &gt; val2</code> and
                        <code>val1 gt val2</code> are equivalent.
                    </td>
                </tr>
                <tr>
                    <td>Greater Than Or Equal To</td>
                    <td>
                        The usual <code>&gt;=</code> operator can be used as well as the abbreviation <code>ge</code>.
                        For example
                        <code>val1 &gt;= val2</code> and
                        <code>val1 ge val2</code> are equivalent.
                    </td>
                </tr>
                <tr>
                    <td>In or Match<code>=~</code></td>
                    <td>
                        The syntactically Perl inspired <code>=~</code> operator can be used to check that a <code>string</code> matches
                        a regular expression (expressed either a Java String or a java.util.regex.Pattern).
                        For example
                        <code>"abcdef" =~ "abc.*</code> returns <code>true</code>.
                        It also checks whether any collection, set or map (on keys) contains a value or not; in that case, it behaves
                        as an "in" operator.
                        Note that arrays and user classes exposing a public 'contains' method will allow their instances
                        to behave as right-hand side operands of this operator.
                        <code> "a" =~ ["a","b","c","d","e",f"]</code> returns <code>true</code>.
                    </td>
                </tr>
                <tr>
                    <td>Not-In or Not-Match<code>!~</code></td>
                    <td>
                        The syntactically Perl inspired <code>!~</code> operator can be used to check that a <code>string</code> does not
                        match a regular expression (expressed either a Java String or a java.util.regex.Pattern).
                        For example
                        <code>"abcdef" !~ "abc.*</code> returns <code>false</code>.
                        It also checks whether any collection, set or map (on keys) does not contain a value; in that case, it behaves
                        as "not in" operator.
                        Note that arrays and user classes exposing a public 'contains' method will allow their instances
                        to behave as right-hand side operands of this operator.
                        <code> "a" !~ ["a","b","c","d","e",f"]</code> returns <code>false</code>.
                    </td>
                </tr>
                 <tr>
                    <td>Starts With<code>=^</code></td>
                    <td>
                        The <code>=^</code> operator is a short-hand for the 'startsWith' method.
                        For example, <code> "abcdef" =^ "abc" </code> returns <code>true</code>.
                        Note that through duck-typing, user classes exposing a public 'startsWith' method will allow their instances
                        to behave as left-hand side operands of this operator.
                    </td>
                </tr>
                <tr>
                    <td>Not Starts With<code>!^</code></td>
                    <td>
                        This is the negation of the 'starts with' operator.
                        <code>a !^ "abc"</code> is equivalent to <code>!(a =^ "abc")</code>
                    </td>
                </tr>
                <tr>
                    <td>Ends With<code>=$</code></td>
                    <td>The <code>=$</code> operator is a short-hand for the 'endsWith' method.
                        For example, <code> "abcdef" =$ "def" </code> returns <code>true</code>.
                        Note that through duck-typing, user classes exposing an 'endsWith' method will allow their instances
                        to behave as left-hand side operands of this operator.
                    </td>
                </tr>
                <tr>
                    <td>Not Ends With<code>!$</code></td>
                    <td>
                        This is the negation of the 'ends with' operator.
                        <code>a !$ "abc"</code> is equivalent to <code>!(a =$ "abc")</code>
                    </td>
                </tr>
                <tr>
                    <td>Addition</td>
                    <td>
                        The usual <code>+</code> operator is used.
                        For example
                        <code>val1 + val2</code>
                    </td>
                </tr>
                <tr>
                    <td>Subtraction</td>
                    <td>
                        The usual <code>-</code> operator is used.
                        For example
                        <code>val1 - val2</code>
                    </td>
                </tr>
                <tr>
                    <td>Multiplication</td>
                    <td>
                        The usual <code>*</code> operator is used.
                        For example
                        <code>val1 * val2</code>
                    </td>
                </tr>
                <tr>
                    <td>Division</td>
                    <td>
                        The usual <code>/</code> operator is used, or one can use the <code>div</code> operator.
                        For example
                        <code>val1 / val2</code>
                        or
                        <code>val1 div val2</code>
                    </td>
                </tr>
                <tr>
                    <td>Modulus (or remainder)</td>
                    <td>
                        The <code>%</code> operator is used. An alternative is the <code>mod</code>
                        operator.
                        For example
                        <code>5 mod 2</code> gives 1 and is equivalent to <code>5 % 2</code>
                    </td>
                </tr>
                <tr>
                    <td>Side-effect operators</td>
                    <td>
                        Some operators exist in side-effect forms.
                        Their default behavior is to execute the operator and assign the left-hand side with the result.
                        For instance <code>a += 2</code> is equivalent to <code>a = a + 2</code>
                        The list of operators is:
                        <ul>
                            <li>+=</li>
                            <li>-=</li>
                            <li>*=</li>
                            <li>/=</li>
                            <li>%=</li>
                            <li>&amp;=</li>
                            <li>|=</li>
                            <li>^=</li>
                            <li>&lt;&lt;=</li>
                            <li>&gt;&gt;=</li>
                            <li>&gt;&gt;&gt;=</li>
                        </ul>
                    </td>
                </tr>
                <tr>
                    <td>Negate</td>
                    <td>
                        The unary <code>-</code> operator is used. It changes the sign of its numeric argument.
                        For example <code>-12</code> or <code>-(a * b)</code>
                    </td>
                </tr>
                <tr>
                    <td>Positivize</td>
                    <td>
                        The unary <code>+</code> operator is used. It performs an integral promotion meaning
                        that byte, short, char arguments will be promoted to integer as a result.
                        For example  <code>+12</code> or <code>+(a * b)</code>
                    </td>
                </tr>
                <tr>
                    <td>Empty</td>
                    <td>
                        The unary <code>empty</code> operator behaves exactly as the corresponding function <code>empty()</code>.
                        For example <code>empty arg</code> and <code>empty(arg)</code> are equivalent
                    </td>
                </tr>
                <tr>
                    <td>Size</td>
                    <td>
                        The unary <code>size</code> operator behaves exactly as the corresponding function <code>size()</code>.
                        For example <code>size [1,2,3]</code> and <code>size([1,2,3])</code> are equivalent
                    </td>
                </tr>
                <tr>
                    <td>instanceof/!instanceof</td>
                    <td>The instanceof operator allows to check whether an object belongs to a certain class.
                        It is using Class.isInstance to perform the check. As a convenience, {{ !instanceof }} is
                        supported as well.
                    </td>
                </tr>
            </table>
        </section>
        <section name="Access">
            <table>
                <tr>
                    <th width="15%">Operator</th>
                    <th>Description</th>
                </tr>
                <tr>
                    <td>Array access</td>
                    <td>
                        Array elements may be accessed using either square brackets or a dotted numeral, e.g.
                        <code>arr1[0]</code> and <code>arr1.0</code> are equivalent
                    </td>
                </tr>
                <tr>
                    <td>List access</td>
                    <td>
                        List elements may be accessed using either square brackets or a dotted numeral, e.g.
                        <code>list[0]</code> and <code>list.0</code> are equivalent
                    </td>
                </tr>
                <tr>
                    <td>Map access</td>
                    <td>
                        Map elements are accessed using square brackets, e.g.
                        <code>map[0]; map['name']; map[var];</code>
                        Note that <code>map['7']</code> and <code>map[7]</code> refer to different elements.
                        Map elements with a numeric key may also be accessed using a dotted numeral, e.g.
                        <code>map[0]</code> and <code>map.0</code> are equivalent.
                        <p>Note that <code>map.1</code> and <code>map.01</code> refer to different elements,
                        while <code>map.1</code> and <code>map[01]</code> are equivalent.</p>
                    </td>
                </tr>
                <tr>
                    <td>JavaBean property access</td>
                    <td>
                        Properties of JavaBean objects that define appropriate getter methods can be accessed
                        using either square brackets or a dotted numeral, e.g.
                        <code>foo['bar']</code> and <code>foo.bar</code> are equivalent.
                        The appropriate <code>Foo.getBar()</code> method will be called.
                        <p>Note that both <code>foo.Bar</code> and <code>foo.bar</code> can be used</p>
                    </td>
                </tr>
                <tr>
                    <td>Indexed JavaBean property access</td>
                    <td>
                        Indexed properties of JavaBean objects that define appropriate getter methods can be accessed
                        using either square brackets or a dotted numeral, e.g.
                        <code>x.attribute['name']</code> and <code>x.attribute.name</code> are equivalent.
                        The appropriate <code>Foo.getAttribute(String index)</code> method will be called
                    </td>
                </tr>
                <tr>
                    <td>Public field access</td>
                    <td>
                        Public fields of java objects can be accessed using either square brackets or a dotted numeral, e.g.
                        <code>foo['bar']</code> and <code>foo.bar</code> are equivalent.
                    </td>
                </tr>
                <tr>
                    <td>Duck-typed collection property access</td>
                    <td>
                        Properties of Java classes that define public <code>Object get(String name)</code> method can be accessed
                        using either square brackets or a dotted numeral, e.g.
                        <code>foo['bar']</code> and <code>foo.bar</code> are equivalent.
                        The appropriate <code>Foo.get(String index)</code> method will be called with the argument of <code>"bar"</code> String
                    </td>
                </tr>
            </table>
        </section>
        <section name="Conditional">
            <table>
                <tr>
                    <th width="15%">Statement</th>
                    <th>Description</th>
                </tr>
                <tr>
                    <td>if</td>
                    <td>
                        Classic, if/else statement, e.g.
                        <code>if ((x * 2) == 5) {
                            y = 1;
                            } else {
                            y = 2;
                            }</code>
                    </td>
                </tr>
                <tr>
                    <td>for</td>
                    <td>
                        <p>Loop through items of an Array, Collection, Map, Iterator or Enumeration, e.g.
                        <code>for (let item : list) {
                            x = x + item;
                            }</code>
                        Where <code>list</code> is a context variable pointing to any iterable structure.
                        </p>
                        <p>The following syntax using a context variable is also supported:
                        <code>for (item : list) {
                            x = x + item;
                            }</code>
                        Note that the loop variable <code>item</code> is accessible after loop evaluation</p>
                        <p>Finally, the conventional syntax using a local variable, initial value, loop condition and
                            loop step is supported.
                            <code>for (let i = 0; i &lt; size(list); ++i) {
                                x = x + list[i];
                                }</code>

                            Where <code>list</code> is a local variable pointing to an array-like structure.</p>
                        <p>The JEXL 1.1 syntax using <code>foreach(item in list)</code> is now <strong>unsupported</strong>.</p>
                    </td>
                </tr>
                <tr>
                    <td>while</td>
                    <td>
                        Loop until a condition is satisfied, e.g.
                        <code>while (x &lt; 10) {
                            x = x + 2;
                            }</code>
                    </td>
                </tr>
                <tr>
                    <td>do/while</td>
                    <td>
                        Loop until a condition is satisfied, e.g.
                        <code>do {
                            x = x + 2;
                            } while (x &lt; 10)</code>
                    </td>
                </tr>
            </table>
        </section>

        <section name="Control Flow">
            <table>
                <tr>
                    <th width="15%">Statement</th>
                    <th>Description</th>
                </tr>
                <tr>
                    <td>if</td>
                    <td>
                        Classic, if/else statement, e.g.
                        <br/>
                        <code>if ((x * 2) == 5) {
                            y = 1;
                            } else {
                            y = 2;
                            }</code>
                    </td>
                </tr>
                <tr>
                    <td>continue</td>
                    <td>
                        Within loops (do/while/for), terminates execution of the statements in the current iteration
                        and skips to the next loop iteration.
                        <br/>
                    <code>
                        let text = '';
                        for (let i : (4..2)) {
                        if (i === 3) {
                        continue;
                        }
                        text += i;
                        }
                        text;
                    </code>
                    Will evaluate as "42".
                    </td>
                </tr>
                <tr>
                    <td>break</td>
                    <td>
                        Within loops (do/while/for), terminates execution of the statements in the current iteration
                        and exits the loop.
                        <br/>
                    <code>
                        let i = 33;
                        while (i &lt; 66) {
                        if (i == 42) {
                        break;
                        }
                        i += 1;
                        }
                        i;
                    </code>
                    Will evaluate as 42.
                    </td>
                </tr>
                <tr>
                    <td>return</td>
                    <td>
                        The return statement ends execution and specifies a value to be returned to the script
                        or lambda caller.
                        <br/>
                        <code>
                            function f(x) {
                                if (x == 42) {
                                    return "The answer to life, the universe, and everything";
                                }
                                return x
                            }
                            f(41);
                        </code>
                        Will evaluate as 41.
                    </td>
                </tr>
                <tr>
                    <td>throw</td>
                    <td>
                        The throw statement throws an object. Execution of the current script will stop
                        (the statements after throw won't be executed), and control will be passed to the first catch
                        block in the call stack. If no catch block exists among caller functions, script execution will
                        terminate.
                    </td>
                </tr>
                <tr>
                <td>try/catch/finally</td>
                <td>The try...catch statement is comprised of a try block and either a catch block, a finally block,
                    or both. The code in the try block is executed first, and if it throws an exception, the code in
                    the catch block will be executed.
                    The code in the finally block will always be executed before control flow exits the entire construct.
                    <br/>
                <code>try {
                    return 42/0;
                    } catch (let e) {
                     // handle the error
                    } </code>
                    <br/>
                    <p>The following syntax is also supported:</p>
                    <code>try {
                        return 42/0;
                        } catch (var e) {
                        // handle the error
                        }
                    </code>
                </td>
                </tr>
                <tr>
                    <td>try-with-resources</td>
                    <td>The try-with-resources statement is a try statement that declares one or more resources.
                        The try-with-resources statement ensures that each resource is closed at
                        the end of the statement; any object that exposes a <code>close()</code> method will see that
                        method invoked.
                        <br/>
                        <code>
                            let g = open("g");
                            try(let f = open("f"), g) {
                                // more code
                            }
                        </code>
                    </td>
                </tr>
            </table>
        </section>

    </body>
</document>
