FileDocCategorySizeDatePackage
PrecedenceQueryParser.javaAPI DocApache Lucene 2.2.038943Sat Jun 16 22:21:02 BST 2007org.apache.lucene.queryParser.precedence

PrecedenceQueryParser

public class PrecedenceQueryParser extends Object implements PrecedenceQueryParserConstants
Experimental query parser variant designed to handle operator precedence in a more sensible fashion than QueryParser. There are still some open issues with this parser. The following tests are currently failing in TestPrecedenceQueryParser and are disabled to make this test pass:
  • testSimple
  • testWildcard
  • testPrecedence
This class is generated by JavaCC. The only method that clients should need to call is {@link #parse(String)}. The syntax for query strings is as follows: A Query is a series of clauses. A clause may be prefixed by:
  • a plus (+) or a minus (-) sign, indicating that the clause is required or prohibited respectively; or
  • a term followed by a colon, indicating the field to be searched. This enables one to construct queries which search multiple fields.
A clause may be either:
  • a term, indicating all the documents that contain this term; or
  • a nested query, enclosed in parentheses. Note that this may be used with a +/- prefix to require any of a set of terms.
Thus, in BNF, the query grammar is:
Query ::= ( Clause )*
Clause ::= ["+", "-"] [<TERM> ":"] ( <TERM> | "(" Query ")" )

Examples of appropriately formatted queries can be found in the query syntax documentation.

author
Brian Goetz
author
Peter Halacsy
author
Tatu Saloranta

Fields Summary
private static final int
CONJ_NONE
private static final int
CONJ_AND
private static final int
CONJ_OR
private static final int
MOD_NONE
private static final int
MOD_NOT
private static final int
MOD_REQ
public static final Operator
AND_OPERATOR
public static final Operator
OR_OPERATOR
private Operator
operator
The actual operator that parser uses to combine query terms
boolean
lowercaseExpandedTerms
Analyzer
analyzer
String
field
int
phraseSlop
float
fuzzyMinSim
int
fuzzyPrefixLength
Locale
locale
public PrecedenceQueryParserTokenManager
token_source
public Token
token
public Token
jj_nt
private int
jj_ntk
private Token
jj_scanpos
private Token
jj_lastpos
private int
jj_la
public boolean
lookingAhead
private boolean
jj_semLA
private int
jj_gen
private final int[]
jj_la1
private static int[]
jj_la1_0
private final JJCalls[]
jj_2_rtns
private boolean
jj_rescan
private int
jj_gc
private final LookaheadSuccess
jj_ls
private Vector
jj_expentries
private int[]
jj_expentry
private int
jj_kind
private int[]
jj_lasttokens
private int
jj_endpos
Constructors Summary
public PrecedenceQueryParser(String f, Analyzer a)
Constructs a query parser.

param
f the default field for query terms.
param
a used to find terms in the query text.

  

                                
       
    this(new FastCharStream(new StringReader("")));
    analyzer = a;
    field = f;
  
public PrecedenceQueryParser(CharStream stream)


     
    token_source = new PrecedenceQueryParserTokenManager(stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 24; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  
public PrecedenceQueryParser(PrecedenceQueryParserTokenManager tm)

    token_source = tm;
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 24; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  
Methods Summary
public final org.apache.lucene.search.QueryClause(java.lang.String field)

  Query q;
  Token fieldToken=null, boost=null;
    if (jj_2_1(2)) {
      fieldToken = jj_consume_token(TERM);
      jj_consume_token(COLON);
      field=discardEscapeChar(fieldToken.image);
    } else {
      ;
    }
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case QUOTED:
    case TERM:
    case PREFIXTERM:
    case WILDTERM:
    case RANGEIN_START:
    case RANGEEX_START:
    case NUMBER:
      q = Term(field);
      break;
    case LPAREN:
      jj_consume_token(LPAREN);
      q = Query(field);
      jj_consume_token(RPAREN);
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case CARAT:
        jj_consume_token(CARAT);
        boost = jj_consume_token(NUMBER);
        break;
      default:
        jj_la1[7] = jj_gen;
        ;
      }
      break;
    default:
      jj_la1[8] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
      if (boost != null) {
        float f = (float)1.0;
  try {
    f = Float.valueOf(boost.image).floatValue();
          q.setBoost(f);
  } catch (Exception ignored) { }
      }
      {if (true) return q;}
    throw new Error("Missing return statement in function");
  
public final intConjunction()

  int ret = CONJ_NONE;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case AND:
    case OR:
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case AND:
        jj_consume_token(AND);
            ret = CONJ_AND;
        break;
      case OR:
        jj_consume_token(OR);
              ret = CONJ_OR;
        break;
      default:
        jj_la1[0] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      break;
    default:
      jj_la1[1] = jj_gen;
      ;
    }
    {if (true) return ret;}
    throw new Error("Missing return statement in function");
  
