
// ----------------------------------------------------------------------------
// Options

options {
    JAVA_UNICODE_ESCAPE = true;
}

// ----------------------------------------------------------------------------
// Parser Begin

PARSER_BEGIN(ExpressionParser)
package prefuse.data.expression.parser;

import java.io.StringReader;
import java.util.logging.Logger;

import prefuse.data.expression.AndPredicate;
import prefuse.data.expression.ArithmeticExpression;
import prefuse.data.expression.BooleanLiteral;
import prefuse.data.expression.ColumnExpression;
import prefuse.data.expression.ComparisonPredicate;
import prefuse.data.expression.Expression;
import prefuse.data.expression.Function;
import prefuse.data.expression.FunctionTable;
import prefuse.data.expression.IfExpression;
import prefuse.data.expression.NotPredicate;
import prefuse.data.expression.NumericLiteral;
import prefuse.data.expression.ObjectLiteral;
import prefuse.data.expression.OrPredicate;
import prefuse.data.expression.Predicate;
import prefuse.data.expression.XorPredicate;
import prefuse.util.StringLib;

/**
 * Parser for statements written in the prefuse expression language. Text
 * expression are parsed into {@link prefuse.data.expression.Expression}
 * instances, and can be used as predicates or to create derived
 * table columns. This parser is implemented using the 
 * <a href="https://javacc.dev.java.net/">JavaCC package</a>. To parse
 * a text String to an {@link prefuse.data.expression.Expression}, use
 * the {@link #parse(String)} method. If a parse error occurs, the method
 * will fail silently and return null. Any generated exception can be
 * later retrieved using the {@link #getError()} method. One can also
 * use the {@link #parse(String, boolean)} with a <code>true</code>
 * boolean argument to request that Exceptions be thrown when
 * errors occur.
 * 
 * <h1>Prefuse Expression Language Reference</h1>
 * <p>
 * The prefuse expression language provides a convenient way of creating manipulable statements
 * over data in a prefuse data structure. For example, the expression language can be used to
 * write {@link prefuse.data.expression.Predicate} instances for querying and filtering a table
 * or graph, or to create arbitrary expressions over a data set to generate new, derived data
 * fields that can in turn be subject to additional processing or visualization. For example,
 * the {@link prefuse.data.tuple.TupleSet#tuples(prefuse.data.expression.Predicate)} method
 * uses a Predicate to filter the requested set of tuples, and the
 * {@link prefuse.data.Table#addColumn(java.lang.String,prefuse.data.expression.Expression)}
 * method creates a new table column whose values are generated by the provided Expression. 
 * The expression machinery is used
 * throughout the toolkit -- it underlies the filtering and query optimization features,
 * is a key component of {@link prefuse.data.query dynamic query bindings}, and is used to
 * create the rule chains evaluated by the
 * {@link prefuse.render.DefaultRendererFactory},
 * {@link prefuse.action.assignment.ColorAction},
 * {@link prefuse.action.assignment.ShapeAction},
 * {@link prefuse.action.assignment.FontAction}, and
 * {@link prefuse.action.assignment.SizeAction} classes.
 * </p>
 * <p>
 * The {@link prefuse.data.expression.Expression} interface is quite simple: given a single
 * Tuple, compute and return a value. The returned value could be an Object, a boolean, an int,
 * or other primitive type. Individual methods for each type are available, and which ones are
 * legal to call for any given Expression depends on the type of Expression.
 * </p>
 * <p>
 * Expressions can be created directly in Java, by instantiating and chaining together the
 * desired Expression instances. This process, however, can be somewhat tedious, so prefuse
 * also provides a built-in parser/compiler for generating these chains of Expression
 * instances from a textual language. The language is based on a subset of SQL, the
 * standard language for database queries. If you have ever written a "WHERE" clause in
 * a SQL "SELECT" query, you probably know most of the language already. To parse an
 * expression, simply pass a text string containing an expression statement to the
 * {@link prefuse.data.expression.parser.ExpressionParser#parse(java.lang.String)}
 * method. If the string parses successfully, the parsed Expression instance will be
 * returned.
 * </p>
 * <p>
 * Below is the reference for the language, including literal types, data field references,
 * basic operators, and included functions. If need be, you can also introduce a new
 * function by creating a new instance of the {@link prefuse.data.expression.Function} interface
 * and registering it with the {@link prefuse.data.expression.FunctionTable} class.
 * </p>
 * <p>
 * All keywords and functions in the prefuse expression language can be written in
 * either uppercase or lowercase. Writing in mixed-case, however, will likely result in parse
 * errors.
 * </p>
 * 
 * <h2>Literal Values and Data Field References</h2>
 * <p>The fundamental building blocks of the expression language, representing data values
 *  or referencing the contents of a Tuple data field.</p>
 * <ul>
 * <li><strong>Boolean literals  (<code>TRUE, FALSE</code>)</strong><br/>
 *   The boolean literals representing true and false conditions, parsed to type <code>boolean</code>
 * </li>
 * <li><strong>Integer literals (<code>1, -5, 12340</code>)</strong><br/>
 *   Undecorated, non-decimal numbers are parsed as numbers of type <code>int</code>
 * </li>
 * <li><strong>Long literals (<code>1L, -5L, 12340L</code>)</strong><br/>
 *   Integer values decorated with the suffix "L" are parsed as numbers of type <code>long</code>
 * </li>
 * <li><strong>Double literals (<code>1.0, 3.1415, 1e-35, 2.3e6</code>)</strong><br/>
 *   Numbers with decimals or exponents in scientific notation are parsed as numbers of type <code>double</code>
 * </li>
 * <li><strong>Float literals (<code>1.0f, 3.1415f, 1e-35f, 2.3e6f</code>)</strong><br/>
 *   Floating-point values decorated with the suffix "f" are parsed as numbers of type <code>float</code>
 * </li>
 * <li><strong>String literals (<code>"some text", 'a label'</code>)</strong><br/>
 *   Text strings placed in double (") or single (') quotations are parsed as <code>String</code> literals
 * </li>
 * <li><strong>Null literal  (<code>null</code>)</strong><br/>
 *   The string <code>null</code> is parsed as an ObjectLiteral of type null.
 * </li>
 * <li><strong>Data field references (<code>_strokeColor, [a data field]</code>)</strong><br/>
 *   Free-standing strings or those placed within brackets are parsed as a reference to the
 *   data field of that name. Brackets are required for any fields that include spaces or other
 *   unusual characters in their name (e.g., characters like +, -, *, etc), or conflict with
 *   an existing keyword For example, <code>true</code> parses to a boolean literal while
 *   <code>[true]</code> parses to a reference to a data field named 'true'.
 * </li>
 * </ul>
 *
 * <h2>Operators and Control Flow</h2>
 * <p>Basic operators and control flow structures for the expression language.</p>
 * <ul>
 * <li><strong><code>x + y</code> (addition)</strong><br/>
 *     Add <code>x</code> and <code>y</code>
 * </li>
 * <li><strong><code>x - y</code> (subtraction)</strong><br/>
 *     Subtract <code>y</code> from <code>x</code>
 * </li>
 * <li><strong><code>x * y</code> (multiplication)</strong><br/>
 *     Multiply <code>x</code> and <code>y</code>
 * </li>
 * <li><strong><code>x / y</code> (division)</strong><br/>
 *     Divide <code>x</code> by <code>y</code>
 * </li>
 * <li><strong><code>x ^ y</code> (exponentiation, pow)</strong><br/>
 *     Raise <code>x</code> to the exponent <code>y</code>
 * </li>
 * <li><strong><code>x % y</code> (modulo)</strong><br/>
 *     Return the remainder of <code>x</code> divded by <code>y</code>
 * </li>
 * <li><strong><code>x = y, x == y</code> (equality)</strong><br/>
 *     Indicates if <code>x</code> and <code>y</code> are equal
 * </li>
 * <li><strong><code>x != y, x <> y</code> (inequality)</strong><br/>
 *     Indicates if <code>x</code> and <code>y</code> are not equal
 * </li>
 * <li><strong><code>x > y</code> (greater than)</strong><br/>
 *     Indicates if <code>x</code> is greater than <code>y</code>
 * </li>
 * <li><strong><code>x >= y</code> (greater than or equal to)</strong><br/>
 *     Indicates if <code>x</code> is greater than or equal to <code>y</code>
 * </li>
 * <li><strong><code>x < y</code> (less than)</strong><br/>
 *     Indicates if <code>x</code> is less than <code>y</code>
 * </li>
 * <li><strong><code>x <= y</code> (less than or equal to)</strong><br/>
 *     Indicates if <code>x</code> is less than or equal to <code>y</code>
 * </li>
 * <li><strong><code>x AND y, x && y</code> (and)</strong><br/>
 *     Indicates if both <code>x</code> and <code>y</code> are true
 * </li>
 * <li><strong><code>x OR y, x || y</code> (or)</strong><br/>
 *     Indicates if either <code>x</code> or <code>y</code> is true
 * </li>
 * <li><strong><code>NOT x, !x</code> (not)</strong><br/>
 *     Indicates if the negation of <code>x</code> is true
 * </li>
 * <li><strong><code>x XOR y</code> (exclusive or)</strong><br/>
 *     Indicates if one, but not both, of <code>x</code> or <code>y</code> is true
 * </li>
 * <li><strong><code>IF test THEN x ELSE y</code> (if-then-else)</strong><br/>
 *     Evaluates the predicate <code>test</code>, and if true evaluates and returns the
 *     expression <code>x</code>, and if false evaluates and returns the expression
 *     <code>y</code>
 * </li>
 * <li><strong><code>()</code> (parentheses)</strong><br/>
 *     Groups expressions together to enfore a particular order of evaluation. For example,
 *     <code>1+2*3</code> evaluates to <code>7</code>, while <code>(1+2)*3</code> evaluates
 *     to <code>9</code>.
 * </li>
 * </ul>
 *
 * <h2>General Functions</h2> 
 * <p>General purpose functions.</p>
 * <ul>
 *   <li><strong><code>ROW()</code></strong><br/>
 *     Returns the table row number (or -1 if none) of the current Tuple.
 *   </li>
 *   <li><strong><code>ISNODE()</code></strong><br/>
 *     Returns true if the current Tuple is a graph Node.
 *   </li>
 *   <li><strong><code>ISEDGE()</code></strong><br/>
 *     Returns true if the current Tuple is a graph Edge.
 *   </li>
 *   <li><strong><code>DEGREE()</code></strong><br/>
 *     If the current Tuple is graph Node, returns the Node degree
 *     (the total number of incident edges). Otherwise returns 0.
 *   </li>
 *   <li><strong><code>INDEGREE()</code></strong><br/>
 *     If the current Tuple is graph Node, returns the Node indegree
 *     (the number of incident edges pointing towards this node).
 *     Otherwise returns 0.
 *   </li>
 *   <li><strong><code>OUTDEGREE()</code></strong><br/>
 *     If the current Tuple is graph Node, returns the Node outdegree
 *     (the number of incident edges pointing away from the node).
 *     Otherwise returns 0.
 *   </li>
 *   <li><strong><code>CHILDCOUNT()</code></strong><br/>
 *     If the current Tuple is graph Node, returns the number of tree
 *     children nodes. If the Tuple is not a Node, this method returns 0.
 *     If the Node is part of a Graph (not a Tree), the number of children
 *     nodes in the current spanning tree is returned. If no spanning tree has
 *     been computed, a new spanning tree will be computed using the default
 *     method. See {@link prefuse.data.Graph#getSpanningTree()} for more.
 *   </li>
 *   <li><strong><code>TREEDEPTH()</code></strong><br/>
 *     If the current Tuple is graph Node, returns the depth of this Node
 *     in its Tree or SpanningTree. If the Tuple is not a Node, this method
 *     returns 0. If the Node is part of a Graph (not a Tree), the tree depth
 *     of the node in the current spanning tree is returned. If no spanning
 *     tree has been computed, a new spanning tree will be computed using the
 *     default method. See {@link prefuse.data.Graph#getSpanningTree()} for
 *     more.
 *   </li>
 * </ul>
 *
 * <h2>Mathematical Functions</h2>
 * <p>Functions for performing mathematical calculations.</p>
 * <ul>
 *   <li><strong><code>ABS(x)</code></strong><br/>
 *     Returns the absolute value of <code>x</code>
 *   </li>
 *   <li><strong><code>ACOS(x)</code></strong><br/>
 *     Returns the inverse cosine (arc cosine) of a <code>x</code>
 *   </li>
 *   <li><strong><code>ASIN(x)</code></strong><br/>
 *     Returns the inverse sine (arc sine) of a <code>x</code>
 *   </li>
 *   <li><strong><code>ATAN(x)</code></strong><br/>
 *     Returns the inverse tangent (arc tangent) of a <code>x</code>
 *   </li>
 *   <li><strong><code>ATAN2(y, x)</code></strong><br/>
 *     For the Cartesian coordinates <code>x</code>, <code>y</code> return the polar coordinate angle theta
 *   </li>
 *   <li><strong><code>CEIL(x), CEILING(x)</code></strong><br/>
 *     Returns the nearest integer value greater than or equal to <code>x</code>.
 *   </li>
 *   <li><strong><code>COS(x)</code></strong><br/>
 *     Returns the cosine of <code>x</code>
 *   </li>
 *   <li><strong><code>COT(x)</code></strong><br/>
 *     Returns the cotangent of <code>x</code>
 *   </li>
 *   <li><strong><code>DEGREES(x)</code></strong><br/>
 *     Converts <code>x</code> from radians to degrees
 *   </li>
 *   <li><strong><code>EXP(x)</code></strong><br/>
 *     Returns the value of <em>e</em> (the base of natural logarithms) raised to the <code>x</code> power
 *   </li>
 *   <li><strong><code>FLOOR(x)</code></strong><br/>
 *     Returns the nearest integer value less than or equal to <code>x</code>.
 *   </li>
 *   <li><strong><code>LOG(x), LOG(b, x)</code></strong><br/>
 *     With one argument, returns the natural logarithm (logarithm base <em>e</em>) of <code>x</code><br/>
 *     With two arguments, returns the logarithm of <code>x</code> for the provided base <code>b</code>
 *   </li>
 *   <li><strong><code>LOG2(x)</code></strong><br/>
 *     Returns the logarithm base 2 of <code>x</code>
 *   </li>
 *   <li><strong><code>LOG10(x)</code></strong><br/>
 *     Returns the logarithm base 10 of <code>x</code>
 *   </li>
 *   <li><strong><code>MAX(a, b, c, ...)</code></strong><br/>
 *     Returns the maximum value among the provided arguments
 *   </li>
 *   <li><strong><code>MIN(a, b, c, ...)</code></strong><br/>
 *     Returns the minimum value among the provided arguments
 *   </li>
 *   <li><strong><code>MOD(x, y)</code></strong><br/>
 *     Returns <code>x</code> modulo <code>y</code> (the remainder of <code>x</code> divided by <code>y</code>)
 *   </li>
 *   <li><strong><code>PI()</code></strong><br/>
 *     Returns the constant &pi; (= 3.1415926535...), the ratio between the circumference and diameter of a circle
 *   </li>
 *   <li><strong><code>POW(x, y), POWER(x, y)</code></strong><br/>
 *     Return the value of <code>x</code> raised to the exponent <code>y</code>
 *   </li>
 *   <li><strong><code>RADIANS(x)</code></strong><br/>
 *     Converts <code>x</code> from degrees to radians
 *   </li>
 *   <li><strong><code>RAND()</code></strong><br/>
 *     Returns a random floating-point value between 0 and 1
 *   </li>
 *   <li><strong><code>ROUND(x)</code></strong><br/>
 *     Returns the value of <code>x</code> rounded to the nearest integer
 *   </li>
 *   <li><strong><code>SIGN(x)</code></strong><br/>
 *     Returns the sign of <code>x</code>: 1 for positive, -1 for negative
 *   </li>
 *   <li><strong><code>SIN(x)</code></strong><br/>
 *     Returns the sine of <code>x</code>
 *   </li>
 *   <li><strong><code>SQRT(x)</code></strong><br/>
 *     Returns the square root of <code>x</code>
 *   </li>
 *   <li><strong><code>SUM(a, b, c, ...)</code></strong><br/>
 *     Returns the sum of the provided input value
 *   </li>
 *   <li><strong><code>TAN(x)</code></strong><br/>
 *     Returns the tangent of <code>x</code>
 *   </li>
 *   <li><strong><code>SAFELOG10(x)</code></strong><br/>
 *     Returns a "negative safe" logarithm base 10 of <code>x</code>, equivalent to
 *     <code>SIGN(x) * LOG10(ABS(x))</code>
 *   </li>
 *   <li><strong><code>POW(x)</code></strong><br/>
 *     Returns a "negative safe" square root of <code>x</code>, equivalent to
 *     <code>SIGN(x) * SQRT(ABS(x))</code>
 *   </li>
 *   </ul>
 *   
 *   <h2>String Functions</h2>
 *   <p>Functions for processing text strings.</p>
 *   <ul>
 *   <li><strong><code>CAP(str)</code></strong><br/>
 *     Capitalize words in the string <code>str</code>. Individual words/names will be given
 *     uppercase first letters, with all other letters in lowercase.
 *   </li>
 *   <li><strong><code>CONCAT(a, b, c, ...)</code></strong><br/>
 *     Concatenate the input strings into one resulting string.
 *   </li>
 *   <li><strong><code>CONCAT_WS(sep, a, b, c, ...)</code></strong><br/>
 *     Concatenate with separator. Concatenates the input strings into one resulting
 *     string, placing the string <code>sep</code> between each of the other arguments
 *   </li>
 *   <li><strong><code>FORMAT(x, d)</code></strong><br/>
 *     Format the number <code>x</code> as a string of the type "#,###.##", showing <code>d</code> decimal places
 *   </li>
 *   <li><strong><code>INSERT(str, pos, len, newstr)</code></strong><br/>
 *     Replaces the substring of length <code>len</code> starting at position <code>pos</code> in input
 *     string <code>str</code> with the string <code>newstr</code>
 *   </li>
 *   <li><strong><code>LEFT(str, len)</code></strong><br/>
 *     Returns the leftmost <code>len</code> characters of string <code>str</code>
 *   </li>
 *   <li><strong><code>LENGTH(str)</code></strong><br/>
 *     Returns the length, in characters, of the input string <code>str</code>
 *   </li>
 *   <li><strong><code>LOWER(str), LCASE(str)</code></strong><br/>
 *     Returns the string <code>str</code> mapped to lowercase letters
 *   </li>
 *   <li><strong><code>LPAD(str, len, pad)</code></strong><br/>
 *     Pad the left side of string <code>str</code> with copies of string <code>pad</code>,
 *     up to a total padding of <code>len</code> characters
 *   </li>
 *   <li><strong><code>MID(str, pos, len)</code></strong><br/>
 *     Return a substring of <code>str</code> of length <code>len</code>, starting at
 *     position <code>pos</code>
 *   </li>
 *   <li><strong><code>POSITION(substr, str)</code></strong><br/>
 *     Returns the starting position of the first occurrence of substring <code>substr</code>
 *     in the string <code>str</code>. Returns -1 if the substring is not found.
 *   </li>
 *   <li><strong><code>REVERSE(str)</code></strong><br/>
 *     Returns a reversed copy of the input string <code>str</code>
 *   </li>
 *   <li><strong><code>REPEAT(str, count)</code></strong><br/>
 *     Returns a string consisting of <code>str</code> repeated <code>count</code> times
 *   </li>
 *   <li><strong><code>REPLACE(str, orig, replace)</code></strong><br/>
 *     Returns a copy of <code>str</code> in which all occurrences of <code>orig</code> have been
 *     replaced by <code>replace</code>
 *   </li>
 *   <li><strong><code>RIGHT(str, len)</code></strong><br/>
 *     Returns the <code>len</code> rightmost characters of string<code>str</code>
 *   </li>
 *   <li><strong><code>RPAD(x)</code></strong><br/>
 *     Pad the right side of string <code>str</code> with copies of string <code>pad</code>,
 *     up to a total padding of <code>len</code> characters
 *   </li>
 *   <li><strong><code>SPACE(n)</code></strong><br/>
 *     Returns a string consisting of <code>n</code> whitespace characters
 *   </li>
 *   <li><strong><code>SUBSTRING(str,pos), SUBSTRING(str,pos,len)</code></strong><br/>
 *     For two arguments, returns the substring of <code>str</code> starting at position
 *     <code>pos</code> and continuing to the end of the string.<br/>
 *     For three arguments, returns the substring of <code>str</code> of length <code>len</code>,
 *     beginning at position <code>pos</code>
 *   </li>
 *   <li><strong><code>UPPER(str), UCASE(str</code></strong><br/>
 *     Returns the string <code>str</code> mapped to uppercase letters
 *   </li>
 *   </ul>
 *
 *    <h2>Color Functions</h2>
 *    <p>Functions for generating, translating, and interpolating color values.</p>
 *   <ul>
 *   <li><strong><code>RGB(r, g, b)</code></strong><br/>
 *     Returns an integer representing a fully opaque RGB (red, green, blue) color value
 *   </li>
 *   <li><strong><code>RGBA(r, g, b, a)</code></strong><br/>
 *     Returns an integer representing an RGBA (red, green, blue, alpha/transparency) color value
 *   </li>
 *   <li><strong><code>GRAY(v)</code></strong><br/>
 *     Returns an integer representing a grayscale color value of intensity <code>v</code>
 *   </li>
 *   <li><strong><code>HEX(hex)</code></strong><br/>
 *     Returns an integer representing the RGB color value encoded by the hexadecimal number
 *     <code>hex</code>
 *   </li>
 *   <li><strong><code>HSB(h, s, b)</code></strong><br/>
 *     Maps the given hue (<code>hue</code>), saturation (<code>s</code>), and brightness
 *     (<code>b</code>) color space values (as floating point numbers between 0 and 1) to
 *     an integer representing an RGB color value
 *   </li>
 *   <li><strong><code>HSBA(h, s, b, a)</code></strong><br/>
 *     Maps the given hue (<code>hue</code>), saturation (<code>s</code>), brightness
 *     (<code>b</code>), and alpha (<code>a</code>) color space values (as floating point
 *     numbers between 0 and 1) to an integer representing an RGBA color value
 *   </li>
 *   <li><strong><code>COLORINTERP(c1, c2, f)</code></strong><br/>
 *     Returns an interpolated color value between the input colors <code>c1</code> and
 *     <code>c2</code> determined by the mixing proportion <code>f</code>, a value
 *     between 0 and 1
 *   </li>
 *   </ul>
 *   
 *   <h2>Visualization Functions</h2>
 *   <p>These functions can only be used when the Tuple being evaluated is
 *    a VisualItem, and provide access to data group information of the VisualItem's
 *    Visualization. Individual visual data fields can be accessed directly using
 *    a data field reference. For example, <code>_x</code>, <code>_y</code>,
 *    <code>_hover</code>, <code>_highlight</code>, <code>_fillColor</code> would
 *    evaluate to references for the x-coordinate, y-coordinate, mouse hover status,
 *    highlight status, and fill color, respectively.</p>
 *   <ul>
 *   <li><strong><code>GROUPSIZE(group)</code></strong><br/>
 *     Returns the number of members in the data group <code>group</code>
 *   </li>
 *   <li><strong><code>INGROUP(group)</code></strong><br/>
 *     Returns true if the current VisualItem is a member of data group <code>group</code>
 *   </li>
 *   <li><strong><code>MATCH(group, includeAll)</code></strong><br/>
 *     Returns true if the current VisualItem is currently a search match. This is similar
 *     to <code>INGROUP(group)</code>, but also includes a possible special case when no
 *     query has been issued and all items should be counted as "matches" (indicated
 *     by <code>includeAll</code> being true).
 *   </li>
 *   <li><strong><code>QUERY(group)</code></strong><br/>
 *     Returns the current search query string in a search group of name <code>group</code>
 *   </li>
 *   <li><strong><code>VISIBLE()</code></strong><br/>
 *     Returns true if the current VisualItem is visible, equivalent to <code>_visible</code>
 *   </li>
 *   <li><strong><code>VALIDATED()</code></strong><br/>
 *     Returns true if the current VisualItem's bounds have been validated,
 *     equivalent to <code>_validated</code>
 *   </li>
 *   </ul>
 * 
 * @author <a href="http://jheer.org">jeffrey heer</a>
 */
