class CQNParser extends QueryParser<O> {

    @Override
    public ParseResult<O> parse(String query) {
        try {
            if (query == null) {
                throw new IllegalArgumentException("Query was null");
            }
            CQNGrammarLexer lexer = new CQNGrammarLexer(new ANTLRInputStream(query));
            lexer.removeErrorListeners();
            lexer.addErrorListener(SYNTAX_ERROR_LISTENER);

            CommonTokenStream tokens = new CommonTokenStream(lexer);

            CQNGrammarParser parser = new CQNGrammarParser(tokens);
            parser.removeErrorListeners();
            parser.addErrorListener(SYNTAX_ERROR_LISTENER);

            CQNGrammarParser.StartContext queryContext = parser.start();

            ParseTreeWalker walker = new ParseTreeWalker();
            CQNAntlrListener<O> listener = new CQNAntlrListener<O>(this);
            walker.walk(listener, queryContext);
            return new ParseResult<O>(listener.getParsedQuery(), listener.getQueryOptions());
        }
        catch (InvalidQueryException e) {
            throw e;
        }
        catch (Exception e) {
            throw new InvalidQueryException("Failed to parse query", e);
        }
    }

    public  CQNParser(Class<O> objectType);

}