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 2015/03/10 14:46:45 UTC
svn commit: r1665548 - in /commons/proper/jexl/trunk/src:
main/java/org/apache/commons/jexl3/
main/java/org/apache/commons/jexl3/internal/
main/java/org/apache/commons/jexl3/parser/ site/xdoc/reference/
test/java/org/apache/commons/jexl3/
Author: henrib
Date: Tue Mar 10 13:46:44 2015
New Revision: 1665548
URL: http://svn.apache.org/r1665548
Log:
JEXL:
Adding pragmas and set literals;
Various small fixes
Added:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/SetBuilder.java (with props)
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTSetLiteral.java (with props)
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/NumberParser.java (with props)
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/PragmaTest.java (with props)
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/SetLiteralTest.java (with props)
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTNumberLiteral.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
commons/proper/jexl/trunk/src/site/xdoc/reference/syntax.xml
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/AssignTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java Tue Mar 10 13:46:44 2015
@@ -267,6 +267,33 @@ public class JexlArithmetic {
}
/**
+ * Helper interface used when creating a set literal.
+ * <p>The default implementation creates a java.util.HashSet.</p>
+ */
+ public interface SetBuilder {
+ /**
+ * Adds a literal to the set.
+ * @param value the item to add
+ */
+ void add(Object value);
+
+ /**
+ * Creates the actual "set" instance.
+ * @return the array
+ */
+ Object create();
+ }
+
+ /**
+ * Called by the interpreter when evaluating a literal array.
+ * @param size the number of elements in the array
+ * @return the array builder
+ */
+ public SetBuilder setBuilder(int size) {
+ return new org.apache.commons.jexl3.internal.SetBuilder(size);
+ }
+
+ /**
* Helper interface used when creating a map literal.
* <p>The default implementation creates a java.util.HashMap.</p>
*/
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java Tue Mar 10 13:46:44 2015
@@ -17,6 +17,7 @@
package org.apache.commons.jexl3;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
@@ -42,7 +43,7 @@ public interface JexlScript {
* @return the source text
*/
String getParsedText();
-
+
/**
* Executes the script with the variables contained in the
* supplied {@link JexlContext}.
@@ -90,6 +91,12 @@ public interface JexlScript {
Set<List<String>> getVariables();
/**
+ * Gets this script pragmas
+ * @return the pragmas map
+ */
+ Map<String, Object> getPragmas();
+
+ /**
* Creates a Callable from this script.
* <p>This allows to submit it to an executor pool and provides support for asynchronous calls.</p>
* <p>The interpreter will handle interruption/cancellation gracefully if needed.</p>
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java Tue Mar 10 13:46:44 2015
@@ -70,6 +70,7 @@ import org.apache.commons.jexl3.parser.A
import org.apache.commons.jexl3.parser.ASTReferenceExpression;
import org.apache.commons.jexl3.parser.ASTReturnStatement;
import org.apache.commons.jexl3.parser.ASTSWNode;
+import org.apache.commons.jexl3.parser.ASTSetLiteral;
import org.apache.commons.jexl3.parser.ASTSizeFunction;
import org.apache.commons.jexl3.parser.ASTSizeMethod;
import org.apache.commons.jexl3.parser.ASTStringLiteral;
@@ -643,6 +644,21 @@ public final class Debugger extends Pars
return data;
}
+ @Override
+ protected Object visit(ASTSetLiteral node, Object data) {
+ int num = node.jjtGetNumChildren();
+ builder.append("{ ");
+ if (num > 0) {
+ accept(node.jjtGetChild(0), data);
+ for (int i = 1; i < num; ++i) {
+ builder.append(",");
+ accept(node.jjtGetChild(i), data);
+ }
+ }
+ builder.append(" }");
+ return data;
+ }
+
@Override
protected Object visit(ASTMapLiteral node, Object data) {
int num = node.jjtGetNumChildren();
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java Tue Mar 10 13:46:44 2015
@@ -493,14 +493,13 @@ public class Engine extends JexlEngine {
xjexl = xany;
} catch (Exception xany) {
xjexl = new JexlException.Method(info, clazz.toString(), xany);
- } finally {
- if (xjexl != null) {
- if (silent) {
- logger.warn(xjexl.getMessage(), xjexl.getCause());
- return null;
- }
- throw xjexl.clean();
+ }
+ if (xjexl != null) {
+ if (silent) {
+ logger.warn(xjexl.getMessage(), xjexl.getCause());
+ return null;
}
+ throw xjexl.clean();
}
return result;
}
@@ -513,9 +512,9 @@ public class Engine extends JexlEngine {
* @return the set of variables, each as a list of strings (ant-ish variables use more than 1 string)
* or the empty set if no variables are used
*/
- protected Set<List<String>> getVariables(JexlNode script) {
+ protected Set<List<String>> getVariables(ASTJexlScript script) {
VarCollector collector = new VarCollector();
- getVariables(script, collector);
+ getVariables(script, script, collector);
return collector.collected();
}
@@ -526,7 +525,7 @@ public class Engine extends JexlEngine {
/**
* The collected variables represented as a set of list of strings.
*/
- private Set<List<String>> refs = new LinkedHashSet<List<String>>();
+ private final Set<List<String>> refs = new LinkedHashSet<List<String>>();
/**
* The current variable being collected.
*/
@@ -576,7 +575,7 @@ public class Engine extends JexlEngine {
* @param node the node
* @param collector the variable collector
*/
- protected void getVariables(JexlNode node, VarCollector collector) {
+ protected void getVariables(final ASTJexlScript script, JexlNode node, VarCollector collector) {
if (node instanceof ASTIdentifier) {
JexlNode parent = node.jjtGetParent();
if (parent instanceof ASTMethodNode || parent instanceof ASTFunctionNode) {
@@ -585,12 +584,14 @@ public class Engine extends JexlEngine {
return;
}
ASTIdentifier identifier = (ASTIdentifier) node;
- if (identifier.getSymbol() < 0) {
+ int symbol = identifier.getSymbol();
+ // symbols that are hoisted are considered "global" variables
+ if (symbol >= 0 && script != null && !script.isHoistedSymbol(symbol)) {
+ collector.collect(null);
+ } else {
// start collecting from identifier
collector.collect(identifier);
collector.add(identifier.getName());
- } else {
- collector.collect(null);
}
} else if (node instanceof ASTIdentifierAccess) {
JexlNode parent = node.jjtGetParent();
@@ -618,13 +619,13 @@ public class Engine extends JexlEngine {
} else {
collecting = false;
collector.collect(null);
- getVariables(child, collector);
+ getVariables(script, child, collector);
}
}
} else {
int num = node.jjtGetNumChildren();
for (int i = 0; i < num; ++i) {
- getVariables(node.jjtGetChild(i), collector);
+ getVariables(script, node.jjtGetChild(i), collector);
}
collector.collect(null);
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java Tue Mar 10 13:46:44 2015
@@ -76,6 +76,7 @@ import org.apache.commons.jexl3.parser.A
import org.apache.commons.jexl3.parser.ASTReferenceExpression;
import org.apache.commons.jexl3.parser.ASTReturnStatement;
import org.apache.commons.jexl3.parser.ASTSWNode;
+import org.apache.commons.jexl3.parser.ASTSetLiteral;
import org.apache.commons.jexl3.parser.ASTSizeFunction;
import org.apache.commons.jexl3.parser.ASTSizeMethod;
import org.apache.commons.jexl3.parser.ASTStringLiteral;
@@ -939,6 +940,21 @@ public class Interpreter extends ParserV
}
@Override
+ protected Object visit(ASTSetLiteral node, Object data) {
+ int childCount = node.jjtGetNumChildren();
+ JexlArithmetic.SetBuilder mb = arithmetic.setBuilder(childCount);
+ if (mb != null) {
+ for (int i = 0; i < childCount; i++) {
+ Object entry = node.jjtGetChild(i).jjtAccept(this, data);
+ mb.add(entry);
+ }
+ return mb.create();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
protected Object visit(ASTMapLiteral node, Object data) {
int childCount = node.jjtGetNumChildren();
JexlArithmetic.MapBuilder mb = arithmetic.mapBuilder(childCount);
@@ -1368,7 +1384,7 @@ public class Interpreter extends ParserV
Object object = null;
JexlNode objectNode;
StringBuilder variableName = null;
- boolean isVariable = !(parent instanceof ASTReference);
+ boolean antish = !(parent instanceof ASTReference);
int v = 0;
main:
for (int c = 0; c < numChildren; c++) {
@@ -1381,9 +1397,15 @@ public class Interpreter extends ParserV
}
// attempt to evaluate the property within the object
object = objectNode.jjtAccept(this, object);
- if (object == null && isVariable) {
+ if (object == null && antish) {
// if we still have a null object and we are evaluating 'x.y', check for an antish variable
if (v == 0) {
+ // if the first node is a local variable or parameter, the object can not be null
+ JexlNode first = node.jjtGetChild(0);
+ if (first instanceof ASTIdentifier && ((ASTIdentifier) first).getSymbol() >= 0) {
+ antish = false;
+ break main;
+ }
// first node must be an Identifier
if (objectNode instanceof ASTIdentifier) {
variableName = new StringBuilder(((ASTIdentifier) objectNode).getName());
@@ -1406,9 +1428,9 @@ public class Interpreter extends ParserV
// variableName can *not* be null; the code before this line made sure of that
object = context.get(variableName.toString());
}
- isVariable &= object == null;
+ antish &= object == null;
}
- if (object == null && isVariable && variableName != null && !isTernaryProtected(node)) {
+ if (object == null && antish && variableName != null && !isTernaryProtected(node)) {
boolean undefined = !(context.has(variableName.toString()) || isLocalVariable(node, 0));
// variable unknown in context and not a local
return unsolvableVariable(node, variableName.toString(), undefined);
@@ -1457,7 +1479,7 @@ public class Interpreter extends ParserV
}
// 1: follow children till penultimate, resolve dot/array
JexlNode objectNode = null;
- boolean isVariable = true;
+ boolean antish = true;
int v = 0;
StringBuilder variableName = null;
// start at 1 if symbol
@@ -1469,29 +1491,35 @@ public class Interpreter extends ParserV
object = objectNode.jjtAccept(this, object);
if (object != null) {
// disallow mixing antish variable & bean with same root; avoid ambiguity
- isVariable = false;
+ antish = false;
continue;
}
// if we still have a null object, check for an antish variable
- if (isVariable) {
+ if (antish) {
if (v == 0) {
+ // if the first node is a local variable or parameter, the object can not be null
+ JexlNode first = left.jjtGetChild(0);
+ if (first instanceof ASTIdentifier && ((ASTIdentifier) first).getSymbol() >= 0) {
+ antish = false;
+ break;
+ }
if (objectNode instanceof ASTIdentifier) {
variableName = new StringBuilder(((ASTIdentifier) objectNode).getName());
v = 1;
} else {
- isVariable = false;
+ antish = false;
}
}
- for (; isVariable && v <= c; ++v) {
+ for (; antish && v <= c; ++v) {
JexlNode child = left.jjtGetChild(v);
if (child instanceof ASTIdentifierAccess) {
variableName.append('.');
variableName.append(((ASTIdentifierAccess) objectNode).getName());
} else {
- isVariable = false;
+ antish = false;
}
}
- if (isVariable) {
+ if (antish) {
object = context.get(variableName.toString());
} else {
break;
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java Tue Mar 10 13:46:44 2015
@@ -129,6 +129,15 @@ public final class Scope {
}
/**
+ * Checks whether a given symbol is hoisted.
+ * @param symbol the symbol number
+ * @return true if hoisted, false otherwise
+ */
+ public boolean isHoistedSymbol(int symbol) {
+ return hoistedVariables != null && hoistedVariables.containsKey(symbol);
+ }
+
+ /**
* Declares a parameter.
* <p>
* This method creates an new entry in the symbol map.
@@ -246,15 +255,16 @@ public final class Scope {
}
/**
- * Gets this script local variable, i.e. symbols assigned to local variables.
+ * Gets this script local variable, i.e. symbols assigned to local variables excluding hoisted variables.
* @return the local variable names
*/
public String[] getLocalVariables() {
if (namedVariables != null && vars > 0) {
- String[] pa = new String[parms];
+ String[] pa = new String[parms - (hoistedVariables == null? 0 : hoistedVariables.size())];
int p = 0;
for (Map.Entry<String, Integer> entry : namedVariables.entrySet()) {
- if (entry.getValue().intValue() >= parms) {
+ int symnum = entry.getValue().intValue();
+ if (symnum >= parms && (hoistedVariables == null || !hoistedVariables.containsKey(symnum))) {
pa[p++] = entry.getKey();
}
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java Tue Mar 10 13:46:44 2015
@@ -22,6 +22,7 @@ import org.apache.commons.jexl3.JexlExpr
import org.apache.commons.jexl3.parser.ASTJexlScript;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
@@ -172,6 +173,16 @@ public class Script implements JexlScrip
}
/**
+ * Get this script pragmas
+ * <p>Pragma keys are ant-ish variables, their values are scalar literals..
+ * @return the pragmas
+ */
+ @Override
+ public Map<String, Object> getPragmas() {
+ return script.getPragmas();
+ }
+
+ /**
* Creates a Callable from this script.
* <p>This allows to submit it to an executor pool and provides support for asynchronous calls.</p>
* <p>The interpreter will handle interruption/cancellation gracefully if needed.</p>
Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/SetBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/SetBuilder.java?rev=1665548&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/SetBuilder.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/SetBuilder.java Tue Mar 10 13:46:44 2015
@@ -0,0 +1,48 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+package org.apache.commons.jexl3.internal;
+
+import org.apache.commons.jexl3.JexlArithmetic;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Helper class to create set literals.
+ */
+public class SetBuilder implements JexlArithmetic.SetBuilder {
+ /** The set being created. */
+ private final Set<Object> set;
+
+ /**
+ * Creates a new builder.
+ * @param size the expected set size
+ */
+ public SetBuilder(int size) {
+ set = new HashSet<Object>(size);
+ }
+
+ @Override
+ public void add(Object value) {
+ set.add(value);
+ }
+
+ @Override
+ public Object create() {
+ return set;
+ }
+
+}
Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/SetBuilder.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java Tue Mar 10 13:46:44 2015
@@ -393,7 +393,7 @@ public final class TemplateEngine extend
@Override
protected void getVariables(Engine.VarCollector collector) {
- jexl.getVariables(node, collector);
+ jexl.getVariables(node instanceof ASTJexlScript? (ASTJexlScript) node : null, node, collector);
}
@Override
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java Tue Mar 10 13:46:44 2015
@@ -17,6 +17,7 @@
package org.apache.commons.jexl3.parser;
import org.apache.commons.jexl3.internal.Scope;
+import java.util.Map;
/**
* Enhanced script to allow parameters declaration.
@@ -24,6 +25,8 @@ import org.apache.commons.jexl3.internal
public class ASTJexlScript extends JexlNode {
/** The script scope. */
protected Scope scope = null;
+ /** The pragmas. */
+ protected Map<String, Object> pragmas = null;
public ASTJexlScript(int id) {
super(id);
@@ -81,6 +84,13 @@ public class ASTJexlScript extends JexlN
}
/**
+ * @return this script pragmas
+ */
+ public Map<String,Object> getPragmas() {
+ return pragmas;
+ }
+
+ /**
* Creates an array of arguments by copying values up to the number of parameters.
* @param values the argument values
* @return the arguments array
@@ -126,4 +136,13 @@ public class ASTJexlScript extends JexlN
public String[] getLocalVariables() {
return scope != null? scope.getLocalVariables() : null;
}
+
+ /**
+ * Checks whether a given symbol is hoisted.
+ * @param symbol the symbol number
+ * @return true if hoisted, false otherwise
+ */
+ public boolean isHoistedSymbol(int symbol) {
+ return scope != null? scope.isHoistedSymbol(symbol) : false;
+ }
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTNumberLiteral.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTNumberLiteral.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTNumberLiteral.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTNumberLiteral.java Tue Mar 10 13:46:44 2015
@@ -16,54 +16,30 @@
*/
package org.apache.commons.jexl3.parser;
-import java.math.BigDecimal;
-import java.math.BigInteger;
import java.text.DecimalFormat;
public final class ASTNumberLiteral extends JexlNode implements JexlNode.Constant<Number> {
- /** The type literal value. */
- private Number literal = null;
- /** The expected class. */
- private Class<?> clazz = null;
-
+ private final NumberParser nlp;
ASTNumberLiteral(int id) {
super(id);
+ nlp = new NumberParser();
}
ASTNumberLiteral(Parser p, int id) {
super(p, id);
+ nlp = new NumberParser();
}
static final DecimalFormat BIGDF = new DecimalFormat("0.0b");
@Override
public String toString() {
- if (literal == null || clazz == null || Double.isNaN(literal.doubleValue())) {
- return "NaN";
- }
- if (BigDecimal.class.equals(clazz)) {
- return BIGDF.format(literal);
- }
- StringBuilder strb = new StringBuilder(literal.toString());
- if (clazz != null) {
- if (Float.class.equals(clazz)) {
- strb.append('f');
- } else if (Double.class.equals(clazz)) {
- strb.append('d');
- } else if (BigDecimal.class.equals(clazz)) {
- strb.append('b');
- } else if (BigInteger.class.equals(clazz)) {
- strb.append('h');
- } else if (Long.class.equals(clazz)) {
- strb.append('l');
- }
- }
- return strb.toString();
+ return nlp.toString();
}
@Override
public Number getLiteral() {
- return literal;
+ return nlp.getLiteralValue();
}
@Override
@@ -72,11 +48,11 @@ public final class ASTNumberLiteral exte
}
public Class<?> getLiteralClass() {
- return clazz;
+ return nlp.getLiteralClass();
}
public boolean isInteger() {
- return Integer.class.equals(clazz);
+ return nlp.isInteger();
}
/**
@@ -85,49 +61,7 @@ public final class ASTNumberLiteral exte
* @param s the natural as string
*/
void setNatural(String s) {
- Number result;
- Class<?> rclass;
- // determine the base
- final int base;
- if (s.charAt(0) == '0') {
- if ((s.length() > 1 && (s.charAt(1) == 'x' || s.charAt(1) == 'X'))) {
- base = 16;
- s = s.substring(2); // Trim the 0x off the front
- } else {
- base = 8;
- }
- } else {
- base = 10;
- }
- final int last = s.length() - 1;
- switch (s.charAt(last)) {
- case 'l':
- case 'L': {
- rclass = Long.class;
- result = Long.valueOf(s.substring(0, last), base);
- break;
- }
- case 'h':
- case 'H': {
- rclass = BigInteger.class;
- result = new BigInteger(s.substring(0, last), base);
- break;
- }
- default: {
- rclass = Integer.class;
- try {
- result = Integer.valueOf(s, base);
- } catch (NumberFormatException take2) {
- try {
- result = Long.valueOf(s, base);
- } catch (NumberFormatException take3) {
- result = new BigInteger(s, base);
- }
- }
- }
- }
- literal = result;
- clazz = rclass;
+ nlp.setNatural(s);
}
/**
@@ -136,44 +70,7 @@ public final class ASTNumberLiteral exte
* @param s the real as string
*/
void setReal(String s) {
- Number result;
- Class<?> rclass;
- if ("#NaN".equals(s) || "NaN".equals(s)) {
- result = Double.NaN;
- rclass = Double.class;
- } else {
- final int last = s.length() - 1;
- switch (s.charAt(last)) {
- case 'b':
- case 'B': {
- rclass = BigDecimal.class;
- result = new BigDecimal(s.substring(0, last));
- break;
- }
- case 'f':
- case 'F': {
- rclass = Float.class;
- result = Float.valueOf(s.substring(0, last));
- break;
- }
- case 'd':
- case 'D':
- rclass = Double.class;
- result = Double.valueOf(s.substring(0, last));
- break;
- default: {
- rclass = Double.class;
- try {
- result = Double.valueOf(s);
- } catch (NumberFormatException take3) {
- result = new BigDecimal(s);
- }
- break;
- }
- }
- }
- literal = result;
- clazz = rclass;
+ nlp.setReal(s);
}
@Override
Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTSetLiteral.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTSetLiteral.java?rev=1665548&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTSetLiteral.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTSetLiteral.java Tue Mar 10 13:46:44 2015
@@ -0,0 +1,64 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+package org.apache.commons.jexl3.parser;
+
+import org.apache.commons.jexl3.internal.Debugger;
+
+public final class ASTSetLiteral extends JexlNode {
+ /** Whether this set is constant or not. */
+ private boolean constant = false;
+
+ ASTSetLiteral(int id) {
+ super(id);
+ }
+
+ ASTSetLiteral(Parser p, int id) {
+ super(p, id);
+ }
+
+ @Override
+ public String toString() {
+ Debugger dbg = new Debugger();
+ return dbg.data(this);
+ }
+
+ @Override
+ protected boolean isConstant(boolean literal) {
+ return constant;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void jjtClose() {
+ constant = true;
+ if (children != null) {
+ for (int c = 0; c < children.length && constant; ++c) {
+ JexlNode child = children[c];
+ if (!child.isConstant()) {
+ constant = false;
+ }
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Object jjtAccept(ParserVisitor visitor, Object data) {
+ return visitor.visit(this, data);
+ }
+
+}
Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTSetLiteral.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java Tue Mar 10 13:46:44 2015
@@ -23,6 +23,9 @@ import org.apache.commons.jexl3.JexlExce
import org.apache.commons.jexl3.JexlInfo;
import org.apache.commons.jexl3.internal.Scope;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
import java.util.Stack;
/**
@@ -40,6 +43,10 @@ public abstract class JexlParser extends
*/
protected Scope frame = null;
protected Stack<Scope> frames = new Stack<Scope>();
+ /**
+ * The list of pragma declarations.
+ */
+ protected Map<String, Object> pragmas = null;
/**
@@ -120,6 +127,18 @@ public abstract class JexlParser extends
}
/**
+ * Adds a pragma declaration.
+ * @param key the pragma key
+ * @param value the pragma value
+ */
+ public void declarePragma(String key, Object value) {
+ if (pragmas == null) {
+ pragmas = new TreeMap<String, Object>();
+ }
+ pragmas.put(key, value);
+ }
+
+ /**
* Declares a local parameter.
* <p> This method creates an new entry in the symbol map. </p>
* @param identifier the parameter name
@@ -175,6 +194,29 @@ public abstract class JexlParser extends
}
}
+ /**
+ * Utility function to create '.' separated string from a list of string.
+ * @param lstr the list of strings
+ * @return the dotted version
+ */
+ String stringify(List<String> lstr) {
+ StringBuilder strb = new StringBuilder();
+ boolean dot = false;
+ for(String str : lstr) {
+ if (!dot) {
+ dot = true;
+ } else {
+ strb.append('.');
+ }
+ strb.append(str);
+ }
+ return strb.toString();
+ }
+
+ /**
+ * Throws a parsing exception.
+ * @param node the node that caused it
+ */
protected void throwParsingException(JexlNode node) {
throwParsingException(null, node);
}
@@ -182,7 +224,7 @@ public abstract class JexlParser extends
/**
* Throws a parsing exception.
* @param xclazz the class of exception
- * @param node the node that provoqued it
+ * @param node the node that caused it
*/
private void throwParsingException(Class<? extends JexlException> xclazz, JexlNode node) {
final JexlInfo dbgInfo;
Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/NumberParser.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/NumberParser.java?rev=1665548&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/NumberParser.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/NumberParser.java Tue Mar 10 13:46:44 2015
@@ -0,0 +1,179 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+package org.apache.commons.jexl3.parser;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.DecimalFormat;
+
+public final class NumberParser {
+ /** The type literal value. */
+ private Number literal = null;
+ /** The expected class. */
+ private Class<?> clazz = null;
+
+ static final DecimalFormat BIGDF = new DecimalFormat("0.0b");
+
+
+ @Override
+ public String toString() {
+ if (literal == null || clazz == null || Double.isNaN(literal.doubleValue())) {
+ return "NaN";
+ }
+ if (BigDecimal.class.equals(clazz)) {
+ return BIGDF.format(literal);
+ }
+ StringBuilder strb = new StringBuilder(literal.toString());
+ if (clazz != null) {
+ if (Float.class.equals(clazz)) {
+ strb.append('f');
+ } else if (Double.class.equals(clazz)) {
+ strb.append('d');
+ } else if (BigDecimal.class.equals(clazz)) {
+ strb.append('b');
+ } else if (BigInteger.class.equals(clazz)) {
+ strb.append('h');
+ } else if (Long.class.equals(clazz)) {
+ strb.append('l');
+ }
+ }
+ return strb.toString();
+ }
+
+
+ Class<?> getLiteralClass() {
+ return clazz;
+ }
+
+ boolean isInteger() {
+ return Integer.class.equals(clazz);
+ }
+
+ Number getLiteralValue() {
+ return literal;
+ }
+
+ static Number parseInteger(String s) {
+ NumberParser np = new NumberParser();
+ np.setNatural(s);
+ return np.getLiteralValue();
+ }
+
+ static Number parseDouble(String s) {
+ NumberParser np = new NumberParser();
+ np.setReal(s);
+ return np.getLiteralValue();
+ }
+
+ /**
+ * Sets this node as a natural literal.
+ * Originally from OGNL.
+ * @param s the natural as string
+ */
+ void setNatural(String s) {
+ Number result;
+ Class<?> rclass;
+ // determine the base
+ final int base;
+ if (s.charAt(0) == '0') {
+ if ((s.length() > 1 && (s.charAt(1) == 'x' || s.charAt(1) == 'X'))) {
+ base = 16;
+ s = s.substring(2); // Trim the 0x off the front
+ } else {
+ base = 8;
+ }
+ } else {
+ base = 10;
+ }
+ final int last = s.length() - 1;
+ switch (s.charAt(last)) {
+ case 'l':
+ case 'L': {
+ rclass = Long.class;
+ result = Long.valueOf(s.substring(0, last), base);
+ break;
+ }
+ case 'h':
+ case 'H': {
+ rclass = BigInteger.class;
+ result = new BigInteger(s.substring(0, last), base);
+ break;
+ }
+ default: {
+ rclass = Integer.class;
+ try {
+ result = Integer.valueOf(s, base);
+ } catch (NumberFormatException take2) {
+ try {
+ result = Long.valueOf(s, base);
+ } catch (NumberFormatException take3) {
+ result = new BigInteger(s, base);
+ }
+ }
+ }
+ }
+ literal = result;
+ clazz = rclass;
+ }
+
+ /**
+ * Sets this node as a real literal.
+ * Originally from OGNL.
+ * @param s the real as string
+ */
+ void setReal(String s) {
+ Number result;
+ Class<?> rclass;
+ if ("#NaN".equals(s) || "NaN".equals(s)) {
+ result = Double.NaN;
+ rclass = Double.class;
+ } else {
+ final int last = s.length() - 1;
+ switch (s.charAt(last)) {
+ case 'b':
+ case 'B': {
+ rclass = BigDecimal.class;
+ result = new BigDecimal(s.substring(0, last));
+ break;
+ }
+ case 'f':
+ case 'F': {
+ rclass = Float.class;
+ result = Float.valueOf(s.substring(0, last));
+ break;
+ }
+ case 'd':
+ case 'D':
+ rclass = Double.class;
+ result = Double.valueOf(s.substring(0, last));
+ break;
+ default: {
+ rclass = Double.class;
+ try {
+ result = Double.valueOf(s);
+ } catch (NumberFormatException take3) {
+ result = new BigDecimal(s);
+ }
+ break;
+ }
+ }
+ }
+ literal = result;
+ clazz = rclass;
+ }
+
+}
Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/NumberParser.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt Tue Mar 10 13:46:44 2015
@@ -31,6 +31,10 @@ PARSER_BEGIN(Parser)
package org.apache.commons.jexl3.parser;
+import java.util.Collections;
+import java.util.List;
+import java.util.LinkedList;
+
import java.io.Reader;
import org.apache.commons.jexl3.JexlInfo;
import org.apache.commons.jexl3.JexlException;
@@ -51,6 +55,9 @@ public final class Parser extends JexlPa
ReInit(new java.io.StringReader(jexlSrc));
frame = scope;
ASTJexlScript script = expr? JexlExpression(scope) : JexlScript(scope) ;
+ script.pragmas = pragmas != null
+ ? Collections.<String,Object>unmodifiableMap(pragmas)
+ : Collections.<String,Object>emptyMap();
script.value = info;
return script;
} catch (TokenMgrError xtme) {
@@ -103,6 +110,7 @@ PARSER_END(Parser)
| < LAMBDA : "->" >
| < BREAK : "break" >
| < CONTINUE : "continue" >
+ | < PRAGMA : "#pragma" >
}
<FOR_EACH_IN> TOKEN : /* foreach in */
@@ -212,7 +220,7 @@ ASTJexlScript JexlScript(Scope frame) :
jjtThis.setScope(frame);
}
{
- ( Statement() )* <EOF>
+ (LOOKAHEAD(<LCURLY> Expression() <SEMICOL>) Block() | ( Statement() )*) <EOF>
{
return jjtThis.script();
}
@@ -231,7 +239,6 @@ ASTJexlScript JexlExpression(Scope frame
void Statement() #void : {}
{
<SEMICOL>
- | LOOKAHEAD(3) Block()
| IfStatement()
| ForeachStatement()
| WhileStatement()
@@ -240,6 +247,7 @@ void Statement() #void : {}
| Continue()
| Break()
| Var()
+ | Pragma()
}
void Block() #Block : {}
@@ -256,13 +264,13 @@ void ExpressionStatement() #void : {}
void IfStatement() : {}
{
- <IF> <LPAREN> Expression() <RPAREN> Statement() ( LOOKAHEAD(1) <ELSE> Statement() )?
+ <IF> <LPAREN> Expression() <RPAREN> (LOOKAHEAD(1) Block() | Statement()) ( LOOKAHEAD(1) <ELSE> (LOOKAHEAD(1) Block() | Statement()) )?
}
void WhileStatement() : {}
{
- <WHILE> <LPAREN> Expression() <RPAREN> { loopCount += 1; } Statement() { loopCount -= 1; }
+ <WHILE> <LPAREN> Expression() <RPAREN> { loopCount += 1; } (LOOKAHEAD(1) Block() | Statement()) { loopCount -= 1; }
}
void ReturnStatement() : {}
@@ -282,9 +290,9 @@ void Break() #Break : {}
void ForeachStatement() : {}
{
- <FOR> <LPAREN> ForEachVar() <COLON> Expression() <RPAREN> { loopCount += 1; } Statement() { loopCount -= 1; }
+ <FOR> <LPAREN> ForEachVar() <COLON> Expression() <RPAREN> { loopCount += 1; } (LOOKAHEAD(1) Block() | Statement()) { loopCount -= 1; }
|
- <FOREACH> <LPAREN> ForEachVar() <IN> Expression() <RPAREN> { loopCount += 1; } Statement() { loopCount -= 1; }
+ <FOREACH> <LPAREN> ForEachVar() <IN> Expression() <RPAREN> { loopCount += 1; } (LOOKAHEAD(1) Block() | Statement()){ loopCount -= 1; }
}
void ForEachVar() #Reference : {}
@@ -307,6 +315,40 @@ void DeclareVar() #Var :
t=<IDENTIFIER> { declareVariable(jjtThis, t.image); }
}
+void Pragma() #void :
+{
+ LinkedList<String> lstr = new LinkedList<String>();
+ Object value;
+}
+{
+<PRAGMA> pragmaKey(lstr) value=pragmaValue() { declarePragma(stringify(lstr), value); }
+}
+
+void pragmaKey(LinkedList<String> lstr) #void :
+{
+ Token t;
+}
+{
+ t=<IDENTIFIER> (LOOKAHEAD(2) <DOT> pragmaKey(lstr) )* { lstr.addFirst(t.image); }
+}
+
+Object pragmaValue() #void :
+{
+Token v;
+LinkedList<String> lstr = new LinkedList<String>();
+}
+{
+ LOOKAHEAD(1) v=<INTEGER_LITERAL> { return NumberParser.parseInteger(v.image); }
+ | LOOKAHEAD(1) v=<FLOAT_LITERAL> { return NumberParser.parseDouble(v.image); }
+ | LOOKAHEAD(1) v=<STRING_LITERAL> { return Parser.buildString(v.image, true); }
+ | LOOKAHEAD(1) pragmaKey(lstr) { return stringify(lstr); }
+ | LOOKAHEAD(1) <TRUE> { return true; }
+ | LOOKAHEAD(1) <FALSE> { return false; }
+ | LOOKAHEAD(1) <NULL> { return null; }
+ | LOOKAHEAD(1) <NAN_LITERAL> { return Double.NaN; }
+}
+
+
/***************************************
* Expression syntax
***************************************/
@@ -555,6 +597,10 @@ void MapEntry() : {}
Expression() <COLON> Expression()
}
+void SetLiteral() : {}
+{
+ <LCURLY> (Expression() ( <COMMA> Expression() )*)? <RCURLY>
+}
/***************************************
* Functions & Methods
@@ -615,6 +661,8 @@ void LambdaLookahead() #void() : {}
<FUNCTION> Parameters()
|
Parameters() <LAMBDA>
+ |
+ Parameter() <LAMBDA>
}
void Lambda() #JexlLambda() :
@@ -625,6 +673,8 @@ void Lambda() #JexlLambda() :
<FUNCTION> Parameters() Block()
|
Parameters() <LAMBDA> Block()
+ |
+ Parameter() <LAMBDA> Block()
}
@@ -670,7 +720,13 @@ void PrimaryExpression() #void : {}
|
LOOKAHEAD( <LPAREN> ) ReferenceExpression()
|
- LOOKAHEAD( <LCURLY> ) MapLiteral()
+ LOOKAHEAD( <LCURLY> Expression() <COLON>) MapLiteral()
+ |
+ LOOKAHEAD( <LCURLY> <COLON>) MapLiteral()
+ |
+ LOOKAHEAD( <LCURLY> Expression() ) SetLiteral()
+ |
+ LOOKAHEAD( <LCURLY> <RCURLY> ) SetLiteral()
|
LOOKAHEAD( <LBRACKET> ) ArrayLiteral()
|
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java Tue Mar 10 13:46:44 2015
@@ -49,7 +49,7 @@ public abstract class ParserVisitor {
protected abstract Object visit(ASTWhileStatement node, Object data);
protected abstract Object visit(ASTContinue node, Object data);
-
+
protected abstract Object visit(ASTBreak node, Object data);
protected abstract Object visit(ASTForeachStatement node, Object data);
@@ -126,6 +126,8 @@ public abstract class ParserVisitor {
protected abstract Object visit(ASTStringLiteral node, Object data);
+ protected abstract Object visit(ASTSetLiteral node, Object data);
+
protected abstract Object visit(ASTArrayLiteral node, Object data);
protected abstract Object visit(ASTRangeNode node, Object data);
Modified: commons/proper/jexl/trunk/src/site/xdoc/reference/syntax.xml
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/site/xdoc/reference/syntax.xml?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/site/xdoc/reference/syntax.xml (original)
+++ commons/proper/jexl/trunk/src/site/xdoc/reference/syntax.xml Tue Mar 10 13:46:44 2015
@@ -148,6 +148,16 @@
the most appropriate non ambiguous method to call.</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.
+ <source>#pragma execution.option 42</source> 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>
+ </td>
+ </tr>
</table>
</section>
<section name="Literals">
@@ -255,6 +265,15 @@
</td>
</tr>
<tr>
+ <td>Set literal</td>
+ <td>
+ A <code>{</code> followed by one or more expressions separated by <code>,</code> and ending
+ with <code>}</code>, e.g.
+ <source>{ "one" , 2, "more"}</source>
+ <p>This syntax creates a <code>HashSet<Object></code>.</p>
+ </td>
+ </tr>
+ <tr>
<td>Map literal</td>
<td>
A <code>{</code> followed by one or more sets of <code>key : value</code> pairs separated by <code>,</code> and ending
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/AssignTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/AssignTest.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/AssignTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/AssignTest.java Tue Mar 10 13:46:44 2015
@@ -164,4 +164,20 @@ public class AssignTest extends JexlTest
o = JEXL.getProperty(quux, "['froboz']['value']");
assertEquals("Result is not 1000", new Integer(1000), o);
}
+
+ public void testRejectLocal() throws Exception {
+ JexlContext jc = new MapContext();
+ JexlScript assign = JEXL.createScript("var quux = null; quux.froboz.value = 10");
+ try {
+ Object o = assign.execute(jc);
+ fail("quux is local and null, should fail");
+ } catch (JexlException xjexl) {
+ String x = xjexl.toString();
+ String y = x;
+ }
+ // quux is a global antish var
+ assign = JEXL.createScript("quux.froboz.value = 10");
+ Object o = assign.execute(jc);
+ assertEquals(10, o);
+ }
}
\ No newline at end of file
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java Tue Mar 10 13:46:44 2015
@@ -50,7 +50,7 @@ public class IssuesTest extends JexlTest
JexlEngine jexl = new Engine();
Map<String, Object> vars = new HashMap<String, Object>();
JexlContext ctxt = new MapContext(vars);
- String stmt = "{a = 'b'; c = 'd';}";
+ String stmt = "a = 'b'; c = 'd';";
JexlScript expr = jexl.createScript(stmt);
/* Object value = */ expr.execute(ctxt);
assertTrue("JEXL-49 is not fixed", vars.get("a").equals("b") && vars.get("c").equals("d"));
@@ -362,8 +362,8 @@ public class IssuesTest extends JexlTest
for (char v = 'a'; v <= 'z'; ++v) {
ctxt.set(Character.toString(v), 10);
}
- String input =
- "(((((((((((((((((((((((((z+y)/x)*w)-v)*u)/t)-s)*r)/q)+p)-o)*n)-m)+l)*k)+j)/i)+h)*g)+f)/e)+d)-c)/b)+a)";
+ String input
+ = "(((((((((((((((((((((((((z+y)/x)*w)-v)*u)/t)-s)*r)/q)+p)-o)*n)-m)+l)*k)+j)/i)+h)*g)+f)/e)+d)-c)/b)+a)";
JexlExpression script;
// Make sure everything is loaded...
@@ -601,7 +601,6 @@ public class IssuesTest extends JexlTest
value = expr.evaluate(context);
assertEquals("FirstValue=9.0", value);
-
context.set("x", -10);
context.set("y", 1);
value = expr.evaluate(context);
@@ -1077,7 +1076,7 @@ public class IssuesTest extends JexlTest
jc.set("one", 1);
jc.set("two", 2);
- int[] o1 = (int[])e147.evaluate(jc);
+ int[] o1 = (int[]) e147.evaluate(jc);
assertEquals(1, o1[0]);
assertEquals(2, o1[1]);
@@ -1087,4 +1086,20 @@ public class IssuesTest extends JexlTest
assertEquals(10, o2[0]);
assertEquals(20, o2[1]);
}
+
+ public void test148() throws Exception {
+ String[] scripts = {"var x = new ('java.util.HashMap'); x.one = 1; x.two = 2; x.one", // results to 1
+ "x = new ('java.util.HashMap'); x.one = 1; x.two = 2; x.one",// results to 1
+ "x = new ('java.util.HashMap'); x.one = 1; x.two = 2; x['one']",//results to 1
+ "var x = new ('java.util.HashMap'); x.one = 1; x.two = 2; x['one']"// result to null?
+ };
+
+ JexlEngine JEXL = new Engine();
+ JexlContext jc = new MapContext();
+ for (String s : scripts) {
+ Object o = JEXL.createScript(s).execute(jc);
+ Assert.assertEquals(1, o);
+ }
+ }
+
}
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java?rev=1665548&r1=1665547&r2=1665548&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java Tue Mar 10 13:46:44 2015
@@ -17,6 +17,8 @@
package org.apache.commons.jexl3;
import org.apache.commons.jexl3.internal.Engine;
+import java.util.List;
+import java.util.Set;
import java.util.concurrent.Callable;
/**
@@ -30,7 +32,7 @@ public class LambdaTest extends JexlTest
public void testScriptArguments() throws Exception {
JexlEngine jexl = new Engine();
- JexlScript s = jexl.createScript("{ x + x }", "x");
+ JexlScript s = jexl.createScript(" x + x ", "x");
JexlScript s42 = jexl.createScript("s(21)", "s");
Object result = s42.execute(null, s);
assertEquals(42, result);
@@ -49,6 +51,9 @@ public class LambdaTest extends JexlTest
assertEquals(42, result);
result = s42.execute(ctxt);
assertEquals(42, result);
+ s = jexl.createScript("x-> { x + x }");
+ result = s42.execute(ctxt);
+ assertEquals(42, result);
}
public void testLambda() throws Exception {
@@ -124,6 +129,40 @@ public class LambdaTest extends JexlTest
assertEquals(42, result);
}
+ public void testHoistLambada() throws Exception {
+ JexlEngine jexl = new Engine();
+ JexlContext ctx = null;
+ JexlScript s42;
+ Object result;
+ JexlScript s15;
+ String[] localv;
+ Set<List<String>> hvars;
+ String strs;
+
+ // hosted variables are NOT local variables
+ strs = "(x)->{ (y)->{ x + y } }";
+ s42 = jexl.createScript(strs);
+ result = s42.execute(ctx, 15);
+ assertTrue(result instanceof JexlScript);
+ s15 = (JexlScript) result;
+ localv = s15.getLocalVariables();
+ assertNull(localv);
+ hvars = s15.getVariables();
+ assertEquals(1, hvars.size());
+
+ // declaring a local that overrides hoisted
+ strs = "(x)->{ (y)->{ var x; x + y } }";
+ s42 = jexl.createScript(strs);
+ result = s42.execute(ctx, 15);
+ assertTrue(result instanceof JexlScript);
+ s15 = (JexlScript) result;
+ localv = s15.getLocalVariables();
+ assertNotNull(localv);
+ assertEquals(1, localv.length);
+ hvars = s15.getVariables();
+ assertEquals(0, hvars.size());
+ }
+
public void testRecurse() throws Exception {
JexlEngine jexl = new Engine();
JexlContext jc = new MapContext();
Added: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/PragmaTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/PragmaTest.java?rev=1665548&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/PragmaTest.java (added)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/PragmaTest.java Tue Mar 10 13:46:44 2015
@@ -0,0 +1,52 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+package org.apache.commons.jexl3;
+
+import java.util.Map;
+import org.junit.Assert;
+
+/**
+ * Tests for pragmas
+ */
+public class PragmaTest extends JexlTestCase {
+ /**
+ * Create a new test case.
+ * @param name case name
+ */
+ public PragmaTest(String name) {
+ super(name);
+ }
+
+ /**
+ * Test creating a script from a string.
+ */
+ public void testPragmas() throws Exception {
+ JexlContext jc = new MapContext();
+ try {
+ JexlScript script = JEXL.createScript("#pragma one 1\n#pragma the.very.hard 'truth'\n2;");
+ Assert.assertTrue(script != null);
+ Map<String, Object> pragmas = script.getPragmas();
+ Assert.assertEquals(2, pragmas.size());
+ Assert.assertEquals(1, pragmas.get("one"));
+ Assert.assertEquals("truth", pragmas.get("the.very.hard"));
+ } catch(JexlException xjexl) {
+ String s = xjexl.toString();
+ }
+ }
+
+
+}
Propchange: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/PragmaTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/SetLiteralTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/SetLiteralTest.java?rev=1665548&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/SetLiteralTest.java (added)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/SetLiteralTest.java Tue Mar 10 13:46:44 2015
@@ -0,0 +1,132 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+package org.apache.commons.jexl3;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Tests for set literals
+ * @since 3.0
+ */
+public class SetLiteralTest extends JexlTestCase {
+
+ public SetLiteralTest() {
+ super("SetLiteralTest");
+ }
+
+ static private Set<?> createSet(Object... args) {
+ return new HashSet<Object>(Arrays.asList(args));
+ }
+
+ public void testSetLiteralWithStrings() throws Exception {
+ JexlExpression e = JEXL.createExpression("{ 'foo' , 'bar' }");
+ JexlContext jc = new MapContext();
+
+ Object o = e.evaluate(jc);
+ Set<?> check = createSet("foo", "bar");
+ assertTrue(Objects.equals(check, o));
+ }
+
+ public void testLiteralWithOneEntry() throws Exception {
+ JexlExpression e = JEXL.createExpression("{ 'foo' }");
+ JexlContext jc = new MapContext();
+
+ Object o = e.evaluate(jc);
+ Set<?> check = createSet("foo");
+ assertTrue(Objects.equals(check, o));
+ }
+
+ public void testSetLiteralWithStringsScript() throws Exception {
+ JexlScript e = JEXL.createScript("{ 'foo' , 'bar' }");
+ JexlContext jc = new MapContext();
+
+ Object o = e.execute(jc);
+ Set<?> check = createSet("foo", "bar");
+ assertTrue(Objects.equals(check, o));
+ }
+
+ public void testSetLiteralWithOneEntryScript() throws Exception {
+ JexlScript e = JEXL.createScript("{ 'foo' }");
+ JexlContext jc = new MapContext();
+
+ Object o = e.execute(jc);
+ Set<?> check = createSet("foo");
+ assertTrue(Objects.equals(check, o));
+ }
+
+ public void testSetLiteralWithOneEntryBlock() throws Exception {
+ JexlScript e = JEXL.createScript("{ { 'foo' }; }");
+ JexlContext jc = new MapContext();
+
+ Object o = e.execute(jc);
+ Set<?> check = createSet("foo");
+ assertTrue(Objects.equals(check, o));
+ }
+
+ public void testSetLiteralWithNumbers() throws Exception {
+ JexlExpression e = JEXL.createExpression("{ 5.0 , 10 }");
+ JexlContext jc = new MapContext();
+
+ Object o = e.evaluate(jc);
+ Set<?> check = createSet(new Double(5.0), new Integer(10));
+ assertTrue(Objects.equals(check, o));
+ }
+
+ public void testSetLiteralWithNulls() throws Exception {
+ String[] exprs = {
+ "{ 10 }",
+ "{ 10 , null }",
+ "{ 10 , null , 20}",
+ "{ '10' , null }",
+ "{ null, '10' , 20 }"
+ };
+ Set<?>[] checks = {
+ createSet(new Integer(10)),
+ createSet(new Integer(10), null),
+ createSet(new Integer(10), null, new Integer(20)),
+ createSet("10", null),
+ createSet(null, "10", new Integer(20))
+ };
+ JexlContext jc = new MapContext();
+ for (int t = 0; t < exprs.length; ++t) {
+ JexlExpression e = JEXL.createExpression(exprs[t]);
+ Object o = e.evaluate(jc);
+ assertTrue(exprs[t], Objects.equals(checks[t], o));
+ }
+
+ }
+
+ public void testSizeOfSimpleSetLiteral() throws Exception {
+ JexlExpression e = JEXL.createExpression("size({ 'foo' , 'bar'})");
+ JexlContext jc = new MapContext();
+
+ Object o = e.evaluate(jc);
+ assertEquals(new Integer(2), o);
+ }
+
+ public void testNotEmptySimpleSetLiteral() throws Exception {
+ JexlExpression e = JEXL.createExpression("empty({ 'foo' , 'bar' })");
+ JexlContext jc = new MapContext();
+
+ Object o = e.evaluate(jc);
+ assertFalse(((Boolean) o).booleanValue());
+ }
+
+}
Propchange: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/SetLiteralTest.java
------------------------------------------------------------------------------
svn:eol-style = native