public class ExpressionParser {

        private static final Logger s_logger
            = Logger.getLogger(ExpressionParser.class.getName());

    private static boolean s_init = false;
    private static Throwable s_error;

    /**
     * Parse an expression.
     * @param expr the expression text to parse
     * @param throwsException true if this method should throw an
     * exception if an error occurs or should fail quietly
     * @return the parsed Expression, or null if the parse failed
     * and throwsException is false
     */
    public synchronized static Expression parse(String expr,
                                                boolean throwsException)
    {
        // initialize the parser
        if ( !s_init ) {
            new ExpressionParser(new StringReader(expr));
            s_init = true;
        } else {
            ExpressionParser.ReInit(new StringReader(expr));
        }
        // attempt to parse the expression
        try {
            Expression e = Parse();
            s_error = null;
            s_logger.info("Parsed Expression: "+e);
            return e;
        } catch ( ParseException t ) {
            s_error = t;
            if ( throwsException ) {
                throw t;
            } else {
                s_logger.warning("Expression Parse Error: " + t.getMessage()
                        + "\n" + StringLib.getStackTrace(t));
                return null;
            }
        }
    }

    /**
     * Parse an expression. This method does not throw an exception if
     * a parse error occurs. Use {@link #getError()} to access any
     * generated exceptions.
     * @param expr the expression text to parse
     * @return the parsed Expression, or null if the parse failed
     */
    public synchronized static Expression parse(String expr) {
        return parse(expr, false);
    }