public final intModifier()

  int ret = MOD_NONE;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case NOT:
    case PLUS:
    case MINUS:
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case PLUS:
        jj_consume_token(PLUS);
              ret = MOD_REQ;
        break;
      case MINUS:
        jj_consume_token(MINUS);
                 ret = MOD_NOT;
        break;
      case NOT:
        jj_consume_token(NOT);
               ret = MOD_NOT;
        break;
      default:
        jj_la1[2] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      break;
    default:
      jj_la1[3] = jj_gen;
      ;
    }
    {if (true) return ret;}
    throw new Error("Missing return statement in function");
  
public final org.apache.lucene.search.QueryQuery(java.lang.String field)

  Vector clauses = new Vector();
  Query q, firstQuery=null;
  boolean orPresent = false;
  int modifier;
    modifier = Modifier();
    q = andExpression(field);
    addClause(clauses, CONJ_NONE, modifier, q);
    if (modifier == MOD_NONE)
      firstQuery = q;
    label_1:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case OR:
      case NOT:
      case PLUS:
      case MINUS:
      case LPAREN:
      case QUOTED:
      case TERM:
      case PREFIXTERM:
      case WILDTERM:
      case RANGEIN_START:
      case RANGEEX_START:
      case NUMBER:
        ;
        break;
      default:
        jj_la1[4] = jj_gen;
        break label_1;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case OR:
        jj_consume_token(OR);
            orPresent=true;
        break;
      default:
        jj_la1[5] = jj_gen;
        ;
      }
      modifier = Modifier();
      q = andExpression(field);
      addClause(clauses, orPresent ? CONJ_OR : CONJ_NONE, modifier, q);
    }
      if (clauses.size() == 1 && firstQuery != null)
        {if (true) return firstQuery;}
      else {
        {if (true) return getBooleanQuery(clauses);}
      }
    throw new Error("Missing return statement in function");
  
