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 2011/06/14 15:33:10 UTC
svn commit: r1135562 - in /commons/proper/jexl/trunk/src:
main/java/org/apache/commons/jexl2/
main/java/org/apache/commons/jexl2/internal/introspection/
main/java/org/apache/commons/jexl2/parser/
test/java/org/apache/commons/jexl2/
Author: henrib
Date: Tue Jun 14 13:33:09 2011
New Revision: 1135562
URL: http://svn.apache.org/viewvc?rev=1135562&view=rev
Log:
JEXL-24, JEXL-112: added syntax for literals of type long integer, big integer, double, big decimal
Added:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTNumberLiteral.java
- copied, changed from r1127914, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTFloatLiteral.java
Removed:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTFloatLiteral.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTIntegerLiteral.java
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Debugger.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/introspection/IntrospectorBase.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/Parser.jjt
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/IssuesTest.java
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Debugger.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Debugger.java?rev=1135562&r1=1135561&r2=1135562&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Debugger.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Debugger.java Tue Jun 14 13:33:09 2011
@@ -34,14 +34,12 @@ import org.apache.commons.jexl2.parser.A
import org.apache.commons.jexl2.parser.ASTERNode;
import org.apache.commons.jexl2.parser.ASTEmptyFunction;
import org.apache.commons.jexl2.parser.ASTFalseNode;
-import org.apache.commons.jexl2.parser.ASTFloatLiteral;
import org.apache.commons.jexl2.parser.ASTForeachStatement;
import org.apache.commons.jexl2.parser.ASTFunctionNode;
import org.apache.commons.jexl2.parser.ASTGENode;
import org.apache.commons.jexl2.parser.ASTGTNode;
import org.apache.commons.jexl2.parser.ASTIdentifier;
import org.apache.commons.jexl2.parser.ASTIfStatement;
-import org.apache.commons.jexl2.parser.ASTIntegerLiteral;
import org.apache.commons.jexl2.parser.ASTJexlScript;
import org.apache.commons.jexl2.parser.ASTLENode;
import org.apache.commons.jexl2.parser.ASTLTNode;
@@ -53,6 +51,7 @@ import org.apache.commons.jexl2.parser.A
import org.apache.commons.jexl2.parser.ASTNENode;
import org.apache.commons.jexl2.parser.ASTNRNode;
import org.apache.commons.jexl2.parser.ASTNotNode;
+import org.apache.commons.jexl2.parser.ASTNumberLiteral;
import org.apache.commons.jexl2.parser.ASTNullLiteral;
import org.apache.commons.jexl2.parser.ASTOrNode;
import org.apache.commons.jexl2.parser.ASTReference;
@@ -376,11 +375,6 @@ final class Debugger implements ParserVi
}
/** {@inheritDoc} */
- public Object visit(ASTFloatLiteral node, Object data) {
- return check(node, node.image, data);
- }
-
- /** {@inheritDoc} */
public Object visit(ASTForeachStatement node, Object data) {
builder.append("for(");
accept(node.jjtGetChild(0), data);
@@ -430,7 +424,7 @@ final class Debugger implements ParserVi
}
/** {@inheritDoc} */
- public Object visit(ASTIntegerLiteral node, Object data) {
+ public Object visit(ASTNumberLiteral node, Object data) {
return check(node, node.image, data);
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java?rev=1135562&r1=1135561&r2=1135562&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java Tue Jun 14 13:33:09 2011
@@ -19,8 +19,6 @@ package org.apache.commons.jexl2;
import java.lang.reflect.Constructor;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
-import java.math.BigDecimal;
-import java.math.BigInteger;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
@@ -49,13 +47,11 @@ import org.apache.commons.jexl2.parser.A
import org.apache.commons.jexl2.parser.ASTEmptyFunction;
import org.apache.commons.jexl2.parser.ASTFalseNode;
import org.apache.commons.jexl2.parser.ASTFunctionNode;
-import org.apache.commons.jexl2.parser.ASTFloatLiteral;
import org.apache.commons.jexl2.parser.ASTForeachStatement;
import org.apache.commons.jexl2.parser.ASTGENode;
import org.apache.commons.jexl2.parser.ASTGTNode;
import org.apache.commons.jexl2.parser.ASTIdentifier;
import org.apache.commons.jexl2.parser.ASTIfStatement;
-import org.apache.commons.jexl2.parser.ASTIntegerLiteral;
import org.apache.commons.jexl2.parser.ASTJexlScript;
import org.apache.commons.jexl2.parser.ASTLENode;
import org.apache.commons.jexl2.parser.ASTLTNode;
@@ -68,6 +64,7 @@ import org.apache.commons.jexl2.parser.A
import org.apache.commons.jexl2.parser.ASTNRNode;
import org.apache.commons.jexl2.parser.ASTNotNode;
import org.apache.commons.jexl2.parser.ASTNullLiteral;
+import org.apache.commons.jexl2.parser.ASTNumberLiteral;
import org.apache.commons.jexl2.parser.ASTOrNode;
import org.apache.commons.jexl2.parser.ASTReference;
import org.apache.commons.jexl2.parser.ASTReferenceExpression;
@@ -273,7 +270,7 @@ public class Interpreter implements Pars
// allow namespace to be instantiated as functor with context if possible, not an error otherwise
if (namespace instanceof Class<?>) {
Object[] args = new Object[]{context};
- Constructor<?> ctor = uberspect.getConstructor(namespace,args, node);
+ Constructor<?> ctor = uberspect.getConstructor(namespace, args, node);
if (ctor != null) {
try {
namespace = ctor.newInstance(args);
@@ -299,7 +296,7 @@ public class Interpreter implements Pars
* be caught explicitly and rethrown.
*/
Object left = node.jjtGetChild(0).jjtAccept(this, data);
- for(int c = 2, size = node.jjtGetNumChildren(); c < size; c += 2) {
+ for (int c = 2, size = node.jjtGetNumChildren(); c < size; c += 2) {
Object right = node.jjtGetChild(c).jjtAccept(this, data);
try {
JexlNode op = node.jjtGetChild(c - 1);
@@ -387,13 +384,13 @@ public class Interpreter implements Pars
}
return literal;
}
-
+
/** {@inheritDoc} */
public Object visit(ASTAssignment node, Object data) {
// left contains the reference to assign to
JexlNode left = node.jjtGetChild(0);
if (!(left instanceof ASTReference)) {
- throw new JexlException(left, "illegal assignment form");
+ throw new JexlException(left, "illegal assignment form 0");
}
// right is the value expression to assign
Object right = node.jjtGetChild(1).jjtAccept(this, data);
@@ -422,7 +419,7 @@ public class Interpreter implements Pars
variableName = new StringBuilder(left.jjtGetChild(0).image);
v = 1;
}
- for(; v <= c; ++v) {
+ for (; v <= c; ++v) {
variableName.append('.');
variableName.append(left.jjtGetChild(v).image);
}
@@ -441,8 +438,8 @@ public class Interpreter implements Pars
if (propertyNode instanceof ASTIdentifier) {
property = ((ASTIdentifier) propertyNode).image;
antVar = true;
- } else if (propertyNode instanceof ASTIntegerLiteral) {
- property = ((ASTIntegerLiteral) propertyNode).getLiteral();
+ } else if (propertyNode instanceof ASTNumberLiteral && ((ASTNumberLiteral)propertyNode).isInteger()) {
+ property = ((ASTNumberLiteral)propertyNode).getLiteral();
antVar = true;
} else if (propertyNode instanceof ASTArrayAccess) {
// first objectNode is the identifier
@@ -468,7 +465,7 @@ public class Interpreter implements Pars
}
property = narray.jjtGetChild(last).jjtAccept(this, null);
} else {
- throw new JexlException(objectNode, "illegal assignment form");
+ throw new JexlException(objectNode, "illegal assignment form");
}
// deal with ant variable; set context
if (antVar) {
@@ -594,11 +591,11 @@ public class Interpreter implements Pars
return Boolean.TRUE;
}
if (o instanceof Collection<?>) {
- return ((Collection<?>) o).isEmpty()? Boolean.TRUE : Boolean.FALSE;
+ return ((Collection<?>) o).isEmpty() ? Boolean.TRUE : Boolean.FALSE;
}
// Map isn't a collection
if (o instanceof Map<?, ?>) {
- return ((Map<?,?>) o).isEmpty()? Boolean.TRUE : Boolean.FALSE;
+ return ((Map<?, ?>) o).isEmpty() ? Boolean.TRUE : Boolean.FALSE;
}
return Boolean.FALSE;
}
@@ -620,14 +617,6 @@ public class Interpreter implements Pars
}
/** {@inheritDoc} */
- public Object visit(ASTFloatLiteral node, Object data) {
- if (data != null) {
- return getAttribute(data, node.getLiteral(), node);
- }
- return node.getLiteral();
- }
-
- /** {@inheritDoc} */
public Object visit(ASTForeachStatement node, Object data) {
Object result = null;
/* first objectNode is the loop variable */
@@ -697,8 +686,8 @@ public class Interpreter implements Pars
}
Object value = context.get(name);
if (value == null
- && !(node.jjtGetParent() instanceof ASTReference)
- && !context.has(name)) {
+ && !(node.jjtGetParent() instanceof ASTReference)
+ && !context.has(name)) {
JexlException xjexl = new JexlException(node, "undefined variable " + name);
return unknownVariable(xjexl);
}
@@ -736,8 +725,8 @@ public class Interpreter implements Pars
}
/** {@inheritDoc} */
- public Object visit(ASTIntegerLiteral node, Object data) {
- if (data != null) {
+ public Object visit(ASTNumberLiteral node, Object data) {
+ if (data != null && node.isInteger()) {
return getAttribute(data, node.getLiteral(), node);
}
return node.getLiteral();
@@ -1000,7 +989,7 @@ public class Interpreter implements Pars
throw new JexlException(node, "!~ error", xrt);
}
}
-
+
/** {@inheritDoc} */
public Object visit(ASTNotNode node, Object data) {
Object val = node.jjtGetChild(0).jjtAccept(this, data);
@@ -1051,7 +1040,7 @@ public class Interpreter implements Pars
for (int c = 0; c < numChildren; c++) {
JexlNode theNode = node.jjtGetChild(c);
// integer literals may be part of an antish var name only if no bean was found so far
- if (result == null && theNode instanceof ASTIntegerLiteral) {
+ if (result == null && theNode instanceof ASTNumberLiteral && theNode.image.matches("\\d*")) {
isVariable &= v > 0;
} else {
isVariable &= (theNode instanceof ASTIdentifier);
@@ -1083,7 +1072,7 @@ public class Interpreter implements Pars
ASTArrayAccess upper = (ASTArrayAccess) node;
return visit(upper, data);
}
-
+
/**
* Check if a null evaluated expression is protected by a ternary expression.
* The rationale is that the ternary / elvis expressions are meant for the user to explictly take
@@ -1093,7 +1082,7 @@ public class Interpreter implements Pars
* @return true if nullable variable, false otherwise
*/
private boolean isTernaryProtected(JexlNode node) {
- for(JexlNode walk = node.jjtGetParent(); walk != null; walk = walk.jjtGetParent()) {
+ for (JexlNode walk = node.jjtGetParent(); walk != null; walk = walk.jjtGetParent()) {
if (walk instanceof ASTTernaryNode) {
return true;
} else if (!(walk instanceof ASTReference || walk instanceof ASTArrayAccess)) {
@@ -1148,37 +1137,21 @@ public class Interpreter implements Pars
public Object visit(ASTTrueNode node, Object data) {
return Boolean.TRUE;
}
-
+
/** {@inheritDoc} */
public Object visit(ASTUnaryMinusNode node, Object data) {
JexlNode valNode = node.jjtGetChild(0);
Object val = valNode.jjtAccept(this, data);
- if (val instanceof Byte) {
- byte valueAsByte = ((Byte) val).byteValue();
- return Byte.valueOf((byte) -valueAsByte);
- } else if (val instanceof Short) {
- short valueAsShort = ((Short) val).shortValue();
- return Short.valueOf((short) -valueAsShort);
- } else if (val instanceof Integer) {
- int valueAsInt = ((Integer) val).intValue();
- return Integer.valueOf(-valueAsInt);
- } else if (val instanceof Long) {
- long valueAsLong = ((Long) val).longValue();
- return Long.valueOf(-valueAsLong);
- } else if (val instanceof Float) {
- float valueAsFloat = ((Float) val).floatValue();
- return new Float(-valueAsFloat);
- } else if (val instanceof Double) {
- double valueAsDouble = ((Double) val).doubleValue();
- return new Double(-valueAsDouble);
- } else if (val instanceof BigDecimal) {
- BigDecimal valueAsBigD = (BigDecimal) val;
- return valueAsBigD.negate();
- } else if (val instanceof BigInteger) {
- BigInteger valueAsBigI = (BigInteger) val;
- return valueAsBigI.negate();
+ try {
+ Object number = arithmetic.negate(val);
+ // attempt to recoerce to literal class
+ if (valNode instanceof ASTNumberLiteral && number instanceof Number) {
+ number = arithmetic.narrowNumber((Number) number, ((ASTNumberLiteral) valNode).getLiteralClass());
+ }
+ return number;
+ } catch (RuntimeException xrt) {
+ throw new JexlException(valNode, "arithmetic error", xrt);
}
- throw new JexlException(valNode, "not a number");
}
/** {@inheritDoc} */
@@ -1348,8 +1321,8 @@ public class Interpreter implements Pars
}
if (xjexl == null) {
String error = "unable to set object property"
- + ", class: " + object.getClass().getName()
- + ", property: " + attribute;
+ + ", class: " + object.getClass().getName()
+ + ", property: " + attribute;
if (node == null) {
throw new UnsupportedOperationException(error);
}
@@ -1382,5 +1355,4 @@ public class Interpreter implements Pars
public Object visit(ASTAmbiguous node, Object data) {
throw new UnsupportedOperationException("unexpected type of node");
}
-
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java?rev=1135562&r1=1135561&r2=1135562&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java Tue Jun 14 13:33:09 2011
@@ -516,6 +516,40 @@ public class JexlArithmetic {
BigInteger result = l.subtract(r);
return narrowBigInteger(left, right, result);
}
+
+ /**
+ * Negates a value (unary minus for numbers).
+ * @param val the value to negate
+ * @return the negated value
+ */
+ public Object negate(Object val) {
+ if (val instanceof Byte) {
+ byte valueAsByte = ((Byte) val).byteValue();
+ return Byte.valueOf((byte) -valueAsByte);
+ } else if (val instanceof Short) {
+ short valueAsShort = ((Short) val).shortValue();
+ return Short.valueOf((short) -valueAsShort);
+ } else if (val instanceof Integer) {
+ int valueAsInt = ((Integer) val).intValue();
+ return Integer.valueOf(-valueAsInt);
+ } else if (val instanceof Long) {
+ long valueAsLong = -((Long) val).longValue();
+ return Long.valueOf(valueAsLong);
+ } else if (val instanceof Float) {
+ float valueAsFloat = ((Float) val).floatValue();
+ return new Float(-valueAsFloat);
+ } else if (val instanceof Double) {
+ double valueAsDouble = ((Double) val).doubleValue();
+ return new Double(-valueAsDouble);
+ } else if (val instanceof BigDecimal) {
+ BigDecimal valueAsBigD = (BigDecimal) val;
+ return valueAsBigD.negate();
+ } else if (val instanceof BigInteger) {
+ BigInteger valueAsBigI = (BigInteger) val;
+ return valueAsBigI.negate();
+ }
+ throw new IllegalArgumentException(val.toString() + ": negate can only be applied to a number");
+ }
/**
* Test if left regexp matches right.
@@ -848,6 +882,26 @@ public class JexlArithmetic {
* @return a value of the smallest type the original number will fit into.
*/
public Number narrow(Number original) {
+ return narrowNumber(original, null);
+ }
+
+ /**
+ * Whether we consider the narrow class as a potential candidate for narrowing the source.
+ * @param narrow the target narrow class
+ * @param source the orginal source class
+ * @return
+ */
+ protected boolean narrowAccept(Class<?> narrow, Class<?> source) {
+ return narrow == null || narrow.equals(source);
+ }
+
+ /**
+ * Given a Number, return back the value attempting to narrow it to a target class.
+ * @param original the original number
+ * @param narrow the attempted target class
+ * @return the narrowed number or the source if no narrowing was possible
+ */
+ protected Number narrowNumber(Number original, Class<?> narrow) {
if (original == null) {
return original;
}
@@ -861,9 +915,9 @@ public class JexlArithmetic {
try {
long l = bigd.longValueExact();
// coerce to int when possible (int being so often used in method parms)
- if (l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) {
+ if (narrowAccept(narrow, Integer.class) && l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) {
return Integer.valueOf((int) l);
- } else {
+ } else if (narrowAccept(narrow, Long.class)) {
return Long.valueOf(l);
}
} catch (ArithmeticException xa) {
@@ -873,7 +927,7 @@ public class JexlArithmetic {
}
if (original instanceof Double || original instanceof Float || original instanceof BigDecimal) {
double value = original.doubleValue();
- if (value <= Float.MAX_VALUE && value >= Float.MIN_VALUE) {
+ if (narrowAccept(narrow, Float.class) && value <= Float.MAX_VALUE && value >= Float.MIN_VALUE) {
result = Float.valueOf(result.floatValue());
}
// else it fits in a double only
@@ -887,12 +941,12 @@ public class JexlArithmetic {
}
}
long value = original.longValue();
- if (value <= Byte.MAX_VALUE && value >= Byte.MIN_VALUE) {
+ if (narrowAccept(narrow, Byte.class) && value <= Byte.MAX_VALUE && value >= Byte.MIN_VALUE) {
// it will fit in a byte
result = Byte.valueOf((byte) value);
- } else if (value <= Short.MAX_VALUE && value >= Short.MIN_VALUE) {
+ } else if (narrowAccept(narrow, Short.class) && value <= Short.MAX_VALUE && value >= Short.MIN_VALUE) {
result = Short.valueOf((short) value);
- } else if (value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE) {
+ } else if (narrowAccept(narrow, Integer.class) && value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE) {
result = Integer.valueOf((int) value);
}
// else it fits in a long
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/introspection/IntrospectorBase.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/introspection/IntrospectorBase.java?rev=1135562&r1=1135561&r2=1135562&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/introspection/IntrospectorBase.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/introspection/IntrospectorBase.java Tue Jun 14 13:33:09 2011
@@ -20,7 +20,6 @@ package org.apache.commons.jexl2.interna
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
-import java.util.Arrays;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
Copied: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTNumberLiteral.java (from r1127914, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTFloatLiteral.java)
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTNumberLiteral.java?p2=commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTNumberLiteral.java&p1=commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTFloatLiteral.java&r1=1127914&r2=1135562&rev=1135562&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTFloatLiteral.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTNumberLiteral.java Tue Jun 14 13:33:09 2011
@@ -16,23 +16,28 @@
*/
package org.apache.commons.jexl2.parser;
-public final class ASTFloatLiteral extends JexlNode implements JexlNode.Literal<Float> {
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class ASTNumberLiteral extends JexlNode implements JexlNode.Literal<Number> {
/** The type literal value. */
- Float literal = null;
+ Number literal = null;
+ /** The expected class. */
+ Class<?> clazz = null;
- public ASTFloatLiteral(int id) {
+ public ASTNumberLiteral(int id) {
super(id);
}
- public ASTFloatLiteral(Parser p, int id) {
+ public ASTNumberLiteral(Parser p, int id) {
super(p, id);
}
/**
* Gets the literal value.
- * @return the float literal
+ * @return the number literal
*/
- public Float getLiteral() {
+ public Number getLiteral() {
return literal;
}
@@ -41,4 +46,74 @@ public final class ASTFloatLiteral exten
public Object jjtAccept(ParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
+
+ public Class<?> getLiteralClass() {
+ return clazz;
+ }
+
+ public boolean isInteger() {
+ return Integer.class.equals(clazz);
+ }
+
+ public boolean isDouble() {
+ return Double.class.equals(clazz);
+ }
+
+ public void setNatural(String s) {
+ Number result;
+ Class<?> rclass;
+ int last = s.length() - 1;
+ switch (s.charAt(last)) {
+ case 'l':
+ case 'L':
+ result = Long.valueOf(s.substring(0, last));
+ rclass = Long.class;
+ break;
+ case 'h':
+ case 'H':
+ result = new BigInteger(s.substring(0, last));
+ rclass = BigInteger.class;
+ break;
+ default:
+ rclass = Integer.class;
+ try {
+ result = Integer.valueOf(s);
+ } catch(NumberFormatException xnumber) {
+ result = Long.valueOf(s);
+ }
+ break;
+ }
+ literal = result;
+ clazz = rclass;
+ }
+
+ public void setReal(String s) {
+ Number result;
+ Class<?> rclass;
+ int last = s.length() - 1;
+ switch (s.charAt(last)) {
+ case 'b':
+ case 'B':
+ result = new BigDecimal(s.substring(0, last));
+ rclass = BigDecimal.class;
+ break;
+ case 'd':
+ case 'D':
+ result = Double.valueOf(s);
+ rclass = Double.class;
+ break;
+ case 'f':
+ case 'F':
+ default:
+ rclass = Float.class;
+ try {
+ result = Float.valueOf(s);
+ } catch(NumberFormatException xnumber) {
+ result = Double.valueOf(s);
+ }
+ break;
+ }
+ literal = result;
+ clazz = rclass;
+ }
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/Parser.jjt
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/Parser.jjt?rev=1135562&r1=1135561&r2=1135562&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/Parser.jjt (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/Parser.jjt Tue Jun 14 13:33:09 2011
@@ -15,14 +15,6 @@
* limitations under the License.
*/
-/**
- * Jexl : Java Expression Language
- *
- * @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
- * @author <a href="mailto:mhw@kremvax.net">Mark H. Wilkinson</a>
- *
- * @version $Id$
- */
options
{
@@ -173,9 +165,12 @@ PARSER_END(Parser)
<*> TOKEN : /* LITERALS */
{
- < INTEGER_LITERAL: (<DIGIT>)+ >
-|
- < FLOAT_LITERAL: (<DIGIT>)+ "."(<DIGIT>)+ >
+ < INTEGER_LITERAL:
+ ( "0" (["0"-"7"])* | ["1"-"9"] (["0"-"9"])* | "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ )
+ (["l","L","h","H"])?
+ >
+ |
+ < FLOAT_LITERAL: (<DIGIT>)+ "."(<DIGIT>)+ (["d","D","f","F","b","B"])? >
}
<*> TOKEN :
@@ -419,22 +414,23 @@ void BooleanLiteral() #void :
<FALSE> #FalseNode
}
-void IntegerLiteral() :
+void IntegerLiteral() #NumberLiteral :
{
Token t;
}
{
t=<INTEGER_LITERAL>
- { jjtThis.image = t.image; jjtThis.literal = Integer.valueOf(t.image); }
+ { jjtThis.image = t.image; jjtThis.setNatural(t.image); }
}
-void FloatLiteral() :
+
+void FloatLiteral() #NumberLiteral:
{
Token t;
}
{
t=<FLOAT_LITERAL>
- { jjtThis.image = t.image; jjtThis.literal = Float.valueOf(t.image); }
+ { jjtThis.image = t.image; jjtThis.setReal(t.image); }
}
void StringLiteral() :
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java?rev=1135562&r1=1135561&r2=1135562&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java Tue Jun 14 13:33:09 2011
@@ -82,7 +82,7 @@ public class ArithmeticTest extends Jexl
public void testNullOperand() throws Exception {
asserter.setVariable("right", null);
asserter.failExpression("~right", ".*null.*");
- asserter.failExpression("-right", ".*number.*");
+ asserter.failExpression("-right", ".*arithmetic.*");
}
public void testBigDecimal() throws Exception {
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/IssuesTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/IssuesTest.java?rev=1135562&r1=1135561&r2=1135562&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/IssuesTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/IssuesTest.java Tue Jun 14 13:33:09 2011
@@ -17,6 +17,7 @@
package org.apache.commons.jexl2;
import java.math.BigDecimal;
+import java.math.BigInteger;
import java.math.MathContext;
import org.apache.commons.jexl2.introspection.Uberspect;
import org.apache.commons.jexl2.internal.Introspector;
@@ -35,6 +36,33 @@ public class IssuesTest extends JexlTest
// ensure jul logging is only error to avoid warning in silent mode
java.util.logging.Logger.getLogger(JexlEngine.class.getName()).setLevel(java.util.logging.Level.SEVERE);
}
+
+ // JEXL-24: long integers (and doubles)
+ public void test24() throws Exception {
+ Map<String, Object> vars = new HashMap<String, Object>();
+ JexlContext ctxt = new MapContext(vars);
+ String stmt = "{a = 10L; b = 10l; c = 42.0D; d = 42.0d;}";
+ Script expr = JEXL.createScript(stmt);
+ /* Object value = */ expr.execute(ctxt);
+ assertEquals(10L, vars.get("a"));
+ assertEquals(10l, vars.get("b"));
+ assertEquals(42.0D, vars.get("c"));
+ assertEquals(42.0d, vars.get("d"));
+
+ }
+ // JEXL-24: big integers and big decimals
+ public void test24B() throws Exception {
+ Map<String, Object> vars = new HashMap<String, Object>();
+ JexlContext ctxt = new MapContext(vars);
+ String stmt = "{a = 10H; b = 10h; c = 42.0B; d = 42.0b;}";
+ Script expr = JEXL.createScript(stmt);
+ /* Object value = */ expr.execute(ctxt);
+ assertEquals(new BigInteger("10"), vars.get("a"));
+ assertEquals(new BigInteger("10"), vars.get("b"));
+ assertEquals(new BigDecimal("42.0"), vars.get("c"));
+ assertEquals(new BigDecimal("42.0"), vars.get("d"));
+
+ }
// JEXL-49: blocks not parsed (fixed)
public void test49() throws Exception {
@@ -600,7 +628,7 @@ public class IssuesTest extends JexlTest
assertEquals("SecondValue=-10.0", value);
}
- public void test112() throws Exception {
+ public void testScaleIssue() throws Exception {
JexlArithmetic arithmetic = new JexlThreadedArithmetic(false);
JexlEngine jexlX = new JexlEngine(null, arithmetic, null, null);
String expStr1 = "result == salary/month * work.percent/100.00";
@@ -618,4 +646,16 @@ public class IssuesTest extends JexlTest
JexlThreadedArithmetic.setMathScale(2);
assertFalse((Boolean) exp1.evaluate(ctx));
}
+
+ public void test112() throws Exception {
+ Object result;
+ JexlEngine jexl = new JexlEngine();
+ result = jexl.createScript(Integer.toString(Integer.MAX_VALUE)).execute(null);
+ assertEquals(Integer.MAX_VALUE, result);
+ result = jexl.createScript(Integer.toString(Integer.MIN_VALUE+1)).execute(null);
+ assertEquals(Integer.MIN_VALUE+1, result);
+ result = jexl.createScript(Integer.toString(Integer.MIN_VALUE)).execute(null);
+ assertEquals(Integer.MIN_VALUE, result);
+ }
+
}
Re: svn commit: r1135562 - in /commons/proper/jexl/trunk/src:
main/java/org/apache/commons/jexl2/ main/java/org/apache/commons/jexl2/internal/introspection/
main/java/org/apache/commons/jexl2/parser/ test/java/org/apache/commons/jexl2/
Posted by sebb <se...@gmail.com>.
On 14 June 2011 14:33, <he...@apache.org> wrote:
> Author: henrib
> Date: Tue Jun 14 13:33:09 2011
> New Revision: 1135562
>
> URL: http://svn.apache.org/viewvc?rev=1135562&view=rev
> Log:
> JEXL-24, JEXL-112: added syntax for literals of type long integer, big integer, double, big decimal
>
...
> --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java (original)
> +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java Tue Jun 14 13:33:09 2011
> @@ -19,8 +19,6 @@ package org.apache.commons.jexl2;
...
> public Object visit(ASTNotNode node, Object data) {
> Object val = node.jjtGetChild(0).jjtAccept(this, data);
> @@ -1051,7 +1040,7 @@ public class Interpreter implements Pars
> for (int c = 0; c < numChildren; c++) {
> JexlNode theNode = node.jjtGetChild(c);
> // integer literals may be part of an antish var name only if no bean was found so far
> - if (result == null && theNode instanceof ASTIntegerLiteral) {
> + if (result == null && theNode instanceof ASTNumberLiteral && theNode.image.matches("\\d*")) {
Is the empty string allowed as a number? I would expect to see at
least one digit, i.e. "\\d+"
If there is a good reason for allowing no digits, please add a comment
to say why.
> isVariable &= v > 0;
> } else {
> isVariable &= (theNode instanceof ASTIdentifier);
> @@ -1083,7 +1072,7 @@ public class Interpreter implements Pars
> ASTArrayAccess upper = (ASTArrayAccess) node;
> return visit(upper, data);
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org