    /**
     * Parse an expression as a predicate. This method does not throw an
     * exception if a parse error occurs. Use {@link #getError()} to access
     * any generated exceptions.
     * @param expr the expression text to parse
     * @return the parsed Expression, or null if the parse failed
     */
    public synchronized static Predicate predicate(String expr) {
        Expression ex = parse(expr, false);
        if ( ex == null ) {
            return null;
        } else if ( ex instanceof Predicate ) {
            return (Predicate) ex;
        } else {
            s_error = new ClassCastException("Expression is not a predicate");
            return null;
        }
    }

    /**
     * Get the last error, if any, generated by a parse operation.
     * @return the last error generated during parsing
     */
    public synchronized static Throwable getError() {
        return s_error;
    }

    /**
     * Replace escape sequences with represented characters. This
     * includes newlines, tabs, and quotes.
     * @param s the input String, possibly with escape sequences
     * @return a String with recognized escape sequences properly replaced
     */
    private static String unescape(String s) {
        int len = s.length(), base = 0, idx;
        String escapes = "tnrbf\\\"'";
        String chars = "\t\n\r\b\f\\\"'";
        
        StringBuffer sbuf = null;
        
        while ( (idx=s.indexOf('\\',base)) != -1) {
            if ( sbuf != null )
                sbuf.append(s.substring(base, idx));
            
            if (idx+1 == len) break;
            
            // find escape character
            char c = s.charAt(idx+1);
            
            // find the index of the escape character
            int cidx = escapes.indexOf(c);
            if (cidx == -1) {
                // no match, so continue
                sbuf.append('\\');
                sbuf.append(c);
            } else {
                // replace escape sequence with true char
                if ( sbuf == null )
                    sbuf = new StringBuffer(s.substring(base, idx));
                sbuf.append(chars.charAt(cidx));   
            }

            // skip over escape sequence
            base = idx + 2;
        }
        if ( sbuf != null && base < len )
            sbuf.append(s.substring(base));
            
        return ( sbuf == null ? s : sbuf.toString() );
    }
    
} // end of class ExpressionParser

