Save This Page
Home » lucene-2.4.1-src » org.apache » lucene » queryParser » [javadoc | source]
    1   /* Generated By:JavaCC: Do not edit this line. QueryParser.java */
    2   package org.apache.lucene.queryParser;
    3   
    4   import java.io.IOException;
    5   import java.io.StringReader;
    6   import java.text.DateFormat;
    7   import java.text.Collator;
    8   import java.util.ArrayList;
    9   import java.util.Calendar;
   10   import java.util.Date;
   11   import java.util.HashMap;
   12   import java.util.List;
   13   import java.util.Locale;
   14   import java.util.Map;
   15   import java.util.Vector;
   16   
   17   import org.apache.lucene.analysis.Analyzer;
   18   import org.apache.lucene.analysis.TokenStream;
   19   import org.apache.lucene.document.DateField;
   20   import org.apache.lucene.document.DateTools;
   21   import org.apache.lucene.index.Term;
   22   import org.apache.lucene.search.BooleanClause;
   23   import org.apache.lucene.search.BooleanQuery;
   24   import org.apache.lucene.search.ConstantScoreRangeQuery;
   25   import org.apache.lucene.search.FuzzyQuery;
   26   import org.apache.lucene.search.MatchAllDocsQuery;
   27   import org.apache.lucene.search.MultiPhraseQuery;
   28   import org.apache.lucene.search.PhraseQuery;
   29   import org.apache.lucene.search.PrefixQuery;
   30   import org.apache.lucene.search.Query;
   31   import org.apache.lucene.search.RangeQuery;
   32   import org.apache.lucene.search.TermQuery;
   33   import org.apache.lucene.search.WildcardQuery;
   34   import org.apache.lucene.util.Parameter;
   35   
   36   /**
   37    * This class is generated by JavaCC.  The most important method is
   38    * {@link #parse(String)}.
   39    *
   40    * The syntax for query strings is as follows:
   41    * A Query is a series of clauses.
   42    * A clause may be prefixed by:
   43    * <ul>
   44    * <li> a plus (<code>+</code>) or a minus (<code>-</code>) sign, indicating
   45    * that the clause is required or prohibited respectively; or
   46    * <li> a term followed by a colon, indicating the field to be searched.
   47    * This enables one to construct queries which search multiple fields.
   48    * </ul>
   49    *
   50    * A clause may be either:
   51    * <ul>
   52    * <li> a term, indicating all the documents that contain this term; or
   53    * <li> a nested query, enclosed in parentheses.  Note that this may be used
   54    * with a <code>+</code>/<code>-</code> prefix to require any of a set of
   55    * terms.
   56    * </ul>
   57    *
   58    * Thus, in BNF, the query grammar is:
   59    * <pre>
   60    *   Query  ::= ( Clause )*
   61    *   Clause ::= ["+", "-"] [&lt;TERM&gt; ":"] ( &lt;TERM&gt; | "(" Query ")" )
   62    * </pre>
   63    *
   64    * <p>
   65    * Examples of appropriately formatted queries can be found in the <a
   66    * href="http://lucene.apache.org/java/docs/queryparsersyntax.html">query syntax
   67    * documentation</a>.
   68    * </p>
   69    *
   70    * <p>
   71    * In {@link RangeQuery}s, QueryParser tries to detect date values, e.g.
   72    * <tt>date:[6/1/2005 TO 6/4/2005]</tt> produces a range query that searches
   73    * for "date" fields between 2005-06-01 and 2005-06-04. Note that the format
   74    * of the accepted input depends on {@link #setLocale(Locale) the locale}.
   75    * By default a date is converted into a search term using the deprecated
   76    * {@link DateField} for compatibility reasons.
   77    * To use the new {@link DateTools} to convert dates, a
   78    * {@link org.apache.lucene.document.DateTools.Resolution} has to be set.
   79    * </p>
   80    * <p>
   81    * The date resolution that shall be used for RangeQueries can be set
   82    * using {@link #setDateResolution(DateTools.Resolution)}
   83    * or {@link #setDateResolution(String, DateTools.Resolution)}. The former
   84    * sets the default date resolution for all fields, whereas the latter can
   85    * be used to set field specific date resolutions. Field specific date
   86    * resolutions take, if set, precedence over the default date resolution.
   87    * </p>
   88    * <p>
   89    * If you use neither {@link DateField} nor {@link DateTools} in your
   90    * index, you can create your own
   91    * query parser that inherits QueryParser and overwrites
   92    * {@link #getRangeQuery(String, String, String, boolean)} to
   93    * use a different method for date conversion.
   94    * </p>
   95    *
   96    * <p>Note that QueryParser is <em>not</em> thread-safe.</p>
   97    *
   98    */
   99   public class QueryParser implements QueryParserConstants {
  100   
  101     private static final int CONJ_NONE   = 0;
  102     private static final int CONJ_AND    = 1;
  103     private static final int CONJ_OR     = 2;
  104   
  105     private static final int MOD_NONE    = 0;
  106     private static final int MOD_NOT     = 10;
  107     private static final int MOD_REQ     = 11;
  108   
  109     // make it possible to call setDefaultOperator() without accessing 
  110     // the nested class:
  111     /** Alternative form of QueryParser.Operator.AND */
  112     public static final Operator AND_OPERATOR = Operator.AND;
  113     /** Alternative form of QueryParser.Operator.OR */
  114     public static final Operator OR_OPERATOR = Operator.OR;
  115   
  116     /** The actual operator that parser uses to combine query terms */
  117     private Operator operator = OR_OPERATOR;
  118   
  119     boolean lowercaseExpandedTerms = true;
  120     boolean useOldRangeQuery= false;
  121     boolean allowLeadingWildcard = false;
  122     boolean enablePositionIncrements = false;
  123   
  124     Analyzer analyzer;
  125     String field;
  126     int phraseSlop = 0;
  127     float fuzzyMinSim = FuzzyQuery.defaultMinSimilarity;
  128     int fuzzyPrefixLength = FuzzyQuery.defaultPrefixLength;
  129     Locale locale = Locale.getDefault();
  130   
  131     // the default date resolution
  132     DateTools.Resolution dateResolution = null;
  133     // maps field names to date resolutions
  134     Map fieldToDateResolution = null;
  135   
  136     // The collator to use when determining range inclusion,
  137     // for use when constructing RangeQuerys and ConstantScoreRangeQuerys.
  138     Collator rangeCollator = null;
  139   
  140     /** The default operator for parsing queries. 
  141      * Use {@link QueryParser#setDefaultOperator} to change it.
  142      */
  143     static public final class Operator extends Parameter {
  144       private Operator(String name) {
  145         super(name);
  146       }
  147       static public final Operator OR = new Operator("OR");
  148       static public final Operator AND = new Operator("AND");
  149     }
  150   
  151   
  152     /** Constructs a query parser.
  153      *  @param f  the default field for query terms.
  154      *  @param a   used to find terms in the query text.
  155      */
  156     public QueryParser(String f, Analyzer a) {
  157       this(new FastCharStream(new StringReader("")));
  158       analyzer = a;
  159       field = f;
  160     }
  161   
  162     /** Parses a query string, returning a {@link org.apache.lucene.search.Query}.
  163      *  @param query  the query string to be parsed.
  164      *  @throws ParseException if the parsing fails
  165      */
  166     public Query parse(String query) throws ParseException {
  167       ReInit(new FastCharStream(new StringReader(query)));
  168       try {
  169         // TopLevelQuery is a Query followed by the end-of-input (EOF)
  170         Query res = TopLevelQuery(field);
  171         return res!=null ? res : newBooleanQuery(false);
  172       }
  173       catch (ParseException tme) {
  174         // rethrow to include the original query:
  175         throw new ParseException("Cannot parse '" +query+ "': " + tme.getMessage());
  176       }
  177       catch (TokenMgrError tme) {
  178         throw new ParseException("Cannot parse '" +query+ "': " + tme.getMessage());
  179       }
  180       catch (BooleanQuery.TooManyClauses tmc) {
  181         throw new ParseException("Cannot parse '" +query+ "': too many boolean clauses");
  182       }
  183     }
  184   
  185      /**
  186      * @return Returns the analyzer.
  187      */
  188     public Analyzer getAnalyzer() {
  189       return analyzer;
  190     }
  191   
  192     /**
  193      * @return Returns the field.
  194      */
  195     public String getField() {
  196       return field;
  197     }
  198   
  199      /**
  200      * Get the minimal similarity for fuzzy queries.
  201      */
  202     public float getFuzzyMinSim() {
  203         return fuzzyMinSim;
  204     }
  205   
  206     /**
  207      * Set the minimum similarity for fuzzy queries.
  208      * Default is 0.5f.
  209      */
  210     public void setFuzzyMinSim(float fuzzyMinSim) {
  211         this.fuzzyMinSim = fuzzyMinSim;
  212     }
  213   
  214      /**
  215      * Get the prefix length for fuzzy queries. 
  216      * @return Returns the fuzzyPrefixLength.
  217      */
  218     public int getFuzzyPrefixLength() {
  219       return fuzzyPrefixLength;
  220     }
  221   
  222     /**
  223      * Set the prefix length for fuzzy queries. Default is 0.
  224      * @param fuzzyPrefixLength The fuzzyPrefixLength to set.
  225      */
  226     public void setFuzzyPrefixLength(int fuzzyPrefixLength) {
  227       this.fuzzyPrefixLength = fuzzyPrefixLength;
  228     }
  229   
  230     /**
  231      * Sets the default slop for phrases.  If zero, then exact phrase matches
  232      * are required.  Default value is zero.
  233      */
  234     public void setPhraseSlop(int phraseSlop) {
  235       this.phraseSlop = phraseSlop;
  236     }
  237   
  238     /**
  239      * Gets the default slop for phrases.
  240      */
  241     public int getPhraseSlop() {
  242       return phraseSlop;
  243     }
  244   
  245   
  246     /**
  247      * Set to <code>true</code> to allow leading wildcard characters.
  248      * <p>
  249      * When set, <code>*</code> or <code>?</code> are allowed as 
  250      * the first character of a PrefixQuery and WildcardQuery.
  251      * Note that this can produce very slow
  252      * queries on big indexes. 
  253      * <p>
  254      * Default: false.
  255      */
  256     public void setAllowLeadingWildcard(boolean allowLeadingWildcard) {
  257       this.allowLeadingWildcard = allowLeadingWildcard;
  258     }
  259   
  260     /**
  261      * @see #setAllowLeadingWildcard(boolean)
  262      */
  263     public boolean getAllowLeadingWildcard() {
  264       return allowLeadingWildcard;
  265     }
  266   
  267     /**
  268      * Set to <code>true</code> to enable position increments in result query.
  269      * <p>
  270      * When set, result phrase and multi-phrase queries will
  271      * be aware of position increments.
  272      * Useful when e.g. a StopFilter increases the position increment of
  273      * the token that follows an omitted token.
  274      * <p>
  275      * Default: false.
  276      */
  277     public void setEnablePositionIncrements(boolean enable) {
  278       this.enablePositionIncrements = enable;
  279     }
  280   
  281     /**
  282      * @see #setEnablePositionIncrements(boolean)
  283      */
  284     public boolean getEnablePositionIncrements() {
  285       return enablePositionIncrements;
  286     }
  287   
  288     /**
  289      * Sets the boolean operator of the QueryParser.
  290      * In default mode (<code>OR_OPERATOR</code>) terms without any modifiers
  291      * are considered optional: for example <code>capital of Hungary</code> is equal to
  292      * <code>capital OR of OR Hungary</code>.<br/>
  293      * In <code>AND_OPERATOR</code> mode terms are considered to be in conjunction: the
  294      * above mentioned query is parsed as <code>capital AND of AND Hungary</code>
  295      */
  296     public void setDefaultOperator(Operator op) {
  297       this.operator = op;
  298     }
  299   
  300   
  301     /**
  302      * Gets implicit operator setting, which will be either AND_OPERATOR
  303      * or OR_OPERATOR.
  304      */
  305     public Operator getDefaultOperator() {
  306       return operator;
  307     }
  308   
  309   
  310     /**
  311      * Whether terms of wildcard, prefix, fuzzy and range queries are to be automatically
  312      * lower-cased or not.  Default is <code>true</code>.
  313      */
  314     public void setLowercaseExpandedTerms(boolean lowercaseExpandedTerms) {
  315       this.lowercaseExpandedTerms = lowercaseExpandedTerms;
  316     }
  317   
  318   
  319     /**
  320      * @see #setLowercaseExpandedTerms(boolean)
  321      */
  322     public boolean getLowercaseExpandedTerms() {
  323       return lowercaseExpandedTerms;
  324     }
  325   
  326     /**
  327      * By default QueryParser uses new ConstantScoreRangeQuery in preference to RangeQuery
  328      * for range queries. This implementation is generally preferable because it 
  329      * a) Runs faster b) Does not have the scarcity of range terms unduly influence score 
  330      * c) avoids any "TooManyBooleanClauses" exception.
  331      * However, if your application really needs to use the old-fashioned RangeQuery and the above
  332      * points are not required then set this option to <code>true</code>
  333      * Default is <code>false</code>.
  334      */
  335     public void setUseOldRangeQuery(boolean useOldRangeQuery) {
  336       this.useOldRangeQuery = useOldRangeQuery;
  337     }
  338   
  339   
  340     /**
  341      * @see #setUseOldRangeQuery(boolean)
  342      */
  343     public boolean getUseOldRangeQuery() {
  344       return useOldRangeQuery;
  345     }
  346   
  347     /**
  348      * Set locale used by date range parsing.
  349      */
  350     public void setLocale(Locale locale) {
  351       this.locale = locale;
  352     }
  353   
  354     /**
  355      * Returns current locale, allowing access by subclasses.
  356      */
  357     public Locale getLocale() {
  358       return locale;
  359     }
  360   
  361     /**
  362      * Sets the default date resolution used by RangeQueries for fields for which no
  363      * specific date resolutions has been set. Field specific resolutions can be set
  364      * with {@link #setDateResolution(String, DateTools.Resolution)}.
  365      *  
  366      * @param dateResolution the default date resolution to set
  367      */
  368     public void setDateResolution(DateTools.Resolution dateResolution) {
  369       this.dateResolution = dateResolution;
  370     }
  371   
  372     /**
  373      * Sets the date resolution used by RangeQueries for a specific field.
  374      *  
  375      * @param fieldName field for which the date resolution is to be set 
  376      * @param dateResolution date resolution to set
  377      */
  378     public void setDateResolution(String fieldName, DateTools.Resolution dateResolution) {
  379       if (fieldName == null) {
  380         throw new IllegalArgumentException("Field cannot be null.");
  381       }
  382   
  383       if (fieldToDateResolution == null) {
  384         // lazily initialize HashMap
  385         fieldToDateResolution = new HashMap();
  386       }
  387   
  388       fieldToDateResolution.put(fieldName, dateResolution);
  389     }
  390   
  391     /**
  392      * Returns the date resolution that is used by RangeQueries for the given field. 
  393      * Returns null, if no default or field specific date resolution has been set
  394      * for the given field.
  395      *
  396      */
  397     public DateTools.Resolution getDateResolution(String fieldName) {
  398       if (fieldName == null) {
  399         throw new IllegalArgumentException("Field cannot be null.");
  400       }
  401   
  402       if (fieldToDateResolution == null) {
  403         // no field specific date resolutions set; return default date resolution instead
  404         return this.dateResolution;
  405       }
  406   
  407       DateTools.Resolution resolution = (DateTools.Resolution) fieldToDateResolution.get(fieldName);
  408       if (resolution == null) {
  409         // no date resolutions set for the given field; return default date resolution instead
  410         resolution = this.dateResolution;
  411       }
  412   
  413       return resolution;
  414     }
  415   
  416     /** 
  417      * Sets the collator used to determine index term inclusion in ranges
  418      * specified either for ConstantScoreRangeQuerys or RangeQuerys (if
  419      * {@link #setUseOldRangeQuery(boolean)} is called with a <code>true</code>
  420      * value.)
  421      * <p/>
  422      * <strong>WARNING:</strong> Setting the rangeCollator to a non-null
  423      * collator using this method will cause every single index Term in the
  424      * Field referenced by lowerTerm and/or upperTerm to be examined.
  425      * Depending on the number of index Terms in this Field, the operation could
  426      * be very slow.
  427      *
  428      *  @param rc  the collator to use when constructing RangeQuerys
  429      *             and ConstantScoreRangeQuerys
  430      */
  431     public void setRangeCollator(Collator rc) {
  432       rangeCollator = rc;
  433     }
  434   
  435     /**
  436      * @return the collator used to determine index term inclusion in ranges
  437      *  specified either for ConstantScoreRangeQuerys or RangeQuerys (if
  438      *  {@link #setUseOldRangeQuery(boolean)} is called with a <code>true</code>
  439      *  value.)
  440      */
  441     public Collator getRangeCollator() {
  442       return rangeCollator;
  443     }
  444   
  445     /**
  446      * @deprecated use {@link #addClause(List, int, int, Query)} instead.
  447      */
  448     protected void addClause(Vector clauses, int conj, int mods, Query q) {
  449       addClause((List) clauses, conj, mods, q);
  450     }
  451   
  452     protected void addClause(List clauses, int conj, int mods, Query q) {
  453       boolean required, prohibited;
  454   
  455       // If this term is introduced by AND, make the preceding term required,
  456       // unless it's already prohibited
  457       if (clauses.size() > 0 && conj == CONJ_AND) {
  458         BooleanClause c = (BooleanClause) clauses.get(clauses.size()-1);
  459         if (!c.isProhibited())
  460           c.setOccur(BooleanClause.Occur.MUST);
  461       }
  462   
  463       if (clauses.size() > 0 && operator == AND_OPERATOR && conj == CONJ_OR) {
  464         // If this term is introduced by OR, make the preceding term optional,
  465         // unless it's prohibited (that means we leave -a OR b but +a OR b-->a OR b)
  466         // notice if the input is a OR b, first term is parsed as required; without
  467         // this modification a OR b would parsed as +a OR b
  468         BooleanClause c = (BooleanClause) clauses.get(clauses.size()-1);
  469         if (!c.isProhibited())
  470           c.setOccur(BooleanClause.Occur.SHOULD);
  471       }
  472   
  473       // We might have been passed a null query; the term might have been
  474       // filtered away by the analyzer.
  475       if (q == null)
  476         return;
  477   
  478       if (operator == OR_OPERATOR) {
  479         // We set REQUIRED if we're introduced by AND or +; PROHIBITED if
  480         // introduced by NOT or -; make sure not to set both.
  481         prohibited = (mods == MOD_NOT);
  482         required = (mods == MOD_REQ);
  483         if (conj == CONJ_AND && !prohibited) {
  484           required = true;
  485         }
  486       } else {
  487         // We set PROHIBITED if we're introduced by NOT or -; We set REQUIRED
  488         // if not PROHIBITED and not introduced by OR
  489         prohibited = (mods == MOD_NOT);
  490         required   = (!prohibited && conj != CONJ_OR);
  491       }
  492       if (required && !prohibited)
  493         clauses.add(newBooleanClause(q, BooleanClause.Occur.MUST));
  494       else if (!required && !prohibited)
  495         clauses.add(newBooleanClause(q, BooleanClause.Occur.SHOULD));
  496       else if (!required && prohibited)
  497         clauses.add(newBooleanClause(q, BooleanClause.Occur.MUST_NOT));
  498       else
  499         throw new RuntimeException("Clause cannot be both required and prohibited");
  500     }
  501   
  502   
  503     /**
  504      * @exception ParseException throw in overridden method to disallow
  505      */
  506     protected Query getFieldQuery(String field, String queryText)  throws ParseException {
  507       // Use the analyzer to get all the tokens, and then build a TermQuery,
  508       // PhraseQuery, or nothing based on the term count
  509   
  510       TokenStream source = analyzer.tokenStream(field, new StringReader(queryText));
  511       List list = new ArrayList();
  512       final org.apache.lucene.analysis.Token reusableToken = new org.apache.lucene.analysis.Token();
  513       org.apache.lucene.analysis.Token nextToken;
  514       int positionCount = 0;
  515       boolean severalTokensAtSamePosition = false;
  516   
  517       while (true) {
  518         try {
  519           nextToken = source.next(reusableToken);
  520         }
  521         catch (IOException e) {
  522           nextToken = null;
  523         }
  524         if (nextToken == null)
  525           break;
  526         list.add(nextToken.clone());
  527         if (nextToken.getPositionIncrement() != 0)
  528           positionCount += nextToken.getPositionIncrement();
  529         else
  530           severalTokensAtSamePosition = true;
  531       }
  532       try {
  533         source.close();
  534       }
  535       catch (IOException e) {
  536         // ignore
  537       }
  538   
  539       if (list.size() == 0)
  540         return null;
  541       else if (list.size() == 1) {
  542         nextToken = (org.apache.lucene.analysis.Token) list.get(0);
  543         return newTermQuery(new Term(field, nextToken.term()));
  544       } else {
  545         if (severalTokensAtSamePosition) {
  546           if (positionCount == 1) {
  547             // no phrase query:
  548             BooleanQuery q = newBooleanQuery(true);
  549             for (int i = 0; i < list.size(); i++) {
  550               nextToken = (org.apache.lucene.analysis.Token) list.get(i);
  551               Query currentQuery = newTermQuery(
  552                   new Term(field, nextToken.term()));
  553               q.add(currentQuery, BooleanClause.Occur.SHOULD);
  554             }
  555             return q;
  556           }
  557           else {
  558             // phrase query:
  559             MultiPhraseQuery mpq = newMultiPhraseQuery();
  560             mpq.setSlop(phraseSlop);
  561             List multiTerms = new ArrayList();
  562             int position = -1;
  563             for (int i = 0; i < list.size(); i++) {
  564               nextToken = (org.apache.lucene.analysis.Token) list.get(i);
  565               if (nextToken.getPositionIncrement() > 0 && multiTerms.size() > 0) {
  566                 if (enablePositionIncrements) {
  567                   mpq.add((Term[])multiTerms.toArray(new Term[0]),position);
  568                 } else {
  569                   mpq.add((Term[])multiTerms.toArray(new Term[0]));
  570                 }
  571                 multiTerms.clear();
  572               }
  573               position += nextToken.getPositionIncrement();
  574               multiTerms.add(new Term(field, nextToken.term()));
  575             }
  576             if (enablePositionIncrements) {
  577               mpq.add((Term[])multiTerms.toArray(new Term[0]),position);
  578             } else {
  579               mpq.add((Term[])multiTerms.toArray(new Term[0]));
  580             }
  581             return mpq;
  582           }
  583         }
  584         else {
  585           PhraseQuery pq = newPhraseQuery();
  586           pq.setSlop(phraseSlop);
  587           int position = -1;
  588           for (int i = 0; i < list.size(); i++) {
  589             nextToken = (org.apache.lucene.analysis.Token) list.get(i);
  590             if (enablePositionIncrements) {
  591               position += nextToken.getPositionIncrement();
  592               pq.add(new Term(field, nextToken.term()),position);
  593             } else {
  594               pq.add(new Term(field, nextToken.term()));
  595             }
  596           }
  597           return pq;
  598         }
  599       }
  600     }
  601   
  602   
  603     /**
  604      * Base implementation delegates to {@link #getFieldQuery(String,String)}.
  605      * This method may be overridden, for example, to return
  606      * a SpanNearQuery instead of a PhraseQuery.
  607      *
  608      * @exception ParseException throw in overridden method to disallow
  609      */
  610     protected Query getFieldQuery(String field, String queryText, int slop)
  611           throws ParseException {
  612       Query query = getFieldQuery(field, queryText);
  613   
  614       if (query instanceof PhraseQuery) {
  615         ((PhraseQuery) query).setSlop(slop);
  616       }
  617       if (query instanceof MultiPhraseQuery) {
  618         ((MultiPhraseQuery) query).setSlop(slop);
  619       }
  620   
  621       return query;
  622     }
  623   
  624   
  625     /**
  626      * @exception ParseException throw in overridden method to disallow
  627      */
  628     protected Query getRangeQuery(String field,
  629                                   String part1,
  630                                   String part2,
  631                                   boolean inclusive) throws ParseException
  632     {
  633       if (lowercaseExpandedTerms) {
  634         part1 = part1.toLowerCase();
  635         part2 = part2.toLowerCase();
  636       }
  637       try {
  638         DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
  639         df.setLenient(true);
  640         Date d1 = df.parse(part1);
  641         Date d2 = df.parse(part2);
  642         if (inclusive) {
  643           // The user can only specify the date, not the time, so make sure
  644           // the time is set to the latest possible time of that date to really
  645           // include all documents:
  646           Calendar cal = Calendar.getInstance(locale);
  647           cal.setTime(d2);
  648           cal.set(Calendar.HOUR_OF_DAY, 23);
  649           cal.set(Calendar.MINUTE, 59);
  650           cal.set(Calendar.SECOND, 59);
  651           cal.set(Calendar.MILLISECOND, 999);
  652           d2 = cal.getTime();
  653         }
  654         DateTools.Resolution resolution = getDateResolution(field);
  655         if (resolution == null) {
  656           // no default or field specific date resolution has been set,
  657           // use deprecated DateField to maintain compatibilty with
  658           // pre-1.9 Lucene versions.
  659           part1 = DateField.dateToString(d1);
  660           part2 = DateField.dateToString(d2);
  661         } else {
  662           part1 = DateTools.dateToString(d1, resolution);
  663           part2 = DateTools.dateToString(d2, resolution);
  664         }
  665       }
  666       catch (Exception e) { }
  667   
  668       return newRangeQuery(field, part1, part2, inclusive);
  669     }
  670   
  671    /**
  672     * Builds a new BooleanQuery instance
  673     * @param disableCoord disable coord
  674     * @return new BooleanQuery instance
  675     */
  676     protected BooleanQuery newBooleanQuery(boolean disableCoord) {
  677       return new BooleanQuery(disableCoord);
  678     }
  679   
  680    /**
  681     * Builds a new BooleanClause instance
  682     * @param q sub query
  683     * @param occur how this clause should occur when matching documents
  684     * @return new BooleanClause instance
  685     */
  686     protected BooleanClause newBooleanClause(Query q, BooleanClause.Occur occur) {
  687       return new BooleanClause(q, occur);
  688     }
  689   
  690     /**
  691      * Builds a new TermQuery instance
  692      * @param term term
  693      * @return new TermQuery instance
  694      */
  695     protected Query newTermQuery(Term term){
  696       return new TermQuery(term);
  697     }
  698   
  699     /**
  700      * Builds a new PhraseQuery instance
  701      * @return new PhraseQuery instance
  702      */
  703     protected PhraseQuery newPhraseQuery(){
  704       return new PhraseQuery();
  705     }
  706   
  707     /**
  708      * Builds a new MultiPhraseQuery instance
  709      * @return new MultiPhraseQuery instance
  710      */
  711     protected MultiPhraseQuery newMultiPhraseQuery(){
  712       return new MultiPhraseQuery();
  713     }
  714   
  715     /**
  716      * Builds a new PrefixQuery instance
  717      * @param prefix Prefix term
  718      * @return new PrefixQuery instance
  719      */
  720     protected Query newPrefixQuery(Term prefix){
  721       return new PrefixQuery(prefix);
  722     }
  723   
  724     /**
  725      * Builds a new FuzzyQuery instance
  726      * @param term Term
  727      * @param minimumSimilarity minimum similarity
  728      * @param prefixLength prefix length
  729      * @return new FuzzyQuery Instance
  730      */
  731     protected Query newFuzzyQuery(Term term, float minimumSimilarity, int prefixLength) {
  732       return new FuzzyQuery(term,minimumSimilarity,prefixLength);
  733     }
  734   
  735     /**
  736      * Builds a new RangeQuery instance
  737      * @param field Field
  738      * @param part1 min
  739      * @param part2 max
  740      * @param inclusive true if range is inclusive
  741      * @return new RangeQuery instance
  742      */
  743     protected Query newRangeQuery(String field, String part1, String part2, boolean inclusive) {
  744       if(useOldRangeQuery)
  745       {
  746         return new RangeQuery(new Term(field, part1),
  747                               new Term(field, part2),
  748                               inclusive, rangeCollator);
  749       }
  750       else
  751       {
  752         return new ConstantScoreRangeQuery
  753           (field, part1, part2, inclusive, inclusive, rangeCollator);
  754       }
  755     }
  756   
  757     /**
  758      * Builds a new MatchAllDocsQuery instance
  759      * @return new MatchAllDocsQuery instance
  760      */
  761     protected Query newMatchAllDocsQuery() {
  762       return new MatchAllDocsQuery();
  763     }
  764   
  765     /**
  766      * Builds a new WildcardQuery instance
  767      * @param t wildcard term
  768      * @return new WildcardQuery instance
  769      */
  770     protected Query newWildcardQuery(Term t) {
  771       return new WildcardQuery(t);
  772     }
  773   
  774     /**
  775      * Factory method for generating query, given a set of clauses.
  776      * By default creates a boolean query composed of clauses passed in.
  777      *
  778      * Can be overridden by extending classes, to modify query being
  779      * returned.
  780      *
  781      * @param clauses List that contains {@link BooleanClause} instances
  782      *    to join.
  783      *
  784      * @return Resulting {@link Query} object.
  785      * @exception ParseException throw in overridden method to disallow
  786      * @deprecated use {@link #getBooleanQuery(List)} instead
  787      */
  788     protected Query getBooleanQuery(Vector clauses) throws ParseException {
  789       return getBooleanQuery((List) clauses, false);
  790     }
  791   
  792     /**
  793      * Factory method for generating query, given a set of clauses.
  794      * By default creates a boolean query composed of clauses passed in.
  795      *
  796      * Can be overridden by extending classes, to modify query being
  797      * returned.
  798      *
  799      * @param clauses List that contains {@link BooleanClause} instances
  800      *    to join.
  801      *
  802      * @return Resulting {@link Query} object.
  803      * @exception ParseException throw in overridden method to disallow
  804      */
  805     protected Query getBooleanQuery(List clauses) throws ParseException {
  806       return getBooleanQuery(clauses, false);
  807     }
  808   
  809     /**
  810      * Factory method for generating query, given a set of clauses.
  811      * By default creates a boolean query composed of clauses passed in.
  812      *
  813      * Can be overridden by extending classes, to modify query being
  814      * returned.
  815      *
  816      * @param clauses List that contains {@link BooleanClause} instances
  817      *    to join.
  818      * @param disableCoord true if coord scoring should be disabled.
  819      *
  820      * @return Resulting {@link Query} object.
  821      * @exception ParseException throw in overridden method to disallow
  822      * @deprecated use {@link #getBooleanQuery(List, boolean)} instead
  823      */
  824     protected Query getBooleanQuery(Vector clauses, boolean disableCoord)
  825       throws ParseException
  826     {
  827       return getBooleanQuery((List) clauses, disableCoord);
  828     }
  829   
  830     /**
  831      * Factory method for generating query, given a set of clauses.
  832      * By default creates a boolean query composed of clauses passed in.
  833      *
  834      * Can be overridden by extending classes, to modify query being
  835      * returned.
  836      *
  837      * @param clauses List that contains {@link BooleanClause} instances
  838      *    to join.
  839      * @param disableCoord true if coord scoring should be disabled.
  840      *
  841      * @return Resulting {@link Query} object.
  842      * @exception ParseException throw in overridden method to disallow
  843      */
  844     protected Query getBooleanQuery(List clauses, boolean disableCoord)
  845       throws ParseException
  846     {
  847       if (clauses.size()==0) {
  848         return null; // all clause words were filtered away by the analyzer.
  849       }
  850       BooleanQuery query = newBooleanQuery(disableCoord);
  851       for (int i = 0; i < clauses.size(); i++) {
  852         query.add((BooleanClause)clauses.get(i));
  853       }
  854       return query;
  855     }
  856   
  857     /**
  858      * Factory method for generating a query. Called when parser
  859      * parses an input term token that contains one or more wildcard
  860      * characters (? and *), but is not a prefix term token (one
  861      * that has just a single * character at the end)
  862      *<p>
  863      * Depending on settings, prefix term may be lower-cased
  864      * automatically. It will not go through the default Analyzer,
  865      * however, since normal Analyzers are unlikely to work properly
  866      * with wildcard templates.
  867      *<p>
  868      * Can be overridden by extending classes, to provide custom handling for
  869      * wildcard queries, which may be necessary due to missing analyzer calls.
  870      *
  871      * @param field Name of the field query will use.
  872      * @param termStr Term token that contains one or more wild card
  873      *   characters (? or *), but is not simple prefix term
  874      *
  875      * @return Resulting {@link Query} built for the term
  876      * @exception ParseException throw in overridden method to disallow
  877      */
  878     protected Query getWildcardQuery(String field, String termStr) throws ParseException
  879     {
  880       if ("*".equals(field)) {
  881         if ("*".equals(termStr)) return newMatchAllDocsQuery();
  882       }
  883       if (!allowLeadingWildcard && (termStr.startsWith("*") || termStr.startsWith("?")))
  884         throw new ParseException("'*' or '?' not allowed as first character in WildcardQuery");
  885       if (lowercaseExpandedTerms) {
  886         termStr = termStr.toLowerCase();
  887       }
  888       Term t = new Term(field, termStr);
  889       return newWildcardQuery(t);
  890     }
  891   
  892     /**
  893      * Factory method for generating a query (similar to
  894      * {@link #getWildcardQuery}). Called when parser parses an input term
  895      * token that uses prefix notation; that is, contains a single '*' wildcard
  896      * character as its last character. Since this is a special case
  897      * of generic wildcard term, and such a query can be optimized easily,
  898      * this usually results in a different query object.
  899      *<p>
  900      * Depending on settings, a prefix term may be lower-cased
  901      * automatically. It will not go through the default Analyzer,
  902      * however, since normal Analyzers are unlikely to work properly
  903      * with wildcard templates.
  904      *<p>
  905      * Can be overridden by extending classes, to provide custom handling for
  906      * wild card queries, which may be necessary due to missing analyzer calls.
  907      *
  908      * @param field Name of the field query will use.
  909      * @param termStr Term token to use for building term for the query
  910      *    (<b>without</b> trailing '*' character!)
  911      *
  912      * @return Resulting {@link Query} built for the term
  913      * @exception ParseException throw in overridden method to disallow
  914      */
  915     protected Query getPrefixQuery(String field, String termStr) throws ParseException
  916     {
  917       if (!allowLeadingWildcard && termStr.startsWith("*"))
  918         throw new ParseException("'*' not allowed as first character in PrefixQuery");
  919       if (lowercaseExpandedTerms) {
  920         termStr = termStr.toLowerCase();
  921       }
  922       Term t = new Term(field, termStr);
  923       return newPrefixQuery(t);
  924     }
  925   
  926      /**
  927      * Factory method for generating a query (similar to
  928      * {@link #getWildcardQuery}). Called when parser parses
  929      * an input term token that has the fuzzy suffix (~) appended.
  930      *
  931      * @param field Name of the field query will use.
  932      * @param termStr Term token to use for building term for the query
  933      *
  934      * @return Resulting {@link Query} built for the term
  935      * @exception ParseException throw in overridden method to disallow
  936      */
  937     protected Query getFuzzyQuery(String field, String termStr, float minSimilarity) throws ParseException
  938     {
  939       if (lowercaseExpandedTerms) {
  940         termStr = termStr.toLowerCase();
  941       }
  942       Term t = new Term(field, termStr);
  943       return newFuzzyQuery(t, minSimilarity, fuzzyPrefixLength);
  944     }
  945   
  946     /**
  947      * Returns a String where the escape char has been
  948      * removed, or kept only once if there was a double escape.
  949      * 
  950      * Supports escaped unicode characters, e. g. translates
  951      * <code>\\u0041</code> to <code>A</code>.
  952      * 
  953      */
  954     private String discardEscapeChar(String input) throws ParseException {
  955       // Create char array to hold unescaped char sequence
  956       char[] output = new char[input.length()];
  957   
  958       // The length of the output can be less than the input
  959       // due to discarded escape chars. This variable holds
  960       // the actual length of the output
  961       int length = 0;
  962   
  963       // We remember whether the last processed character was 
  964       // an escape character
  965       boolean lastCharWasEscapeChar = false;
  966   
  967       // The multiplier the current unicode digit must be multiplied with.
  968       // E. g. the first digit must be multiplied with 16^3, the second with 16^2...
  969       int codePointMultiplier = 0;
  970   
  971       // Used to calculate the codepoint of the escaped unicode character
  972       int codePoint = 0;
  973   
  974       for (int i = 0; i < input.length(); i++) {
  975         char curChar = input.charAt(i);
  976         if (codePointMultiplier > 0) {
  977           codePoint += hexToInt(curChar) * codePointMultiplier;
  978           codePointMultiplier >>>= 4;
  979           if (codePointMultiplier == 0) {
  980             output[length++] = (char)codePoint;
  981             codePoint = 0;
  982           }
  983         } else if (lastCharWasEscapeChar) {
  984           if (curChar == 'u') {
  985             // found an escaped unicode character
  986             codePointMultiplier = 16 * 16 * 16;
  987           } else {
  988             // this character was escaped
  989             output[length] = curChar;
  990             length++;
  991           }
  992           lastCharWasEscapeChar = false;
  993         } else {
  994           if (curChar == '\\') {
  995             lastCharWasEscapeChar = true;
  996           } else {
  997             output[length] = curChar;
  998             length++;
  999           }
 1000         }
 1001       }
 1002   
 1003       if (codePointMultiplier > 0) {
 1004         throw new ParseException("Truncated unicode escape sequence.");
 1005       }
 1006   
 1007       if (lastCharWasEscapeChar) {
 1008         throw new ParseException("Term can not end with escape character.");
 1009       }
 1010   
 1011       return new String(output, 0, length);
 1012     }
 1013   
 1014     /** Returns the numeric value of the hexadecimal character */
 1015     private static final int hexToInt(char c) throws ParseException {
 1016       if ('0' <= c && c <= '9') {
 1017         return c - '0';
 1018       } else if ('a' <= c && c <= 'f'){
 1019         return c - 'a' + 10;
 1020       } else if ('A' <= c && c <= 'F') {
 1021         return c - 'A' + 10;
 1022       } else {
 1023         throw new ParseException("None-hex character in unicode escape sequence: " + c);
 1024       }
 1025     }
 1026   
 1027     /**
 1028      * Returns a String where those characters that QueryParser
 1029      * expects to be escaped are escaped by a preceding <code>\</code>.
 1030      */
 1031     public static String escape(String s) {
 1032       StringBuffer sb = new StringBuffer();
 1033       for (int i = 0; i < s.length(); i++) {
 1034         char c = s.charAt(i);
 1035         // These characters are part of the query syntax and must be escaped
 1036         if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':'
 1037           || c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~'
 1038           || c == '*' || c == '?' || c == '|' || c == '&') {
 1039           sb.append('\\');
 1040         }
 1041         sb.append(c);
 1042       }
 1043       return sb.toString();
 1044     }
 1045   
 1046     /**
 1047      * Command line tool to test QueryParser, using {@link org.apache.lucene.analysis.SimpleAnalyzer}.
 1048      * Usage:<br>
 1049      * <code>java org.apache.lucene.queryParser.QueryParser &lt;input&gt;</code>
 1050      */
 1051     public static void main(String[] args) throws Exception {
 1052       if (args.length == 0) {
 1053         System.out.println("Usage: java org.apache.lucene.queryParser.QueryParser <input>");
 1054         System.exit(0);
 1055       }
 1056       QueryParser qp = new QueryParser("field",
 1057                              new org.apache.lucene.analysis.SimpleAnalyzer());
 1058       Query q = qp.parse(args[0]);
 1059       System.out.println(q.toString("field"));
 1060     }
 1061   
 1062   // *   Query  ::= ( Clause )*
 1063   // *   Clause ::= ["+", "-"] [<TERM> ":"] ( <TERM> | "(" Query ")" )
 1064     final public int Conjunction() throws ParseException {
 1065     int ret = CONJ_NONE;
 1066       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1067       case AND:
 1068       case OR:
 1069         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1070         case AND:
 1071           jj_consume_token(AND);
 1072               ret = CONJ_AND;
 1073           break;
 1074         case OR:
 1075           jj_consume_token(OR);
 1076                 ret = CONJ_OR;
 1077           break;
 1078         default:
 1079           jj_la1[0] = jj_gen;
 1080           jj_consume_token(-1);
 1081           throw new ParseException();
 1082         }
 1083         break;
 1084       default:
 1085         jj_la1[1] = jj_gen;
 1086         ;
 1087       }
 1088       {if (true) return ret;}
 1089       throw new Error("Missing return statement in function");
 1090     }
 1091   
 1092     final public int Modifiers() throws ParseException {
 1093     int ret = MOD_NONE;
 1094       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1095       case NOT:
 1096       case PLUS:
 1097       case MINUS:
 1098         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1099         case PLUS:
 1100           jj_consume_token(PLUS);
 1101                 ret = MOD_REQ;
 1102           break;
 1103         case MINUS:
 1104           jj_consume_token(MINUS);
 1105                    ret = MOD_NOT;
 1106           break;
 1107         case NOT:
 1108           jj_consume_token(NOT);
 1109                  ret = MOD_NOT;
 1110           break;
 1111         default:
 1112           jj_la1[2] = jj_gen;
 1113           jj_consume_token(-1);
 1114           throw new ParseException();
 1115         }
 1116         break;
 1117       default:
 1118         jj_la1[3] = jj_gen;
 1119         ;
 1120       }
 1121       {if (true) return ret;}
 1122       throw new Error("Missing return statement in function");
 1123     }
 1124   
 1125   // This makes sure that there is no garbage after the query string
 1126     final public Query TopLevelQuery(String field) throws ParseException {
 1127           Query q;
 1128       q = Query(field);
 1129       jj_consume_token(0);
 1130                   {if (true) return q;}
 1131       throw new Error("Missing return statement in function");
 1132     }
 1133   
 1134     final public Query Query(String field) throws ParseException {
 1135     List clauses = new ArrayList();
 1136     Query q, firstQuery=null;
 1137     int conj, mods;
 1138       mods = Modifiers();
 1139       q = Clause(field);
 1140       addClause(clauses, CONJ_NONE, mods, q);
 1141       if (mods == MOD_NONE)
 1142           firstQuery=q;
 1143       label_1:
 1144       while (true) {
 1145         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1146         case AND:
 1147         case OR:
 1148         case NOT:
 1149         case PLUS:
 1150         case MINUS:
 1151         case LPAREN:
 1152         case STAR:
 1153         case QUOTED:
 1154         case TERM:
 1155         case PREFIXTERM:
 1156         case WILDTERM:
 1157         case RANGEIN_START:
 1158         case RANGEEX_START:
 1159         case NUMBER:
 1160           ;
 1161           break;
 1162         default:
 1163           jj_la1[4] = jj_gen;
 1164           break label_1;
 1165         }
 1166         conj = Conjunction();
 1167         mods = Modifiers();
 1168         q = Clause(field);
 1169         addClause(clauses, conj, mods, q);
 1170       }
 1171         if (clauses.size() == 1 && firstQuery != null)
 1172           {if (true) return firstQuery;}
 1173         else {
 1174     {if (true) return getBooleanQuery(clauses);}
 1175         }
 1176       throw new Error("Missing return statement in function");
 1177     }
 1178   
 1179     final public Query Clause(String field) throws ParseException {
 1180     Query q;
 1181     Token fieldToken=null, boost=null;
 1182       if (jj_2_1(2)) {
 1183         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1184         case TERM:
 1185           fieldToken = jj_consume_token(TERM);
 1186           jj_consume_token(COLON);
 1187                                  field=discardEscapeChar(fieldToken.image);
 1188           break;
 1189         case STAR:
 1190           jj_consume_token(STAR);
 1191           jj_consume_token(COLON);
 1192                         field="*";
 1193           break;
 1194         default:
 1195           jj_la1[5] = jj_gen;
 1196           jj_consume_token(-1);
 1197           throw new ParseException();
 1198         }
 1199       } else {
 1200         ;
 1201       }
 1202       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1203       case STAR:
 1204       case QUOTED:
 1205       case TERM:
 1206       case PREFIXTERM:
 1207       case WILDTERM:
 1208       case RANGEIN_START:
 1209       case RANGEEX_START:
 1210       case NUMBER:
 1211         q = Term(field);
 1212         break;
 1213       case LPAREN:
 1214         jj_consume_token(LPAREN);
 1215         q = Query(field);
 1216         jj_consume_token(RPAREN);
 1217         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1218         case CARAT:
 1219           jj_consume_token(CARAT);
 1220           boost = jj_consume_token(NUMBER);
 1221           break;
 1222         default:
 1223           jj_la1[6] = jj_gen;
 1224           ;
 1225         }
 1226         break;
 1227       default:
 1228         jj_la1[7] = jj_gen;
 1229         jj_consume_token(-1);
 1230         throw new ParseException();
 1231       }
 1232         if (boost != null) {
 1233           float f = (float)1.0;
 1234     try {
 1235       f = Float.valueOf(boost.image).floatValue();
 1236             q.setBoost(f);
 1237     } catch (Exception ignored) { }
 1238         }
 1239         {if (true) return q;}
 1240       throw new Error("Missing return statement in function");
 1241     }
 1242   
 1243     final public Query Term(String field) throws ParseException {
 1244     Token term, boost=null, fuzzySlop=null, goop1, goop2;
 1245     boolean prefix = false;
 1246     boolean wildcard = false;
 1247     boolean fuzzy = false;
 1248     boolean rangein = false;
 1249     Query q;
 1250       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1251       case STAR:
 1252       case TERM:
 1253       case PREFIXTERM:
 1254       case WILDTERM:
 1255       case NUMBER:
 1256         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1257         case TERM:
 1258           term = jj_consume_token(TERM);
 1259           break;
 1260         case STAR:
 1261           term = jj_consume_token(STAR);
 1262                          wildcard=true;
 1263           break;
 1264         case PREFIXTERM:
 1265           term = jj_consume_token(PREFIXTERM);
 1266                                prefix=true;
 1267           break;
 1268         case WILDTERM:
 1269           term = jj_consume_token(WILDTERM);
 1270                              wildcard=true;
 1271           break;
 1272         case NUMBER:
 1273           term = jj_consume_token(NUMBER);
 1274           break;
 1275         default:
 1276           jj_la1[8] = jj_gen;
 1277           jj_consume_token(-1);
 1278           throw new ParseException();
 1279         }
 1280         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1281         case FUZZY_SLOP:
 1282           fuzzySlop = jj_consume_token(FUZZY_SLOP);
 1283                                   fuzzy=true;
 1284           break;
 1285         default:
 1286           jj_la1[9] = jj_gen;
 1287           ;
 1288         }
 1289         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1290         case CARAT:
 1291           jj_consume_token(CARAT);
 1292           boost = jj_consume_token(NUMBER);
 1293           switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1294           case FUZZY_SLOP:
 1295             fuzzySlop = jj_consume_token(FUZZY_SLOP);
 1296                                                            fuzzy=true;
 1297             break;
 1298           default:
 1299             jj_la1[10] = jj_gen;
 1300             ;
 1301           }
 1302           break;
 1303         default:
 1304           jj_la1[11] = jj_gen;
 1305           ;
 1306         }
 1307          String termImage=discardEscapeChar(term.image);
 1308          if (wildcard) {
 1309          q = getWildcardQuery(field, termImage);
 1310          } else if (prefix) {
 1311            q = getPrefixQuery(field,
 1312              discardEscapeChar(term.image.substring
 1313             (0, term.image.length()-1)));
 1314          } else if (fuzzy) {
 1315             float fms = fuzzyMinSim;
 1316             try {
 1317               fms = Float.valueOf(fuzzySlop.image.substring(1)).floatValue();
 1318             } catch (Exception ignored) { }
 1319            if(fms < 0.0f || fms > 1.0f){
 1320              {if (true) throw new ParseException("Minimum similarity for a FuzzyQuery has to be between 0.0f and 1.0f !");}
 1321            }
 1322            q = getFuzzyQuery(field, termImage,fms);
 1323          } else {
 1324            q = getFieldQuery(field, termImage);
 1325          }
 1326         break;
 1327       case RANGEIN_START:
 1328         jj_consume_token(RANGEIN_START);
 1329         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1330         case RANGEIN_GOOP:
 1331           goop1 = jj_consume_token(RANGEIN_GOOP);
 1332           break;
 1333         case RANGEIN_QUOTED:
 1334           goop1 = jj_consume_token(RANGEIN_QUOTED);
 1335           break;
 1336         default:
 1337           jj_la1[12] = jj_gen;
 1338           jj_consume_token(-1);
 1339           throw new ParseException();
 1340         }
 1341         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1342         case RANGEIN_TO:
 1343           jj_consume_token(RANGEIN_TO);
 1344           break;
 1345         default:
 1346           jj_la1[13] = jj_gen;
 1347           ;
 1348         }
 1349         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1350         case RANGEIN_GOOP:
 1351           goop2 = jj_consume_token(RANGEIN_GOOP);
 1352           break;
 1353         case RANGEIN_QUOTED:
 1354           goop2 = jj_consume_token(RANGEIN_QUOTED);
 1355           break;
 1356         default:
 1357           jj_la1[14] = jj_gen;
 1358           jj_consume_token(-1);
 1359           throw new ParseException();
 1360         }
 1361         jj_consume_token(RANGEIN_END);
 1362         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1363         case CARAT:
 1364           jj_consume_token(CARAT);
 1365           boost = jj_consume_token(NUMBER);
 1366           break;
 1367         default:
 1368           jj_la1[15] = jj_gen;
 1369           ;
 1370         }
 1371             if (goop1.kind == RANGEIN_QUOTED) {
 1372               goop1.image = goop1.image.substring(1, goop1.image.length()-1);
 1373             }
 1374             if (goop2.kind == RANGEIN_QUOTED) {
 1375               goop2.image = goop2.image.substring(1, goop2.image.length()-1);
 1376             }
 1377             q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), true);
 1378         break;
 1379       case RANGEEX_START:
 1380         jj_consume_token(RANGEEX_START);
 1381         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1382         case RANGEEX_GOOP:
 1383           goop1 = jj_consume_token(RANGEEX_GOOP);
 1384           break;
 1385         case RANGEEX_QUOTED:
 1386           goop1 = jj_consume_token(RANGEEX_QUOTED);
 1387           break;
 1388         default:
 1389           jj_la1[16] = jj_gen;
 1390           jj_consume_token(-1);
 1391           throw new ParseException();
 1392         }
 1393         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1394         case RANGEEX_TO:
 1395           jj_consume_token(RANGEEX_TO);
 1396           break;
 1397         default:
 1398           jj_la1[17] = jj_gen;
 1399           ;
 1400         }
 1401         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1402         case RANGEEX_GOOP:
 1403           goop2 = jj_consume_token(RANGEEX_GOOP);
 1404           break;
 1405         case RANGEEX_QUOTED:
 1406           goop2 = jj_consume_token(RANGEEX_QUOTED);
 1407           break;
 1408         default:
 1409           jj_la1[18] = jj_gen;
 1410           jj_consume_token(-1);
 1411           throw new ParseException();
 1412         }
 1413         jj_consume_token(RANGEEX_END);
 1414         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1415         case CARAT:
 1416           jj_consume_token(CARAT);
 1417           boost = jj_consume_token(NUMBER);
 1418           break;
 1419         default:
 1420           jj_la1[19] = jj_gen;
 1421           ;
 1422         }
 1423             if (goop1.kind == RANGEEX_QUOTED) {
 1424               goop1.image = goop1.image.substring(1, goop1.image.length()-1);
 1425             }
 1426             if (goop2.kind == RANGEEX_QUOTED) {
 1427               goop2.image = goop2.image.substring(1, goop2.image.length()-1);
 1428             }
 1429   
 1430             q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), false);
 1431         break;
 1432       case QUOTED:
 1433         term = jj_consume_token(QUOTED);
 1434         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1435         case FUZZY_SLOP:
 1436           fuzzySlop = jj_consume_token(FUZZY_SLOP);
 1437           break;
 1438         default:
 1439           jj_la1[20] = jj_gen;
 1440           ;
 1441         }
 1442         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
 1443         case CARAT:
 1444           jj_consume_token(CARAT);
 1445           boost = jj_consume_token(NUMBER);
 1446           break;
 1447         default:
 1448           jj_la1[21] = jj_gen;
 1449           ;
 1450         }
 1451            int s = phraseSlop;
 1452   
 1453            if (fuzzySlop != null) {
 1454              try {
 1455                s = Float.valueOf(fuzzySlop.image.substring(1)).intValue();
 1456              }
 1457              catch (Exception ignored) { }
 1458            }
 1459            q = getFieldQuery(field, discardEscapeChar(term.image.substring(1, term.image.length()-1)), s);
 1460         break;
 1461       default:
 1462         jj_la1[22] = jj_gen;
 1463         jj_consume_token(-1);
 1464         throw new ParseException();
 1465       }
 1466       if (boost != null) {
 1467         float f = (float) 1.0;
 1468         try {
 1469           f = Float.valueOf(boost.image).floatValue();
 1470         }
 1471         catch (Exception ignored) {
 1472       /* Should this be handled somehow? (defaults to "no boost", if
 1473        * boost number is invalid)
 1474        */
 1475         }
 1476   
 1477         // avoid boosting null queries, such as those caused by stop words
 1478         if (q != null) {
 1479           q.setBoost(f);
 1480         }
 1481       }
 1482       {if (true) return q;}
 1483       throw new Error("Missing return statement in function");
 1484     }
 1485   
 1486     private boolean jj_2_1(int xla) {
 1487       jj_la = xla; jj_lastpos = jj_scanpos = token;
 1488       try { return !jj_3_1(); }
 1489       catch(LookaheadSuccess ls) { return true; }
 1490       finally { jj_save(0, xla); }
 1491     }
 1492   
 1493     private boolean jj_3R_3() {
 1494       if (jj_scan_token(STAR)) return true;
 1495       if (jj_scan_token(COLON)) return true;
 1496       return false;
 1497     }
 1498   
 1499     private boolean jj_3R_2() {
 1500       if (jj_scan_token(TERM)) return true;
 1501       if (jj_scan_token(COLON)) return true;
 1502       return false;
 1503     }
 1504   
 1505     private boolean jj_3_1() {
 1506       Token xsp;
 1507       xsp = jj_scanpos;
 1508       if (jj_3R_2()) {
 1509       jj_scanpos = xsp;
 1510       if (jj_3R_3()) return true;
 1511       }
 1512       return false;
 1513     }
 1514   
 1515     /** Generated Token Manager. */
 1516     public QueryParserTokenManager token_source;
 1517     /** Current token. */
 1518     public Token token;
 1519     /** Next token. */
 1520     public Token jj_nt;
 1521     private int jj_ntk;
 1522     private Token jj_scanpos, jj_lastpos;
 1523     private int jj_la;
 1524     private int jj_gen;
 1525     final private int[] jj_la1 = new int[23];
 1526     static private int[] jj_la1_0;
 1527     static private int[] jj_la1_1;
 1528     static {
 1529         jj_la1_init_0();
 1530         jj_la1_init_1();
 1531      }
 1532      private static void jj_la1_init_0() {
 1533         jj_la1_0 = new int[] {0x300,0x300,0x1c00,0x1c00,0x3ed3f00,0x90000,0x20000,0x3ed2000,0x2690000,0x100000,0x100000,0x20000,0x30000000,0x4000000,0x30000000,0x20000,0x0,0x40000000,0x0,0x20000,0x100000,0x20000,0x3ed0000,};
 1534      }
 1535      private static void jj_la1_init_1() {
 1536         jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x0,0x3,0x0,0x0,0x0,0x0,};
 1537      }
 1538     final private JJCalls[] jj_2_rtns = new JJCalls[1];
 1539     private boolean jj_rescan = false;
 1540     private int jj_gc = 0;
 1541   
 1542     /** Constructor with user supplied CharStream. */
 1543     public QueryParser(CharStream stream) {
 1544       token_source = new QueryParserTokenManager(stream);
 1545       token = new Token();
 1546       jj_ntk = -1;
 1547       jj_gen = 0;
 1548       for (int i = 0; i < 23; i++) jj_la1[i] = -1;
 1549       for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
 1550     }
 1551   
 1552     /** Reinitialise. */
 1553     public void ReInit(CharStream stream) {
 1554       token_source.ReInit(stream);
 1555       token = new Token();
 1556       jj_ntk = -1;
 1557       jj_gen = 0;
 1558       for (int i = 0; i < 23; i++) jj_la1[i] = -1;
 1559       for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
 1560     }
 1561   
 1562     /** Constructor with generated Token Manager. */
 1563     public QueryParser(QueryParserTokenManager tm) {
 1564       token_source = tm;
 1565       token = new Token();
 1566       jj_ntk = -1;
 1567       jj_gen = 0;
 1568       for (int i = 0; i < 23; i++) jj_la1[i] = -1;
 1569       for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
 1570     }
 1571   
 1572     /** Reinitialise. */
 1573     public void ReInit(QueryParserTokenManager tm) {
 1574       token_source = tm;
 1575       token = new Token();
 1576       jj_ntk = -1;
 1577       jj_gen = 0;
 1578       for (int i = 0; i < 23; i++) jj_la1[i] = -1;
 1579       for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
 1580     }
 1581   
 1582     private Token jj_consume_token(int kind) throws ParseException {
 1583       Token oldToken;
 1584       if ((oldToken = token).next != null) token = token.next;
 1585       else token = token.next = token_source.getNextToken();
 1586       jj_ntk = -1;
 1587       if (token.kind == kind) {
 1588         jj_gen++;
 1589         if (++jj_gc > 100) {
 1590           jj_gc = 0;
 1591           for (int i = 0; i < jj_2_rtns.length; i++) {
 1592             JJCalls c = jj_2_rtns[i];
 1593             while (c != null) {
 1594               if (c.gen < jj_gen) c.first = null;
 1595               c = c.next;
 1596             }
 1597           }
 1598         }
 1599         return token;
 1600       }
 1601       token = oldToken;
 1602       jj_kind = kind;
 1603       throw generateParseException();
 1604     }
 1605   
 1606     static private final class LookaheadSuccess extends java.lang.Error { }
 1607     final private LookaheadSuccess jj_ls = new LookaheadSuccess();
 1608     private boolean jj_scan_token(int kind) {
 1609       if (jj_scanpos == jj_lastpos) {
 1610         jj_la--;
 1611         if (jj_scanpos.next == null) {
 1612           jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
 1613         } else {
 1614           jj_lastpos = jj_scanpos = jj_scanpos.next;
 1615         }
 1616       } else {
 1617         jj_scanpos = jj_scanpos.next;
 1618       }
 1619       if (jj_rescan) {
 1620         int i = 0; Token tok = token;
 1621         while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
 1622         if (tok != null) jj_add_error_token(kind, i);
 1623       }
 1624       if (jj_scanpos.kind != kind) return true;
 1625       if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
 1626       return false;
 1627     }
 1628   
 1629   
 1630   /** Get the next Token. */
 1631     final public Token getNextToken() {
 1632       if (token.next != null) token = token.next;
 1633       else token = token.next = token_source.getNextToken();
 1634       jj_ntk = -1;
 1635       jj_gen++;
 1636       return token;
 1637     }
 1638   
 1639   /** Get the specific Token. */
 1640     final public Token getToken(int index) {
 1641       Token t = token;
 1642       for (int i = 0; i < index; i++) {
 1643         if (t.next != null) t = t.next;
 1644         else t = t.next = token_source.getNextToken();
 1645       }
 1646       return t;
 1647     }
 1648   
 1649     private int jj_ntk() {
 1650       if ((jj_nt=token.next) == null)
 1651         return (jj_ntk = (token.next=token_source.getNextToken()).kind);
 1652       else
 1653         return (jj_ntk = jj_nt.kind);
 1654     }
 1655   
 1656     private java.util.List jj_expentries = new java.util.ArrayList();
 1657     private int[] jj_expentry;
 1658     private int jj_kind = -1;
 1659     private int[] jj_lasttokens = new int[100];
 1660     private int jj_endpos;
 1661   
 1662     private void jj_add_error_token(int kind, int pos) {
 1663       if (pos >= 100) return;
 1664       if (pos == jj_endpos + 1) {
 1665         jj_lasttokens[jj_endpos++] = kind;
 1666       } else if (jj_endpos != 0) {
 1667         jj_expentry = new int[jj_endpos];
 1668         for (int i = 0; i < jj_endpos; i++) {
 1669           jj_expentry[i] = jj_lasttokens[i];
 1670         }
 1671         jj_entries_loop: for (java.util.Iterator it = jj_expentries.iterator(); it.hasNext();) {
 1672           int[] oldentry = (int[])(it.next());
 1673           if (oldentry.length == jj_expentry.length) {
 1674             for (int i = 0; i < jj_expentry.length; i++) {
 1675               if (oldentry[i] != jj_expentry[i]) {
 1676                 continue jj_entries_loop;
 1677               }
 1678             }
 1679             jj_expentries.add(jj_expentry);
 1680             break jj_entries_loop;
 1681           }
 1682         }
 1683         if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
 1684       }
 1685     }
 1686   
 1687     /** Generate ParseException. */
 1688     public ParseException generateParseException() {
 1689       jj_expentries.clear();
 1690       boolean[] la1tokens = new boolean[34];
 1691       if (jj_kind >= 0) {
 1692         la1tokens[jj_kind] = true;
 1693         jj_kind = -1;
 1694       }
 1695       for (int i = 0; i < 23; i++) {
 1696         if (jj_la1[i] == jj_gen) {
 1697           for (int j = 0; j < 32; j++) {
 1698             if ((jj_la1_0[i] & (1<<j)) != 0) {
 1699               la1tokens[j] = true;
 1700             }
 1701             if ((jj_la1_1[i] & (1<<j)) != 0) {
 1702               la1tokens[32+j] = true;
 1703             }
 1704           }
 1705         }
 1706       }
 1707       for (int i = 0; i < 34; i++) {
 1708         if (la1tokens[i]) {
 1709           jj_expentry = new int[1];
 1710           jj_expentry[0] = i;
 1711           jj_expentries.add(jj_expentry);
 1712         }
 1713       }
 1714       jj_endpos = 0;
 1715       jj_rescan_token();
 1716       jj_add_error_token(0, 0);
 1717       int[][] exptokseq = new int[jj_expentries.size()][];
 1718       for (int i = 0; i < jj_expentries.size(); i++) {
 1719         exptokseq[i] = (int[])jj_expentries.get(i);
 1720       }
 1721       return new ParseException(token, exptokseq, tokenImage);
 1722     }
 1723   
 1724     /** Enable tracing. */
 1725     final public void enable_tracing() {
 1726     }
 1727   
 1728     /** Disable tracing. */
 1729     final public void disable_tracing() {
 1730     }
 1731   
 1732     private void jj_rescan_token() {
 1733       jj_rescan = true;
 1734       for (int i = 0; i < 1; i++) {
 1735       try {
 1736         JJCalls p = jj_2_rtns[i];
 1737         do {
 1738           if (p.gen > jj_gen) {
 1739             jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
 1740             switch (i) {
 1741               case 0: jj_3_1(); break;
 1742             }
 1743           }
 1744           p = p.next;
 1745         } while (p != null);
 1746         } catch(LookaheadSuccess ls) { }
 1747       }
 1748       jj_rescan = false;
 1749     }
 1750   
 1751     private void jj_save(int index, int xla) {
 1752       JJCalls p = jj_2_rtns[index];
 1753       while (p.gen > jj_gen) {
 1754         if (p.next == null) { p = p.next = new JJCalls(); break; }
 1755         p = p.next;
 1756       }
 1757       p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
 1758     }
 1759   
 1760     static final class JJCalls {
 1761       int gen;
 1762       Token first;
 1763       int arg;
 1764       JJCalls next;
 1765     }
 1766   
 1767   }

Save This Page
Home » lucene-2.4.1-src » org.apache » lucene » queryParser » [javadoc | source]