class LuceneQueryParser implements QueryParser {

    @Override
    public datawave.query.language.tree.QueryNode parse(String query) throws ParseException {
        query = query.replaceAll("\\u0093", "\""); // replace open smart quote 147
        query = query.replaceAll("\\u0094", "\""); // replace close smart quote 148
        
        datawave.query.language.tree.QueryNode parsedQuery = null;
        
        try {
            Locale.setDefault(Locale.US);
            AccumuloSyntaxParser syntaxParser = new AccumuloSyntaxParser();
            syntaxParser.enable_tracing();
            
            org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler queryConfigHandler = new QueryConfigHandler();
            QueryNodeProcessor processor = new CustomQueryNodeProcessorPipeline(queryConfigHandler);
            QueryBuilder builder = null;
            if (allowedFunctions == null) {
                builder = new AccumuloQueryTreeBuilder();
            } else {
                builder = new AccumuloQueryTreeBuilder(allowedFunctions);
            }
            
            QueryNode queryTree = syntaxParser.parse(query, "");
            queryTree = processor.process(queryTree);
            parsedQuery = (datawave.query.language.tree.QueryNode) builder.build(queryTree);
            
            Set<FieldedTerm> positiveFilters = new TreeSet<>();
            
            if (log.isTraceEnabled()) {
                log.trace("Query before filters extracted: " + parsedQuery.getContents());
            }
            extractFilters(parsedQuery, positiveFilters);
            
            parsedQuery.setPositiveFilters(positiveFilters);
            if (log.isTraceEnabled()) {
                log.trace("Query after filters extracted: " + parsedQuery.getContents());
            }
        } catch (QueryNodeException | RuntimeException e) {
            throw new ParseException(e);
        }
        
        return parsedQuery;
    }

}