Skip to content
Permalink
Browse files
JEXL-360: added operators, syntax, basic tests
  • Loading branch information
henrib committed Apr 11, 2022
1 parent e2c841f commit 84668ca9bc05297b5621137c0078ededbf0190c2
Showing 9 changed files with 277 additions and 237 deletions.
@@ -1308,6 +1308,45 @@ public Object not(final Object val) {
return !toBoolean(val);
}

/**
* 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 &gt;&gt; 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 &gt;&gt;&gt; right.
*/
public Object shiftRightUnsigned(Object left, Object right) {
final long l = toLong(left);
final long r = toInteger(right);
return l >>> r;
}

/**
* Performs a comparison.
*
@@ -104,6 +104,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>
@@ -272,6 +296,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
@@ -20,86 +20,9 @@
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.
@@ -520,6 +443,21 @@ protected Object visit(final ASTBitwiseAndNode node, final Object data) {
return infixChildren(node, " & ", false, data);
}

@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);
@@ -1097,6 +1035,21 @@ protected Object visit(final ASTSetXorNode node, final Object data) {
return infixChildren(node, " ^= ", false, data);
}

@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();
@@ -33,82 +33,7 @@
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.
@@ -358,6 +283,42 @@ protected Object visit(final ASTBitwiseXorNode node, final Object data) {
}
}

@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);
@@ -1277,6 +1238,21 @@ protected Object visit(final ASTSetXorNode node, final Object data) {
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
@@ -187,6 +187,12 @@ protected Object tryAssignOverload(final JexlNode node, final JexlOperator opera
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());

0 comments on commit 84668ca

Please sign in to comment.