Modified: 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTStringLiteral.java
URL: 
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTStringLiteral.java?rev=1616957&r1=1616956&r2=1616957&view=diff
==============================================================================
--- 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTStringLiteral.java
 (original)
+++ 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTStringLiteral.java
 Sat Aug  9 14:12:09 2014
@@ -17,6 +17,8 @@
 package org.apache.commons.jexl3.parser;
 
 public final class ASTStringLiteral extends JexlNode implements 
JexlNode.Constant<String> {
+    /** The actual literal value; the inherited 'value' member may host a 
cached getter. */
+    private String literal = null;
 
     ASTStringLiteral(int id) {
         super(id);
@@ -28,7 +30,7 @@ public final class ASTStringLiteral exte
 
     @Override
     public String toString() {
-        return value.toString();
+        return this.literal;
     }
 
     /**
@@ -37,7 +39,7 @@ public final class ASTStringLiteral exte
      */
     @Override
     public String getLiteral() {
-        return value.toString();
+        return this.literal;
     }
 
 
@@ -48,7 +50,7 @@ public final class ASTStringLiteral exte
     }
 
     void setLiteral(String literal) {
-        value = literal;
+        this.literal = literal;
     }
 
 

Modified: 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
URL: 
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java?rev=1616957&r1=1616956&r2=1616957&view=diff
==============================================================================
--- 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
 (original)
+++ 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
 Sat Aug  9 14:12:09 2014
@@ -175,6 +175,10 @@ public abstract class JexlParser extends
         }
     }
 
+    protected void throwParsingException(JexlNode node) {
+        throwParsingException(null, node);
+    }
+
     /**
      * Throws a parsing exception.
      * @param xclazz the class of exception

Modified: 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
URL: 
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt?rev=1616957&r1=1616956&r2=1616957&view=diff
==============================================================================
--- 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
 (original)
+++ 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
 Sat Aug  9 14:12:09 2014
@@ -38,6 +38,8 @@ import org.apache.commons.jexl3.internal
 
 public final class Parser extends JexlParser
 {
+    private int loopCount = 0;
+
     public ASTJexlScript parse(JexlInfo info, String jexlSrc, Scope scope, 
boolean registers, boolean expr) {
         try {
             // If registers are allowed, the default parser state has to be 
REGISTERS.
@@ -99,6 +101,8 @@ PARSER_END(Parser)
     | < RETURN : "return" >
     | < FUNCTION : "function" >
     | < LAMBDA : "->" >
+    | < BREAK : "break" >
+    | < CONTINUE : "continue" >
 }
 
 <FOR_EACH_IN> TOKEN : /* foreach in */
@@ -233,6 +237,8 @@ void Statement() #void : {}
     | WhileStatement()
     | ExpressionStatement()
     | ReturnStatement()
+    | Continue()
+    | Break()
     | Var()
 }
 
@@ -256,7 +262,7 @@ void IfStatement() : {}
 
 void WhileStatement() : {}
 {
-    <WHILE> <LPAREN> Expression() <RPAREN> Statement()
+    <WHILE> <LPAREN> Expression() <RPAREN>  { loopCount += 1; } Statement() { 
loopCount -= 1; }
 }
 
 void ReturnStatement() : {}
@@ -264,11 +270,21 @@ void ReturnStatement() : {}
     <RETURN> Expression()
 }
 
+void Continue() #Continue : {}
+{
+    <CONTINUE> { if (loopCount == 0) { throwParsingException(jjtThis); } }
+}
+
+void Break() #Break : {}
+{
+    <BREAK> { if (loopCount == 0) { throwParsingException(jjtThis); } }
+}
+
 void ForeachStatement() : {}
 {
-    <FOR> <LPAREN> ForEachVar() <COLON>  Expression() <RPAREN> Statement()
+    <FOR> <LPAREN> ForEachVar() <COLON>  Expression() <RPAREN> { loopCount += 
1; } Statement() { loopCount -= 1; }
 |
-    <FOREACH> <LPAREN> ForEachVar() <IN>  Expression() <RPAREN> Statement()
+    <FOREACH> <LPAREN> ForEachVar() <IN>  Expression() <RPAREN>  { loopCount 
+= 1; } Statement() { loopCount -= 1; }
 }
 
 void ForEachVar() #Reference : {}