public voidReInit(CharStream stream)

    token_source.ReInit(stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 24; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  
public voidReInit(PrecedenceQueryParserTokenManager tm)

    token_source = tm;
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 24; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  
public final org.apache.lucene.search.QueryTerm(java.lang.String field)

  Token term, boost=null, fuzzySlop=null, goop1, goop2;
  boolean prefix = false;
  boolean wildcard = false;
  boolean fuzzy = false;
  Query q;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case TERM:
    case PREFIXTERM:
    case WILDTERM:
    case NUMBER:
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case TERM:
        term = jj_consume_token(TERM);
        break;
      case PREFIXTERM:
        term = jj_consume_token(PREFIXTERM);
                             prefix=true;
        break;
      case WILDTERM:
        term = jj_consume_token(WILDTERM);
                           wildcard=true;
        break;
      case NUMBER:
        term = jj_consume_token(NUMBER);
        break;
      default:
        jj_la1[9] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case FUZZY_SLOP:
        fuzzySlop = jj_consume_token(FUZZY_SLOP);
                                fuzzy=true;
        break;
      default:
        jj_la1[10] = jj_gen;
        ;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case CARAT:
        jj_consume_token(CARAT);
        boost = jj_consume_token(NUMBER);
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case FUZZY_SLOP:
          fuzzySlop = jj_consume_token(FUZZY_SLOP);
                                                         fuzzy=true;
          break;
        default:
          jj_la1[11] = jj_gen;
          ;
        }
        break;
      default:
        jj_la1[12] = jj_gen;
        ;
      }
       String termImage=discardEscapeChar(term.image);
       if (wildcard) {
       q = getWildcardQuery(field, termImage);
       } else if (prefix) {
         q = getPrefixQuery(field,
           discardEscapeChar(term.image.substring
          (0, term.image.length()-1)));
       } else if (fuzzy) {
          float fms = fuzzyMinSim;
          try {
            fms = Float.valueOf(fuzzySlop.image.substring(1)).floatValue();
          } catch (Exception ignored) { }
         if(fms < 0.0f || fms > 1.0f){
           {if (true) throw new ParseException("Minimum similarity for a FuzzyQuery has to be between 0.0f and 1.0f !");}
         }
         q = getFuzzyQuery(field, termImage, fms);
       } else {
         q = getFieldQuery(field, termImage);
       }
      break;
    case RANGEIN_START:
      jj_consume_token(RANGEIN_START);
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case RANGEIN_GOOP:
        goop1 = jj_consume_token(RANGEIN_GOOP);
        break;
      case RANGEIN_QUOTED:
        goop1 = jj_consume_token(RANGEIN_QUOTED);
        break;
      default:
        jj_la1[13] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case RANGEIN_TO:
        jj_consume_token(RANGEIN_TO);
        break;
      default:
        jj_la1[14] = jj_gen;
        ;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case RANGEIN_GOOP:
        goop2 = jj_consume_token(RANGEIN_GOOP);
        break;
      case RANGEIN_QUOTED:
        goop2 = jj_consume_token(RANGEIN_QUOTED);
        break;
      default:
        jj_la1[15] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      jj_consume_token(RANGEIN_END);
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case CARAT:
        jj_consume_token(CARAT);
        boost = jj_consume_token(NUMBER);
        break;
      default:
        jj_la1[16] = jj_gen;
        ;
      }
          if (goop1.kind == RANGEIN_QUOTED) {
            goop1.image = goop1.image.substring(1, goop1.image.length()-1);
          } else {
            goop1.image = discardEscapeChar(goop1.image);
          }
          if (goop2.kind == RANGEIN_QUOTED) {
            goop2.image = goop2.image.substring(1, goop2.image.length()-1);
      } else {
        goop2.image = discardEscapeChar(goop2.image);
      }
          q = getRangeQuery(field, goop1.image, goop2.image, true);
      break;
    case RANGEEX_START:
      jj_consume_token(RANGEEX_START);
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case RANGEEX_GOOP:
        goop1 = jj_consume_token(RANGEEX_GOOP);
        break;
      case RANGEEX_QUOTED:
        goop1 = jj_consume_token(RANGEEX_QUOTED);
        break;
      default:
        jj_la1[17] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case RANGEEX_TO:
        jj_consume_token(RANGEEX_TO);
        break;
      default:
        jj_la1[18] = jj_gen;
        ;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case RANGEEX_GOOP:
        goop2 = jj_consume_token(RANGEEX_GOOP);
        break;
      case RANGEEX_QUOTED:
        goop2 = jj_consume_token(RANGEEX_QUOTED);
        break;
      default:
        jj_la1[19] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      jj_consume_token(RANGEEX_END);
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case CARAT:
        jj_consume_token(CARAT);
        boost = jj_consume_token(NUMBER);
        break;
      default:
        jj_la1[20] = jj_gen;
        ;
      }
          if (goop1.kind == RANGEEX_QUOTED) {
            goop1.image = goop1.image.substring(1, goop1.image.length()-1);
          } else {
            goop1.image = discardEscapeChar(goop1.image);
          }
          if (goop2.kind == RANGEEX_QUOTED) {
            goop2.image = goop2.image.substring(1, goop2.image.length()-1);
      } else {
        goop2.image = discardEscapeChar(goop2.image);
      }

          q = getRangeQuery(field, goop1.image, goop2.image, false);
      break;
    case QUOTED:
      term = jj_consume_token(QUOTED);
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case FUZZY_SLOP:
        fuzzySlop = jj_consume_token(FUZZY_SLOP);
        break;
      default:
        jj_la1[21] = jj_gen;
        ;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case CARAT:
        jj_consume_token(CARAT);
        boost = jj_consume_token(NUMBER);
        break;
      default:
        jj_la1[22] = jj_gen;
        ;
      }
         int s = phraseSlop;

         if (fuzzySlop != null) {
           try {
             s = Float.valueOf(fuzzySlop.image.substring(1)).intValue();
           }
           catch (Exception ignored) { }
         }
         q = getFieldQuery(field, term.image.substring(1, term.image.length()-1), s);
      break;
    default:
      jj_la1[23] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    if (boost != null) {
      float f = (float) 1.0;
      try {
        f = Float.valueOf(boost.image).floatValue();
      }
      catch (Exception ignored) {
    /* Should this be handled somehow? (defaults to "no boost", if
     * boost number is invalid)
     */
      }

      // avoid boosting null queries, such as those caused by stop words
      if (q != null) {
        q.setBoost(f);
      }
    }
    {if (true) return q;}
    throw new Error("Missing return statement in function");
  
