This is an automated email from the ASF dual-hosted git repository.

henrib pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git

commit 0d51800d90fb783a65d266ea41d0bdad1709edb4
Author: henrib <[email protected]>
AuthorDate: Thu Jun 3 13:31:47 2021 +0200

    JEXL-348: refined grammar using semantic infos and a syntactic kludge as 
fallback to allow user disambiguation of namespace usage, tests
---
 .../apache/commons/jexl3/parser/JexlParser.java    | 62 +++++++++-------------
 .../apache/commons/jexl3/ContextNamespaceTest.java |  9 ++--
 .../org/apache/commons/jexl3/Issues300Test.java    |  9 +++-
 3 files changed, 39 insertions(+), 41 deletions(-)

diff --git a/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java 
b/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
index 3116916..59dcb3e 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
@@ -31,7 +31,6 @@ import java.util.ArrayDeque;
 import java.util.Arrays;
 import java.util.Deque;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
@@ -131,6 +130,7 @@ public abstract class JexlParser extends StringParser {
         loopCount = 0;
         blocks.clear();
         block = null;
+        this.setFeatures(features);
     }
 
     /**
@@ -138,7 +138,7 @@ public abstract class JexlParser extends StringParser {
      * @param lstr the list of strings
      * @return the dotted version
      */
