1 package com
.google
.appengine
.api
.search
.query
;
3 import com
.google
.common
.base
.Preconditions
;
5 import org
.antlr
.runtime
.ANTLRStringStream
;
6 import org
.antlr
.runtime
.RecognitionException
;
7 import org
.antlr
.runtime
.TokenRewriteStream
;
8 import org
.antlr
.runtime
.tree
.CommonTree
;
9 import org
.antlr
.runtime
.tree
.CommonTreeAdaptor
;
12 * A generator of AST representation of a query. This class uses the given factory
13 * to produce a query parser which parses user specified query. If successful it
14 * returns the root of an AST representing the parsed query.
16 public class QueryTreeBuilder
{
17 private static final ThreadLocal
<QueryLexer
> LEXER_POOL
= new ThreadLocal
<QueryLexer
>() {
19 protected QueryLexer
initialValue() {
20 return new QueryLexer();
24 private final QueryParserFactory parserFactory
;
25 private final CommonTreeAdaptor adaptor
= new CommonTreeAdaptor();
27 public QueryTreeBuilder() {
28 this.parserFactory
= new QueryParserFactory();
31 public QueryTreeBuilder(QueryParserFactory parserFactory
) {
32 this.parserFactory
= parserFactory
;
36 * Parses the user query and returns its AST.
38 * @param query the user query to be parsed
39 * @return a CommonTree constructed from the query
40 * @throws RecognitionException if the user query is invalid
41 * @throws NullPointerException if query is null
43 public CommonTree
parse(String query
) throws RecognitionException
{
44 Preconditions
.checkNotNull(query
, "query must not be null");
45 ANTLRStringStream stream
= new ANTLRStringStream(query
);
46 QueryLexer lexer
= LEXER_POOL
.get();
47 lexer
.setCharStream(stream
);
48 TokenRewriteStream tokens
= new TokenRewriteStream(lexer
);
49 QueryParser parser
= parserFactory
.newParser(tokens
);
50 CommonTree tree
= (CommonTree
) parser
.query().getTree();
51 if (tree
.getType() == QueryParser
.EMPTY
&& tree
.getChildCount() == 0) {
52 tree
= (CommonTree
) adaptor
.nil();