// Path: nexusdata/src/main/java/com/github/dkharrat/nexusdata/predicate/CompoundPredicate.java
// public class CompoundPredicate implements Predicate {
//     public static enum Operator {
//         AND,
//         OR,
//     }
// 
//     private final Predicate lhs, rhs;
//     private final Operator op;
// 
//     public CompoundPredicate(Predicate lhs, Operator op, Predicate rhs) {
//         this.lhs = lhs;
//         this.op = op;
//         this.rhs = rhs;
//     }
// 
//     public Predicate getLhs() {
//         return lhs;
//     }
// 
//     public Operator getOperator() {
//         return op;
//     }
// 
//     public Predicate getRhs() {
//         return rhs;
//     }
// 
//     @Override
//     public <T> T accept(ExpressionVisitor<T> visitor) {
//         return visitor.visit(this);
//     }
// 
//     @Override
//     public Boolean evaluate(Object object) {
//         boolean lhsValue = lhs.evaluate(object);
//         boolean rhsValue = rhs.evaluate(object);
// 
//         switch (op) {
//             case AND:
//                 return lhsValue && rhsValue;
//             case OR:
//                 return lhsValue || rhsValue;
//             default:
//                 throw new UnsupportedOperationException("Unsupported compound operator: " + op);
//         }
//     }
// 
//     @Override
//     public String toString() {
//         return "(" + lhs + " " + op + " " + rhs + ")";
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         CompoundPredicate that = (CompoundPredicate) o;
// 
//         if (!lhs.equals(that.lhs)) return false;
//         if (op != that.op) return false;
//         if (!rhs.equals(that.rhs)) return false;
// 
//         return true;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = lhs.hashCode();
//         result = 31 * result + rhs.hashCode();
//         result = 31 * result + op.hashCode();
//         return result;
//     }
// }
// 
// Path: nexusdata/src/main/java/com/github/dkharrat/nexusdata/predicate/Expression.java
// public interface Expression<T> {
// 
//     public <V> V accept(ExpressionVisitor<V> visitor);
//     public T evaluate(Object object);
// }


