Update for 1.4.20
[xapian.git] / xapian-core / queryparser / queryparser.cc
blob94ed6eecf5dda6598859268e1cc13ec755656a53
1 /** @file
2 * @brief The non-lemon-generated parts of the QueryParser class.
3 */
4 /* Copyright (C) 2005,2006,2007,2008,2010,2011,2012,2013,2015,2016 Olly Betts
5 * Copyright (C) 2010 Adam Sjøgren
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
20 * USA
23 #include <config.h>
25 #include "xapian/error.h"
26 #include <xapian/queryparser.h>
27 #include <xapian/termiterator.h>
29 #include "api/vectortermlist.h"
30 #include "omassert.h"
31 #include "queryparser_internal.h"
33 #include <cstring>
35 using namespace Xapian;
37 using namespace std;
39 // Default implementation in case the user hasn't implemented it.
40 string
41 Stopper::get_description() const
43 return "Xapian::Stopper subclass";
46 string
47 SimpleStopper::get_description() const
49 string desc("Xapian::SimpleStopper(");
50 set<string>::const_iterator i;
51 for (i = stop_words.begin(); i != stop_words.end(); ++i) {
52 if (i != stop_words.begin()) desc += ' ';
53 desc += *i;
55 desc += ')';
56 return desc;
59 RangeProcessor::~RangeProcessor() { }
61 ValueRangeProcessor::~ValueRangeProcessor() { }
63 FieldProcessor::~FieldProcessor() { }
65 QueryParser::QueryParser(const QueryParser & o) : internal(o.internal) { }
67 QueryParser &
68 QueryParser::operator=(const QueryParser & o)
70 internal = o.internal;
71 return *this;
74 QueryParser::QueryParser(QueryParser &&) = default;
76 QueryParser &
77 QueryParser::operator=(QueryParser &&) = default;
79 QueryParser::QueryParser() : internal(new QueryParser::Internal) { }
81 QueryParser::~QueryParser() { }
83 void
84 QueryParser::set_stemmer(const Xapian::Stem & stemmer)
86 internal->stemmer = stemmer;
89 void
90 QueryParser::set_stemming_strategy(stem_strategy strategy)
92 internal->stem_action = strategy;
95 void
96 QueryParser::set_stopper(const Stopper * stopper)
98 internal->stopper = stopper;
101 void
102 QueryParser::set_default_op(Query::op default_op)
104 switch (default_op) {
105 case Query::OP_AND:
106 case Query::OP_OR:
107 case Query::OP_NEAR:
108 case Query::OP_PHRASE:
109 case Query::OP_ELITE_SET:
110 case Query::OP_SYNONYM:
111 case Query::OP_MAX:
112 // These are OK.
113 break;
114 default:
115 throw Xapian::InvalidArgumentError(
116 "QueryParser::set_default_op() only accepts "
117 "OP_AND"
118 ", "
119 "OP_OR"
120 ", "
121 "OP_NEAR"
122 ", "
123 "OP_PHRASE"
124 ", "
125 "OP_ELITE_SET"
126 ", "
127 "OP_SYNONYM"
128 " or "
129 "OP_MAX");
131 internal->default_op = default_op;
134 Query::op
135 QueryParser::get_default_op() const
137 return internal->default_op;
140 void
141 QueryParser::set_database(const Database &db) {
142 internal->db = db;
145 void
146 QueryParser::set_max_expansion(Xapian::termcount max_expansion,
147 int max_type,
148 unsigned flags)
150 if (flags & FLAG_WILDCARD) {
151 internal->max_wildcard_expansion = max_expansion;
152 internal->max_wildcard_type = max_type;
154 if (flags & FLAG_PARTIAL) {
155 internal->max_partial_expansion = max_expansion;
156 internal->max_partial_type = max_type;
160 Query
161 QueryParser::parse_query(const string &query_string, unsigned flags,
162 const string &default_prefix)
164 if (!(flags & FLAG_ACCUMULATE)) {
165 internal->stoplist.clear();
166 internal->unstem.clear();
168 internal->errmsg = NULL;
170 if (query_string.empty()) return Query();
172 Query result = internal->parse_query(query_string, flags, default_prefix);
173 if (internal->errmsg && strcmp(internal->errmsg, "parse error") == 0) {
174 flags &= FLAG_CJK_NGRAM | FLAG_NO_POSITIONS;
175 result = internal->parse_query(query_string, flags, default_prefix);
178 if (internal->errmsg) throw Xapian::QueryParserError(internal->errmsg);
179 return result;
182 void
183 QueryParser::add_prefix(const string &field, const string &prefix)
185 Assert(internal.get());
186 internal->add_prefix(field, prefix);
189 void
190 QueryParser::add_prefix(const string &field, Xapian::FieldProcessor * proc)
192 Assert(internal.get());
193 internal->add_prefix(field, proc);
196 void
197 QueryParser::add_boolean_prefix(const string &field, const string &prefix,
198 const string* grouping)
200 Assert(internal.get());
201 internal->add_boolean_prefix(field, prefix, grouping);
204 void
205 QueryParser::add_boolean_prefix(const string &field,
206 Xapian::FieldProcessor * proc,
207 const string* grouping)
209 Assert(internal.get());
210 internal->add_boolean_prefix(field, proc, grouping);
213 TermIterator
214 QueryParser::stoplist_begin() const
216 const list<string> & sl = internal->stoplist;
217 return TermIterator(new VectorTermList(sl.begin(), sl.end()));
220 TermIterator
221 QueryParser::unstem_begin(const string &term) const
223 struct range_adaptor : public multimap<string, string>::iterator {
224 range_adaptor(multimap<string, string>::iterator i) :
225 multimap<string, string>::iterator(i) {}
226 const string & operator*() const { return (*this)->second; }
228 auto range = internal->unstem.equal_range(term);
229 return TermIterator(new VectorTermList(range_adaptor(range.first),
230 range_adaptor(range.second)));
233 void
234 QueryParser::add_rangeprocessor(Xapian::RangeProcessor * range_proc,
235 const std::string* grouping)
237 Assert(internal.get());
238 internal->rangeprocs.push_back(RangeProc(range_proc, grouping));
241 string
242 QueryParser::get_corrected_query_string() const
244 return internal->corrected_query;
247 string
248 QueryParser::get_description() const
250 // FIXME : describe better!
251 return "Xapian::QueryParser()";