PARSER_END(ExpressionParser)

// ----------------------------------------------------------------------------
// Token definitions

/* characters to skip */
SKIP : { " " | "\t" | "\n" | "\r" | "\f" }

/* keywords */
TOKEN : {
    < TRUE : "TRUE"|"true" >
|   < FALSE : "FALSE"|"false" >
|   < NULL : "NULL"|"null" >
|   < IF : "IF"|"if" >
|   < THEN : "THEN"|"then" >
|   < ELSE : "ELSE"|"else" >
|   < AND : "AND"|"and"|"&&" >
|   < OR : "OR"|"or"|"||" >
|   < NOT : "NOT"|"not"|"!" >
|   < XOR : "XOR"|"xor" >
}

/* literal values */
TOKEN : {
	< INT : <DECIMAL_LITERAL> | <HEX_LITERAL> | <OCTAL_LITERAL> >
|   < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
|   < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
|   < #OCTAL_LITERAL: "0" (["0"-"7"])* >
|   < LONG : <INT>["l","L"] >
|   < DOUBLE : 
	   (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)?
	    | "." (["0"-"9"])* (<EXPONENT>)?
	    | (["0"-"9"])+ <EXPONENT>
    >
|   < FLOAT : <DOUBLE>["f","F"] >
|   < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
|   < STRING:
      "\""
      (   (~["\"","\\","\n","\r"])
        | ("\\"
            ( ["n","t","b","r","f","\\","'","\""]
            | ["0"-"7"] ( ["0"-"7"] )?
            | ["0"-"3"] ["0"-"7"] ["0"-"7"]
            )
          )
      )*
      "\""
      |
      "'"
      (   (~["'","\\","\n","\r"])
        | ("\\"
            ( ["n","t","b","r","f","\\","'","\""]
            | ["0"-"7"] ( ["0"-"7"] )?
            | ["0"-"3"] ["0"-"7"] ["0"-"7"]
            )
          )
      )*
      "'"
    >
}

