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 2009/08/29 18:59:55 UTC
svn commit: r809160 - in
/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl:
Debugger.java Interpreter.java JexlEngine.java parser/Parser.jjt
Author: henrib
Date: Sat Aug 29 16:59:55 2009
New Revision: 809160
URL: http://svn.apache.org/viewvc?rev=809160&view=rev
Log:
*Parser.jjt*: modified grammar to make last statement terminator (aka ';') optional.
This implied a change in AdditiveOperation and the introduction of AdditiveOperator to break conflicts.
*Interpreter.java*: modified according to grammar ({Add,Subtract}Node replaced by AdditiveNode.
Debugger.java: made debugger expression-AST roundtrip enabled; the Debugger can regenerate an expression from AST that when parsed, will give back an equivalent AST (fixes JEXL-86).
JexlEngine.java: modified because StatementExpression are no longer creating nodes (#void)
Modified:
commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/Debugger.java
commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/Interpreter.java
commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/JexlEngine.java
commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/parser/Parser.jjt
Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/Debugger.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/Debugger.java?rev=809160&r1=809159&r2=809160&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/Debugger.java (original)
+++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/Debugger.java Sat Aug 29 16:59:55 2009
@@ -16,7 +16,8 @@
*/
package org.apache.commons.jexl;
-import org.apache.commons.jexl.parser.ASTAddNode;
+import org.apache.commons.jexl.parser.ASTAdditiveNode;
+import org.apache.commons.jexl.parser.ASTAdditiveOperator;
import org.apache.commons.jexl.parser.ASTAndNode;
import org.apache.commons.jexl.parser.ASTArrayAccess;
import org.apache.commons.jexl.parser.ASTArrayLiteral;
@@ -30,8 +31,6 @@
import org.apache.commons.jexl.parser.ASTDivNode;
import org.apache.commons.jexl.parser.ASTEQNode;
import org.apache.commons.jexl.parser.ASTEmptyFunction;
-import org.apache.commons.jexl.parser.ASTExpression;
-import org.apache.commons.jexl.parser.ASTExpressionExpression;
import org.apache.commons.jexl.parser.ASTFalseNode;
import org.apache.commons.jexl.parser.ASTFloatLiteral;
import org.apache.commons.jexl.parser.ASTForeachStatement;
@@ -54,12 +53,9 @@
import org.apache.commons.jexl.parser.ASTNullLiteral;
import org.apache.commons.jexl.parser.ASTOrNode;
import org.apache.commons.jexl.parser.ASTReference;
-import org.apache.commons.jexl.parser.ASTReferenceExpression;
import org.apache.commons.jexl.parser.ASTSizeFunction;
import org.apache.commons.jexl.parser.ASTSizeMethod;
-import org.apache.commons.jexl.parser.ASTStatementExpression;
import org.apache.commons.jexl.parser.ASTStringLiteral;
-import org.apache.commons.jexl.parser.ASTSubtractNode;
import org.apache.commons.jexl.parser.ASTTernaryNode;
import org.apache.commons.jexl.parser.ASTTrueNode;
import org.apache.commons.jexl.parser.ASTUnaryMinusNode;
@@ -157,6 +153,25 @@
}
/**
+ * Adds a statement node to the rebuilt expression.
+ * @param child the child node
+ * @param data visitor pattern argument
+ * @return visitor pattern value
+ */
+ private Object acceptStatement(JexlNode child, Object data) {
+ Object value = accept(child, data);
+ // blocks, if, for & while dont need a ';' at end
+ if (child instanceof ASTBlock
+ || child instanceof ASTIfStatement
+ || child instanceof ASTForeachStatement
+ || child instanceof ASTWhileStatement) {
+ return value;
+ }
+ builder.append(";");
+ return value;
+ }
+
+ /**
* Checks if a terminal node is the the cause to debug & adds its
* representation to the rebuilt expression.
* @param node the child node
@@ -184,28 +199,79 @@
* adds their representation to the rebuilt expression.
* @param node the child node
* @param infix the child node token
+ * @param paren whether the child should be parenthesized
* @param data visitor pattern argument
* @return visitor pattern value
*/
- private Object infixChildren(JexlNode node, String infix, Object data) {
- int num = node.jjtGetNumChildren();
+ private Object infixChildren(JexlNode node, String infix, boolean paren, Object data) {
+ int num = node.jjtGetNumChildren(); //child.jjtGetNumChildren() > 1;
+ if (paren) {
+ builder.append("(");
+ }
for (int i = 0; i < num; ++i) {
if (i > 0) {
builder.append(infix);
}
accept(node.jjtGetChild(i), data);
}
+ if (paren) {
+ builder.append(")");
+ }
+ return data;
+ }
+
+ /**
+ * Checks if the child of a node using prefix notation is the cause to debug,
+ * adds their representation to the rebuilt expression.
+ * @param node the node
+ * @param prefix the node token
+ * @param data visitor pattern argument
+ * @return visitor pattern value
+ */
+ private Object prefixChild(JexlNode node, String prefix, Object data) {
+ boolean paren = node.jjtGetChild(0).jjtGetNumChildren() > 1;
+ builder.append(prefix);
+ if (paren) {
+ builder.append("(");
+ }
+ accept(node.jjtGetChild(0), data);
+ if (paren) {
+ builder.append(")");
+ }
+ return data;
+ }
+
+ /** {@inheritDoc} */
+ public Object visit(ASTAdditiveNode node, Object data) {
+ // need parenthesis if not in operator precedence order
+ boolean paren = node.jjtGetParent() instanceof ASTMulNode
+ || node.jjtGetParent() instanceof ASTDivNode
+ || node.jjtGetParent() instanceof ASTModNode;
+ int num = node.jjtGetNumChildren(); //child.jjtGetNumChildren() > 1;
+ if (paren) {
+ builder.append("(");
+ }
+ accept(node.jjtGetChild(0), data);
+ for (int i = 1; i < num; ++i) {
+ accept(node.jjtGetChild(i), data);
+ }
+ if (paren) {
+ builder.append(")");
+ }
return data;
}
/** {@inheritDoc} */
- public Object visit(ASTAddNode node, Object data) {
- return infixChildren(node, " + ", data);
+ public Object visit(ASTAdditiveOperator node, Object data) {
+ builder.append(' ');
+ builder.append(node.image);
+ builder.append(' ');
+ return data;
}
/** {@inheritDoc} */
public Object visit(ASTAndNode node, Object data) {
- return infixChildren(node, " && ", data);
+ return infixChildren(node, " && ", false, data);
}
/** {@inheritDoc} */
@@ -235,28 +301,29 @@
/** {@inheritDoc} */
public Object visit(ASTAssignment node, Object data) {
- return infixChildren(node, " = ", data);
+ return infixChildren(node, " = ", false, data);
}
/** {@inheritDoc} */
public Object visit(ASTBitwiseAndNode node, Object data) {
- return infixChildren(node, " & ", data);
+ return infixChildren(node, " & ", false, data);
}
/** {@inheritDoc} */
public Object visit(ASTBitwiseComplNode node, Object data) {
- builder.append("~");
- return accept(node.jjtGetChild(0), data);
+ return prefixChild(node, "~", data);
}
/** {@inheritDoc} */
public Object visit(ASTBitwiseOrNode node, Object data) {
- return infixChildren(node, " | ", data);
+ boolean paren = node.jjtGetParent() instanceof ASTBitwiseAndNode;
+ return infixChildren(node, " | ", paren, data);
}
/** {@inheritDoc} */
public Object visit(ASTBitwiseXorNode node, Object data) {
- return infixChildren(node, " ^ ", data);
+ boolean paren = node.jjtGetParent() instanceof ASTBitwiseAndNode;
+ return infixChildren(node, " ^ ", paren, data);
}
/** {@inheritDoc} */
@@ -264,7 +331,8 @@
builder.append("{ ");
int num = node.jjtGetNumChildren();
for (int i = 0; i < num; ++i) {
- accept(node.jjtGetChild(0), data);
+ JexlNode child = node.jjtGetChild(i);
+ acceptStatement(child, data);
}
builder.append(" }");
return data;
@@ -272,7 +340,7 @@
/** {@inheritDoc} */
public Object visit(ASTDivNode node, Object data) {
- return infixChildren(node, " / ", data);
+ return infixChildren(node, " / ", false, data);
}
/** {@inheritDoc} */
@@ -285,26 +353,7 @@
/** {@inheritDoc} */
public Object visit(ASTEQNode node, Object data) {
- return infixChildren(node, " == ", data);
- }
-
- /** {@inheritDoc} */
- public Object visit(ASTExpression node, Object data) {
- int num = node.jjtGetNumChildren();
- for (int i = 0; i < num; ++i) {
- accept(node.jjtGetChild(i), data);
- }
- return data;
- }
-
- /** {@inheritDoc} */
- public Object visit(ASTExpressionExpression node, Object data) {
- int num = node.jjtGetNumChildren();
- for (int i = 0; i < num; ++i) {
- accept(node.jjtGetChild(i), data);
- }
- builder.append(";");
- return data;
+ return infixChildren(node, " == ", false, data);
}
/** {@inheritDoc} */
@@ -319,25 +368,27 @@
/** {@inheritDoc} */
public Object visit(ASTForeachStatement node, Object data) {
- builder.append("foreach(");
+ builder.append("for(");
accept(node.jjtGetChild(0), data);
- builder.append(" in ");
+ builder.append(" : ");
accept(node.jjtGetChild(1), data);
builder.append(") ");
if (node.jjtGetNumChildren() > 2) {
- accept(node.jjtGetChild(2), data);
+ acceptStatement(node.jjtGetChild(2), data);
+ } else {
+ builder.append(';');
}
return data;
}
/** {@inheritDoc} */
public Object visit(ASTGENode node, Object data) {
- return infixChildren(node, " >= ", data);
+ return infixChildren(node, " >= ", false, data);
}
/** {@inheritDoc} */
public Object visit(ASTGTNode node, Object data) {
- return infixChildren(node, " > ", data);
+ return infixChildren(node, " > ", false, data);
}
/** {@inheritDoc} */
@@ -347,13 +398,19 @@
/** {@inheritDoc} */
public Object visit(ASTIfStatement node, Object data) {
- builder.append("if(");
+ builder.append("if (");
accept(node.jjtGetChild(0), data);
builder.append(") ");
- accept(node.jjtGetChild(1), data);
- if (node.jjtGetNumChildren() > 2) {
- builder.append(" else ");
- accept(node.jjtGetChild(2), data);
+ if (node.jjtGetNumChildren() > 1) {
+ acceptStatement(node.jjtGetChild(1), data);
+ if (node.jjtGetNumChildren() > 2) {
+ builder.append(" else ");
+ acceptStatement(node.jjtGetChild(2), data);
+ } else {
+ builder.append(';');
+ }
+ } else {
+ builder.append(';');
}
return data;
}
@@ -367,25 +424,26 @@
public Object visit(ASTJexlScript node, Object data) {
int num = node.jjtGetNumChildren();
for (int i = 0; i < num; ++i) {
- accept(node.jjtGetChild(i), data);
+ JexlNode child = node.jjtGetChild(i);
+ acceptStatement(child, data);
}
return data;
}
/** {@inheritDoc} */
public Object visit(ASTLENode node, Object data) {
- return infixChildren(node, " <= ", data);
+ return infixChildren(node, " <= ", false, data);
}
/** {@inheritDoc} */
public Object visit(ASTLTNode node, Object data) {
- return infixChildren(node, " < ", data);
+ return infixChildren(node, " < ", false, data);
}
/** {@inheritDoc} */
public Object visit(ASTMapEntry node, Object data) {
accept(node.jjtGetChild(0), data);
- builder.append(" => ");
+ builder.append(" : ");
accept(node.jjtGetChild(1), data);
return data;
}
@@ -404,15 +462,13 @@
}
/** {@inheritDoc} */
- public Object visit(ASTConstructorNode node, Object data) {
+ public Object visit(ASTConstructorNode node, Object data) {
int num = node.jjtGetNumChildren();
builder.append("new ");
- accept(node.jjtGetChild(0), data);
builder.append("(");
+ accept(node.jjtGetChild(0), data);
for (int i = 1; i < num; ++i) {
- if (i > 1) {
- builder.append(", ");
- }
+ builder.append(", ");
accept(node.jjtGetChild(i), data);
}
builder.append(")");
@@ -453,17 +509,17 @@
/** {@inheritDoc} */
public Object visit(ASTModNode node, Object data) {
- return infixChildren(node, " % ", data);
+ return infixChildren(node, " % ", false, data);
}
/** {@inheritDoc} */
public Object visit(ASTMulNode node, Object data) {
- return infixChildren(node, " * ", data);
+ return infixChildren(node, " * ", false, data);
}
/** {@inheritDoc} */
public Object visit(ASTNENode node, Object data) {
- return infixChildren(node, " != ", data);
+ return infixChildren(node, " != ", false, data);
}
/** {@inheritDoc} */
@@ -480,8 +536,10 @@
}
/** {@inheritDoc} */
- public Object visit(ASTOrNode node, Object data) {
- return infixChildren(node, " ||", data);
+ public Object visit(ASTOrNode node, Object data) {
+ // need parenthesis if not in operator precedence order
+ boolean paren = node.jjtGetParent() instanceof ASTAndNode;
+ return infixChildren(node, " || ", paren, data);
}
/** {@inheritDoc} */
@@ -496,18 +554,6 @@
}
/** {@inheritDoc} */
- public Object visit(ASTReferenceExpression node, Object data) {
- int num = node.jjtGetNumChildren();
- accept(node.jjtGetChild(0), data);
- for (int i = 1; i < num; ++i) {
- builder.append(".");
- accept(node.jjtGetChild(i), data);
- }
- builder.append(";");
- return data;
- }
-
- /** {@inheritDoc} */
public Object visit(ASTSizeFunction node, Object data) {
builder.append("size(");
accept(node.jjtGetChild(0), data);
@@ -520,19 +566,7 @@
check(node, "size()", data);
return data;
}
-
- /** {@inheritDoc} */
- public Object visit(ASTStatementExpression node, Object data) {
- int num = node.jjtGetNumChildren();
- for (int i = 0; i < num; ++i) {
- accept(node.jjtGetChild(i), data);
- if (i > 0) {
- builder.append(";");
- }
- }
- return data;
- }
-
+
/** {@inheritDoc} */
public Object visit(ASTStringLiteral node, Object data) {
String img = node.image.replace("'", "\\'");
@@ -540,11 +574,6 @@
}
/** {@inheritDoc} */
- public Object visit(ASTSubtractNode node, Object data) {
- return infixChildren(node, " - ", data);
- }
-
- /** {@inheritDoc} */
public Object visit(ASTTernaryNode node, Object data) {
accept(node.jjtGetChild(0), data);
if (node.jjtGetNumChildren() > 2) {
@@ -568,17 +597,19 @@
/** {@inheritDoc} */
public Object visit(ASTUnaryMinusNode node, Object data) {
- builder.append("-");
- accept(node.jjtGetChild(0), data);
- return data;
+ return prefixChild(node, "-", data);
}
/** {@inheritDoc} */
public Object visit(ASTWhileStatement node, Object data) {
- builder.append("while(");
+ builder.append("while (");
accept(node.jjtGetChild(0), data);
builder.append(") ");
- accept(node.jjtGetChild(1), data);
+ if (node.jjtGetNumChildren() > 1) {
+ acceptStatement(node.jjtGetChild(1), data);
+ } else {
+ builder.append(';');
+ }
return data;
}
Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/Interpreter.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/Interpreter.java?rev=809160&r1=809159&r2=809160&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/Interpreter.java (original)
+++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/Interpreter.java Sat Aug 29 16:59:55 2009
@@ -30,7 +30,8 @@
import org.apache.commons.logging.Log;
import org.apache.commons.jexl.parser.JexlNode;
-import org.apache.commons.jexl.parser.ASTAddNode;
+import org.apache.commons.jexl.parser.ASTAdditiveNode;
+import org.apache.commons.jexl.parser.ASTAdditiveOperator;
import org.apache.commons.jexl.parser.ASTAndNode;
import org.apache.commons.jexl.parser.ASTArrayAccess;
import org.apache.commons.jexl.parser.ASTArrayLiteral;
@@ -44,8 +45,6 @@
import org.apache.commons.jexl.parser.ASTDivNode;
import org.apache.commons.jexl.parser.ASTEQNode;
import org.apache.commons.jexl.parser.ASTEmptyFunction;
-import org.apache.commons.jexl.parser.ASTExpression;
-import org.apache.commons.jexl.parser.ASTExpressionExpression;
import org.apache.commons.jexl.parser.ASTFalseNode;
import org.apache.commons.jexl.parser.ASTFunctionNode;
import org.apache.commons.jexl.parser.ASTFloatLiteral;
@@ -68,12 +67,9 @@
import org.apache.commons.jexl.parser.ASTNullLiteral;
import org.apache.commons.jexl.parser.ASTOrNode;
import org.apache.commons.jexl.parser.ASTReference;
-import org.apache.commons.jexl.parser.ASTReferenceExpression;
import org.apache.commons.jexl.parser.ASTSizeFunction;
import org.apache.commons.jexl.parser.ASTSizeMethod;
-import org.apache.commons.jexl.parser.ASTStatementExpression;
import org.apache.commons.jexl.parser.ASTStringLiteral;
-import org.apache.commons.jexl.parser.ASTSubtractNode;
import org.apache.commons.jexl.parser.ASTTernaryNode;
import org.apache.commons.jexl.parser.ASTTrueNode;
import org.apache.commons.jexl.parser.ASTUnaryMinusNode;
@@ -205,8 +201,8 @@
return node;
}
- /** {@inheritDoc} */
- public Object visit(ASTAddNode node, Object data) {
+/** {@inheritDoc} */
+ public Object visit(ASTAdditiveNode node, Object data) {
/**
* The pattern for exception mgmt is to let the child*.jjtAccept
* out of the try/catch loop so that if one fails, the ex will
@@ -215,13 +211,34 @@
* be caught explicitly and rethrown.
*/
Object left = node.jjtGetChild(0).jjtAccept(this, data);
- Object right = node.jjtGetChild(1).jjtAccept(this, data);
- try {
- return arithmetic.add(left, right);
- } catch (RuntimeException xrt) {
- JexlNode xnode = findNullOperand(xrt, node, left, right);
- throw new JexlException(xnode, "add error", xrt);
+ for(int c = 2, size = node.jjtGetNumChildren(); c < size; c += 2) {
+ Object right = node.jjtGetChild(c).jjtAccept(this, data);
+ try {
+ JexlNode op = node.jjtGetChild(c - 1);
+ if (op instanceof ASTAdditiveOperator) {
+ String which = ((ASTAdditiveOperator) op).image;
+ if ("+".equals(which)) {
+ left = arithmetic.add(left, right);
+ continue;
+ }
+ if ("-".equals(which)) {
+ left = arithmetic.subtract(left, right);
+ continue;
+ }
+ throw new UnsupportedOperationException("unknown operator " + which);
+ }
+ throw new IllegalArgumentException("unknown operator " + op);
+ } catch (RuntimeException xrt) {
+ JexlNode xnode = findNullOperand(xrt, node, left, right);
+ throw new JexlException(xnode, "+/- error", xrt);
+ }
}
+ return left;
+ }
+
+ /** {@inheritDoc} */
+ public Object visit(ASTAdditiveOperator node, Object data) {
+ throw new UnsupportedOperationException("Shoud not be called.");
}
/** {@inheritDoc} */
@@ -504,16 +521,6 @@
}
/** {@inheritDoc} */
- public Object visit(ASTExpression node, Object data) {
- return node.jjtGetChild(0).jjtAccept(this, data);
- }
-
- /** {@inheritDoc} */
- public Object visit(ASTExpressionExpression node, Object data) {
- return node.jjtGetChild(0).jjtAccept(this, data);
- }
-
- /** {@inheritDoc} */
public Object visit(ASTFalseNode node, Object data) {
return Boolean.FALSE;
}
@@ -1015,11 +1022,6 @@
}
/** {@inheritDoc} */
- public Object visit(ASTReferenceExpression node, Object data) {
- return node.jjtGetChild(0).jjtAccept(this, data);
- }
-
- /** {@inheritDoc} */
public Object visit(ASTSizeFunction node, Object data) {
Object val = node.jjtGetChild(0).jjtAccept(this, data);
@@ -1036,28 +1038,11 @@
}
/** {@inheritDoc} */
- public Object visit(ASTStatementExpression node, Object data) {
- return node.jjtGetChild(0).jjtAccept(this, data);
- }
-
- /** {@inheritDoc} */
public Object visit(ASTStringLiteral node, Object data) {
return node.image;
}
/** {@inheritDoc} */
- public Object visit(ASTSubtractNode node, Object data) {
- Object left = node.jjtGetChild(0).jjtAccept(this, data);
- Object right = node.jjtGetChild(1).jjtAccept(this, data);
- try {
- return arithmetic.subtract(left, right);
- } catch (RuntimeException xrt) {
- JexlNode xnode = findNullOperand(xrt, node, left, right);
- throw new JexlException(xnode, "- error", xrt);
- }
- }
-
- /** {@inheritDoc} */
public Object visit(ASTTernaryNode node, Object data) {
Object condition = node.jjtGetChild(0).jjtAccept(this, data);
if (node.jjtGetNumChildren() == 3) {
Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/JexlEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/JexlEngine.java?rev=809160&r1=809159&r2=809160&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/JexlEngine.java (original)
+++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/JexlEngine.java Sat Aug 29 16:59:55 2009
@@ -435,7 +435,7 @@
expr = r0 + (expr.charAt(0) == '[' ? "" : ".") + expr + ";";
try {
JexlNode tree = parse(expr, null);
- JexlNode node = tree.jjtGetChild(0).jjtGetChild(0);
+ JexlNode node = tree.jjtGetChild(0);
Interpreter interpreter = createInterpreter(context);
// ensure 4 objects in register array
Object[] r = {r0, bean, r0, bean};
@@ -502,7 +502,7 @@
expr = r0 + (expr.charAt(0) == '[' ? "" : ".") + expr + "=" + r1 + ";";
try {
JexlNode tree = parse(expr, null);
- JexlNode node = tree.jjtGetChild(0).jjtGetChild(0);
+ JexlNode node = tree.jjtGetChild(0);
Interpreter interpreter = createInterpreter(context);
// set the registers
Object[] r = {r0, bean, r1, value};
@@ -570,7 +570,7 @@
}
}
try {
- Reader reader = expr.endsWith(";") ? new StringReader(expr) : new StringReader(expr + ";");
+ Reader reader = new StringReader(expr);
// use first calling method of JexlEngine as debug info
if (info == null && debug) {
Throwable xinfo = new Throwable();
Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/parser/Parser.jjt
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/parser/Parser.jjt?rev=809160&r1=809159&r2=809160&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/parser/Parser.jjt (original)
+++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/parser/Parser.jjt Sat Aug 29 16:59:55 2009
@@ -43,10 +43,7 @@
public class Parser extends StringParser
{
- /** Base debug information. */
- protected Info debug = null;
-
- public JexlNode parse(Reader reader, Info info)
+ public ASTJexlScript parse(Reader reader, Info info)
throws ParseException
{
ReInit(reader);
@@ -55,7 +52,7 @@
* safe - it's a pain to remember
*/
- JexlNode tree = JexlScript();
+ ASTJexlScript tree = JexlScript();
tree.value = info;
return tree;
}
@@ -64,6 +61,10 @@
PARSER_END(Parser)
+/***************************************
+ * Skip & Number literal tokens
+ ***************************************/
+
SKIP : /* WHITE SPACE */
{
<COMMENT: ( "##" ( ~["\"","\n","\r"] )* ("\n" | "\r") ) >
@@ -83,27 +84,21 @@
< FLOAT_LITERAL: (<DIGIT>)+ "."(<DIGIT>)+ >
}
-/*
- * Program structuring syntax follows.
- */
-JexlNode JexlScript() :
-{
- String name;
-}
+/***************************************
+ * Program
+ ***************************************/
+
+ASTJexlScript JexlScript() : {}
{
- (
- Statement()
- )*
- <EOF>
+ ( Statement() )* <EOF>
{ return jjtThis;}
}
-void Block() :
-{}
+void Block() #Block : {}
{
- "{" ( Statement() )* "}"
+ "{" ( Statement() )* "}"
}
void EmptyFunction() : {}
@@ -127,16 +122,11 @@
}
-/*
- * Expression syntax follows.
- */
-
-void Expression() : {}
+void Expression() #void : {}
{
- LOOKAHEAD( Reference() "=" )
- Assignment()
+ LOOKAHEAD( Reference() "=" ) Assignment()
|
- ConditionalOrExpression()
+ ConditionalExpression()
}
@@ -145,6 +135,20 @@
Reference() "=" Expression()
}
+/***************************************
+ * Conditional & relational
+ ***************************************/
+
+void ConditionalExpression() #void : {}
+{
+ ConditionalOrExpression()
+ (
+ "?" Expression() ":" Expression() #TernaryNode(3)
+ |
+ "?:" Expression() #TernaryNode(2)
+ )?
+}
+
void ConditionalOrExpression() #void :
{}
{
@@ -153,11 +157,6 @@
"||" ConditionalAndExpression() #OrNode(2)
|
"or" ConditionalAndExpression() #OrNode(2)
- )*
- (
- "?" Expression() ":" Expression() #TernaryNode(3)
- |
- "?:" Expression() #TernaryNode(2)
)?
}
@@ -169,28 +168,28 @@
"&&" InclusiveOrExpression() #AndNode(2)
|
"and" InclusiveOrExpression() #AndNode(2)
- )*
+ )?
}
void InclusiveOrExpression() #void :
{}
{
ExclusiveOrExpression()
- ( "|" ExclusiveOrExpression() #BitwiseOrNode(2) )*
+ ( "|" ExclusiveOrExpression() #BitwiseOrNode(2) )?
}
void ExclusiveOrExpression() #void :
{}
{
AndExpression()
- ( "^" AndExpression() #BitwiseXorNode(2) )*
+ ( "^" AndExpression() #BitwiseXorNode(2) )?
}
void AndExpression() #void :
{}
{
EqualityExpression()
- ( "&" EqualityExpression() #BitwiseAndNode(2) )*
+ ( "&" EqualityExpression() #BitwiseAndNode(2) )?
}
void EqualityExpression() #void :
@@ -205,7 +204,7 @@
"!=" RelationalExpression() #NENode(2)
|
"ne" RelationalExpression() #NENode(2)
- )*
+ )?
}
void RelationalExpression() #void :
@@ -228,18 +227,23 @@
">=" AdditiveExpression() #GENode(2)
|
"ge" AdditiveExpression() #GENode(2)
- )*
+ )?
}
-void AdditiveExpression() #void :
-{}
+/***************************************
+ * Arithmetic
+ ***************************************/
+
+void AdditiveExpression() #AdditiveNode(>1) : {}
{
- MultiplicativeExpression()
- (
- "+" MultiplicativeExpression() #AddNode(2)
- |
- "-" MultiplicativeExpression() #SubtractNode(2)
- )*
+ MultiplicativeExpression() ( LOOKAHEAD(1) AdditiveOperator() MultiplicativeExpression())*
+}
+
+void AdditiveOperator() : {}
+{
+ "+" { jjtThis.image = "+"; }
+|
+ "-" { jjtThis.image = "-"; }
}
void MultiplicativeExpression() #void :
@@ -256,7 +260,7 @@
"%" UnaryExpression() #ModNode(2)
|
"mod" UnaryExpression() #ModNode(2)
- )*
+ )?
}
void UnaryExpression() #void :
@@ -273,13 +277,11 @@
PrimaryExpression()
}
-void PrimaryExpression() #void :
-{}
+void PrimaryExpression() #void : {}
{
Literal()
|
- LOOKAHEAD(3)
- Reference()
+ LOOKAHEAD(3) Reference()
|
LOOKAHEAD("(") "(" Expression() ")"
|
@@ -289,14 +291,16 @@
|
LOOKAHEAD("new" "(") Constructor()
|
- LOOKAHEAD( "{" MapEntry() ( "," MapEntry() )* "}" )
- MapLiteral()
+ LOOKAHEAD( "{" MapEntry() ) MapLiteral()
|
- LOOKAHEAD( "[" Parameter() ( "," Parameter() )* "]" )
- ArrayLiteral()
+ LOOKAHEAD( "[" Expression() ) ArrayLiteral()
}
+/***************************************
+ * Literals
+ ***************************************/
+
void Literal() #void :
{
Token t;
@@ -331,10 +335,8 @@
Token t;
}
{
- (
t=<INTEGER_LITERAL>
{ jjtThis.image = t.image; }
- )
}
void FloatLiteral() :
@@ -342,10 +344,8 @@
Token t;
}
{
- (
t=<FLOAT_LITERAL>
{ jjtThis.image = t.image; }
- )
}
void StringLiteral() :
@@ -353,76 +353,52 @@
Token t;
}
{
- (
t=<STRING_LITERAL>
{ jjtThis.image = Parser.buildString(t.image, true); }
- )
}
-/*
- * Statement syntax follows.
- */
+/***************************************
+ * Statements
+ ***************************************/
-void Statement() #void :
-{}
+void Statement() #void : {}
{
- ";"
-|
- LOOKAHEAD(3)
- Block()
-|
- LOOKAHEAD( Reference() ";" ) ReferenceExpression()
-|
- LOOKAHEAD( Reference() "=" ) StatementExpression()
-|
- ExpressionExpression()
-|
- IfStatement()
-|
- ForeachStatement()
-|
- WhileStatement()
+ ";"
+ | LOOKAHEAD(3) Block()
+ | IfStatement()
+ | ForeachStatement()
+ | WhileStatement()
+ | ExpressionStatement()
}
-void ExpressionExpression() : {}
-{
- Expression() ";"
-}
-
-void StatementExpression() : {}
+void ExpressionStatement() #void : {}
{
- Assignment() ";"
+ Expression() (LOOKAHEAD(2) ";")?
}
-void ReferenceExpression() : {}
-{
- Reference() ";"
-}
-void IfStatement() :{}
+void IfStatement() : {}
{
- "if" "(" Expression() ")" Statement() [ LOOKAHEAD(1) "else" Statement() ]
+ "if" "(" Expression() ")" Statement() ( LOOKAHEAD(1) "else" Statement() )?
}
-void WhileStatement() :
-{}
+void WhileStatement() : {}
{
"while" "(" Expression() ")" Statement()
}
-void ForeachStatement() :
-{}
+void ForeachStatement() : {}
{
- "for" "(" Reference() ":" Reference() ")" Statement()
+ "for" "(" Reference() ":" Expression() ")" Statement()
|
- "foreach" "(" Reference() "in" Reference() ")" Statement()
+ "foreach" "(" Reference() "in" Expression() ")" Statement()
}
void ArrayLiteral() : {}
{
- "[" Parameter() ( "," Parameter() )* "]"
+ "[" Expression() ( "," Expression() )* "]"
}
void MapLiteral() : {}
@@ -432,22 +408,22 @@
void MapEntry() : {}
{
- Parameter() ":" Parameter()
+ Expression() ":" Expression()
}
void Method() #MethodNode: {}
{
- Identifier() "("[ Parameter() ( "," Parameter() )* ] ")"
+ Identifier() "("[ Expression() ( "," Expression() )* ] ")"
}
void Function() #FunctionNode: {}
{
- Identifier() ":" Identifier() "("[ Parameter() ( "," Parameter() )* ] ")"
+ Identifier() ":" Identifier() "("[ Expression() ( "," Expression() )* ] ")"
}
void ArrayAccess() : {}
{
- Identifier() ("[" ( LOOKAHEAD(3) Expression() | IntegerLiteral() | Reference() ) "]")+
+ Identifier() (LOOKAHEAD(2) "[" Expression() "]")+
}
void AnyMethod() #void : {}
@@ -459,7 +435,7 @@
void Constructor() # ConstructorNode() : {}
{
- "new" "("[ Parameter() ( "," Parameter() )* ] ")"
+ "new" "("[ Expression() ( "," Expression() )* ] ")"
}
void SizeMethod() : {}
@@ -469,26 +445,43 @@
void Reference() : {}
{
- (LOOKAHEAD("new") Constructor() |
- LOOKAHEAD(Identifier() "[" ( Expression() | IntegerLiteral() | Reference()) "]") ArrayAccess() |
- LOOKAHEAD(Identifier() ":" Identifier() "(") Function() |
- LOOKAHEAD(Identifier() "(") Method() |
- Identifier() |
- MapLiteral())
- (LOOKAHEAD(2) "."
- (
- LOOKAHEAD(Identifier() "[" ( Expression() | IntegerLiteral() | Reference()) "]") ArrayAccess() |
- (LOOKAHEAD(3) AnyMethod() | Identifier() | IntegerLiteral() )
- )
- )*
+ ( LOOKAHEAD("new") Constructor()
+|
+ LOOKAHEAD(Identifier() "[" ) ArrayAccess()
+|
+ LOOKAHEAD(Identifier() ":" Identifier() "(") Function()
+|
+ LOOKAHEAD(Identifier() "(") Method()
+|
+ Identifier()
+|
+ LOOKAHEAD("{") MapLiteral()
+|
+ LOOKAHEAD("[") ArrayLiteral() ) DotReference()
}
-
-void Parameter() #void: {}
+void DotReference() #void : {}
{
- LOOKAHEAD(3) Expression() | Literal() | Reference()
+ ("."
+ ( LOOKAHEAD(Identifier() "[" )
+ ArrayAccess()
+ |
+ ( LOOKAHEAD(3)
+ AnyMethod()
+ |
+ Identifier()
+ |
+ IntegerLiteral()
+ )
+ )
+ )*
}
+
+/***************************************
+ * Identifier & String tokens
+ ***************************************/
+
TOKEN : /* IDENTIFIERS */
{
< IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* >
@@ -501,8 +494,8 @@
TOKEN :
{
<STRING_LITERAL :
- ("\"" ( ~["\"","\n","\r"] | "\\" ["n","t","b","r","f","\\","\""] )* "\"" )
+ ("\"" ( ~["\"","\n","\r"] | "\\" ["u","n","t","b","r","f","\\","\""] )* "\"" )
|
- ("\'" ( ~["\'","\n","\r"] | "\\" ["n","t","b","r","f","\\","\'"])* "\'" )
+ ("\'" ( ~["\'","\n","\r"] | "\\" ["u","n","t","b","r","f","\\","\'"])* "\'" )
>
}