protected voidaddClause(java.util.Vector clauses, int conj, int modifier, org.apache.lucene.search.Query q)

    boolean required, prohibited;

    // If this term is introduced by AND, make the preceding term required,
    // unless it's already prohibited
    if (clauses.size() > 0 && conj == CONJ_AND) {
      BooleanClause c = (BooleanClause) clauses.elementAt(clauses.size()-1);
      if (!c.isProhibited())
        c.setOccur(BooleanClause.Occur.MUST);
    }

    if (clauses.size() > 0 && operator == AND_OPERATOR && conj == CONJ_OR) {
      // If this term is introduced by OR, make the preceding term optional,
      // unless it's prohibited (that means we leave -a OR b but +a OR b-->a OR b)
      // notice if the input is a OR b, first term is parsed as required; without
      // this modification a OR b would parsed as +a OR b
      BooleanClause c = (BooleanClause) clauses.elementAt(clauses.size()-1);
      if (!c.isProhibited())
        c.setOccur(BooleanClause.Occur.SHOULD);
    }

    // We might have been passed a null query; the term might have been
    // filtered away by the analyzer.
    if (q == null)
      return;

    if (operator == OR_OPERATOR) {
      // We set REQUIRED if we're introduced by AND or +; PROHIBITED if
      // introduced by NOT or -; make sure not to set both.
      prohibited = (modifier == MOD_NOT);
      required = (modifier == MOD_REQ);
      if (conj == CONJ_AND && !prohibited) {
        required = true;
      }
    } else {
      // We set PROHIBITED if we're introduced by NOT or -; We set REQUIRED
      // if not PROHIBITED and not introduced by OR
      prohibited = (modifier == MOD_NOT);
      required   = (!prohibited && conj != CONJ_OR);
    }
    if (required && !prohibited)
      clauses.addElement(new BooleanClause(q, BooleanClause.Occur.MUST));
    else if (!required && !prohibited)
      clauses.addElement(new BooleanClause(q, BooleanClause.Occur.SHOULD));
    else if (!required && prohibited)
      clauses.addElement(new BooleanClause(q, BooleanClause.Occur.MUST_NOT));
    else
      throw new RuntimeException("Clause cannot be both required and prohibited");
  
public final org.apache.lucene.search.QueryandExpression(java.lang.String field)

  Vector clauses = new Vector();
  Query q, firstQuery=null;
  int modifier;
    q = Clause(field);
    addClause(clauses, CONJ_NONE, MOD_NONE, q);
    firstQuery = q;
    label_2:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case AND:
        ;
        break;
      default:
        jj_la1[6] = jj_gen;
        break label_2;
      }
      jj_consume_token(AND);
      modifier = Modifier();
      q = Clause(field);
      addClause(clauses, CONJ_AND, modifier, q);
    }
      if (clauses.size() == 1 && firstQuery != null)
        {if (true) return firstQuery;}
      else {
        {if (true) return getBooleanQuery(clauses);}
      }
    throw new Error("Missing return statement in function");
  