/* identifiers */
TOKEN : {
    < QUOTED: "[" (~["]"])+ "]" >
|   < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* >
|   < #LETTER:
      [
       "\u0024",
       "\u0041"-"\u005a",
       "\u005f",
       "\u0061"-"\u007a",
       "\u00c0"-"\u00d6",
       "\u00d8"-"\u00f6",
       "\u00f8"-"\u00ff",
       "\u0100"-"\u1fff",
       "\u3040"-"\u318f",
       "\u3300"-"\u337f",
       "\u3400"-"\u3d2d",
       "\u4e00"-"\u9fff",
       "\uf900"-"\ufaff"
      ]
    >
|   < #DIGIT:
      [
       "\u0030"-"\u0039",
       "\u0660"-"\u0669",
       "\u06f0"-"\u06f9",
       "\u0966"-"\u096f",
       "\u09e6"-"\u09ef",
       "\u0a66"-"\u0a6f",
       "\u0ae6"-"\u0aef",
       "\u0b66"-"\u0b6f",
       "\u0be7"-"\u0bef",
       "\u0c66"-"\u0c6f",
       "\u0ce6"-"\u0cef",
       "\u0d66"-"\u0d6f",
       "\u0e50"-"\u0e59",
       "\u0ed0"-"\u0ed9",
       "\u1040"-"\u1049"
      ]
    >
}

