public class ArithmeticMultiplyExpression extends ArithmeticBinaryOperatorExpression {
    public ArithmeticMultiplyExpression(Expression leftOprand, Expression rightOprand) {
        super(leftOprand, rightOprand, PRECEDENCE_ARITHMETIC_FACTOR_OP);
    }

    @Override
    public String getOperator() {
        return "*";
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    @Override
    public Number calculate(Integer integer1, Integer integer2) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Number calculate(Long long1, Long long2) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Number calculate(BigInteger bigint1, BigInteger bigint2) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Number calculate(BigDecimal bigDecimal1, BigDecimal bigDecimal2) {
        throw new UnsupportedOperationException();
    }

} public class ComparisionLessOrGreaterThanExpression extends BinaryOperatorExpression {
    public ComparisionLessOrGreaterThanExpression(Expression leftOprand, Expression rightOprand) {
        super(leftOprand, rightOprand, PRECEDENCE_COMPARISION);
    }

    @Override
    public String getOperator() {
        return "<>";
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
} public class ComparisionNullSafeEqualsExpression extends BinaryOperatorExpression
        implements ReplacableExpression {
    public ComparisionNullSafeEqualsExpression(Expression leftOprand, Expression rightOprand) {
        super(leftOprand, rightOprand, PRECEDENCE_COMPARISION);
    }

    @Override
    public String getOperator() {
        return "<=>";
    }

    @Override
    public Object evaluationInternal(Map<? extends Object, ? extends Object> parameters) {
        Object left = leftOprand.evaluation(parameters);
        Object right = rightOprand.evaluation(parameters);
        if (left == UNEVALUATABLE || right == UNEVALUATABLE)
            return UNEVALUATABLE;
        if (left == null)
            return right == null ? LiteralBoolean.TRUE : LiteralBoolean.FALSE;
        if (right == null)
            return LiteralBoolean.FALSE;
        if (left instanceof Number || right instanceof Number) {
            Pair<Number, Number> pair = ExprEvalUtils.convertNum2SameLevel(left, right);
            left = pair.getKey();
            right = pair.getValue();
        }
        return left.equals(right) ? LiteralBoolean.TRUE : LiteralBoolean.FALSE;
    }

    private Expression replaceExpr;

    @Override
    public void setReplaceExpr(Expression replaceExpr) {
        this.replaceExpr = replaceExpr;
    }

    @Override
    public void clearReplaceExpr() {
        this.replaceExpr = null;
    }

    @Override
    public void accept(Visitor visitor) {
        if (replaceExpr == null)
            visitor.visit(this);
        else
            replaceExpr.accept(visitor);
    }
} public class AssignmentExpression extends BinaryOperatorExpression {
    public AssignmentExpression(Expression left, Expression right) {
        super(left, right, Expression.PRECEDENCE_ASSIGNMENT, false);
    }

    public String getOperator() {
        return ":=";
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

} public class UserExpression extends PrimaryExpression {
    private final String userAtHost;

    /**
     * @param userAtHost
     */
    public UserExpression(String userAtHost) {
        super();
        this.userAtHost = userAtHost;
    }

    public String getUserAtHost() {
        return userAtHost;
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
} public abstract class FunctionExpression extends PrimaryExpression {
    protected static List<Expression> wrapList(Expression expr) {
        List<Expression> list = new ArrayList<Expression>(1);
        list.add(expr);
        return list;
    }

    /**
     * <code>this</code> function object being called is a prototype
     */
    public abstract FunctionExpression constructFunction(List<Expression> arguments);

    protected final String           functionName;
    protected final List<Expression> arguments;

    public FunctionExpression(String functionName, List<Expression> arguments) {
        super();
        this.functionName = functionName;
        if (arguments == null || arguments.isEmpty()) {
            this.arguments = Collections.emptyList();
        } else {
            if (arguments instanceof ArrayList) {
                this.arguments = arguments;
            } else {
                this.arguments = new ArrayList<Expression>(arguments);
            }
        }
    }

    public void init() {}

    /**
     * @return never null
     */
    public List<Expression> getArguments() {
        return arguments;
    }

    public String getFunctionName() {
        return functionName;
    }

    @Override
    public Expression setCacheEvalRst(boolean cacheEvalRst) {
        return super.setCacheEvalRst(cacheEvalRst);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
} public class GroupConcat extends FunctionExpression {
    private final boolean          distinct;
    private final Expression       orderBy;
    private final boolean          isDesc;
    private final List<Expression> appendedColumnNames;
    private final String           separator;

    public GroupConcat(boolean distinct, List<Expression> exprList, Expression orderBy,
            boolean isDesc, List<Expression> appendedColumnNames, String separator) {
        super("GROUP_CONCAT", exprList);
        this.distinct = distinct;
        this.orderBy = orderBy;
        this.isDesc = isDesc;
        if (appendedColumnNames == null || appendedColumnNames.isEmpty()) {
            this.appendedColumnNames = Collections.emptyList();
        } else if (appendedColumnNames instanceof ArrayList) {
            this.appendedColumnNames = appendedColumnNames;
        } else {
            this.appendedColumnNames = new ArrayList<Expression>(appendedColumnNames);
        }
        this.separator = separator == null ? "," : separator;
    }

    public boolean isDistinct() {
        return distinct;
    }

    public Expression getOrderBy() {
        return orderBy;
    }

    public boolean isDesc() {
        return isDesc;
    }

    public List<Expression> getAppendedColumnNames() {
        return appendedColumnNames;
    }

    public String getSeparator() {
        return separator;
    }

    @Override
    public FunctionExpression constructFunction(List<Expression> arguments) {
        throw new UnsupportedOperationException("function of char has special arguments");
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
} public class Centroid extends FunctionExpression {

    public Centroid(Expression expr) {
        super("CENTROID", wrapList(expr));
    }

    @Override
    public FunctionExpression constructFunction(List<Expression> arguments) {
        throw new UnsupportedOperationException("function of char has special arguments");
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
} public class Point extends FunctionExpression {

    public Point(List<Expression> arguments) {
        super("POINT", arguments);
    }

    @Override
    public FunctionExpression constructFunction(List<Expression> arguments) {
        return new Point(arguments);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
} public class ST_Distance extends FunctionExpression {

    public ST_Distance(List<Expression> arguments) {
        super("ST_DISTANCE", arguments);
    }

    @Override
    public FunctionExpression constructFunction(List<Expression> arguments) {
        return new ST_Distance(arguments);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

} public class Char extends FunctionExpression {
    private final String charset;

    public Char(List<Expression> arguments, String charset) {
        super("CHAR", arguments);
        this.charset = charset;
    }

    @Override
    public FunctionExpression constructFunction(List<Expression> arguments) {
        throw new UnsupportedOperationException("function of char has special arguments");
    }

    public String getCharset() {
        return charset;
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
} public class LiteralString extends Literal {
    private final String  introducer;
    private final String  string;
    private final boolean nchars;

    /**
     * @param string content of string, excluded of head and tail "'". e.g. for string token of
     *        "'don\\'t'", argument of string is "don\\'t"
     */
    public LiteralString(String introducer, String string, boolean nchars) {
        super();
        this.introducer = introducer;
        if (string == null)
            throw new IllegalArgumentException("argument string is null!");
        this.string = string;
        this.nchars = nchars;
    }

    public String getIntroducer() {
        return introducer;
    }

    public String getString() {
        return string;
    }

    public boolean isNchars() {
        return nchars;
    }

    public String getUnescapedString() {
        return getUnescapedString(string, false);
    }

    public String getUnescapedString(boolean toUppercase) {
        return getUnescapedString(string, toUppercase);
    }

    public static String getUnescapedString(String string) {
        return getUnescapedString(string, false);
    }

    public static String getUnescapedString(String string, boolean toUppercase) {
        StringBuilder sb = new StringBuilder();
        char[] chars = string.toCharArray();
        for (int i = 0; i < chars.length; ++i) {
            char c = chars[i];
            if (c == '\\') {
                switch (c = chars[++i]) {
                    case '0':
                        sb.append('\0');
                        break;
                    case 'b':
                        sb.append('\b');
                        break;
                    case 'n':
                        sb.append('\n');
                        break;
                    case 'r':
                        sb.append('\r');
                        break;
                    case 't':
                        sb.append('\t');
                        break;
                    case 'Z':
                        sb.append((char) 26);
                        break;
                    default:
                        sb.append(c);
                }
            } else if (c == '\'') {
                ++i;
                sb.append('\'');
            } else {
                if (toUppercase && c >= 'a' && c <= 'z')
                    c -= 32;
                sb.append(c);
            }
        }
        return sb.toString();
    }

    @Override
    public Object evaluationInternal(Map<? extends Object, ? extends Object> parameters) {
        if (string == null)
            return null;
        return getUnescapedString();
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
} public class RegexpExpression extends BinaryOperatorExpression {
    private final boolean not;

    public RegexpExpression(boolean not, Expression comparee, Expression pattern) {
        super(comparee, pattern, PRECEDENCE_COMPARISION);
        this.not = not;
    }

    public boolean isNot() {
        return not;
    }

    @Override
    public String getOperator() {
        return not ? "NOT REGEXP" : "REGEXP";
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

}
import static fm.liu.timo.parser.recognizer.mysql.MySQLToken.*;
import java.sql.SQLSyntaxErrorException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import fm.liu.timo.parser.ast.expression.Expression;
import fm.liu.timo.parser.ast.expression.arithmeic.ArithmeticAddExpression;
import fm.liu.timo.parser.ast.expression.arithmeic.ArithmeticDivideExpression;
import fm.liu.timo.parser.ast.expression.arithmeic.ArithmeticIntegerDivideExpression;
import fm.liu.timo.parser.ast.expression.arithmeic.ArithmeticModExpression;
import fm.liu.timo.parser.ast.expression.arithmeic.ArithmeticMultiplyExpression;
import fm.liu.timo.parser.ast.expression.arithmeic.ArithmeticSubtractExpression;
import fm.liu.timo.parser.ast.expression.arithmeic.MinusExpression;
import fm.liu.timo.parser.ast.expression.bit.BitAndExpression;
import fm.liu.timo.parser.ast.expression.bit.BitInvertExpression;
import fm.liu.timo.parser.ast.expression.bit.BitOrExpression;
import fm.liu.timo.parser.ast.expression.bit.BitShiftExpression;
import fm.liu.timo.parser.ast.expression.bit.BitXORExpression;
import fm.liu.timo.parser.ast.expression.comparison.BetweenAndExpression;
import fm.liu.timo.parser.ast.expression.comparison.ComparisionEqualsExpression;
import fm.liu.timo.parser.ast.expression.comparison.ComparisionGreaterThanExpression;
import fm.liu.timo.parser.ast.expression.comparison.ComparisionGreaterThanOrEqualsExpression;
import fm.liu.timo.parser.ast.expression.comparison.ComparisionIsExpression;
import fm.liu.timo.parser.ast.expression.comparison.ComparisionLessOrGreaterThanExpression;
import fm.liu.timo.parser.ast.expression.comparison.ComparisionLessThanExpression;
import fm.liu.timo.parser.ast.expression.comparison.ComparisionLessThanOrEqualsExpression;
import fm.liu.timo.parser.ast.expression.comparison.ComparisionNotEqualsExpression;
import fm.liu.timo.parser.ast.expression.comparison.ComparisionNullSafeEqualsExpression;
import fm.liu.timo.parser.ast.expression.comparison.InExpression;
import fm.liu.timo.parser.ast.expression.logical.LogicalAndExpression;
import fm.liu.timo.parser.ast.expression.logical.LogicalNotExpression;
import fm.liu.timo.parser.ast.expression.logical.LogicalOrExpression;
import fm.liu.timo.parser.ast.expression.logical.LogicalXORExpression;
import fm.liu.timo.parser.ast.expression.logical.NegativeValueExpression;
import fm.liu.timo.parser.ast.expression.misc.AssignmentExpression;
import fm.liu.timo.parser.ast.expression.misc.InExpressionList;
import fm.liu.timo.parser.ast.expression.misc.QueryExpression;
import fm.liu.timo.parser.ast.expression.misc.SubqueryAllExpression;
import fm.liu.timo.parser.ast.expression.misc.SubqueryAnyExpression;
import fm.liu.timo.parser.ast.expression.misc.UserExpression;
import fm.liu.timo.parser.ast.expression.primary.CaseWhenOperatorExpression;
import fm.liu.timo.parser.ast.expression.primary.DefaultValue;
import fm.liu.timo.parser.ast.expression.primary.ExistsPrimary;
import fm.liu.timo.parser.ast.expression.primary.Identifier;
import fm.liu.timo.parser.ast.expression.primary.MatchExpression;
import fm.liu.timo.parser.ast.expression.primary.RowExpression;
import fm.liu.timo.parser.ast.expression.primary.UsrDefVarPrimary;
import fm.liu.timo.parser.ast.expression.primary.Wildcard;
import fm.liu.timo.parser.ast.expression.primary.MatchExpression.Modifier;
import fm.liu.timo.parser.ast.expression.primary.function.DefaultFunction;
import fm.liu.timo.parser.ast.expression.primary.function.FunctionExpression;
import fm.liu.timo.parser.ast.expression.primary.function.cast.Cast;
import fm.liu.timo.parser.ast.expression.primary.function.cast.Convert;
import fm.liu.timo.parser.ast.expression.primary.function.comparison.Interval;
import fm.liu.timo.parser.ast.expression.primary.function.datetime.CurTimestamp;
import fm.liu.timo.parser.ast.expression.primary.function.datetime.Curdate;
import fm.liu.timo.parser.ast.expression.primary.function.datetime.Curtime;
import fm.liu.timo.parser.ast.expression.primary.function.datetime.Extract;
import fm.liu.timo.parser.ast.expression.primary.function.datetime.GetFormat;
import fm.liu.timo.parser.ast.expression.primary.function.datetime.Now;
import fm.liu.timo.parser.ast.expression.primary.function.datetime.Timestampadd;
import fm.liu.timo.parser.ast.expression.primary.function.datetime.Timestampdiff;
import fm.liu.timo.parser.ast.expression.primary.function.datetime.UtcDate;
import fm.liu.timo.parser.ast.expression.primary.function.datetime.UtcTime;
import fm.liu.timo.parser.ast.expression.primary.function.datetime.UtcTimestamp;
import fm.liu.timo.parser.ast.expression.primary.function.groupby.Avg;
import fm.liu.timo.parser.ast.expression.primary.function.groupby.Count;
import fm.liu.timo.parser.ast.expression.primary.function.groupby.GroupConcat;
import fm.liu.timo.parser.ast.expression.primary.function.groupby.Max;
import fm.liu.timo.parser.ast.expression.primary.function.groupby.Min;
import fm.liu.timo.parser.ast.expression.primary.function.groupby.Sum;
import fm.liu.timo.parser.ast.expression.primary.function.info.CurrentUser;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.Area;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.AsText;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.AsWKT;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.Centroid;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.Contains;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.Equals;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.ExteriorRing;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.GeomFromText;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.GeometryFromText;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.IsClosed;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.IsEmpty;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.MBRContains;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.MBREqual;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.MBRWithin;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.Point;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.SRID;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.ST_Area;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.ST_Centroid;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.ST_Contains;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.ST_Distance;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.ST_Equals;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.ST_Within;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.Within;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.X;
import fm.liu.timo.parser.ast.expression.primary.function.spatial.Y;
import fm.liu.timo.parser.ast.expression.primary.function.string.Char;
import fm.liu.timo.parser.ast.expression.primary.function.string.Locate;
import fm.liu.timo.parser.ast.expression.primary.function.string.Substring;
import fm.liu.timo.parser.ast.expression.primary.function.string.Trim;
import fm.liu.timo.parser.ast.expression.primary.function.string.Trim.Direction;
import fm.liu.timo.parser.ast.expression.primary.literal.IntervalPrimary;
import fm.liu.timo.parser.ast.expression.primary.literal.LiteralBitField;
import fm.liu.timo.parser.ast.expression.primary.literal.LiteralBoolean;
import fm.liu.timo.parser.ast.expression.primary.literal.LiteralHexadecimal;
import fm.liu.timo.parser.ast.expression.primary.literal.LiteralNull;
import fm.liu.timo.parser.ast.expression.primary.literal.LiteralNumber;
import fm.liu.timo.parser.ast.expression.primary.literal.LiteralString;
import fm.liu.timo.parser.ast.expression.string.LikeExpression;
import fm.liu.timo.parser.ast.expression.string.RegexpExpression;
import fm.liu.timo.parser.ast.expression.string.SoundsLikeExpression;
import fm.liu.timo.parser.ast.expression.type.CastBinaryExpression;
import fm.liu.timo.parser.ast.expression.type.CollateExpression;
import fm.liu.timo.parser.recognizer.mysql.MySQLFunctionManager;
import fm.liu.timo.parser.recognizer.mysql.MySQLToken;
import fm.liu.timo.parser.recognizer.mysql.lexer.MySQLLexer;
import fm.liu.timo.parser.util.Pair;
                return tempExpr;
            case LITERAL_BIT:
                if (consumed.charAt(0) != '_') {
                    return new Identifier(null, consumed, consumedUp).setCacheEvalRst(cacheEvalRst);
                }
                tempStr = lexer.stringValue();
                lexer.nextToken();
                return new LiteralBitField(consumed, tempStr).setCacheEvalRst(cacheEvalRst);
            case LITERAL_HEX:
                if (consumed.charAt(0) != '_') {
                    return new Identifier(null, consumed, consumedUp).setCacheEvalRst(cacheEvalRst);
                }
                LiteralHexadecimal hex = new LiteralHexadecimal(consumed, lexer.getSQL(),
                        lexer.getOffsetCache(), lexer.getSizeCache(), charset);
                lexer.nextToken();
                return hex.setCacheEvalRst(cacheEvalRst);
            case LITERAL_CHARS:
                if (consumed.charAt(0) != '_') {
                    return new Identifier(null, consumed, consumedUp).setCacheEvalRst(cacheEvalRst);
                }
                tempSb = new StringBuilder();
                do {
                    lexer.appendStringContent(tempSb);
                } while (lexer.nextToken() == LITERAL_CHARS);
                return new LiteralString(consumed, tempSb.toString(), false)
                        .setCacheEvalRst(cacheEvalRst);
            case PUNC_LEFT_PAREN:
                consumedUp = Identifier.unescapeName(consumedUp);
                switch (functionManager.getParsingStrategy(consumedUp)) {
                    case AREA:
                        tempExpr = expression();
                        return new Area(tempExpr).setCacheEvalRst(cacheEvalRst);
                    case ASTEXT:
                        tempExpr = expression();
                        return new AsText(tempExpr).setCacheEvalRst(cacheEvalRst);
                    case ASWKT:
                        tempExpr = expression();
                        return new AsWKT(tempExpr).setCacheEvalRst(cacheEvalRst);
                    case CENTROID:
                        tempExpr = expression();
                        return new Centroid(tempExpr).setCacheEvalRst(cacheEvalRst);
                    case CONTAINS:
                        lexer.nextToken();
                        tempExprList = new ArrayList<Expression>(2);
                        tempExprList.add(expression());
                        match(PUNC_COMMA);
                        tempExprList.add(expression());
                        match(PUNC_RIGHT_PAREN);
                        return new Contains(tempExprList).setCacheEvalRst(cacheEvalRst);
                    case EQUALS:
                        lexer.nextToken();
                        tempExprList = new ArrayList<Expression>(2);
                        tempExprList.add(expression());
                        match(PUNC_COMMA);
                        tempExprList.add(expression());
                        match(PUNC_RIGHT_PAREN);
                        return new Equals(tempExprList).setCacheEvalRst(cacheEvalRst);
                    case EXTERIORRING:
                        tempExpr = expression();
                        return new ExteriorRing(tempExpr).setCacheEvalRst(cacheEvalRst);
                    case GEOMFROMTEXT:
                        tempExpr = expression();
                        return new GeomFromText(tempExpr).setCacheEvalRst(cacheEvalRst);
                    case GEOMETRYFROMTEXT:
                        tempExpr = expression();
                        return new GeometryFromText(tempExpr).setCacheEvalRst(cacheEvalRst);
                    case ISCLOSED:
                        tempExpr = expression();
                        return new IsClosed(tempExpr).setCacheEvalRst(cacheEvalRst);
                    case ISEMPTY:
                        tempExpr = expression();
                        return new IsEmpty(tempExpr).setCacheEvalRst(cacheEvalRst);
                    case MBRCONTAINS:
                        lexer.nextToken();
                        tempExprList = new ArrayList<Expression>(2);
                        tempExprList.add(expression());
                        match(PUNC_COMMA);
                        tempExprList.add(expression());
                        match(PUNC_RIGHT_PAREN);
                        return new MBRContains(tempExprList).setCacheEvalRst(cacheEvalRst);
                    case MBREQUAL:
                        lexer.nextToken();
                        tempExprList = new ArrayList<Expression>(2);
                        tempExprList.add(expression());
                        match(PUNC_COMMA);
                        tempExprList.add(expression());
                        match(PUNC_RIGHT_PAREN);
                        return new MBREqual(tempExprList).setCacheEvalRst(cacheEvalRst);
                    case MBRWITHIN:
                        lexer.nextToken();
                        tempExprList = new ArrayList<Expression>(2);
                        tempExprList.add(expression());
                        match(PUNC_COMMA);
                        tempExprList.add(expression());
                        match(PUNC_RIGHT_PAREN);
                        return new MBRWithin(tempExprList).setCacheEvalRst(cacheEvalRst);
                    case SRID:
                        tempExpr = expression();
                        return new SRID(tempExpr).setCacheEvalRst(cacheEvalRst);
                    case ST_AREA:
                        tempExpr = expression();
                        return new ST_Area(tempExpr).setCacheEvalRst(cacheEvalRst);
                    case ST_CENTROID:
                        tempExpr = expression();
                        return new ST_Centroid(tempExpr).setCacheEvalRst(cacheEvalRst);
                    case ST_CONTAINS:
                        lexer.nextToken();
                        tempExprList = new ArrayList<Expression>(2);
                        tempExprList.add(expression());
                        match(PUNC_COMMA);
                        tempExprList.add(expression());
                        match(PUNC_RIGHT_PAREN);
                        return new ST_Contains(tempExprList).setCacheEvalRst(cacheEvalRst);
                    case ST_DISTANCE:
                        lexer.nextToken();
                        tempExprList = new ArrayList<Expression>(2);
                        tempExprList.add(expression());
                        match(PUNC_COMMA);
                        tempExprList.add(expression());
                        match(PUNC_RIGHT_PAREN);
                        return new ST_Distance(tempExprList).setCacheEvalRst(cacheEvalRst);