public final voiddisable_tracing()

  
private java.lang.StringdiscardEscapeChar(java.lang.String input)
Returns a String where the escape char has been removed, or kept only once if there was a double escape.

    char[] caSource = input.toCharArray();
    char[] caDest = new char[caSource.length];
    int j = 0;
    for (int i = 0; i < caSource.length; i++) {
      if ((caSource[i] != '\\") || (i > 0 && caSource[i-1] == '\\")) {
        caDest[j++]=caSource[i];
      }
    }
    return new String(caDest, 0, j);
  
public final voidenable_tracing()

  
public static java.lang.Stringescape(java.lang.String s)
Returns a String where those characters that QueryParser expects to be escaped are escaped by a preceding \.

    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < s.length(); i++) {
      char c = s.charAt(i);
      // NOTE: keep this in sync with _ESCAPED_CHAR below!
      if (c == '\\" || c == '+" || c == '-" || c == '!" || c == '(" || c == ')" || c == ':"
        || c == '^" || c == '[" || c == ']" || c == '\"" || c == '{" || c == '}" || c == '~"
        || c == '*" || c == '?") {
        sb.append('\\");
      }
      sb.append(c);
    }
    return sb.toString();
  
public java.text.ParseExceptiongenerateParseException()

    jj_expentries.removeAllElements();
    boolean[] la1tokens = new boolean[32];
    for (int i = 0; i < 32; i++) {
      la1tokens[i] = false;
    }
    if (jj_kind >= 0) {
      la1tokens[jj_kind] = true;
      jj_kind = -1;
    }
    for (int i = 0; i < 24; i++) {
      if (jj_la1[i] == jj_gen) {
        for (int j = 0; j < 32; j++) {
          if ((jj_la1_0[i] & (1<<j)) != 0) {
            la1tokens[j] = true;
          }
        }
      }
    }
    for (int i = 0; i < 32; i++) {
      if (la1tokens[i]) {
        jj_expentry = new int[1];
        jj_expentry[0] = i;
        jj_expentries.addElement(jj_expentry);
      }
    }
    jj_endpos = 0;
    jj_rescan_token();
    jj_add_error_token(0, 0);
    int[][] exptokseq = new int[jj_expentries.size()][];
    for (int i = 0; i < jj_expentries.size(); i++) {
      exptokseq[i] = (int[])jj_expentries.elementAt(i);
    }
    return new ParseException(token, exptokseq, tokenImage);
  
public org.apache.lucene.analysis.AnalyzergetAnalyzer()

return
Returns the analyzer.

    return analyzer;
  
protected org.apache.lucene.search.QuerygetBooleanQuery(java.util.Vector clauses)
Factory method for generating query, given a set of clauses. By default creates a boolean query composed of clauses passed in. Can be overridden by extending classes, to modify query being returned.

param
clauses Vector that contains {@link BooleanClause} instances to join.
return
Resulting {@link Query} object.
exception
ParseException throw in overridden method to disallow

    return getBooleanQuery(clauses, false);
  
protected org.apache.lucene.search.QuerygetBooleanQuery(java.util.Vector clauses, boolean disableCoord)
Factory method for generating query, given a set of clauses. By default creates a boolean query composed of clauses passed in. Can be overridden by extending classes, to modify query being returned.

param
clauses Vector that contains {@link BooleanClause} instances to join.
param
disableCoord true if coord scoring should be disabled.
return
Resulting {@link Query} object.
exception
ParseException throw in overridden method to disallow

    if (clauses == null || clauses.size() == 0)
      return null;

    BooleanQuery query = new BooleanQuery(disableCoord);
    for (int i = 0; i < clauses.size(); i++) {
      query.add((BooleanClause)clauses.elementAt(i));
    }
    return query;
  
public org.apache.lucene.queryParser.precedence.PrecedenceQueryParser$OperatorgetDefaultOperator()
Gets implicit operator setting, which will be either AND_OPERATOR or OR_OPERATOR.

    return operator;
  
public java.lang.StringgetField()

return
Returns the field.

    return field;
  
protected org.apache.lucene.search.QuerygetFieldQuery(java.lang.String field, java.lang.String queryText)

exception
ParseException throw in overridden method to disallow

    // Use the analyzer to get all the tokens, and then build a TermQuery,
    // PhraseQuery, or nothing based on the term count

    TokenStream source = analyzer.tokenStream(field, new StringReader(queryText));
    Vector v = new Vector();
    org.apache.lucene.analysis.Token t;
    int positionCount = 0;
    boolean severalTokensAtSamePosition = false;

    while (true) {
      try {
        t = source.next();
      }
      catch (IOException e) {
        t = null;
      }
      if (t == null)
        break;
      v.addElement(t);
      if (t.getPositionIncrement() == 1)
        positionCount++;
      else
        severalTokensAtSamePosition = true;
    }
    try {
      source.close();
    }
    catch (IOException e) {
      // ignore
    }

    if (v.size() == 0)
      return null;
    else if (v.size() == 1) {
      t = (org.apache.lucene.analysis.Token) v.elementAt(0);
      return new TermQuery(new Term(field, t.termText()));
    } else {
      if (severalTokensAtSamePosition) {
        if (positionCount == 1) {
          // no phrase query:
          BooleanQuery q = new BooleanQuery();
          for (int i = 0; i < v.size(); i++) {
            t = (org.apache.lucene.analysis.Token) v.elementAt(i);
            TermQuery currentQuery = new TermQuery(
                new Term(field, t.termText()));
            q.add(currentQuery, BooleanClause.Occur.SHOULD);
          }
          return q;
        }
        else {
          // phrase query:
          MultiPhraseQuery mpq = new MultiPhraseQuery();
          List multiTerms = new ArrayList();
          for (int i = 0; i < v.size(); i++) {
            t = (org.apache.lucene.analysis.Token) v.elementAt(i);
            if (t.getPositionIncrement() == 1 && multiTerms.size() > 0) {
              mpq.add((Term[])multiTerms.toArray(new Term[0]));
              multiTerms.clear();
            }
            multiTerms.add(new Term(field, t.termText()));
          }
          mpq.add((Term[])multiTerms.toArray(new Term[0]));
          return mpq;
        }
      }
      else {
        PhraseQuery q = new PhraseQuery();
        q.setSlop(phraseSlop);
        for (int i = 0; i < v.size(); i++) {
          q.add(new Term(field, ((org.apache.lucene.analysis.Token)
              v.elementAt(i)).termText()));

        }
        return q;
      }
    }
  
protected org.apache.lucene.search.QuerygetFieldQuery(java.lang.String field, java.lang.String queryText, int slop)
Base implementation delegates to {@link #getFieldQuery(String,String)}. This method may be overridden, for example, to return a SpanNearQuery instead of a PhraseQuery.

exception
ParseException throw in overridden method to disallow

    Query query = getFieldQuery(field, queryText);

    if (query instanceof PhraseQuery) {
      ((PhraseQuery) query).setSlop(slop);
    }
    if (query instanceof MultiPhraseQuery) {
      ((MultiPhraseQuery) query).setSlop(slop);
    }

    return query;
  
public floatgetFuzzyMinSim()
Get the minimal similarity for fuzzy queries.

      return fuzzyMinSim;
  
public intgetFuzzyPrefixLength()
Get the prefix length for fuzzy queries.

return
Returns the fuzzyPrefixLength.

    return fuzzyPrefixLength;
  
protected org.apache.lucene.search.QuerygetFuzzyQuery(java.lang.String field, java.lang.String termStr, float minSimilarity)
Factory method for generating a query (similar to {@link #getWildcardQuery}). Called when parser parses an input term token that has the fuzzy suffix (~) appended.

param
field Name of the field query will use.
param
termStr Term token to use for building term for the query
return
Resulting {@link Query} built for the term
exception
ParseException throw in overridden method to disallow

    if (lowercaseExpandedTerms) {
      termStr = termStr.toLowerCase();
    }
    Term t = new Term(field, termStr);
    return new FuzzyQuery(t, minSimilarity, fuzzyPrefixLength);
  
public java.util.LocalegetLocale()
Returns current locale, allowing access by subclasses.

    return locale;
  
public booleangetLowercaseExpandedTerms()

see
#setLowercaseExpandedTerms(boolean)

    return lowercaseExpandedTerms;
  
public final org.apache.lucene.analysis.TokengetNextToken()

    if (token.next != null) token = token.next;
    else token = token.next = token_source.getNextToken();
    jj_ntk = -1;
    jj_gen++;
    return token;
  
public intgetPhraseSlop()
Gets the default slop for phrases.

    return phraseSlop;
  
protected org.apache.lucene.search.QuerygetPrefixQuery(java.lang.String field, java.lang.String termStr)
Factory method for generating a query (similar to {@link #getWildcardQuery}). Called when parser parses an input term token that uses prefix notation; that is, contains a single '*' wildcard character as its last character. Since this is a special case of generic wildcard term, and such a query can be optimized easily, this usually results in a different query object.

Depending on settings, a prefix term may be lower-cased automatically. It will not go through the default Analyzer, however, since normal Analyzers are unlikely to work properly with wildcard templates.

Can be overridden by extending classes, to provide custom handling for wild card queries, which may be necessary due to missing analyzer calls.

param
field Name of the field query will use.
param
termStr Term token to use for building term for the query (without trailing '*' character!)
return
Resulting {@link Query} built for the term
exception
ParseException throw in overridden method to disallow

    if (lowercaseExpandedTerms) {
      termStr = termStr.toLowerCase();
    }
    Term t = new Term(field, termStr);
    return new PrefixQuery(t);
  
protected org.apache.lucene.search.QuerygetRangeQuery(java.lang.String field, java.lang.String part1, java.lang.String part2, boolean inclusive)

exception
ParseException throw in overridden method to disallow

    if (lowercaseExpandedTerms) {
      part1 = part1.toLowerCase();
      part2 = part2.toLowerCase();
    }
    try {
      DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
      df.setLenient(true);
      Date d1 = df.parse(part1);
      Date d2 = df.parse(part2);
      part1 = DateTools.dateToString(d1, DateTools.Resolution.DAY);
      part2 = DateTools.dateToString(d2, DateTools.Resolution.DAY);
    }
    catch (Exception e) { }

    return new RangeQuery(new Term(field, part1),
                          new Term(field, part2),
                          inclusive);
  
public final org.apache.lucene.analysis.TokengetToken(int index)

    Token t = lookingAhead ? jj_scanpos : token;
    for (int i = 0; i < index; i++) {
      if (t.next != null) t = t.next;
      else t = t.next = token_source.getNextToken();
    }
    return t;
  
protected org.apache.lucene.search.QuerygetWildcardQuery(java.lang.String field, java.lang.String termStr)
Factory method for generating a query. Called when parser parses an input term token that contains one or more wildcard characters (? and *), but is not a prefix term token (one that has just a single * character at the end)

Depending on settings, prefix term may be lower-cased automatically. It will not go through the default Analyzer, however, since normal Analyzers are unlikely to work properly with wildcard templates.

Can be overridden by extending classes, to provide custom handling for wildcard queries, which may be necessary due to missing analyzer calls.

param
field Name of the field query will use.
param
termStr Term token that contains one or more wild card characters (? or *), but is not simple prefix term
return
Resulting {@link Query} built for the term
exception
ParseException throw in overridden method to disallow

    if (lowercaseExpandedTerms) {
      termStr = termStr.toLowerCase();
    }
    Term t = new Term(field, termStr);
    return new WildcardQuery(t);
  
private final booleanjj_2_1(int xla)

    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_1(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(0, xla); }
  
private final booleanjj_3_1()

    if (jj_scan_token(TERM)) return true;
    if (jj_scan_token(COLON)) return true;
    return false;
  
private voidjj_add_error_token(int kind, int pos)


        
    if (pos >= 100) return;
    if (pos == jj_endpos + 1) {
      jj_lasttokens[jj_endpos++] = kind;
    } else if (jj_endpos != 0) {
      jj_expentry = new int[jj_endpos];
      for (int i = 0; i < jj_endpos; i++) {
        jj_expentry[i] = jj_lasttokens[i];
      }
      boolean exists = false;
      for (java.util.Enumeration e = jj_expentries.elements(); e.hasMoreElements();) {
        int[] oldentry = (int[])(e.nextElement());
        if (oldentry.length == jj_expentry.length) {
          exists = true;
          for (int i = 0; i < jj_expentry.length; i++) {
            if (oldentry[i] != jj_expentry[i]) {
              exists = false;
              break;
            }
          }
          if (exists) break;
        }
      }
      if (!exists) jj_expentries.addElement(jj_expentry);
      if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
    }
  
private final org.apache.lucene.analysis.Tokenjj_consume_token(int kind)

    Token oldToken;
    if ((oldToken = token).next != null) token = token.next;
    else token = token.next = token_source.getNextToken();
    jj_ntk = -1;
    if (token.kind == kind) {
      jj_gen++;
      if (++jj_gc > 100) {
        jj_gc = 0;
        for (int i = 0; i < jj_2_rtns.length; i++) {
          JJCalls c = jj_2_rtns[i];
          while (c != null) {
            if (c.gen < jj_gen) c.first = null;
            c = c.next;
          }
        }
      }
      return token;
    }
    token = oldToken;
    jj_kind = kind;
    throw generateParseException();
  
private static voidjj_la1_0()

   
      jj_la1_0();
   
      jj_la1_0 = new int[] {0x180,0x180,0xe00,0xe00,0xfb1f00,0x100,0x80,0x8000,0xfb1000,0x9a0000,0x40000,0x40000,0x8000,0xc000000,0x1000000,0xc000000,0x8000,0xc0000000,0x10000000,0xc0000000,0x8000,0x40000,0x8000,0xfb0000,};
   
private final intjj_ntk()

    if ((jj_nt=token.next) == null)
      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
    else
      return (jj_ntk = jj_nt.kind);
  
private final voidjj_rescan_token()

    jj_rescan = true;
    for (int i = 0; i < 1; i++) {
      JJCalls p = jj_2_rtns[i];
      do {
        if (p.gen > jj_gen) {
          jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
          switch (i) {
            case 0: jj_3_1(); break;
          }
        }
        p = p.next;
      } while (p != null);
    }
    jj_rescan = false;
  
private final voidjj_save(int index, int xla)

    JJCalls p = jj_2_rtns[index];
    while (p.gen > jj_gen) {
      if (p.next == null) { p = p.next = new JJCalls(); break; }
      p = p.next;
    }
    p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
  
private final booleanjj_scan_token(int kind)

       
    if (jj_scanpos == jj_lastpos) {
      jj_la--;
      if (jj_scanpos.next == null) {
        jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
      } else {
        jj_lastpos = jj_scanpos = jj_scanpos.next;
      }
    } else {
      jj_scanpos = jj_scanpos.next;
    }
    if (jj_rescan) {
      int i = 0; Token tok = token;
      while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
      if (tok != null) jj_add_error_token(kind, i);
    }
    if (jj_scanpos.kind != kind) return true;
    if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
    return false;
  
public static voidmain(java.lang.String[] args)
Command line tool to test QueryParser, using {@link org.apache.lucene.analysis.SimpleAnalyzer}. Usage:
java org.apache.lucene.queryParser.QueryParser <input>

    if (args.length == 0) {
      System.out.println("Usage: java org.apache.lucene.queryParser.QueryParser <input>");
      System.exit(0);
    }
    PrecedenceQueryParser qp = new PrecedenceQueryParser("field",
                           new org.apache.lucene.analysis.SimpleAnalyzer());
    Query q = qp.parse(args[0]);
    System.out.println(q.toString("field"));
  
public org.apache.lucene.search.Queryparse(java.lang.String expression)
Parses a query string, returning a {@link org.apache.lucene.search.Query}.

param
expression the query string to be parsed.
throws
ParseException if the parsing fails

    // optimize empty query to be empty BooleanQuery
    if (expression == null || expression.trim().length() == 0) {
      return new BooleanQuery();
    }

    ReInit(new FastCharStream(new StringReader(expression)));
    try {
      Query query = Query(field);
      return (query != null) ? query : new BooleanQuery();
    }
    catch (TokenMgrError tme) {
      throw new ParseException(tme.getMessage());
    }
    catch (BooleanQuery.TooManyClauses tmc) {
      throw new ParseException("Too many boolean clauses");
    }
  
public voidsetDefaultOperator(org.apache.lucene.queryParser.precedence.PrecedenceQueryParser$Operator op)
Sets the boolean operator of the QueryParser. In default mode (OR_OPERATOR) terms without any modifiers are considered optional: for example capital of Hungary is equal to capital OR of OR Hungary.
In AND_OPERATOR mode terms are considered to be in conjuction: the above mentioned query is parsed as capital AND of AND Hungary

    this.operator = op;
  
public voidsetFuzzyMinSim(float fuzzyMinSim)
Set the minimum similarity for fuzzy queries. Default is 0.5f.

      this.fuzzyMinSim = fuzzyMinSim;
  
public voidsetFuzzyPrefixLength(int fuzzyPrefixLength)
Set the prefix length for fuzzy queries. Default is 0.

param
fuzzyPrefixLength The fuzzyPrefixLength to set.

    this.fuzzyPrefixLength = fuzzyPrefixLength;
  
public voidsetLocale(java.util.Locale locale)
Set locale used by date range parsing.

    this.locale = locale;
  
public voidsetLowercaseExpandedTerms(boolean lowercaseExpandedTerms)
Whether terms of wildcard, prefix, fuzzy and range queries are to be automatically lower-cased or not. Default is true.

    this.lowercaseExpandedTerms = lowercaseExpandedTerms;
  
public voidsetPhraseSlop(int phraseSlop)
Sets the default slop for phrases. If zero, then exact phrase matches are required. Default value is zero.

    this.phraseSlop = phraseSlop;