/* separators */
TOKEN : {
    < LPAREN: "(" >
|   < RPAREN: ")" >
}

/* operators */
TOKEN : {
  < EQ: "=" | "==" >
| < GT: ">" >
| < LT: "<" >
| < LE: "<=" >
| < GE: ">=" >
| < NE: "!=" | "<>" >
| < ADD: "+" >
| < SUB: "-" >
| < MUL: "*" >
| < DIV: "/" >
| < POW: "^" >
| < MOD: "%" >
}

  // ----------------------------------------------------------------------------
  // Grammar definitions

String Name() :
{ Token t; }
{
  t=<IDENTIFIER> { return t.image; }
}

String Quoted() :
{ Token t; }
{
  t=<QUOTED> { return t.image.substring(1,t.image.length()-1); }
}

Expression Parse() :
{ Expression e; }
{
  e=Expression() <EOF> { return e; }
| <EOF> { throw new ParseException("No expression provided"); }
}

Expression Expression() :
{ Expression e; }
{
  e=OrExpression() { return e; }
}

Expression OrExpression() :
{ Expression l, r; }
{
  l=XorExpression() ( <OR> r=XorExpression()
  {
      if ( l instanceof OrPredicate ) {
          ((OrPredicate)l).add((Predicate)r);
      } else {
          l = new OrPredicate((Predicate)l,(Predicate)r);
      }
  }
  )* { return l; }
}

