[ci] Try to get .gitignore check to work
[xapian.git] / xapian-core / queryparser / queryparser.cc
blobae39450f2eb245eb4dea12582763828fa99e125d
1 /* queryparser.cc: The non-lemon-generated parts of the QueryParser
2 * class.
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 unordered_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() : internal(new QueryParser::Internal) { }
76 QueryParser::~QueryParser() { }
78 void
79 QueryParser::set_stemmer(const Xapian::Stem & stemmer)
81 internal->stemmer = stemmer;
84 void
85 QueryParser::set_stemming_strategy(stem_strategy strategy)
87 internal->stem_action = strategy;
90 void
91 QueryParser::set_stopper(const Stopper * stopper)
93 internal->stopper = stopper;
96 void
97 QueryParser::set_default_op(Query::op default_op)
99 switch (default_op) {
100 case Query::OP_AND:
101 case Query::OP_OR:
102 case Query::OP_NEAR:
103 case Query::OP_PHRASE:
104 case Query::OP_ELITE_SET:
105 case Query::OP_SYNONYM:
106 case Query::OP_MAX:
107 // These are OK.
108 break;
109 default:
110 throw Xapian::InvalidArgumentError(
111 "QueryParser::set_default_op() only accepts "
112 "OP_AND"
113 ", "
114 "OP_OR"
115 ", "
116 "OP_NEAR"
117 ", "
118 "OP_PHRASE"
119 ", "
120 "OP_ELITE_SET"
121 ", "
122 "OP_SYNONYM"
123 " or "
124 "OP_MAX");
126 internal->default_op = default_op;
129 Query::op
130 QueryParser::get_default_op() const
132 return internal->default_op;
135 void
136 QueryParser::set_database(const Database &db) {
137 internal->db = db;
140 void
141 QueryParser::set_max_expansion(Xapian::termcount max_expansion,
142 int max_type,
143 unsigned flags)
145 if (flags & FLAG_WILDCARD) {
146 internal->max_wildcard_expansion = max_expansion;
147 internal->max_wildcard_type = max_type;
149 if (flags & FLAG_PARTIAL) {
150 internal->max_partial_expansion = max_expansion;
151 internal->max_partial_type = max_type;
155 Query
156 QueryParser::parse_query(const string &query_string, unsigned flags,
157 const string &default_prefix)
159 internal->stoplist.clear();
160 internal->unstem.clear();
161 internal->errmsg = NULL;
163 if (query_string.empty()) return Query();
165 Query result = internal->parse_query(query_string, flags, default_prefix);
166 if (internal->errmsg && strcmp(internal->errmsg, "parse error") == 0) {
167 flags &= FLAG_CJK_NGRAM;
168 result = internal->parse_query(query_string, flags, default_prefix);
171 if (internal->errmsg) throw Xapian::QueryParserError(internal->errmsg);
172 return result;
175 void
176 QueryParser::add_prefix(const string &field, const string &prefix)
178 Assert(internal.get());
179 internal->add_prefix(field, prefix);
182 void
183 QueryParser::add_prefix(const string &field, Xapian::FieldProcessor * proc)
185 Assert(internal.get());
186 internal->add_prefix(field, proc);
189 void
190 QueryParser::add_boolean_prefix(const string &field, const string &prefix,
191 const string* grouping)
193 Assert(internal.get());
194 internal->add_boolean_prefix(field, prefix, grouping);
197 void
198 QueryParser::add_boolean_prefix(const string &field,
199 Xapian::FieldProcessor * proc,
200 const string* grouping)
202 Assert(internal.get());
203 internal->add_boolean_prefix(field, proc, grouping);
206 TermIterator
207 QueryParser::stoplist_begin() const
209 const list<string> & sl = internal->stoplist;
210 return TermIterator(new VectorTermList(sl.begin(), sl.end()));
213 TermIterator
214 QueryParser::unstem_begin(const string &term) const
216 pair<multimap<string, string>::iterator,
217 multimap<string, string>::iterator> range;
218 range = internal->unstem.equal_range(term);
219 list<string> l;
220 multimap<string, string>::iterator & i = range.first;
221 while (i != range.second) {
222 l.push_back(i->second);
223 ++i;
225 return TermIterator(new VectorTermList(l.begin(), l.end()));
228 void
229 QueryParser::add_rangeprocessor(Xapian::RangeProcessor * range_proc,
230 const std::string* grouping)
232 Assert(internal.get());
233 internal->rangeprocs.push_back(RangeProc(range_proc, grouping));
236 string
237 QueryParser::get_corrected_query_string() const
239 return internal->corrected_query;
242 string
243 QueryParser::get_description() const
245 // FIXME : describe better!
246 return "Xapian::QueryParser()";