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/12/18 14:02:16 UTC

[commons-jexl] branch master updated: JEXL-280: added stack of loop counters in parser and tests

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 1a9f28f  JEXL-280: added stack of loop counters in parser and tests
1a9f28f is described below

commit 1a9f28fb6992c641af1c12531716e18dcde4fad6
Author: henrib <he...@apache.org>
AuthorDate: Tue Dec 18 15:01:52 2018 +0100

    JEXL-280: added stack of loop counters in parser and tests
---
 RELEASE-NOTES.txt                                  |  1 +
 .../apache/commons/jexl3/parser/JexlParser.java    | 19 +++++++++++++++++
 .../org/apache/commons/jexl3/parser/Parser.jjt     | 14 +++++++------
 src/site/xdoc/changes.xml                          |  3 +++
 .../java/org/apache/commons/jexl3/DoWhileTest.java | 24 +++++++++++++++++++++-
 5 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 4ae8c28..97ba55c 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -62,6 +62,7 @@ Bugs Fixed in 3.2:
 
 * JEXL-282:      Pragmas with antish names are broken
 * JEXL-281:      MethodExecutor incorrectly tests for empty parameters list
+* JEXL-280:      break/continue statements outside of the loop
 * JEXL-279:      Null variables property access do not throw exceptions
 * JEXL-278:      Ambiguous exceptions should point to actual statement ambiguity
 * JEXL-272:      Dereferencing null property not reported on method call
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 61756ea..39c2cee 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
@@ -28,8 +28,10 @@ import java.io.StringReader;
 import java.lang.reflect.Constructor;
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import java.util.Set;
 import java.util.Stack;
 import java.util.TreeMap;
@@ -65,6 +67,15 @@ public abstract class JexlParser extends StringParser {
      * The list of pragma declarations.
      */
     protected Map<String, Object> pragmas = null;
+    /**
+     * The number of imbricated loops.
+     */
+    protected int loopCount = 0;
+    /**
+     * Stack of parsing loop counts.
+     */
+    protected Queue<Integer> loopCounts = null;
+
 
     /**
      * Utility function to create '.' separated string from a list of string.
@@ -156,6 +167,11 @@ public abstract class JexlParser extends StringParser {
             frames.push(frame);
         }
         frame = new Scope(frame, (String[]) null);
+        if (loopCounts == null) {
+            loopCounts = new LinkedList<Integer>();
+        }
+        loopCounts.add(loopCount);
+        loopCount = 0;
     }
 
     /**
@@ -167,6 +183,9 @@ public abstract class JexlParser extends StringParser {
         } else {
             frame = null;
         }
+        if (loopCounts != null && !loopCounts.isEmpty()) {
+            loopCount = loopCounts.remove();
+        }
     }
 
     /**
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 d2589e2..c54f2ce 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
+++ b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
@@ -44,8 +44,6 @@ import org.apache.commons.jexl3.internal.Scope;
 
 public final class Parser extends JexlParser
 {
-    private int loopCount = 0;
-
     public ASTJexlScript parse(JexlInfo jexlInfo, JexlFeatures jexlFeatures, String jexlSrc, Scope scope) {
         JexlFeatures previous = getFeatures();
         try {
@@ -364,14 +362,18 @@ void ReturnStatement() : {}
     <RETURN> ExpressionStatement()
 }
 
-void Continue() #Continue : {}
+void Continue() #Continue : {
+    Token t;
+}
 {
-    <CONTINUE> { if (loopCount == 0) { throwParsingException(jjtThis); } }
+    t=<CONTINUE> { if (loopCount == 0) { throwParsingException(null, t); } }
 }
 
-void Break() #Break : {}
+void Break() #Break : {
+    Token t;
+}
 {
-    <BREAK> { if (loopCount == 0) { throwParsingException(jjtThis); } }
+    t=<BREAK> { if (loopCount == 0) { throwParsingException(null, t); } }
 }
 
 void ForeachStatement() : {}
diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml
index 0de4bc0..91a8d08 100644
--- a/src/site/xdoc/changes.xml
+++ b/src/site/xdoc/changes.xml
@@ -32,6 +32,9 @@
             <action dev="henrib" type="fix" issue="JEXL-281" due-to="Mirek Hankus">
                 MethodExecutor incorrectly tests for empty parameters list
             </action>
+            <action dev="henrib" type="fix" issue="JEXL-280" due-to="Dmitri Blinov">
+                break/continue statements outside of the loop
+            </action>
             <action dev="henrib" type="fix" issue="JEXL-279">
                 Null variables property access do not throw exceptions
             </action>
diff --git a/src/test/java/org/apache/commons/jexl3/DoWhileTest.java b/src/test/java/org/apache/commons/jexl3/DoWhileTest.java
index b712821..7260363 100644
--- a/src/test/java/org/apache/commons/jexl3/DoWhileTest.java
+++ b/src/test/java/org/apache/commons/jexl3/DoWhileTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.commons.jexl3;
 
+import org.apache.commons.jexl3.internal.Debugger;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -77,5 +78,26 @@ public class DoWhileTest extends JexlTestCase {
         Assert.assertEquals("x is wrong", new Integer(10), jc.get("x"));
         Assert.assertEquals("y is wrong", new Integer(512), jc.get("y"));
     }
-
+    
+    @Test
+    public void testForEachBreakInsideFunction() throws Exception {
+        try {
+            JexlScript e = JEXL.createScript("for (i : 1..2) {  y = function() { break; } }");
+            Assert.fail("break is out of loop!");
+        } catch (JexlException.Parsing xparse) {
+            String str = xparse.detailedMessage();
+            Assert.assertTrue(str.contains("break"));
+        }
+    }
+        
+    @Test
+    public void testForEachContinueInsideFunction() throws Exception {
+        try {
+            JexlScript e = JEXL.createScript("for (i : 1..2) {  y = function() { continue; } }");
+            Assert.fail("continue is out of loop!");
+        } catch (JexlException.Parsing xparse) {
+            String str = xparse.detailedMessage();
+            Assert.assertTrue(str.contains("continue"));
+        }
+    }
 }