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 2022/11/19 15:43:12 UTC

[commons-jexl] branch master updated: JEXL-385: use Dmitri PR, neat trick avoiding comparator names to be parsed as lexicons; - renamed feature to 'comparatorNames';

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 2d19757e JEXL-385: use Dmitri PR, neat trick avoiding comparator names to be parsed as lexicons; - renamed feature to 'comparatorNames';
2d19757e is described below

commit 2d19757ee8000c07204106991c9c8fc1d00fb656
Author: Dmitri Blinov <dm...@mail.ru>
AuthorDate: Sat Nov 19 16:43:00 2022 +0100

    JEXL-385: use Dmitri PR, neat trick avoiding comparator names to be parsed as lexicons;
    - renamed feature to 'comparatorNames';
---
 RELEASE-NOTES.txt                                  |  1 +
 src/changes/changes.xml                            |  3 ++
 .../org/apache/commons/jexl3/JexlFeatures.java     | 35 ++++++++++++++++++++--
 .../org/apache/commons/jexl3/parser/Parser.jjt     | 22 ++++++++++++--
 .../org/apache/commons/jexl3/FeaturesTest.java     | 14 +++++++++
 5 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index eaee759b..d7c35449 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -40,6 +40,7 @@ the skill set required to write scripts.
 
 New Features in 3.3:
 ====================
+* JEXL-385:     Support disabling fortran-style relational operators syntax
 * JEXL-382:     Simplify grammar and lexical state management
 * JEXL-380:     Multiple values per pragma key
 * JEXL-379:     Allow new to use class identifier
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 9aa7acc3..c3136c7c 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -27,6 +27,9 @@
     <body>
         <release version="3.3" date="YYYY-MM-DD">
             <!-- ADD -->
+            <action dev="Dmitri Blinov" type="add" issue="JEXL-385" due-to="Dmitri Blinov">
+                Support disabling fortran-style relational operators syntax
+            </action>
             <action dev="Dmitri Blinov" type="add" issue="JEXL-382" due-to="Dmitri Blinov">
                 Simplify grammar and lexical state management
             </action>
diff --git a/src/main/java/org/apache/commons/jexl3/JexlFeatures.java b/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
index 2b692fd1..35a80276 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
@@ -60,7 +60,7 @@ public final class JexlFeatures {
         "register", "reserved variable", "local variable", "assign/modify",
         "global assign/modify", "array reference", "create instance", "loop", "function",
         "method call", "set/map/array literal", "pragma", "annotation", "script", "lexical", "lexicalShade",
-        "thin-arrow", "fat-arrow", "namespace pragma", "import pragma"
+        "thin-arrow", "fat-arrow", "namespace pragma", "import pragma", "comparator names"
     };
     /** Registers feature ordinal. */
     private static final int REGISTER = 0;
@@ -102,6 +102,8 @@ public final class JexlFeatures {
     public static final int NS_PRAGMA = 18;
     /** Import pragma feature ordinal. */
     public static final int IMPORT_PRAGMA = 19;
+    /** Comparator names (legacy) syntax. */
+    public static final int COMPARATOR_NAMES = 20;
     /**
      * The default features flag mask.
      */
@@ -120,7 +122,8 @@ public final class JexlFeatures {
             | (1L << SCRIPT)
             | (1L << THIN_ARROW)
             | (1L << NS_PRAGMA)
-            | (1L << IMPORT_PRAGMA);
+            | (1L << IMPORT_PRAGMA)
+            | (1L << COMPARATOR_NAMES);
 
     /**
      * Creates an all-features-enabled instance.
@@ -457,6 +460,7 @@ public final class JexlFeatures {
      * will throw a parsing exception.
      * @param flag true to enable, false to disable
      * @return this features instance
+     * @since 3.3
      */
     public JexlFeatures thinArrow(final boolean flag) {
         setFeature(THIN_ARROW, flag);
@@ -465,6 +469,7 @@ public final class JexlFeatures {
 
     /**
      * @return true if thin-arrow lambda syntax is enabled, false otherwise
+     * @since 3.3
      */
     public boolean supportsThinArrow() {
         return getFeature(THIN_ARROW);
@@ -477,6 +482,7 @@ public final class JexlFeatures {
      * will throw a parsing exception.
      * @param flag true to enable, false to disable
      * @return this features instance
+     * @since 3.3
      */
     public JexlFeatures fatArrow(final boolean flag) {
         setFeature(FAT_ARROW, flag);
@@ -485,11 +491,34 @@ public final class JexlFeatures {
 
     /**
      * @return true if fat-arrow lambda syntax is enabled, false otherwise
+     * @since 3.3
      */
     public boolean supportsFatArrow() {
         return getFeature(FAT_ARROW);
     }
 
+    /**
+     * Sets whether the legacy comparison operator names syntax is enabled.
+     * <p>
+     * When disabled, comparison operators names (eq;ne;le;lt;ge;gt)
+     * will be treated as plain identifiers.
+     * @param flag true to enable, false to disable
+     * @return this features instance
+     * @since 3.3
+     */
+    public JexlFeatures comparatorNames(final boolean flag) {
+        setFeature(COMPARATOR_NAMES, flag);
+        return this;
+    }
+
+    /**
+     * @return true if legacy comparison operator names syntax is enabled, false otherwise
+     * @since 3.3
+     */
+    public boolean supportsComparatorNames() {
+        return getFeature(COMPARATOR_NAMES);
+    }
+
     /**
      * Sets whether pragma constructs are enabled.
      * <p>
@@ -540,6 +569,7 @@ public final class JexlFeatures {
      * (#pragma jexl.import....) will throw a parsing exception.
      * @param flag true to enable, false to disable
      * @return this features instance
+     * @since 3.3
      */
     public JexlFeatures importPragma(final boolean flag) {
         setFeature(IMPORT_PRAGMA, flag);
@@ -548,6 +578,7 @@ public final class JexlFeatures {
 
     /**
      * @return true if import pragma are enabled, false otherwise
+     * @since 3.3
      */
     public boolean supportsImportPragma() {
         return getFeature(IMPORT_PRAGMA);
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 98b4657c..05a17285 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
+++ b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
@@ -56,6 +56,7 @@ public final class Parser extends JexlParser
             source = jexlSrc;
             pragmas = null;
             this.scope = jexlScope;
+            token_source.comparatorNames = jexlFeatures.supportsComparatorNames();
             ReInit(jexlSrc);
             ASTJexlScript script = jexlFeatures.supportsScript()? JexlScript(jexlScope) : JexlExpression(jexlScope);
             script.jjtSetValue(info.detach());
@@ -79,7 +80,9 @@ public final class Parser extends JexlParser
 
 PARSER_END(Parser)
 
-TOKEN_MGR_DECLS : {}
+TOKEN_MGR_DECLS : {
+    boolean comparatorNames = false;
+}
 
 /***************************************
  *     Skip & Number literal tokens
@@ -140,7 +143,7 @@ TOKEN_MGR_DECLS : {}
     | < ene : "!$" > // ends not equal
 }
 
-<DEFAULT> TOKEN : { /* COMPARISONS */
+<NEVER> TOKEN : { /* COMPARISONS */
       < EQ : "eq" >
     | < NE : "ne" >
     | < GT : "gt" >
@@ -237,7 +240,20 @@ TOKEN_MGR_DECLS : {}
 
 <DEFAULT> TOKEN : /* IDENTIFIERS */
 {
-  < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>|<ESCAPE>)* > { matchedToken.image = StringParser.unescapeIdentifier(matchedToken.image); }
+  < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>|<ESCAPE>)* >
+  {
+      matchedToken.image = StringParser.unescapeIdentifier(matchedToken.image);
+      if (comparatorNames && matchedToken.image.length() == 2) {
+          switch (matchedToken.image) {
+             case "ne" : matchedToken.kind = NE; break;
+             case "eq" : matchedToken.kind = EQ; break;
+             case "lt" : matchedToken.kind = LT; break;
+             case "le" : matchedToken.kind = LE; break;
+             case "gt" : matchedToken.kind = GT; break;
+             case "ge" : matchedToken.kind = GE; break;
+          }
+      }
+  }
 |
   < #LETTER: [ "a"-"z", "A"-"Z", "_", "$", "@" ] >
 |
diff --git a/src/test/java/org/apache/commons/jexl3/FeaturesTest.java b/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
index 6893b46f..e635291f 100644
--- a/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
+++ b/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
@@ -289,4 +289,18 @@ public class FeaturesTest extends JexlTestCase {
         checkFeature(f, scripts);
     }
 
+    @Test
+    public void testNoComparatorNames() throws Exception {
+        final JexlFeatures f = new JexlFeatures().comparatorNames(false);
+        final String[] scripts = new String[]{
+            "1 eq 1",
+            "2 ne 3",
+            "1 lt 2",
+            "3 le 3",
+            "4 gt 2",
+            "3 ge 2"
+        };
+        checkFeature(f, scripts);
+    }
+
 }