Expression XorExpression() :
{ Expression l, r; }
{
  l=AndExpression() ( <XOR> r=AndExpression()
  {
      if ( l instanceof XorPredicate ) {
          ((XorPredicate)l).add((Predicate)r);
      } else {
          l = new XorPredicate((Predicate)l,(Predicate)r);
      }
  }
  )* { return l; }
}

Expression AndExpression() :
{ Expression l, r; }
{
  l=EqualityExpression() ( <AND> r=EqualityExpression()
  {
      if ( l instanceof AndPredicate ) {
          ((AndPredicate)l).add((Predicate)r);
      } else {
          l = new AndPredicate((Predicate)l,(Predicate)r);
      }
  }
  )* { return l; }
}

Expression EqualityExpression() :
{ Expression l, r; Token t; int op; }
{
  l=RelationalExpression() (
      ( t=<EQ> | t=<NE> ) r=RelationalExpression()
  {
      op = (t.kind==EQ ? ComparisonPredicate.EQ : ComparisonPredicate.NEQ);
      l = new ComparisonPredicate(op, l, r);
  }
      )* { return l; }
}

Expression RelationalExpression() :
{ Expression l, r; Token t; int op=-1; }
{
  l=AdditiveExpression() ( 
      ( t=<LT> | t=<GT> | t=<LE> | t=<GE> ) r=AdditiveExpression()
  {
      switch ( t.kind ) {
      case LT:
          op = ComparisonPredicate.LT;
          break;
      case GT:
          op = ComparisonPredicate.GT;
          break;
      case LE:
          op = ComparisonPredicate.LTEQ;
          break;
      case GE:
          op = ComparisonPredicate.GTEQ;
          break;
      }
      l = new ComparisonPredicate(op, l, r);
  }
      )* { return l; }
}

