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 2021/06/03 11:32:08 UTC

[commons-jexl] branch master updated (5b84709 -> 263e221)

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

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


    from 5b84709  Merge pull request #50 from csamak/master
     new 0d51800  JEXL-348: refined grammar using semantic infos and a syntactic kludge as fallback to allow user disambiguation of namespace usage, tests
     new 263e221  JEXL-348: refined grammar using semantic infos and a syntactic kludge as fallback to allow user disambiguation of namespace usage, tests

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/commons/jexl3/parser/JexlParser.java    | 62 +++++++++-------------
 .../org/apache/commons/jexl3/parser/Parser.jjt     | 24 +++------
 .../apache/commons/jexl3/ContextNamespaceTest.java |  9 ++--
 .../org/apache/commons/jexl3/Issues300Test.java    |  9 +++-
 4 files changed, 45 insertions(+), 59 deletions(-)

[commons-jexl] 01/02: JEXL-348: refined grammar using semantic infos and a syntactic kludge as fallback to allow user disambiguation of namespace usage, tests

Posted by he...@apache.org.
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 <he...@apache.org>
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);
+    }
 }

[commons-jexl] 02/02: JEXL-348: refined grammar using semantic infos and a syntactic kludge as fallback to allow user disambiguation of namespace usage, tests

Posted by he...@apache.org.
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 263e221a7a71b1b14469d6778b681f5100fa4e81
Author: henrib <he...@apache.org>
AuthorDate: Thu Jun 3 13:32:00 2021 +0200

    JEXL-348: refined grammar using semantic infos and a syntactic kludge as fallback to allow user disambiguation of namespace usage, tests
---
 .../org/apache/commons/jexl3/parser/Parser.jjt     | 24 ++++++----------------
 1 file changed, 6 insertions(+), 18 deletions(-)

diff --git a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
index 8280a6d..73622ea 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
+++ b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
@@ -19,7 +19,7 @@
 options
 {
    MULTI=true;
-   STATIC=false;
+   //STATIC=false;
    VISITOR=true;
    NODE_SCOPE_HOOK=true;
    NODE_CLASS="JexlNode";
@@ -507,11 +507,7 @@ void ConditionalExpression() #void : {}
 {
   ConditionalOrExpression()
   (
-    <QMARK> (LOOKAHEAD(<IDENTIFIER> <COLON> ,  { !isDeclaredNamespace(getToken(1), getToken(2)) })
-            Identifier(true)
-         |
-            Expression()
-         ) <COLON> Expression() #TernaryNode(3)
+    <QMARK> Expression() <COLON> Expression() #TernaryNode(3)
      |
     <ELVIS> Expression() #TernaryNode(2)
   |
@@ -651,15 +647,7 @@ void NamespaceIdentifier()  #NamespaceIdentifier :
     Token id;
 }
 {
-    ns=<IDENTIFIER> <COLON> id=<IDENTIFIER> { jjtThis.setNamespace(ns.image, id.image); }
-}
-
-void StringIdentifier() #Identifier :
-{
-    Token t;
-}
-{
-    t=<STRING_LITERAL>  { jjtThis.setSymbol(Parser.buildString(t.image, true));  }
+   ns=<IDENTIFIER> <COLON> id=<IDENTIFIER> { jjtThis.setNamespace(ns.image, id.image); }
 }
 
 void Literal() #void :
@@ -799,7 +787,7 @@ void Arguments() #Arguments : {}
 
 void FunctionCallLookahead() #void : {}
 {
-    LOOKAHEAD(2) <IDENTIFIER> <COLON> <IDENTIFIER> <LPAREN>
+    LOOKAHEAD(<IDENTIFIER> <COLON> <IDENTIFIER> <LPAREN>,  { isDeclaredNamespace(getToken(1), getToken(2)) }) <IDENTIFIER> <COLON> <IDENTIFIER> <LPAREN>
     |
     LOOKAHEAD(2) <IDENTIFIER> <LPAREN>
     |
@@ -808,9 +796,9 @@ void FunctionCallLookahead() #void : {}
 
 void FunctionCall() #void : {}
 {
-      LOOKAHEAD(2) NamespaceIdentifier() Arguments() #FunctionNode(2)
+    LOOKAHEAD(<IDENTIFIER> <COLON> <IDENTIFIER> <LPAREN>,  { isDeclaredNamespace(getToken(1), getToken(2)) })  NamespaceIdentifier() Arguments() #FunctionNode(2)
     |
-      LOOKAHEAD(2) Identifier(true) Arguments() #FunctionNode(2)
+    LOOKAHEAD(<IDENTIFIER> <LPAREN>) Identifier(true) Arguments() #FunctionNode(2)
 }
 
 void Constructor() #ConstructorNode : {}