计算表达式语法手册


概述

该语法手册基于JEXL,主要从以下几个方面论述:
  1. 语言元素
  2. 变量类型
  3. 函数
  4. 运算符
  5. 条件语句

语言元素

项目 描述
注释 使用指定的##或//并延伸到行的结束,例如:
           ## This is a comment
           

使用指定//,例如:
          // This is a comment
           

多行注释使用指定/*...*/,例如:
          /* This is a
            multi-line comment */
           
变量 必须以a-z,A-Z,_或$开头。然后可以接着0-9,a-z,A-Z,_或$。例如:
•有效: var1,_a99,$1
•无效: 9var,!a99,1$
变量名称是区分大小写的,例如var1和Var1是不同的变量。
注:JEXL不支持带连字符的变量,例如:
Commons-logging//无效的变量名(带连字符的)
这不是有效的变量,而是被视为变量的减法。
JEXL还支持 . 样式的变量,下面是一个有效的变量名:
my.dotted.var
注意:下列关键字or and eq ne lt gt le ge div mod not null true false new var return被保留,并且使用点运算符时,不能用作变量名称或属性,例如,以下是无效的:
my.new.dotted.var // 无效 ('new'是关键字)
在这样的情况下,引用标识符或[]操作符可以使用,例如:
my.'new'.dotted.var
my['new'].dotted.var
脚本 JEXL中的脚本是由零个或多个语句组成的。脚本可以从一个字符串,文件或URL读取。
他们可以用命名的参数进行创建,并允许以参数进行以后的评价。
脚本默认返回最后计算的表达式。
使用return关键字,脚本将返回其下面的表达式(或空)。
局部变量 可以使用关键字var来定义; 其识别规则和情境变量一样。
    •基本声明:var x;
•声明与分配:var theAnswer = 42;
•无效的声明:var x.y;
他们的范围是整个脚本范围并且以情境变量的分辨率优先。当脚本使用命名参数创建的,就表现为局部变量。局部变量不能使用.样式命名,只有一个标识符。
声明 可以为空,分号(;),块,赋值或表达式。声明可选用分号结束。
块是花括号内的简单多条语句({,})。
赋值 给一个变量赋值(my.var = 'a value')使用JexlContext作为初始解析器。支持beans and ant-ish两种变量分配。
方法调用 调用一个对象的方法,例如:
"hello world".hashCode()
将调用“Hello World”的字符串的hashCode方法。
在多个参数和重载的情况下,JEXL将尽最大的努力去找到最合适的非歧义的方式来调用。
#编译指示 声明一个编译指示,从一个脚本给其执行环境传达信息的方法,例如:
#pragma execution.option 42
将声明一个名为execution.option编译指示,值为42。
编译指示的关键字可以是标识符或antish名,值可以是literals(boolean, integer, real, string, null, NaN)和antish名。

变量类型