import com.github.dkharrat.nexusdata.predicate.ComparisonPredicate;
import com.github.dkharrat.nexusdata.predicate.CompoundPredicate;
import com.github.dkharrat.nexusdata.predicate.Expression;
import com.github.dkharrat.nexusdata.predicate.Predicate;
        public static final int POSTFIX     = 7;
    }

    private final Parser<TokenType,Expression<?>> parser;
    private final static LexerGrammar<TokenType> lexerGrammar = new LexerGrammar<TokenType>(TokenType.EOF);
    static {
        lexerGrammar.add("\\(",     TokenType.OPEN_PAREN);
        lexerGrammar.add("\\)",     TokenType.CLOSE_PAREN);
        lexerGrammar.add("&&",      TokenType.AND);
        lexerGrammar.add("\\|\\|",  TokenType.OR);
        lexerGrammar.add("==",      TokenType.EQUAL);
        lexerGrammar.add("!=",      TokenType.NOT_EQUAL);
        lexerGrammar.add(">=",      TokenType.GREATER_THAN_OR_EQUAL);
        lexerGrammar.add("<=",      TokenType.LESS_THAN_OR_EQUAL);
        lexerGrammar.add(">",       TokenType.GREATER_THAN);
        lexerGrammar.add("<",       TokenType.LESS_THAN);
        lexerGrammar.add("(\"[^\"\\\\\\r\\n]*(?:\\\\.[^\"\\\\\\r\\n]*)*\")|\\d+|true|false|null",       TokenType.CONSTANT);
        lexerGrammar.add("[a-zA-Z][a-zA-Z0-9_]*",   TokenType.FIELD_NAME);
    }

    public PredicateParser(String text) {
        Lexer<TokenType> tokenizer = new Lexer<TokenType>(lexerGrammar, text);
        parser = new Parser<TokenType,Expression<?>>(tokenizer);
        parser.registerParslets(TokenType.OPEN_PAREN, new GroupParselet());
        parser.registerParslets(TokenType.EQUAL, new ComparisonParselet(ComparisonPredicate.Operator.EQUAL, Precedence.EQUALITY));
        parser.registerParslets(TokenType.NOT_EQUAL, new ComparisonParselet(ComparisonPredicate.Operator.NOT_EQUAL, Precedence.EQUALITY));
        parser.registerParslets(TokenType.GREATER_THAN, new ComparisonParselet(ComparisonPredicate.Operator.GREATER_THAN, Precedence.INEQUALITY));
        parser.registerParslets(TokenType.GREATER_THAN_OR_EQUAL, new ComparisonParselet(ComparisonPredicate.Operator.GREATER_THAN_OR_EQUAL, Precedence.INEQUALITY));
        parser.registerParslets(TokenType.LESS_THAN, new ComparisonParselet(ComparisonPredicate.Operator.LESS_THAN, Precedence.INEQUALITY));
        parser.registerParslets(TokenType.LESS_THAN_OR_EQUAL, new ComparisonParselet(ComparisonPredicate.Operator.LESS_THAN_OR_EQUAL, Precedence.INEQUALITY));
// Path: nexusdata/src/main/java/com/github/dkharrat/nexusdata/predicate/CompoundPredicate.java
// public class CompoundPredicate implements Predicate {
//     public static enum Operator {
//         AND,
//         OR,
//     }
// 
//     private final Predicate lhs, rhs;
//     private final Operator op;
// 
//     public CompoundPredicate(Predicate lhs, Operator op, Predicate rhs) {
//         this.lhs = lhs;
//         this.op = op;
//         this.rhs = rhs;
//     }
// 
//     public Predicate getLhs() {
//         return lhs;
//     }
// 
//     public Operator getOperator() {
//         return op;
//     }
// 
//     public Predicate getRhs() {
//         return rhs;
//     }
// 
//     @Override
//     public <T> T accept(ExpressionVisitor<T> visitor) {
//         return visitor.visit(this);
//     }
// 
//     @Override
//     public Boolean evaluate(Object object) {
//         boolean lhsValue = lhs.evaluate(object);
//         boolean rhsValue = rhs.evaluate(object);
// 
//         switch (op) {
//             case AND:
//                 return lhsValue && rhsValue;
//             case OR:
//                 return lhsValue || rhsValue;
//             default:
//                 throw new UnsupportedOperationException("Unsupported compound operator: " + op);
//         }
//     }
// 
//     @Override
//     public String toString() {
//         return "(" + lhs + " " + op + " " + rhs + ")";
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         CompoundPredicate that = (CompoundPredicate) o;
// 
//         if (!lhs.equals(that.lhs)) return false;
//         if (op != that.op) return false;
//         if (!rhs.equals(that.rhs)) return false;
// 
//         return true;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = lhs.hashCode();
//         result = 31 * result + rhs.hashCode();
//         result = 31 * result + op.hashCode();
//         return result;
//     }
// }
// 
// Path: nexusdata/src/main/java/com/github/dkharrat/nexusdata/predicate/Expression.java
// public interface Expression<T> {
// 
//     public <V> V accept(ExpressionVisitor<V> visitor);
//     public T evaluate(Object object);
// }


// Path: nexusdata/src/main/java/com/github/dkharrat/nexusdata/predicate/parser/PredicateParser.java
import com.github.dkharrat.nexusdata.predicate.ComparisonPredicate;
import com.github.dkharrat.nexusdata.predicate.CompoundPredicate;
import com.github.dkharrat.nexusdata.predicate.Expression;
import com.github.dkharrat.nexusdata.predicate.Predicate;

        public static final int POSTFIX     = 7;
    }

    private final Parser<TokenType,Expression<?>> parser;
    private final static LexerGrammar<TokenType> lexerGrammar = new LexerGrammar<TokenType>(TokenType.EOF);
    static {
        lexerGrammar.add("\\(",     TokenType.OPEN_PAREN);
        lexerGrammar.add("\\)",     TokenType.CLOSE_PAREN);
        lexerGrammar.add("&&",      TokenType.AND);
        lexerGrammar.add("\\|\\|",  TokenType.OR);
        lexerGrammar.add("==",      TokenType.EQUAL);
        lexerGrammar.add("!=",      TokenType.NOT_EQUAL);
        lexerGrammar.add(">=",      TokenType.GREATER_THAN_OR_EQUAL);
        lexerGrammar.add("<=",      TokenType.LESS_THAN_OR_EQUAL);
        lexerGrammar.add(">",       TokenType.GREATER_THAN);
        lexerGrammar.add("<",       TokenType.LESS_THAN);
        lexerGrammar.add("(\"[^\"\\\\\\r\\n]*(?:\\\\.[^\"\\\\\\r\\n]*)*\")|\\d+|true|false|null",       TokenType.CONSTANT);
        lexerGrammar.add("[a-zA-Z][a-zA-Z0-9_]*",   TokenType.FIELD_NAME);
    }

    public PredicateParser(String text) {
        Lexer<TokenType> tokenizer = new Lexer<TokenType>(lexerGrammar, text);
        parser = new Parser<TokenType,Expression<?>>(tokenizer);
        parser.registerParslets(TokenType.OPEN_PAREN, new GroupParselet());
        parser.registerParslets(TokenType.EQUAL, new ComparisonParselet(ComparisonPredicate.Operator.EQUAL, Precedence.EQUALITY));
        parser.registerParslets(TokenType.NOT_EQUAL, new ComparisonParselet(ComparisonPredicate.Operator.NOT_EQUAL, Precedence.EQUALITY));
        parser.registerParslets(TokenType.GREATER_THAN, new ComparisonParselet(ComparisonPredicate.Operator.GREATER_THAN, Precedence.INEQUALITY));
        parser.registerParslets(TokenType.GREATER_THAN_OR_EQUAL, new ComparisonParselet(ComparisonPredicate.Operator.GREATER_THAN_OR_EQUAL, Precedence.INEQUALITY));
        parser.registerParslets(TokenType.LESS_THAN, new ComparisonParselet(ComparisonPredicate.Operator.LESS_THAN, Precedence.INEQUALITY));
        parser.registerParslets(TokenType.LESS_THAN_OR_EQUAL, new ComparisonParselet(ComparisonPredicate.Operator.LESS_THAN_OR_EQUAL, Precedence.INEQUALITY));
        parser.registerParslets(TokenType.AND, new LogicalParselet(CompoundPredicate.Operator.AND, Precedence.AND));