Modified: 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
URL: 
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java?rev=1616957&r1=1616956&r2=1616957&view=diff
==============================================================================
--- 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
 (original)
+++ 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
 Sat Aug  9 14:12:09 2014
@@ -48,6 +48,10 @@ public abstract class ParserVisitor {
 
     protected abstract Object visit(ASTWhileStatement node, Object data);
 
+    protected abstract Object visit(ASTContinue node, Object data);
+    
+    protected abstract Object visit(ASTBreak node, Object data);
+
     protected abstract Object visit(ASTForeachStatement node, Object data);
 
     protected abstract Object visit(ASTReturnStatement node, Object data);

Modified: 
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ForEachTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ForEachTest.java?rev=1616957&r1=1616956&r2=1616957&view=diff
==============================================================================
--- 
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ForEachTest.java
 (original)
+++ 
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ForEachTest.java
 Sat Aug  9 14:12:09 2014
@@ -96,7 +96,7 @@ public class ForEachTest extends JexlTes
     }
 
     public void testForEachWithBlock() throws Exception {
-        JexlScript exs0 = JEXL.createScript("for(in : list) { x = x + in; }");
+        JexlScript exs0 = JEXL.createScript("for(var in : list) { x = x + in; 
}");
         JexlScript exs1 = JEXL.createScript("foreach(item in list) { x = x + 
item; }");
         JexlScript []exs = { exs0, exs1 };
         JexlContext jc = new MapContext();
@@ -110,7 +110,7 @@ public class ForEachTest extends JexlTes
     }
 
     public void testForEachWithListExpression() throws Exception {
-        JexlScript e = JEXL.createScript("for(item : list.keySet()) item");
+        JexlScript e = JEXL.createScript("for(var item : list.keySet()) item");
         JexlContext jc = new MapContext();
         Map<?, ?> map = System.getProperties();
         String lastKey = (String) new 
ArrayList<Object>(map.keySet()).get(System.getProperties().size() - 1);
@@ -120,7 +120,7 @@ public class ForEachTest extends JexlTes
     }
 
     public void testForEachWithProperty() throws Exception {
-        JexlScript e = JEXL.createScript("for(item : list.cheeseList) item");
+        JexlScript e = JEXL.createScript("for(var item : list.cheeseList) 
item");
         JexlContext jc = new MapContext();
         jc.set("list", new Foo());
         Object o = e.execute(jc);
@@ -128,10 +128,50 @@ public class ForEachTest extends JexlTes
     }
 
     public void testForEachWithIteratorMethod() throws Exception {
-        JexlScript e = JEXL.createScript("for(item : list.cheezy) item");
+        JexlScript e = JEXL.createScript("for(var item : list.cheezy) item");
         JexlContext jc = new MapContext();
         jc.set("list", new Foo());
         Object o = e.execute(jc);
         assertEquals("Result is not last evaluated expression", "brie", o);
     }
+
+    public void testForEachBreakMethod() throws Exception {
+        JexlScript e = JEXL.createScript(
+                "var rr = -1; for(var item : [1, 2, 3 ,4 ,5, 6]) { if (item == 
3) { rr = item; break; }} rr"
+        );
+        JexlContext jc = new MapContext();
+        jc.set("list", new Foo());
+        Object o = e.execute(jc);
+        assertEquals("Result is not last evaluated expression", 3, o);
+    }
+
+    public void testForEachContinueMethod() throws Exception {
+        JexlScript e = JEXL.createScript(
+                "var rr = 0; for(var item : [1, 2, 3 ,4 ,5, 6]) { if (item <= 
3) continue; rr = rr + item;}"
+        );
+        JexlContext jc = new MapContext();
+        jc.set("list", new Foo());
+        Object o = e.execute(jc);
+        assertEquals("Result is not last evaluated expression", 15, o);
+    }
+
+    public void testForEachContinueBroken() throws Exception {
+        try {
+            JexlScript e = JEXL.createScript("var rr = 0; continue;");
+            fail("continue is out of loop!");
+        } catch (JexlException.Parsing xparse) {
+            String str = xparse.detailedMessage();
+            assertTrue(str.contains("continue"));
+        }
+    }
+
+    public void testForEachBreakBroken() throws Exception {
+        try {
+            JexlScript e = JEXL.createScript("if (true) { break; }");
+            fail("break is out of loop!");
+        } catch (JexlException.Parsing xparse) {
+            String str = xparse.detailedMessage();
+            assertTrue(str.contains("break"));
+        }
+    }
 }
\ No newline at end of file

Modified: 
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JXLTTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JXLTTest.java?rev=1616957&r1=1616956&r2=1616957&view=diff
==============================================================================
--- 
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JXLTTest.java 
(original)
+++ 
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JXLTTest.java 
Sat Aug  9 14:12:09 2014
@@ -27,6 +27,7 @@ import java.io.Writer;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
+import junit.framework.Assert;
 
 /**
  * Test cases for the UnifiedEL.
@@ -205,6 +206,42 @@ public class JXLTTest extends JexlTestCa
         assertEquals(source, getSource(expr.toString()));
     }
 
+    public void testConstant2() throws Exception {
+        JexlContext none = null;
+        final String source = "${size({'map':123,'map2':456})}";
+        JxltEngine.Expression expr = JXLT.createExpression(source);
+        //assertTrue("prepare should return same expression", 
expr.prepare(none) == expr);
+        Object o = expr.evaluate(none);
+        assertTrue("expression should be immediate", expr.isImmediate());
+        assertEquals(2, o);
+
+        assertEquals(source, getSource(expr.toString()));
+    }
+
+    public void testConstant3() throws Exception {
+        JexlContext none = null;
+        final String source = "#{size({'map':123,'map2':456})}";
+        JxltEngine.Expression expr = JXLT.createExpression(source);
+        //assertTrue("prepare should return same expression", 
expr.prepare(none) == expr);
+        Object o = expr.evaluate(none);
+        assertTrue("expression should be deferred", expr.isDeferred());
+        assertEquals(2, o);
+
+        assertEquals(source, getSource(expr.toString()));
+    }
+
+    public void testConstant4() throws Exception {
+        JexlContext none = null;
+        final String source = "#{ ${size({'1':2,'2': 3})} }";
+        JxltEngine.Expression expr = JXLT.createExpression(source);
+        //assertTrue("prepare should return same expression", 
expr.prepare(none) == expr);
+        Object o = expr.evaluate(none);
+        assertTrue("expression should be deferred", expr.isDeferred());
+        assertEquals(2, o);
+
+        assertEquals(source, getSource(expr.toString()));
+    }
+
     public void testDeferred() throws Exception {
         JexlContext none = null;
         final String source = "#{'world'}";
@@ -340,6 +377,20 @@ public class JXLTTest extends JexlTestCa
         String dstr = t.toString();
         assertNotNull(dstr);
     }
+    public void testTemplate10() throws Exception {
+        String source = "$$(x)->{ if(x) {\nx is ${x}\n$$ } else {\n${'no 
x'}\n$$ } }\n";
+        StringWriter strw;
+        String output;
+
+        JxltEngine.Template t = JXLT.createTemplate("$$", new 
StringReader(source), (String[])null);
+        String dstr = t.asString();
+        assertNotNull(dstr);
+
+        strw = new StringWriter();
+        t.evaluate(context, strw, 42);
+        output = strw.toString();
+        assertEquals("x is 42\n", output);
+    }
 
     public void testTemplate1() throws Exception {
         String source = "$$ if(x) {\nx is ${x}\n$$ } else {\n${'no x'}\n$$ 
}\n";
@@ -462,6 +513,29 @@ public class JXLTTest extends JexlTestCa
         assertEquals(ctl, output);
     }
 
+    public void testReport1() throws Exception {
+        String rpt =
+                  "<report>\n"
+                + "this is ${x}\n"
+                + "${x + 1}\n"
+                + "${x + 2}\n"
+                + "${x + 3}\n"
+                + "</report>\n";
+        JxltEngine.Template t = JXLT.createTemplate("$$", new 
StringReader(rpt));
+        StringWriter strw = new StringWriter();
+        context.set("x", 42);
+        t.evaluate(context, strw, 42);
+        String output = strw.toString();
+        int count = 0;
+        for(int i = 0; i < output.length(); ++i) {
+            char c = output.charAt(i);
+            if ('\n' == c) {
+                count += 1;
+            }
+        }
+        assertEquals(6, count);
+    }
+
 
     public void testOneLiner() throws Exception {
         JxltEngine.Template t = JXLT.createTemplate("$$", new 
StringReader("fourty-two"));


Reply via email to