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 2018/08/06 09:15:25 UTC

[commons-jexl] branch master updated: JEXL-265: making namespace identifier explicit in grammar and code

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


The following commit(s) were added to refs/heads/master by this push:
     new 3520002  JEXL-265: making namespace identifier explicit in grammar and code
3520002 is described below

commit 3520002a25461a7b9de0da0ca1005326e2175e28
Author: henrib <he...@apache.org>
AuthorDate: Mon Aug 6 11:15:04 2018 +0200

    JEXL-265: making namespace identifier explicit in grammar and code
---
 .../apache/commons/jexl3/internal/Debugger.java    |  8 ++-
 .../apache/commons/jexl3/internal/Interpreter.java | 19 ++------
 .../commons/jexl3/internal/TemplateDebugger.java   | 24 ++++-----
 .../apache/commons/jexl3/parser/ASTIdentifier.java |  8 ++-
 ...Identifier.java => ASTNamespaceIdentifier.java} | 57 ++++++++--------------
 .../org/apache/commons/jexl3/parser/Parser.jjt     | 21 +++++---
 .../org/apache/commons/jexl3/Issues200Test.java    | 24 +++++++++
 7 files changed, 85 insertions(+), 76 deletions(-)

diff --git a/src/main/java/org/apache/commons/jexl3/internal/Debugger.java b/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
index 08fec42..db75d81 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
@@ -602,8 +602,14 @@ public class Debugger extends ParserVisitor implements JexlInfo.Detail {
 
     @Override
     protected Object visit(ASTIdentifier node, Object data) {
+        String ns = node.getNamespace();
         String image = StringParser.escapeIdentifier(node.getName());
-        return check(node, image, data);
+        if (ns == null) {
+            return check(node, image, data);
+        } else {
+            String nsid = StringParser.escapeIdentifier(ns) + ":" + image;
+            return check(node, nsid, data);
+        }
     }
 
     @Override
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
index 7c39199..0ff4796 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
@@ -1368,20 +1368,11 @@ public class Interpreter extends InterpreterBase {
 
     @Override
     protected Object visit(ASTFunctionNode node, Object data) {
-        int argc = node.jjtGetNumChildren();
-        if (argc == 2) {
-            ASTIdentifier functionNode = (ASTIdentifier) node.jjtGetChild(0);
-            ASTArguments argNode = (ASTArguments) node.jjtGetChild(1);
-            return call(node, context, functionNode, argNode);
-        } else {
-            // objectNode 0 is the prefix
-            String prefix = ((ASTIdentifier) node.jjtGetChild(0)).getName();
-            Object namespace = resolveNamespace(prefix, node);
-            // objectNode 1 is the identifier , the others are parameters.
-            ASTIdentifier functionNode = (ASTIdentifier) node.jjtGetChild(1);
-            ASTArguments argNode = (ASTArguments) node.jjtGetChild(2);
-            return call(node, namespace, functionNode, argNode);
-        }
+        ASTIdentifier functionNode = (ASTIdentifier) node.jjtGetChild(0);
+        String nsid = functionNode.getNamespace();
+        Object namespace = (nsid != null)? resolveNamespace(nsid, node) : context;
+        ASTArguments argNode = (ASTArguments) node.jjtGetChild(1);
+        return call(node, namespace, functionNode, argNode);
     }
 
     /**
diff --git a/src/main/java/org/apache/commons/jexl3/internal/TemplateDebugger.java b/src/main/java/org/apache/commons/jexl3/internal/TemplateDebugger.java
index 4bccc56..394d9b9 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/TemplateDebugger.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/TemplateDebugger.java
@@ -151,20 +151,16 @@ public class TemplateDebugger extends Debugger {
     private int getPrintStatement(JexlNode child) {
         if (child instanceof ASTFunctionNode) {
             ASTFunctionNode node = (ASTFunctionNode) child;
-            int num = node.jjtGetNumChildren();
-            if (num == 3) {
-                ASTIdentifier ns = (ASTIdentifier) node.jjtGetChild(0);
-                ASTIdentifier fn = (ASTIdentifier) node.jjtGetChild(1);
-                JexlNode args = node.jjtGetChild(2);
-                if ("jexl".equals(ns.getName())
-                    && "print".equals(fn.getName())
-                    && args.jjtGetNumChildren() == 1
-                    && args.jjtGetChild(0) instanceof ASTNumberLiteral) {
-                    ASTNumberLiteral exprn = (ASTNumberLiteral) args.jjtGetChild(0);
-                    int n = exprn.getLiteral().intValue();
-                    if (exprs != null && n >= 0 && n < exprs.length) {
-                        return n;
-                    }
+            ASTIdentifier ns = (ASTIdentifier) node.jjtGetChild(0);
+            JexlNode args = node.jjtGetChild(1);
+            if ("jexl".equals(ns.getNamespace())
+                && "print".equals(ns.getName())
+                && args.jjtGetNumChildren() == 1
+                && args.jjtGetChild(0) instanceof ASTNumberLiteral) {
+                ASTNumberLiteral exprn = (ASTNumberLiteral) args.jjtGetChild(0);
+                int n = exprn.getLiteral().intValue();
+                if (exprs != null && n >= 0 && n < exprs.length) {
+                    return n;
                 }
             }
         }
diff --git a/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifier.java b/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifier.java
index d53f22e..782ebf5 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifier.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifier.java
@@ -20,8 +20,8 @@ package org.apache.commons.jexl3.parser;
  * Identifiers, variables, ie symbols.
  */
 public class ASTIdentifier extends JexlNode {
-    private String name = null;
-    private int symbol = -1;
+    protected String name = null;
+    protected int symbol = -1;
 
     ASTIdentifier(int id) {
         super(id);
@@ -55,6 +55,10 @@ public class ASTIdentifier extends JexlNode {
     public String getName() {
         return name;
     }
+    
+    public String getNamespace() {
+        return null;
+    }
 
     @Override
     public Object jjtAccept(ParserVisitor visitor, Object data) {
diff --git a/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifier.java b/src/main/java/org/apache/commons/jexl3/parser/ASTNamespaceIdentifier.java
similarity index 52%
copy from src/main/java/org/apache/commons/jexl3/parser/ASTIdentifier.java
copy to src/main/java/org/apache/commons/jexl3/parser/ASTNamespaceIdentifier.java
index d53f22e..698fbd9 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifier.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/ASTNamespaceIdentifier.java
@@ -17,47 +17,28 @@
 package org.apache.commons.jexl3.parser;
 
 /**
- * Identifiers, variables, ie symbols.
+ * Namespace : identifier.
  */
-public class ASTIdentifier extends JexlNode {
-    private String name = null;
-    private int symbol = -1;
-
-    ASTIdentifier(int id) {
+public class ASTNamespaceIdentifier extends ASTIdentifier {
+    private String namespace;
+    
+    public ASTNamespaceIdentifier(int id) {
         super(id);
     }
-
-    ASTIdentifier(Parser p, int id) {
-        super(p, id);
-    }
-
-    @Override
-    public String toString() {
-        return name;
-    }
-
-    void setSymbol(String identifier) {
-        if (identifier.charAt(0) == '#') {
-            symbol = Integer.parseInt(identifier.substring(1));
-        }
-        name = identifier;
-    }
-
-    void setSymbol(int r, String identifier) {
-        symbol = r;
-        name = identifier;
-    }
-
-    public int getSymbol() {
-        return symbol;
-    }
-
-    public String getName() {
-        return name;
-    }
-
+    
     @Override
-    public Object jjtAccept(ParserVisitor visitor, Object data) {
-        return visitor.visit(this, data);
+    public String getNamespace() {
+        return namespace;
+    }
+
+    /**
+     * Sets the namespace:identifier.
+     *
+     * @param ns the namespace
+     * @param id the names
+     */
+    public void setNamespace(String ns, String id) {
+        this.namespace = ns;
+        this.name = id;
     }
 }
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 a2a2d27..6bcaae4 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
+++ b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
@@ -144,7 +144,7 @@ TOKEN_MGR_DECLS : {
     | < LBRACKET : "[" >
     | < RBRACKET : "]" >
     | < SEMICOL : ";" >
-    | < COLON : ":" >
+    | < COLON : ":" > 
     | < COMMA : "," >
     | < DOT : "." > { pushDot(); } /* Lexical state is now DOT_ID */
     | < QDOT : "?." > { pushDot(); } /* Lexical state is now DOT_ID */
@@ -591,15 +591,22 @@ void Identifier(boolean top) :
     t=<REGISTER> { jjtThis.setSymbol(t.image); }
 }
 
+
+void NamespaceIdentifier()  #NamespaceIdentifier :
+{
+    Token ns;
+    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));
-  }
+    t=<STRING_LITERAL>  { jjtThis.setSymbol(Parser.buildString(t.image, true));  }
 }
 
 void Literal() #void :
@@ -736,7 +743,7 @@ void Arguments() #Arguments : {}
 
 void FunctionCallLookahead() #void : {}
 {
-    LOOKAHEAD(4) <IDENTIFIER> <COLON> <IDENTIFIER> <LPAREN>
+    LOOKAHEAD(2) <IDENTIFIER> <COLON> <IDENTIFIER> <LPAREN>
     |
     LOOKAHEAD(2) <IDENTIFIER> <LPAREN>
     |
@@ -745,7 +752,7 @@ void FunctionCallLookahead() #void : {}
 
 void FunctionCall() #void : {}
 {
-      LOOKAHEAD(2) Identifier() <COLON> Identifier() Arguments() #FunctionNode(3)
+      LOOKAHEAD(2) NamespaceIdentifier() Arguments() #FunctionNode(2)
     |
       LOOKAHEAD(2) Identifier(true) Arguments() #FunctionNode(2)
 }
diff --git a/src/test/java/org/apache/commons/jexl3/Issues200Test.java b/src/test/java/org/apache/commons/jexl3/Issues200Test.java
index f35e0ef..a18dd9c 100644
--- a/src/test/java/org/apache/commons/jexl3/Issues200Test.java
+++ b/src/test/java/org/apache/commons/jexl3/Issues200Test.java
@@ -18,6 +18,7 @@ package org.apache.commons.jexl3;
 
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -483,4 +484,27 @@ public class Issues200Test extends JexlTestCase {
             Assert.assertEquals(42, value);
         }
     }
+    
+    @Test
+    public void test265() throws Exception {
+        JexlEngine jexl = new JexlBuilder().cache(4).create();
+        JexlContext ctxt = new MapContext();
+        ctxt.set("x", 42);
+        Object result;
+        JexlScript script;
+        try {
+            script = jexl.createScript("(true) ? x : abs(1)");
+        } catch (JexlException.Parsing xparse) {
+            // ambiguous, parsing fails
+        }
+        script = jexl.createScript("(true) ? (x) : abs(2)");
+        result = script.execute(ctxt);  
+        Assert.assertEquals(42, result);
+        script = jexl.createScript("(true) ? x : (abs(3))");
+        result = script.execute(ctxt);  
+        Assert.assertEquals(42, result);
+        script = jexl.createScript("(!true) ? abs(4) : x");
+        result = script.execute(ctxt);  
+        Assert.assertEquals(42, result);
+    }
 }