项目 描述
Integer Literals 1个或多个数字从0到9,例如42。
Float Literals 1个或多个数字0到9,随后一个小数点,然后一个或多个数字从0至9,任选随后f或F,例如42.0或42.0f。
Long Literals 1或多个数字从0至9,后缀是l或L ,例如42l。
Double Literals 1个或多个数字0到9,后面一个小数点,然后一个或多个数字从 0到9,后缀是d或D ,例如42.0d。
Big Integer Literals 1个或多个数字从0到9,后缀为h或H (对于巨大的表达式语法,“不使用十六进制数字”),例如42H。
Big Decimal Literals 1个或多个数字0至9,随后一个小数点,然后一个或多个数字从 0至9,后缀为b或B,例如42.0b。
Natural literals - octal and hex support 自然数(即Integer, Long, BigInteger)也可以使用和Java相同格式的八进制或十六进制表示。即前缀为数字0的八进制,和前缀为0x或0X的十六进制。例如010或0x10。
Real literals - exponent support 实数(即Float, Double, BigDecimal),也可以使用标准的Java指数记数法表示。即后缀为e或E后跟符号+或-,后面再跟着一个或多个十进制数字。例如42.0E-1D或42.0E+3B。
String literals 开头和结尾使用 ’或 ”分隔符,例如:
"Hello world"
'Hello world'
是等价的。
转义字符是\(反斜杠); 它只是转义字符串分隔符
Multiline format literals 开头和结尾使用`分隔符 -反引用- ,例如:
`Hello world`
转义字符是\(反斜杠); 它只是转义字符串分隔符
这些格式的文本可以跨越多行,并允许统一JEXL表达式(JSTL像表达式)来进行插值。如果一个变量用户的值JEXL存在于环境中,无论是作为一个局部变量还是全局变量,格式
`Hello ${user}`
将评估为
Hello JEXL
Boolean literals 可以使用文字true和false,例如:
val1 == true
Null literal 空值在Java中使用null表示,例如:
val1 == null
Array literal 一个 [ 跟随一个或多个用 ,分离的表达式,并以 ] 结尾,例如:
[ 1, 2, "three" ]
该语法创建了一个[]对象。
JEXL将尝试强类型数组;如果所有条目都是相同的类,或者如果所有条目都是数字实例,这个数组文本将是前者情况中的一个MyClass的[],后一种情况中的一个Number[]。
此外,如果数组文本中的所有项目都是字面相同的类,并且该类具有等效的原始类型,那返回的数组将是一个原始数组。如 [1,2,3]将被解释为int[]。
Set literal 一个 { 跟随一个或多个用 ,分离的表达式,并以 } 结尾,例如:
{ "one" , 2, "more"}
此语法创建一个HashSet < Object >。
Map literal 一个 { 跟随一个或多个用 ,分离的key : value,并以 } 结尾,例如:
{ "one" : 1, "two" : 2, "three" : 3, "more": "many more" }
此语法创建一个HashMap < Object,Object >。

函数

函数 描述
empty 评估一个表达式是否为“空”,当参数为下列情况时为真:
1.null
2.当参数是空的,C类和派生JexlArithmetic 重载一个方法'public boolean empty(C arg)' 返回为真。
3.空字符串
4.长度为零的数组
5.尺寸为0的集合
6.空图
7.当实例被认为是空的,定义一个方法'public boolean isEmpty()'返回为真。
在其他情况下为假(除了错误)。
   empty(arg)
size 评估一个表达式的“大小”。将返回:
1.0若参数为null
2.调用从派生JexlArithmetic重载的'public int size(C arg)'方法的结果,C成为参数的类。
3.数组的长度
4.字符串的长度
5.集合的大小
6.图的大小
7.调用参数类定义的 'public int size()'方法的结果。
在其他情况下返回0(除了错误)。
   size("Hello")
返回5。
New 使用完全限定的类名或类创建一个新的实例:
          new("java.lang.Double", 10)
        
返回10.0。
请注意,第一个参数new可以是一个变量或作为一个字符串或类的任何表达式; 剩余参数被考虑用于类的构造函数的参数。
在多个构造的情况下,JEXL将尽最大的努力去找到最合适的非歧义的方式来调用。
ns:function 一个JexlEngine可以注册对象或类作为函数的命名空间。可以允许表达式:
          math:cosinus(23.0)
        
function 定义脚本中的函数,通常关联一个局部变量赋值。var fun = function(x, y) { x + y }调用函数遵循通常的惯例:fun(17, 25)
注意,函数可以使用来自声明脚本的局部变量和参数。这些变量值绑定在定义时的功能环境中。
var t = 20; var s = function(x, y) {x + y + t}; t = 54; s(15, 7)当定义“t”的时候该功能关闭; 评估的结果为15 +7 + 20 = 42

运算符

运算符 描述
Boolean and 通常使用&&运算符,也可以使用单词and,例如:
cond1 and cond2
cond1 && cond2
是等价的
Boolean or 通常使用||运算符,也可以使用单词or,例如:
cond1 or cond2
cond1 || cond2
是等价的
Boolean not 通常使用!运算符,也可以使用单词not,例如:
!cond1
not cond1
是等价的
Bitwise and 通常使用&运算符,例如:
  33 & 4  
0010 0001 & 0000 0100 = 0.
Bitwise or 通常使用|运算符,例如:
  33 | 4 
0010 0001 | 0000 0100 = 0010 0101 = 37.
Bitwise xor 通常使用^运算符,例如:
  33 ^ 4 
0010 0001 ^ 0000 0100 = 0010 0100 = 37.
Bitwise complement 通常使用〜运算符,例如:
  ~33  
~0010 0001 = 1101 1110 = -34.
Ternary conditional ?: 通常使用 condition ? if_true : if_false三元条件运算符,也可以使用缩写value ?: if_false,如果其定义非空和非假则返回value,例如:
val1 ? val1 : val2
val1 ?: val2
是等价的。
注:当该条件指向一个不确定的变量或为空的所有JexlEngine 标志组合时将评估为假。这允许显式的句法宽大处理,在所有情况下“如果未定义或为空或假的”的条件以同样的方式对待。
Equality 通常使用==运算符,也可以使用缩写eq。例如:
val1 == val2
val1 eq val2
是等价的。
1.null仅仅为空,也就是如果你将空与任何非空的值比较,结果为假。
2.等式使用java的equals方法
Inequality 通常使用!=运算符,也可以使用缩写ne。例如:
val1 != val2
val1 ne val2
是等价的。
Less Than 通常使用 < 运算符,也可以使用缩写lt。例如:
val1 < val2
val1 lt val2
是等价的。
Less Than Or Equal To 通常使用 < =运算符,也可以使用缩写le。例如:
val1 <= val2
val1 le val2
是等价的。
Greater Than 通常使用>运算符,也可以使用缩写gt,例如:
val1 > val2
val1 gt val2
是等价的。
Greater Than Or Equal To 通常使用>=运算符,也可以使用缩写ge,例如:
val1 >= val2
val1 ge val2
是等价的。
In or Match=~ =〜运算符,可以用来检查一个字符串和正则表达式(或者一个Java String或java.util.regex.Pattern)是否相匹配。例如"abcdef" =~ "abc.*返回真,它还可以检查 collection, set or map (on keys) 是否包含一个值;在这种情况下,它表现为一个”in“操作符。注意,它也适用于数组和“duck-typed”集合,即表现出“包含”的方法。 "a" =~ ["a","b","c","d","e",f"]返回真。
Not-In or Not-Match!~ !~运算符,可以用来检查一个字符串和正则表达式(或者一个Java String或java.util.regex.Pattern)是否不匹配。例如"abcdef" !~ "abc.*返回假,它还可以检查 collection, set or map (on keys) 是否不包含一个值;在这种情况下,它表现为一个”not in“操作符。 "a" !~ ["a","b","c","d","e",f"]返回假。需要注意的是通过duck-typing,定义了公共'contains'方法的用户类将允许它们的实例行为具有该操作符的right-hand-size操作数。
Starts With=^ = ^运算符是一个short-hand为“startsWith”的方法。例如, "abcdef" = ^"abc"返回真。需要注意的是通过duck-typing,定义了公共'startsWith'方法的用户类将允许它们的实例行为具有该操作符的left-hand-size操作数。
Not Starts With!^ 这是 'starts with' 运算符的否定。 a ^! "abc"相当于!(a =^ "abc")
Ends With=$ =$运算符是一个 short-hand为“endsWith”的方法。例如, "abcdef" =$ "def"返回真。需要注意的是通过duck-typing,定义了公共'endsWith'方法的用户类将允许它们的实例行为具有该操作符的left-hand-size 操作数。
Not Ends With!^ 这是'ends with'运算符的否定。 a $! "abc" 相当于!(a $= "abc")
Range.. 该..操作符创建了一个值的“范围”(在Java迭代的形式)。例如,for(var x: 1 .. 3) {}将循环3次,'x'的值为1,2和3。
Addition 通常使用+运算符。例如:
        val1 + val2
        
Subtraction 通常使用-运算符。例如:
        val1 - val2
        
Multiplication 通常使用*运算符。例如:
        val1 * val2
        
Division 通常使用/运算符,也可以使用div操作符。例如:
        val1 / val2
        
      val1 div val2
        
Modulus (or remainder) 使用%运算符。另一种是在mod操作符。例如:
        5 mod 2
        
相当于
      5 % 2
        
Negation 使用一元 -运算符。例如:
        -12
        
Array access 数组元素可以使用方括号或点数字访问,例如:
       arr1[0]
        
     arr1.0
        
是等价的
HashMap access 图元素是用方括号访问,例如:
        map[0]; map['name']; map[var];
        
注意
     map['7']
        
        map[7]
        
指的是不同的元素。使用数字键的图元素也可以使用点数字访问,例如:
      map[0]
        
        map.0
        
是等价的

条件语句

运算符 描述
if 经典的if / else语句,例如:
if ((x * 2) == 5) {
    y = 1;
} else {
    y = 2;
}
         
for 通过Array, Collection, Map, Iterator or Enumeration等循环,例如:
for(item : list) {
    x = x + item;
}
        

其中,item和list是变量。该JEXL 1.1使用foreach(item in list)语法现在是不支持的
while 循环,直到一个条件被满足,例如:
while (x lt 10) {
    x = x + 2;
}
        
Top