Expression AdditiveExpression() :
{ Expression l, r; Token t; int op=-1; }
{
  l=MultiplicativeExpression() (
      ( t=<ADD> | t=<SUB> | t=<MOD> ) r=MultiplicativeExpression()
  {
      switch ( t.kind ) {
      case ADD:
        op = ArithmeticExpression.ADD;
        break;
      case SUB:
        op = ArithmeticExpression.SUB;
        break;
      case MOD:
        op = ArithmeticExpression.MOD;
        break;
      }
      l = new ArithmeticExpression(op, l, r);
  }
      )* { return l; }
}

Expression MultiplicativeExpression() :
{ Expression l, r; Token t; int op=-1; }
{
  l=UnaryExpression() ( 
     ( t=<MUL> | t=<DIV> | t=<POW> ) r=UnaryExpression()
  {
      switch ( t.kind ) {
      case MUL:
        op = ArithmeticExpression.MUL;
        break;
      case DIV:
        op = ArithmeticExpression.DIV;
        break;
      case POW:
        op = ArithmeticExpression.POW;
        break;
      }
      l = new ArithmeticExpression(op, l, r);
  }
      )* { return l; }
}

Expression UnaryExpression() :
{ Expression e; Token t;}
{
    ( t=<ADD> | t=<SUB> ) e=UnaryExpression() {
    	if ( t.kind == SUB  && e instanceof NumericLiteral ) {
    	  Number n = (Number)e.get(null);
    	  if ( n instanceof Integer ) {
    	      return new NumericLiteral(-1*n.intValue());
    	  } if ( n instanceof Double ) {
    	      return new NumericLiteral(-1*n.doubleValue());
    	  } if ( n instanceof Long ) {
    	      return new NumericLiteral(-1*n.longValue());
    	  } if ( n instanceof Float ) {
    	      return new NumericLiteral(-1*n.floatValue());
    	  } else {
    	      return new ArithmeticExpression(ArithmeticExpression.MUL,
    	                                      new NumericLiteral(-1), e);
    	  }
    	} else if ( t.kind == SUB ) {
    	  return new ArithmeticExpression(ArithmeticExpression.MUL,
    	                                  new NumericLiteral(-1), e);
    	} else {
    	  return e;
    	}
    } 
|   e=UnaryExpressionNotPlusMinus() { return e; }
|   e=PrimaryExpression() { return e; }
}

Expression UnaryExpressionNotPlusMinus() :
{ Expression e; }
{
    <NOT> e=UnaryExpression() {
        if ( e instanceof NotPredicate ) {
            return ((NotPredicate)e).getPredicate();
        } else {
            if ( !(e instanceof Predicate) ) {
                throw new ParseException("Can't negate a non-predicate");
            } else {
                return new NotPredicate((Predicate)e);
            }
        }
    }
}

Expression PrimaryExpression() :
{ Expression e; }
{
    e=Literal() { return e; }
|   e=IfStatement() { return e; }
|   e=Identifier() { return e; }
|   <LPAREN> e=Expression() <RPAREN> { return e; }
}

Expression Literal() :
{ Token t; }
{
    t=<INT> { return new NumericLiteral(Integer.parseInt(t.image)); }
|   t=<LONG> { return new NumericLiteral(Long.parseLong(t.image.substring(0,t.image.length()-1))); }
|   t=<FLOAT> { return new NumericLiteral(Float.parseFloat(t.image)); }
|   t=<DOUBLE> { return new NumericLiteral(Double.parseDouble(t.image)); }
|   t=<STRING> {
		String s = unescape(t.image.substring(1, t.image.length()-1));
		return new ObjectLiteral(s); }
|   <TRUE> { return new BooleanLiteral(true); }
|   <FALSE> { return new BooleanLiteral(false); }
|   <NULL> { return new ObjectLiteral(null); }
}

Expression Identifier() :
{ String s; Function f=null; Expression e; }
{
    s=Quoted() { return new ColumnExpression(s); }
|   s=Name()
    ( <LPAREN> { f = FunctionTable.createFunction(s); }
      ( e=Expression() { f.addParameter(e); } 
        ("," e=Expression() { f.addParameter(e); } )* )?
      <RPAREN> )?
    { return f==null ? new ColumnExpression(s) : (Expression)f; }
}

Expression IfStatement() :
/*
 * The disambiguating algorithm of JavaCC automatically binds dangling
 * else's to the innermost if statement.  The LOOKAHEAD specification
 * is to tell JavaCC that we know what we are doing.
 */
{ Expression p, t, e; }
{
  <IF> p=Expression() <THEN> t=Expression() <ELSE> e=Expression()
  {
      if ( !(p instanceof Predicate) )
          throw new ParseException("IF-statement test must be a predicate");
      return new IfExpression((Predicate)p, t, e);
  }
}


