You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2022/02/15 15:20:58 UTC
[commons-jexl] 01/01: JEXL-360: added operators, syntax, basic tests
This is an automated email from the ASF dual-hosted git repository.
henrib pushed a commit to branch JEXL-360
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git
commit 9f768d75c5967e331d2c415e792ac15ef959655d
Author: henrib <he...@apache.org>
AuthorDate: Tue Feb 15 16:20:42 2022 +0100
JEXL-360: added operators, syntax, basic tests
---
.../org/apache/commons/jexl3/JexlArithmetic.java | 39 ++++++
.../org/apache/commons/jexl3/JexlOperator.java | 45 +++++++
.../apache/commons/jexl3/internal/Debugger.java | 109 +++++------------
.../apache/commons/jexl3/internal/Interpreter.java | 131 ++++++++-------------
.../apache/commons/jexl3/internal/Operators.java | 6 +
.../commons/jexl3/internal/ScriptVisitor.java | 106 +++++------------
.../org/apache/commons/jexl3/parser/Parser.jjt | 45 +++++--
.../apache/commons/jexl3/parser/ParserVisitor.java | 12 ++
.../org/apache/commons/jexl3/ArithmeticTest.java | 30 +++++
9 files changed, 280 insertions(+), 243 deletions(-)
diff --git a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
index 9c3033a..b34d367 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
@@ -1309,6 +1309,45 @@ public class JexlArithmetic {
}
/**
+ * Shifts a bit pattern to the right.
+ *
+ * @param left left argument
+ * @param right right argument
+ * @return left << right.
+ */
+ public Object shiftLeft(Object left, Object right) {
+ final long l = toLong(left);
+ final int r = toInteger(right);
+ return l << r;
+ }
+
+ /**
+ * Shifts a bit pattern to the right.
+ *
+ * @param left left argument
+ * @param right right argument
+ * @return left >> right.
+ */
+ public Object shiftRight(Object left, Object right) {
+ final long l = toLong(left);
+ final long r = toInteger(right);
+ return l >> r;
+ }
+
+ /**
+ * Shifts a bit pattern to the right unsigned.
+ *
+ * @param left left argument
+ * @param right right argument
+ * @return left >>> right.
+ */
+ public Object shiftRightUnsigned(Object left, Object right) {
+ final long l = toLong(left);
+ final long r = toInteger(right);
+ return l >>> r;
+ }
+
+ /**
* Performs a comparison.
*
* @param left the left operand
diff --git a/src/main/java/org/apache/commons/jexl3/JexlOperator.java b/src/main/java/org/apache/commons/jexl3/JexlOperator.java
index 6f21e41..daa68f3 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlOperator.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlOperator.java
@@ -105,6 +105,30 @@ public enum JexlOperator {
XOR("^", "xor", 2),
/**
+ * Bit-pattern right-shift operator.
+ * <br><strong>Syntax:</strong> <code>x >> y</code>
+ * <br><strong>Method:</strong> <code>T rightShift(L x, R y);</code>.
+ * @see JexlArithmetic#shiftRight(Object, Object)
+ */
+ SHIFTRIGHT(">>", "shiftRight", 2),
+
+ /**
+ * Bit-pattern right-shift unsigned operator.
+ * <br><strong>Syntax:</strong> <code>x >>> y</code>
+ * <br><strong>Method:</strong> <code>T rightShiftUnsigned(L x, R y);</code>.
+ * @see JexlArithmetic#shiftRightUnsigned(Object, Object)
+ */
+ SHIFTRIGHTU(">>>", "shiftRightUnsigned", 2),
+
+ /**
+ * Bit-pattern left-shift operator.
+ * <br><strong>Syntax:</strong> <code>x << y</code>
+ * <br><strong>Method:</strong> <code>T leftShift(L x, R y);</code>.
+ * @see JexlArithmetic#shiftLeft(Object, Object)
+ */
+ SHIFTLEFT("<<", "shiftLeft", 2),
+
+ /**
* Equals operator.
* <br><strong>Syntax:</strong> <code>x == y</code>
* <br><strong>Method:</strong> <code>boolean equals(L x, R y);</code>.
@@ -273,6 +297,27 @@ public enum JexlOperator {
SELF_XOR("^=", "selfXor", XOR),
/**
+ * Self-right-shift operator.
+ * <br><strong>Syntax:</strong> <code>x >>= y</code>
+ * <br><strong>Method:</strong> <code>T selfShiftRight(L x, R y);</code>.
+ */
+ SELF_SHIFTRIGHT(">>", "selfShiftRight", SHIFTRIGHT),
+
+ /**
+ * Self-right-shift unsigned operator.
+ * <br><strong>Syntax:</strong> <code>x >>> y</code>
+ * <br><strong>Method:</strong> <code>T selfShiftRightUnsigned(L x, R y);</code>.
+ */
+ SELF_SHIFTRIGHTU(">>>=", "selfShiftRightUnsigned", SHIFTRIGHTU),
+
+ /**
+ * Self-left-shift operator.
+ * <br><strong>Syntax:</strong> <code>x << y</code>
+ * <br><strong>Method:</strong> <code>T selfShiftLeft(L x, R y);</code>.
+ */
+ SELF_SHIFTLEFT("<<=", "selfShiftLeft", SHIFTLEFT),
+
+ /**
* Marker for side effect.
* <br>Returns this from 'self*' overload method to let the engine know the side effect has been performed and
* there is no need to assign the result.
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Debugger.java b/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
index 0f5e577..d3f52a2 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
@@ -20,86 +20,9 @@ package org.apache.commons.jexl3.internal;
import org.apache.commons.jexl3.JexlExpression;
import org.apache.commons.jexl3.JexlInfo;
import org.apache.commons.jexl3.JexlScript;
-import org.apache.commons.jexl3.parser.ASTAddNode;
-import org.apache.commons.jexl3.parser.ASTAndNode;
-import org.apache.commons.jexl3.parser.ASTArguments;
-import org.apache.commons.jexl3.parser.ASTArrayAccess;
-import org.apache.commons.jexl3.parser.ASTArrayLiteral;
-import org.apache.commons.jexl3.parser.ASTAssignment;
-import org.apache.commons.jexl3.parser.ASTBitwiseAndNode;
-import org.apache.commons.jexl3.parser.ASTBitwiseComplNode;
-import org.apache.commons.jexl3.parser.ASTBitwiseOrNode;
-import org.apache.commons.jexl3.parser.ASTBitwiseXorNode;
-import org.apache.commons.jexl3.parser.ASTBlock;
-import org.apache.commons.jexl3.parser.ASTBreak;
-import org.apache.commons.jexl3.parser.ASTConstructorNode;
-import org.apache.commons.jexl3.parser.ASTContinue;
-import org.apache.commons.jexl3.parser.ASTDivNode;
-import org.apache.commons.jexl3.parser.ASTDoWhileStatement;
-import org.apache.commons.jexl3.parser.ASTEQNode;
-import org.apache.commons.jexl3.parser.ASTERNode;
-import org.apache.commons.jexl3.parser.ASTEWNode;
-import org.apache.commons.jexl3.parser.ASTEmptyFunction;
-import org.apache.commons.jexl3.parser.ASTExtendedLiteral;
-import org.apache.commons.jexl3.parser.ASTFalseNode;
-import org.apache.commons.jexl3.parser.ASTForeachStatement;
-import org.apache.commons.jexl3.parser.ASTFunctionNode;
-import org.apache.commons.jexl3.parser.ASTGENode;
-import org.apache.commons.jexl3.parser.ASTGTNode;
-import org.apache.commons.jexl3.parser.ASTIdentifier;
-import org.apache.commons.jexl3.parser.ASTIdentifierAccess;
-import org.apache.commons.jexl3.parser.ASTIfStatement;
-import org.apache.commons.jexl3.parser.ASTJexlLambda;
-import org.apache.commons.jexl3.parser.ASTJexlScript;
-import org.apache.commons.jexl3.parser.ASTJxltLiteral;
-import org.apache.commons.jexl3.parser.ASTLENode;
-import org.apache.commons.jexl3.parser.ASTLTNode;
-import org.apache.commons.jexl3.parser.ASTMapEntry;
-import org.apache.commons.jexl3.parser.ASTMapLiteral;
-import org.apache.commons.jexl3.parser.ASTMethodNode;
-import org.apache.commons.jexl3.parser.ASTModNode;
-import org.apache.commons.jexl3.parser.ASTMulNode;
-import org.apache.commons.jexl3.parser.ASTNENode;
-import org.apache.commons.jexl3.parser.ASTNEWNode;
-import org.apache.commons.jexl3.parser.ASTNRNode;
-import org.apache.commons.jexl3.parser.ASTNSWNode;
-import org.apache.commons.jexl3.parser.ASTNotNode;
-import org.apache.commons.jexl3.parser.ASTNullLiteral;
-import org.apache.commons.jexl3.parser.ASTNumberLiteral;
-import org.apache.commons.jexl3.parser.ASTOrNode;
-import org.apache.commons.jexl3.parser.ASTRangeNode;
-import org.apache.commons.jexl3.parser.ASTReference;
-import org.apache.commons.jexl3.parser.ASTReferenceExpression;
-import org.apache.commons.jexl3.parser.ASTRegexLiteral;
-import org.apache.commons.jexl3.parser.ASTReturnStatement;
-import org.apache.commons.jexl3.parser.ASTSWNode;
-import org.apache.commons.jexl3.parser.ASTSetAddNode;
-import org.apache.commons.jexl3.parser.ASTSetAndNode;
-import org.apache.commons.jexl3.parser.ASTSetDivNode;
-import org.apache.commons.jexl3.parser.ASTSetLiteral;
-import org.apache.commons.jexl3.parser.ASTSetModNode;
-import org.apache.commons.jexl3.parser.ASTSetMultNode;
-import org.apache.commons.jexl3.parser.ASTSetOrNode;
-import org.apache.commons.jexl3.parser.ASTSetSubNode;
-import org.apache.commons.jexl3.parser.ASTSetXorNode;
-import org.apache.commons.jexl3.parser.ASTSizeFunction;
-import org.apache.commons.jexl3.parser.ASTStringLiteral;
-import org.apache.commons.jexl3.parser.ASTSubNode;
-import org.apache.commons.jexl3.parser.ASTTernaryNode;
-import org.apache.commons.jexl3.parser.ASTTrueNode;
-import org.apache.commons.jexl3.parser.ASTUnaryMinusNode;
-import org.apache.commons.jexl3.parser.ASTVar;
-import org.apache.commons.jexl3.parser.ASTWhileStatement;
-import org.apache.commons.jexl3.parser.ASTAnnotatedStatement;
-import org.apache.commons.jexl3.parser.ASTAnnotation;
-import org.apache.commons.jexl3.parser.ASTNullpNode;
-
-import org.apache.commons.jexl3.parser.JexlNode;
-import org.apache.commons.jexl3.parser.ParserVisitor;
+import org.apache.commons.jexl3.parser.*;
import java.util.regex.Pattern;
-import org.apache.commons.jexl3.parser.ASTUnaryPlusNode;
-import org.apache.commons.jexl3.parser.StringParser;
/**
* Helps pinpoint the cause of problems in expressions that fail during evaluation.
@@ -492,6 +415,21 @@ public class Debugger extends ParserVisitor implements JexlInfo.Detail {
}
@Override
+ protected Object visit(final ASTShiftRightNode node, final Object data) {
+ return infixChildren(node, " >> ", false, data);
+ }
+
+ @Override
+ protected Object visit(final ASTShiftRightUnsignedNode node, final Object data) {
+ return infixChildren(node, " >>> ", false, data);
+ }
+
+ @Override
+ protected Object visit(final ASTShiftLeftNode node, final Object data) {
+ return infixChildren(node, " << ", false, data);
+ }
+
+ @Override
protected Object visit(final ASTBitwiseComplNode node, final Object data) {
return prefixChild(node, "~", data);
}
@@ -1059,6 +997,21 @@ public class Debugger extends ParserVisitor implements JexlInfo.Detail {
}
@Override
+ protected Object visit(final ASTSetShiftRightNode node, final Object data) {
+ return infixChildren(node, " >>= ", false, data);
+ }
+
+ @Override
+ protected Object visit(final ASTSetShiftRightUnsignedNode node, final Object data) {
+ return infixChildren(node, " >>>= ", false, data);
+ }
+
+ @Override
+ protected Object visit(final ASTSetShiftLeftNode node, final Object data) {
+ return infixChildren(node, " <<= ", false, data);
+ }
+
+ @Override
protected Object visit(final ASTAnnotation node, final Object data) {
final int num = node.jjtGetNumChildren();
builder.append('@');
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
index 3590d9c..7141b0e 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
@@ -33,82 +33,7 @@ import org.apache.commons.jexl3.JxltEngine;
import org.apache.commons.jexl3.introspection.JexlMethod;
import org.apache.commons.jexl3.introspection.JexlPropertyGet;
-import org.apache.commons.jexl3.parser.ASTAddNode;
-import org.apache.commons.jexl3.parser.ASTAndNode;
-import org.apache.commons.jexl3.parser.ASTAnnotatedStatement;
-import org.apache.commons.jexl3.parser.ASTAnnotation;
-import org.apache.commons.jexl3.parser.ASTArguments;
-import org.apache.commons.jexl3.parser.ASTArrayAccess;
-import org.apache.commons.jexl3.parser.ASTArrayLiteral;
-import org.apache.commons.jexl3.parser.ASTAssignment;
-import org.apache.commons.jexl3.parser.ASTBitwiseAndNode;
-import org.apache.commons.jexl3.parser.ASTBitwiseComplNode;
-import org.apache.commons.jexl3.parser.ASTBitwiseOrNode;
-import org.apache.commons.jexl3.parser.ASTBitwiseXorNode;
-import org.apache.commons.jexl3.parser.ASTBlock;
-import org.apache.commons.jexl3.parser.ASTBreak;
-import org.apache.commons.jexl3.parser.ASTConstructorNode;
-import org.apache.commons.jexl3.parser.ASTContinue;
-import org.apache.commons.jexl3.parser.ASTDivNode;
-import org.apache.commons.jexl3.parser.ASTDoWhileStatement;
-import org.apache.commons.jexl3.parser.ASTEQNode;
-import org.apache.commons.jexl3.parser.ASTERNode;
-import org.apache.commons.jexl3.parser.ASTEWNode;
-import org.apache.commons.jexl3.parser.ASTEmptyFunction;
-import org.apache.commons.jexl3.parser.ASTExtendedLiteral;
-import org.apache.commons.jexl3.parser.ASTFalseNode;
-import org.apache.commons.jexl3.parser.ASTForeachStatement;
-import org.apache.commons.jexl3.parser.ASTFunctionNode;
-import org.apache.commons.jexl3.parser.ASTGENode;
-import org.apache.commons.jexl3.parser.ASTGTNode;
-import org.apache.commons.jexl3.parser.ASTIdentifier;
-import org.apache.commons.jexl3.parser.ASTIdentifierAccess;
-import org.apache.commons.jexl3.parser.ASTIdentifierAccessJxlt;
-import org.apache.commons.jexl3.parser.ASTIfStatement;
-import org.apache.commons.jexl3.parser.ASTJexlLambda;
-import org.apache.commons.jexl3.parser.ASTJexlScript;
-import org.apache.commons.jexl3.parser.ASTJxltLiteral;
-import org.apache.commons.jexl3.parser.ASTLENode;
-import org.apache.commons.jexl3.parser.ASTLTNode;
-import org.apache.commons.jexl3.parser.ASTMapEntry;
-import org.apache.commons.jexl3.parser.ASTMapLiteral;
-import org.apache.commons.jexl3.parser.ASTMethodNode;
-import org.apache.commons.jexl3.parser.ASTModNode;
-import org.apache.commons.jexl3.parser.ASTMulNode;
-import org.apache.commons.jexl3.parser.ASTNENode;
-import org.apache.commons.jexl3.parser.ASTNEWNode;
-import org.apache.commons.jexl3.parser.ASTNRNode;
-import org.apache.commons.jexl3.parser.ASTNSWNode;
-import org.apache.commons.jexl3.parser.ASTNotNode;
-import org.apache.commons.jexl3.parser.ASTNullLiteral;
-import org.apache.commons.jexl3.parser.ASTNullpNode;
-import org.apache.commons.jexl3.parser.ASTNumberLiteral;
-import org.apache.commons.jexl3.parser.ASTOrNode;
-import org.apache.commons.jexl3.parser.ASTRangeNode;
-import org.apache.commons.jexl3.parser.ASTReference;
-import org.apache.commons.jexl3.parser.ASTReferenceExpression;
-import org.apache.commons.jexl3.parser.ASTRegexLiteral;
-import org.apache.commons.jexl3.parser.ASTReturnStatement;
-import org.apache.commons.jexl3.parser.ASTSWNode;
-import org.apache.commons.jexl3.parser.ASTSetAddNode;
-import org.apache.commons.jexl3.parser.ASTSetAndNode;
-import org.apache.commons.jexl3.parser.ASTSetDivNode;
-import org.apache.commons.jexl3.parser.ASTSetLiteral;
-import org.apache.commons.jexl3.parser.ASTSetModNode;
-import org.apache.commons.jexl3.parser.ASTSetMultNode;
-import org.apache.commons.jexl3.parser.ASTSetOrNode;
-import org.apache.commons.jexl3.parser.ASTSetSubNode;
-import org.apache.commons.jexl3.parser.ASTSetXorNode;
-import org.apache.commons.jexl3.parser.ASTSizeFunction;
-import org.apache.commons.jexl3.parser.ASTStringLiteral;
-import org.apache.commons.jexl3.parser.ASTSubNode;
-import org.apache.commons.jexl3.parser.ASTTernaryNode;
-import org.apache.commons.jexl3.parser.ASTTrueNode;
-import org.apache.commons.jexl3.parser.ASTUnaryMinusNode;
-import org.apache.commons.jexl3.parser.ASTUnaryPlusNode;
-import org.apache.commons.jexl3.parser.ASTVar;
-import org.apache.commons.jexl3.parser.ASTWhileStatement;
-import org.apache.commons.jexl3.parser.JexlNode;
+import org.apache.commons.jexl3.parser.*;
/**
* An interpreter of JEXL syntax.
@@ -338,9 +263,6 @@ public class Interpreter extends InterpreterBase {
protected Object visit(final ASTBitwiseOrNode node, final Object data) {
final Object left = node.jjtGetChild(0).jjtAccept(this, data);
final Object right = node.jjtGetChild(1).jjtAccept(this, data);
- if (arithmetic.isStrict(JexlOperator.OR) && left == null || right == null) {
- // boum
- }
try {
final Object result = operators.tryOverload(node, JexlOperator.OR, left, right);
return result != JexlEngine.TRY_FAILED ? result : arithmetic.or(left, right);
@@ -362,6 +284,42 @@ public class Interpreter extends InterpreterBase {
}
@Override
+ protected Object visit(final ASTShiftLeftNode node, final Object data) {
+ final Object left = node.jjtGetChild(0).jjtAccept(this, data);
+ final Object right = node.jjtGetChild(1).jjtAccept(this, data);
+ try {
+ final Object result = operators.tryOverload(node, JexlOperator.SHIFTLEFT, left, right);
+ return result != JexlEngine.TRY_FAILED ? result : arithmetic.shiftLeft(left, right);
+ } catch (final ArithmeticException xrt) {
+ throw new JexlException(findNullOperand(node, left, right), "<< error", xrt);
+ }
+ }
+
+ @Override
+ protected Object visit(final ASTShiftRightNode node, final Object data) {
+ final Object left = node.jjtGetChild(0).jjtAccept(this, data);
+ final Object right = node.jjtGetChild(1).jjtAccept(this, data);
+ try {
+ final Object result = operators.tryOverload(node, JexlOperator.SHIFTRIGHT, left, right);
+ return result != JexlEngine.TRY_FAILED ? result : arithmetic.shiftRight(left, right);
+ } catch (final ArithmeticException xrt) {
+ throw new JexlException(findNullOperand(node, left, right), ">> error", xrt);
+ }
+ }
+
+ @Override
+ protected Object visit(final ASTShiftRightUnsignedNode node, final Object data) {
+ final Object left = node.jjtGetChild(0).jjtAccept(this, data);
+ final Object right = node.jjtGetChild(1).jjtAccept(this, data);
+ try {
+ final Object result = operators.tryOverload(node, JexlOperator.SHIFTRIGHTU, left, right);
+ return result != JexlEngine.TRY_FAILED ? result : arithmetic.shiftRightUnsigned(left, right);
+ } catch (final ArithmeticException xrt) {
+ throw new JexlException(findNullOperand(node, left, right), ">> error", xrt);
+ }
+ }
+
+ @Override
protected Object visit(final ASTEQNode node, final Object data) {
final Object left = node.jjtGetChild(0).jjtAccept(this, data);
final Object right = node.jjtGetChild(1).jjtAccept(this, data);
@@ -1283,6 +1241,21 @@ public class Interpreter extends InterpreterBase {
return executeAssign(node, JexlOperator.SELF_XOR, data);
}
+ @Override
+ protected Object visit(final ASTSetShiftLeftNode node, final Object data) {
+ return executeAssign(node, JexlOperator.SELF_SHIFTLEFT, data);
+ }
+
+ @Override
+ protected Object visit(final ASTSetShiftRightNode node, final Object data) {
+ return executeAssign(node, JexlOperator.SELF_SHIFTRIGHT, data);
+ }
+
+ @Override
+ protected Object visit(final ASTSetShiftRightUnsignedNode node, final Object data) {
+ return executeAssign(node, JexlOperator.SELF_SHIFTRIGHTU, data);
+ }
+
/**
* Executes an assignment with an optional side-effect operator.
* @param node the node
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Operators.java b/src/main/java/org/apache/commons/jexl3/internal/Operators.java
index a72dc1d..e26d1ea 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Operators.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Operators.java
@@ -187,6 +187,12 @@ public class Operators {
return arithmetic.or(args[0], args[1]);
case SELF_XOR:
return arithmetic.xor(args[0], args[1]);
+ case SELF_SHIFTLEFT:
+ return arithmetic.shiftLeft(args[0], args[1]);
+ case SELF_SHIFTRIGHT:
+ return arithmetic.shiftRight(args[0], args[1]);
+ case SELF_SHIFTRIGHTU:
+ return arithmetic.shiftRightUnsigned(args[0], args[1]);
default:
// unexpected, new operator added?
throw new UnsupportedOperationException(operator.getOperatorSymbol());
diff --git a/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java b/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java
index 19afd27..bdcd51e 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java
@@ -18,81 +18,7 @@ package org.apache.commons.jexl3.internal;
import org.apache.commons.jexl3.JexlExpression;
import org.apache.commons.jexl3.JexlScript;
-import org.apache.commons.jexl3.parser.ASTAddNode;
-import org.apache.commons.jexl3.parser.ASTAndNode;
-import org.apache.commons.jexl3.parser.ASTAnnotatedStatement;
-import org.apache.commons.jexl3.parser.ASTAnnotation;
-import org.apache.commons.jexl3.parser.ASTArguments;
-import org.apache.commons.jexl3.parser.ASTArrayAccess;
-import org.apache.commons.jexl3.parser.ASTArrayLiteral;
-import org.apache.commons.jexl3.parser.ASTAssignment;
-import org.apache.commons.jexl3.parser.ASTBitwiseAndNode;
-import org.apache.commons.jexl3.parser.ASTBitwiseComplNode;
-import org.apache.commons.jexl3.parser.ASTBitwiseOrNode;
-import org.apache.commons.jexl3.parser.ASTBitwiseXorNode;
-import org.apache.commons.jexl3.parser.ASTBlock;
-import org.apache.commons.jexl3.parser.ASTBreak;
-import org.apache.commons.jexl3.parser.ASTConstructorNode;
-import org.apache.commons.jexl3.parser.ASTContinue;
-import org.apache.commons.jexl3.parser.ASTDivNode;
-import org.apache.commons.jexl3.parser.ASTDoWhileStatement;
-import org.apache.commons.jexl3.parser.ASTEQNode;
-import org.apache.commons.jexl3.parser.ASTERNode;
-import org.apache.commons.jexl3.parser.ASTEWNode;
-import org.apache.commons.jexl3.parser.ASTEmptyFunction;
-import org.apache.commons.jexl3.parser.ASTExtendedLiteral;
-import org.apache.commons.jexl3.parser.ASTFalseNode;
-import org.apache.commons.jexl3.parser.ASTForeachStatement;
-import org.apache.commons.jexl3.parser.ASTFunctionNode;
-import org.apache.commons.jexl3.parser.ASTGENode;
-import org.apache.commons.jexl3.parser.ASTGTNode;
-import org.apache.commons.jexl3.parser.ASTIdentifier;
-import org.apache.commons.jexl3.parser.ASTIdentifierAccess;
-import org.apache.commons.jexl3.parser.ASTIfStatement;
-import org.apache.commons.jexl3.parser.ASTJexlScript;
-import org.apache.commons.jexl3.parser.ASTJxltLiteral;
-import org.apache.commons.jexl3.parser.ASTLENode;
-import org.apache.commons.jexl3.parser.ASTLTNode;
-import org.apache.commons.jexl3.parser.ASTMapEntry;
-import org.apache.commons.jexl3.parser.ASTMapLiteral;
-import org.apache.commons.jexl3.parser.ASTMethodNode;
-import org.apache.commons.jexl3.parser.ASTModNode;
-import org.apache.commons.jexl3.parser.ASTMulNode;
-import org.apache.commons.jexl3.parser.ASTNENode;
-import org.apache.commons.jexl3.parser.ASTNEWNode;
-import org.apache.commons.jexl3.parser.ASTNRNode;
-import org.apache.commons.jexl3.parser.ASTNSWNode;
-import org.apache.commons.jexl3.parser.ASTNotNode;
-import org.apache.commons.jexl3.parser.ASTNullLiteral;
-import org.apache.commons.jexl3.parser.ASTNullpNode;
-import org.apache.commons.jexl3.parser.ASTNumberLiteral;
-import org.apache.commons.jexl3.parser.ASTOrNode;
-import org.apache.commons.jexl3.parser.ASTRangeNode;
-import org.apache.commons.jexl3.parser.ASTReference;
-import org.apache.commons.jexl3.parser.ASTReferenceExpression;
-import org.apache.commons.jexl3.parser.ASTRegexLiteral;
-import org.apache.commons.jexl3.parser.ASTReturnStatement;
-import org.apache.commons.jexl3.parser.ASTSWNode;
-import org.apache.commons.jexl3.parser.ASTSetAddNode;
-import org.apache.commons.jexl3.parser.ASTSetAndNode;
-import org.apache.commons.jexl3.parser.ASTSetDivNode;
-import org.apache.commons.jexl3.parser.ASTSetLiteral;
-import org.apache.commons.jexl3.parser.ASTSetModNode;
-import org.apache.commons.jexl3.parser.ASTSetMultNode;
-import org.apache.commons.jexl3.parser.ASTSetOrNode;
-import org.apache.commons.jexl3.parser.ASTSetSubNode;
-import org.apache.commons.jexl3.parser.ASTSetXorNode;
-import org.apache.commons.jexl3.parser.ASTSizeFunction;
-import org.apache.commons.jexl3.parser.ASTStringLiteral;
-import org.apache.commons.jexl3.parser.ASTSubNode;
-import org.apache.commons.jexl3.parser.ASTTernaryNode;
-import org.apache.commons.jexl3.parser.ASTTrueNode;
-import org.apache.commons.jexl3.parser.ASTUnaryMinusNode;
-import org.apache.commons.jexl3.parser.ASTUnaryPlusNode;
-import org.apache.commons.jexl3.parser.ASTVar;
-import org.apache.commons.jexl3.parser.ASTWhileStatement;
-import org.apache.commons.jexl3.parser.JexlNode;
-import org.apache.commons.jexl3.parser.ParserVisitor;
+import org.apache.commons.jexl3.parser.*;
/**
* Fully abstract to avoid public interface exposition.
@@ -231,6 +157,21 @@ public class ScriptVisitor extends ParserVisitor {
}
@Override
+ protected Object visit(final ASTShiftLeftNode node, final Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(final ASTShiftRightUnsignedNode node, final Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(final ASTShiftRightNode node, final Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
protected Object visit(final ASTEQNode node, final Object data) {
return visitNode(node, data);
}
@@ -486,6 +427,21 @@ public class ScriptVisitor extends ParserVisitor {
}
@Override
+ protected Object visit(final ASTSetShiftLeftNode node, final Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(final ASTSetShiftRightUnsignedNode node, final Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(final ASTSetShiftRightNode node, final Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
protected Object visit(final ASTJxltLiteral node, final Object data) {
return visitNode(node, data);
}
diff --git a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
index 46fb92c..d167b36 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
+++ b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
@@ -195,6 +195,9 @@ TOKEN_MGR_DECLS : {
| < and_assign : "&=" >
| < or_assign : "|=" >
| < xor_assign : "^=" >
+ | < lshift_assign : "<<=" >
+ | < rshiftu_assign : ">>>=" >
+ | < rshift_assign : ">>=" >
| < assign : "=" >
| < plus : "+" >
@@ -209,6 +212,9 @@ TOKEN_MGR_DECLS : {
| < and : "&" >
| < or : "|" >
| < xor : "^" >
+ | < lshift : "<<" >
+ | < rshiftu : ">>>" >
+ | < rshift : ">>" >
| < tilda : "~" >
| < range : ".." >
@@ -505,6 +511,12 @@ void AssignmentExpression() #void : {}
|
<minus_assign> Expression() #SetSubNode(2)
|
+ <lshift_assign> Expression() #SetShiftLeftNode(2)
+ |
+ <rshift_assign> Expression() #SetShiftRightNode(2)
+ |
+ <rshiftu_assign> Expression() #SetShiftRightUnsignedNode(2)
+ |
<assign> Expression() #Assignment(2)
) )*
}
@@ -569,33 +581,44 @@ void EqualityExpression() #void : {}
void RelationalExpression() #void : {}
{
- AdditiveExpression()
+ ShiftExpression()
(
- (<lt> |<LT>) AdditiveExpression() #LTNode(2)
+ (<lt> |<LT>) ShiftExpression() #LTNode(2)
|
- (<gt> | <GT>) AdditiveExpression() #GTNode(2)
+ (<gt> | <GT>) ShiftExpression() #GTNode(2)
|
- (<le> | <LE>) AdditiveExpression() #LENode(2)
+ (<le> | <LE>) ShiftExpression() #LENode(2)
|
- (<ge> | <GE>) AdditiveExpression() #GENode(2)
+ (<ge> | <GE>) ShiftExpression() #GENode(2)
|
- <req> AdditiveExpression() #ERNode(2) // equals regexp
+ <req> ShiftExpression() #ERNode(2) // equals regexp
|
- <rne> AdditiveExpression() #NRNode(2) // not equals regexp
+ <rne> ShiftExpression() #NRNode(2) // not equals regexp
|
- <seq> AdditiveExpression() #SWNode(2) // starts with
+ <seq> ShiftExpression() #SWNode(2) // starts with
|
- <sne> AdditiveExpression() #NSWNode(2) // not starts with
+ <sne> ShiftExpression() #NSWNode(2) // not starts with
|
- <eeq> AdditiveExpression() #EWNode(2) // ends with
+ <eeq> ShiftExpression() #EWNode(2) // ends with
|
- <ene> AdditiveExpression() #NEWNode(2) // not ends with
+ <ene> ShiftExpression() #NEWNode(2) // not ends with
)?
}
/***************************************
* Arithmetic
***************************************/
+void ShiftExpression() #void : {}
+{
+ AdditiveExpression()
+ ( LOOKAHEAD(2) (
+ <lshift> AdditiveExpression() #ShiftLeftNode(2) // left shift
+ |
+ <rshift> AdditiveExpression() #ShiftRightNode(2) // right shift
+ |
+ <rshiftu> AdditiveExpression() #ShiftRightUnsignedNode(2) // right shift unsigned
+ ) )*
+}
void AdditiveExpression() #void : {}
{
diff --git a/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java b/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
index 876a61b..a656022 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
@@ -78,6 +78,12 @@ public abstract class ParserVisitor {
protected abstract Object visit(ASTBitwiseAndNode node, Object data);
+ protected abstract Object visit(ASTShiftLeftNode node, final Object data);
+
+ protected abstract Object visit(ASTShiftRightNode node, final Object data);
+
+ protected abstract Object visit(ASTShiftRightUnsignedNode node, final Object data);
+
protected abstract Object visit(ASTEQNode node, Object data);
protected abstract Object visit(ASTNENode node, Object data);
@@ -180,6 +186,12 @@ public abstract class ParserVisitor {
protected abstract Object visit(ASTSetXorNode node, Object data);
+ protected abstract Object visit(ASTSetShiftLeftNode node, final Object data);
+
+ protected abstract Object visit(ASTSetShiftRightNode node, final Object data);
+
+ protected abstract Object visit(ASTSetShiftRightUnsignedNode node, final Object data);
+
protected abstract Object visit(ASTJxltLiteral node, Object data);
protected abstract Object visit(ASTAnnotation node, Object data);
diff --git a/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java b/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
index 91f704c..8b8cacc 100644
--- a/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
+++ b/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
@@ -980,6 +980,18 @@ public class ArithmeticTest extends JexlTestCase {
return new Var(lhs.value ^ rhs.value);
}
+ public Var shiftRight(final Var lhs, final Var rhs) {
+ return new Var(lhs.value >> rhs.value);
+ }
+
+ public Var shiftRightUnsigned(final Var lhs, final Var rhs) {
+ return new Var(lhs.value >>> rhs.value);
+ }
+
+ public Var shiftLeft(final Var lhs, final Var rhs) {
+ return new Var(lhs.value << rhs.value);
+ }
+
public Boolean contains(final Var lhs, final Var rhs) {
return lhs.toString().contains(rhs.toString());
}
@@ -1163,6 +1175,24 @@ public class ArithmeticTest extends JexlTestCase {
result = script.execute(jc, new Var(35), new Var(7));
Assert.assertEquals(36L, ((Var) result).value);
+ script = jexl.createScript("(x, y)->{ x << y }");
+ result = script.execute(jc, 35, 1);
+ Assert.assertEquals(70L, result);
+ result = script.execute(jc, new Var(35), new Var(1));
+ Assert.assertEquals(70L, ((Var) result).value);
+
+ script = jexl.createScript("(x, y)->{ x >> y }");
+ result = script.execute(jc, 42, 1);
+ Assert.assertEquals(21L, result);
+ result = script.execute(jc, new Var(42), new Var(1));
+ Assert.assertEquals(21, ((Var) result).value);
+
+ script = jexl.createScript("(x, y)->{ x >>> y }");
+ result = script.execute(jc, 84, 2);
+ Assert.assertEquals(21L, result);
+ result = script.execute(jc, new Var(84), new Var(2));
+ Assert.assertEquals(21, ((Var) result).value);
+
script = jexl.createScript("(x, y)->{ x & y }");
result = script.execute(jc, 35, 7);
Assert.assertEquals(3L, result);