-    protected static String stringify(final List<String> lstr) {
+    protected static String stringify(final Iterable<String> lstr) {
         final StringBuilder strb = new StringBuilder();
         boolean dot = false;
         for(final String str : lstr) {
@@ -183,7 +183,7 @@ public abstract class JexlParser extends StringParser {
 
     /**
      * Sets a new set of options.
-     * @param features
+     * @param features the parser features
      */
     protected void setFeatures(final JexlFeatures features) {
         this.featureController.setFeatures(features);
@@ -269,7 +269,7 @@ public abstract class JexlParser extends StringParser {
      * Checks if a symbol is defined in lexical scopes.
      * <p>This works with with parsed scripts in template resolution only.
      * @param info an info linked to a node
-     * @param symbol
+     * @param symbol the symbol number
      * @return true if symbol accessible in lexical scope
      */
     private boolean isSymbolDeclared(final JexlNode.Info info, final int 
symbol) {
@@ -364,15 +364,13 @@ public abstract class JexlParser extends StringParser {
      * if it is already declared
      */
     private boolean declareSymbol(final int symbol) {
-        if (blocks != null) {
-            for (final LexicalUnit lu : blocks) {
-                if (lu.hasSymbol(symbol)) {
-                    return false;
-                }
-                // stop at first new scope reset, aka lambda
-                if (lu instanceof ASTJexlLambda) {
-                    break;
-                }
+        for (final LexicalUnit lu : blocks) {
+            if (lu.hasSymbol(symbol)) {
+                return false;
+            }
+            // stop at first new scope reset, aka lambda
+            if (lu instanceof ASTJexlLambda) {
+                break;
             }
         }
         return block == null || block.declareSymbol(symbol);
@@ -381,10 +379,10 @@ public abstract class JexlParser extends StringParser {
     /**
      * Declares a local variable.
      * <p> This method creates an new entry in the symbol map. </p>
-     * @param var the identifier used to declare
+     * @param variable the identifier used to declare
      * @param token      the variable name toekn
      */
-    protected void declareVariable(final ASTVar var, final Token token) {
+    protected void declareVariable(final ASTVar variable, final Token token) {
         final String name = token.image;
         if (!allowVariable(name)) {
             throwFeatureException(JexlFeatures.LOCAL_VAR, token);
@@ -393,16 +391,16 @@ public abstract class JexlParser extends StringParser {
             frame = new Scope(null, (String[]) null);
         }
         final int symbol = frame.declareVariable(name);
-        var.setSymbol(symbol, name);
+        variable.setSymbol(symbol, name);
         if (frame.isCapturedSymbol(symbol)) {
-            var.setCaptured(true);
+            variable.setCaptured(true);
         }
         // lexical feature error
         if (!declareSymbol(symbol)) {
             if (getFeatures().isLexical()) {
-                throw new JexlException(var, name + ": variable is already 
declared");
+                throw new JexlException(variable, name + ": variable is 
already declared");
             }
-            var.setRedefined(true);
+            variable.setRedefined(true);
         }
     }
 
@@ -421,7 +419,7 @@ public abstract class JexlParser extends StringParser {
             throwFeatureException(JexlFeatures.PRAGMA, getToken(0));
         }
         if (pragmas == null) {
-            pragmas = new TreeMap<String, Object>();
+            pragmas = new TreeMap<>();
         }
         // declaring a namespace
         Predicate<String> ns = getFeatures().namespaceTest();
@@ -495,10 +493,6 @@ public abstract class JexlParser extends StringParser {
         // Overriden by generated code
     }
 
-    final protected void Identifier() throws ParseException {
-        Identifier(false);
-    }
-
     /**
      * Overridden in actual parser to access tokens stack.
      * @param index 0 to get current token
@@ -515,8 +509,7 @@ public abstract class JexlParser extends StringParser {
     /**
      * The set of assignment operators as classes.
      */
-    @SuppressWarnings("unchecked")
-    private static final Set<Class<? extends JexlNode>> ASSIGN_NODES = new 
HashSet<Class<? extends JexlNode>>(
+    private static final Set<Class<? extends JexlNode>> ASSIGN_NODES = new 
HashSet<>(
         Arrays.asList(
             ASTAssignment.class,
             ASTSetAddNode.class,
@@ -542,9 +535,9 @@ public abstract class JexlParser extends StringParser {
      * <p>
      * Detects "Ambiguous statement" and 'non-left value assignment'.</p>
      * @param node the node
-     * @throws ParseException
+     * @throws JexlException.Parsing when parsing fails
      */
-    protected void jjtreeCloseNodeScope(final JexlNode node) throws 
ParseException {
+    protected void jjtreeCloseNodeScope(final JexlNode node) {
         if (node instanceof ASTAmbiguous) {
             throwAmbiguousException(node);
         }
@@ -572,6 +565,7 @@ public abstract class JexlParser extends StringParser {
      * Throws Ambiguous exception.
      * <p>Seeks the end of the ambiguous statement to recover.
      * @param node the first token in ambiguous expression
+     * @throws JexlException.Ambiguous in all cases
      */
     protected void throwAmbiguousException(final JexlNode node) {
         final JexlInfo begin = node.jexlInfo();
@@ -585,6 +579,7 @@ public abstract class JexlParser extends StringParser {
      * Throws a feature exception.
      * @param feature the feature code
      * @param info the exception surroundings
+     * @throws JexlException.Feature in all cases
      */
     protected void throwFeatureException(final int feature, final JexlInfo 
info) {
         final String msg = info != null? readSourceLine(source, 
info.getLine()) : null;
@@ -595,6 +590,8 @@ public abstract class JexlParser extends StringParser {
      * Throws a feature exception.
      * @param feature the feature code
      * @param token the token that triggered it
+     * @throws JexlException.Parsing if actual error token can not be found
+     * @throws JexlException.Feature in all other cases
      */
     protected void throwFeatureException(final int feature, Token token) {
         if (token == null) {
@@ -608,18 +605,11 @@ public abstract class JexlParser extends StringParser {
     }
 
     /**
-     * Throws a parsing exception.
-     * @param node the node that caused it
-     */
-    protected void throwParsingException(final JexlNode node) {
-        throwParsingException(null, null);
-    }
-
-    /**
      * Creates a parsing exception.
      * @param xclazz the class of exception
      * @param tok the token to report
      * @param <T> the parsing exception subclass
+     * @throws JexlException.Parsing in all cases
      */
     protected <T extends JexlException.Parsing> void 
throwParsingException(final Class<T> xclazz, Token tok) {
         JexlInfo xinfo  = null;
diff --git a/src/test/java/org/apache/commons/jexl3/ContextNamespaceTest.java 
b/src/test/java/org/apache/commons/jexl3/ContextNamespaceTest.java
index c06b8bb..942fa95 100644
--- a/src/test/java/org/apache/commons/jexl3/ContextNamespaceTest.java
+++ b/src/test/java/org/apache/commons/jexl3/ContextNamespaceTest.java
@@ -164,10 +164,11 @@ public class ContextNamespaceTest extends JexlTestCase {
     public void testNamespace348b() throws Exception {
         JexlContext ctxt = new ContextNs348();
         final JexlEngine jexl = new JexlBuilder().safe(false).create();
-        run348a(jexl, ctxt, "ns:"); // no space for ns name
-        run348b(jexl, ctxt, "ns:"); // no space for ns name
-        run348c(jexl, ctxt);
-        run348d(jexl, ctxt);
+        // no space for ns name as syntactic hint
+        run348a(jexl, ctxt, "ns:");
+        run348b(jexl, ctxt, "ns:");
+        run348c(jexl, ctxt, "ns:");
+        run348d(jexl, ctxt, "ns:");
     }
 
     @Test
diff --git a/src/test/java/org/apache/commons/jexl3/Issues300Test.java 
b/src/test/java/org/apache/commons/jexl3/Issues300Test.java
index f3267d4..b5f774d 100644
--- a/src/test/java/org/apache/commons/jexl3/Issues300Test.java
+++ b/src/test/java/org/apache/commons/jexl3/Issues300Test.java
@@ -497,7 +497,7 @@ public class Issues300Test {
             final JexlExpression expr = jexl.createExpression("new()");
             Assert.fail("should not parse");
         } catch (final JexlException.Parsing xparse) {
-            Assert.assertTrue(xparse.toString().contains("new"));
+            Assert.assertTrue(xparse.toString().contains(")"));
         }
     }
 
@@ -593,4 +593,11 @@ public class Issues300Test {
         result = script.execute(ctxt);
         Assert.assertFalse((Boolean) result);
     }
+
+    @Test public void test349() throws Exception {
+        String text = "(A ? C.D : E)";
+        JexlEngine jexl = new JexlBuilder().safe(true).create();
+        JexlExpression expr = jexl.createExpression(text);
+        JexlScript script = jexl.createScript(text);
+    }
 }

Reply via email to