📄 queryparser.cs
字号:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JavaCC: Do not edit this line. QueryParser.java */
using System;
using Term = Lucene.Net.Index.Term;
using Lucene.Net.Analysis;
using Lucene.Net.Documents;
using Lucene.Net.Search;
using Searchable = Lucene.Net.Search.Searchable;
using Parameter = Lucene.Net.Util.Parameter;
namespace Lucene.Net.QueryParsers
{
/// <summary> This class is generated by JavaCC. The most important method 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:
/// <ul>
/// <li> a plus (<code>+</code>) or a minus (<code>-</code>) sign, indicating
/// that the clause is required or prohibited respectively; or
/// <li> a term followed by a colon, indicating the field to be searched.
/// This enables one to construct queries which search multiple fields.
/// </ul>
///
/// A clause may be either:
/// <ul>
/// <li> a term, indicating all the documents that contain this term; or
/// <li> a nested query, enclosed in parentheses. Note that this may be used
/// with a <code>+</code>/<code>-</code> prefix to require any of a set of
/// terms.
/// </ul>
///
/// Thus, in BNF, the query grammar is:
/// <pre>
/// Query ::= ( Clause )*
/// Clause ::= ["+", "-"] [<TERM> ":"] ( <TERM> | "(" Query ")" )
/// </pre>
///
/// <p>
/// Examples of appropriately formatted queries can be found in the <a
/// href="http://lucene.apache.org/java/docs/queryparsersyntax.html">query syntax
/// documentation</a>.
/// </p>
///
/// <p>
/// In {@link RangeQuery}s, QueryParser tries to detect date values, e.g.
/// <tt>date:[6/1/2005 TO 6/4/2005]</tt> produces a range query that searches
/// for "date" fields between 2005-06-01 and 2005-06-04. Note that the format
/// of the accepted input depends on {@link #SetLocale(Locale) the locale}.
/// By default a date is converted into a search term using the deprecated
/// {@link DateField} for compatibility reasons.
/// To use the new {@link DateTools} to convert dates, a
/// {@link DateTools.Resolution} has to be set.
/// </p>
/// <p>
/// The date resolution that shall be used for RangeQueries can be set
/// using {@link #SetDateResolution(DateTools.Resolution)}
/// or {@link #SetDateResolution(String, DateTools.Resolution)}. The former
/// sets the default date resolution for all fields, whereas the latter can
/// be used to set field specific date resolutions. Field specific date
/// resolutions take, if set, precedence over the default date resolution.
/// </p>
/// <p>
/// If you use neither {@link DateField} nor {@link DateTools} in your
/// index, you can create your own
/// query parser that inherits QueryParser and overwrites
/// {@link #GetRangeQuery(String, String, String, boolean)} to
/// use a different method for date conversion.
/// </p>
///
/// <p>Note that QueryParser is <em>not</em> thread-safe.</p>
///
/// </summary>
/// <author> Brian Goetz
/// </author>
/// <author> Peter Halacsy
/// </author>
/// <author> Tatu Saloranta
/// </author>
public class QueryParser : QueryParserConstants
{
private void InitBlock()
{
fuzzyMinSim = FuzzyQuery.defaultMinSimilarity;
fuzzyPrefixLength = FuzzyQuery.defaultPrefixLength;
jj_2_rtns = new JJCalls[1];
jj_ls = new LookaheadSuccess();
}
private const int CONJ_NONE = 0;
private const int CONJ_AND = 1;
private const int CONJ_OR = 2;
private const int MOD_NONE = 0;
private const int MOD_NOT = 10;
private const int MOD_REQ = 11;
// make it possible to call setDefaultOperator() without accessing
// the nested class:
/// <summary>Alternative form of QueryParser.Operator.AND </summary>
public static readonly Operator AND_OPERATOR = Operator.AND;
/// <summary>Alternative form of QueryParser.Operator.OR </summary>
public static readonly Operator OR_OPERATOR = Operator.OR;
/// <summary>The actual operator that parser uses to combine query terms </summary>
private Operator operator_Renamed = OR_OPERATOR;
internal bool lowercaseExpandedTerms = true;
internal bool useOldRangeQuery = false;
internal bool allowLeadingWildcard = false;
internal Analyzer analyzer;
internal System.String field;
internal int phraseSlop = 0;
internal float fuzzyMinSim;
internal int fuzzyPrefixLength;
internal System.Globalization.CultureInfo locale = System.Threading.Thread.CurrentThread.CurrentCulture;
// the default date resolution
internal DateTools.Resolution dateResolution = null;
// maps field names to date resolutions
internal System.Collections.IDictionary fieldToDateResolution = null;
/// <summary>The default operator for parsing queries.
/// Use {@link QueryParser#setDefaultOperator} to change it.
/// </summary>
[Serializable]
public sealed class Operator : Parameter
{
internal Operator(System.String name) : base(name)
{
}
public static readonly Operator OR = new Operator("OR");
public static readonly Operator AND = new Operator("AND");
}
/// <summary>Constructs a query parser.</summary>
/// <param name="f"> the default field for query terms.
/// </param>
/// <param name="a"> used to find terms in the query text.
/// </param>
public QueryParser(System.String f, Analyzer a) : this(new FastCharStream(new System.IO.StringReader("")))
{
analyzer = a;
field = f;
}
/// <summary>Parses a query string, returning a {@link Lucene.Net.Search.Query}.</summary>
/// <param name="query"> the query string to be parsed.
/// </param>
/// <throws> ParseException if the parsing fails </throws>
public virtual Query Parse(System.String query)
{
ReInit(new FastCharStream(new System.IO.StringReader(query)));
try
{
return Query(field);
}
catch (ParseException tme)
{
// rethrow to include the original query:
throw new ParseException("Cannot parse '" + query + "': " + tme.Message);
}
catch (TokenMgrError tme)
{
throw new ParseException("Cannot parse '" + query + "': " + tme.Message);
}
catch (BooleanQuery.TooManyClauses tmc)
{
throw new ParseException("Cannot parse '" + query + "': too many boolean clauses");
}
}
/// <returns> Returns the analyzer.
/// </returns>
public virtual Analyzer GetAnalyzer()
{
return analyzer;
}
/// <returns> Returns the field.
/// </returns>
public virtual System.String GetField()
{
return field;
}
/// <summary> Get the minimal similarity for fuzzy queries.</summary>
public virtual float GetFuzzyMinSim()
{
return fuzzyMinSim;
}
/// <summary> Set the minimum similarity for fuzzy queries.
/// Default is 0.5f.
/// </summary>
public virtual void SetFuzzyMinSim(float fuzzyMinSim)
{
this.fuzzyMinSim = fuzzyMinSim;
}
/// <summary> Get the prefix length for fuzzy queries. </summary>
/// <returns> Returns the fuzzyPrefixLength.
/// </returns>
public virtual int GetFuzzyPrefixLength()
{
return fuzzyPrefixLength;
}
/// <summary> Set the prefix length for fuzzy queries. Default is 0.</summary>
/// <param name="fuzzyPrefixLength">The fuzzyPrefixLength to set.
/// </param>
public virtual void SetFuzzyPrefixLength(int fuzzyPrefixLength)
{
this.fuzzyPrefixLength = fuzzyPrefixLength;
}
/// <summary> Sets the default slop for phrases. If zero, then exact phrase matches
/// are required. Default value is zero.
/// </summary>
public virtual void SetPhraseSlop(int phraseSlop)
{
this.phraseSlop = phraseSlop;
}
/// <summary> Gets the default slop for phrases.</summary>
public virtual int GetPhraseSlop()
{
return phraseSlop;
}
/// <summary> Set to <code>true</code> to allow <code>*</code> and <code>?</code> as the first character
/// of a PrefixQuery and WildcardQuery. Note that this can produce very slow
/// queries on big indexes. Default: false.
/// </summary>
public virtual void SetAllowLeadingWildcard(bool allowLeadingWildcard)
{
this.allowLeadingWildcard = allowLeadingWildcard;
}
/// <seealso cref="#setAllowLeadingWildcard">
/// </seealso>
public virtual bool GetAllowLeadingWildcard()
{
return allowLeadingWildcard;
}
/// <summary> Sets the boolean operator of the QueryParser.
/// In default mode (<code>OR_OPERATOR</code>) terms without any modifiers
/// are considered optional: for example <code>capital of Hungary</code> is equal to
/// <code>capital OR of OR Hungary</code>.<br/>
/// In <code>AND_OPERATOR</code> mode terms are considered to be in conjuction: the
/// above mentioned query is parsed as <code>capital AND of AND Hungary</code>
/// </summary>
public virtual void SetDefaultOperator(Operator op)
{
this.operator_Renamed = op;
}
/// <summary> Gets implicit operator setting, which will be either AND_OPERATOR
/// or OR_OPERATOR.
/// </summary>
public virtual Operator GetDefaultOperator()
{
return operator_Renamed;
}
/// <summary> Whether terms of wildcard, prefix, fuzzy and range queries are to be automatically
/// lower-cased or not. Default is <code>true</code>.
/// </summary>
public virtual void SetLowercaseExpandedTerms(bool lowercaseExpandedTerms)
{
this.lowercaseExpandedTerms = lowercaseExpandedTerms;
}
/// <seealso cref="#SetLowercaseExpandedTerms(boolean)">
/// </seealso>
public virtual bool GetLowercaseExpandedTerms()
{
return lowercaseExpandedTerms;
}
/// <summary> By default QueryParser uses new ConstantScoreRangeQuery in preference to RangeQuery
/// for range queries. This implementation is generally preferable because it
/// a) Runs faster b) Does not have the scarcity of range terms unduly influence score
/// c) avoids any "TooManyBooleanClauses" exception.
/// However, if your application really needs to use the old-fashioned RangeQuery and the above
/// points are not required then set this option to <code>true</code>
/// Default is <code>false</code>.
/// </summary>
public virtual void SetUseOldRangeQuery(bool useOldRangeQuery)
{
this.useOldRangeQuery = useOldRangeQuery;
}
/// <seealso cref="#SetUseOldRangeQuery(boolean)">
/// </seealso>
public virtual bool GetUseOldRangeQuery()
{
return useOldRangeQuery;
}
/// <summary> Set locale used by date range parsing.</summary>
public virtual void SetLocale(System.Globalization.CultureInfo locale)
{
this.locale = locale;
}
/// <summary> Returns current locale, allowing access by subclasses.</summary>
public virtual System.Globalization.CultureInfo GetLocale()
{
return locale;
}
/// <summary> Sets the default date resolution used by RangeQueries for fields for which no
/// specific date resolutions has been set. Field specific resolutions can be set
/// with {@link #SetDateResolution(String, DateTools.Resolution)}.
///
/// </summary>
/// <param name="dateResolution">the default date resolution to set
/// </param>
public virtual void SetDateResolution(DateTools.Resolution dateResolution)
{
this.dateResolution = dateResolution;
}
/// <summary> Sets the date resolution used by RangeQueries for a specific field.
///
/// </summary>
/// <param name="field">field for which the date resolution is to be set
/// </param>
/// <param name="dateResolution">date resolution to set
/// </param>
public virtual void SetDateResolution(System.String fieldName, DateTools.Resolution dateResolution)
{
if (fieldName == null)
{
throw new System.ArgumentException("Field cannot be null.");
}
if (fieldToDateResolution == null)
{
// lazily initialize HashMap
fieldToDateResolution = new System.Collections.Hashtable();
}
fieldToDateResolution[fieldName] = dateResolution;
}
/// <summary> Returns the date resolution that is used by RangeQueries for the given field.
/// Returns null, if no default or field specific date resolution has been set
/// for the given field.
///
/// </summary>
public virtual DateTools.Resolution GetDateResolution(System.String fieldName)
{
if (fieldName == null)
{
throw new System.ArgumentException("Field cannot be null.");
}
if (fieldToDateResolution == null)
{
// no field specific date resolutions set; return default date resolution instead
return this.dateResolution;
}
DateTools.Resolution resolution = (DateTools.Resolution) fieldToDateResolution[fieldName];
if (resolution == null)
{
// no date resolutions set for the given field; return default date resolution instead
resolution = this.dateResolution;
}
return resolution;
}
protected internal virtual void AddClause(System.Collections.ArrayList clauses, int conj, int mods, Query q)
{
bool required, prohibited;
// If this term is introduced by AND, make the preceding term required,
// unless it's already prohibited
if (clauses.Count > 0 && conj == CONJ_AND)
{
BooleanClause c = (BooleanClause) clauses[clauses.Count - 1];
if (!c.IsProhibited())
c.SetOccur(BooleanClause.Occur.MUST);
}
if (clauses.Count > 0 && operator_Renamed == 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[clauses.Count - 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_Renamed == 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 = (mods == MOD_NOT);
required = (mods == 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 = (mods == MOD_NOT);
required = (!prohibited && conj != CONJ_OR);
}
if (required && !prohibited)
clauses.Add(new BooleanClause(q, BooleanClause.Occur.MUST));
else if (!required && !prohibited)
clauses.Add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
else if (!required && prohibited)
clauses.Add(new BooleanClause(q, BooleanClause.Occur.MUST_NOT));
else
throw new System.SystemException("Clause cannot be both required and prohibited");
}
/// <exception cref=""> ParseException throw in overridden method to disallow
/// </exception>
protected internal virtual Query GetFieldQuery(System.String field, System.String queryText)
{
// 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 System.IO.StringReader(queryText));
System.Collections.ArrayList v = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
Lucene.Net.Analysis.Token t;
int positionCount = 0;
bool severalTokensAtSamePosition = false;
while (true)
{
try
{
t = source.Next();
}
catch (System.IO.IOException e)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -