00001
00002
00003
00004
00005
00006
00007
00008
00009 #line 1 "queryparser/queryparser.lemony"
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <config.h>
00034
00035 #include "omassert.h"
00036 #include "queryparser_internal.h"
00037 #include <xapian/error.h>
00038 #include <xapian/unicode.h>
00039 #include "str.h"
00040 #include "stringutils.h"
00041
00042
00043 #include "queryparser_token.h"
00044
00045 #include "cjk-tokenizer.h"
00046
00047 #include <algorithm>
00048 #include <limits>
00049 #include <list>
00050 #include <string>
00051
00052 #include <string.h>
00053
00054 using namespace std;
00055
00056 using namespace Xapian;
00057
00058 inline bool
00059 U_isupper(unsigned ch) {
00060 return (ch < 128 && C_isupper((unsigned char)ch));
00061 }
00062
00063 inline bool
00064 U_isdigit(unsigned ch) {
00065 return (ch < 128 && C_isdigit((unsigned char)ch));
00066 }
00067
00068 inline bool
00069 U_isalpha(unsigned ch) {
00070 return (ch < 128 && C_isalpha((unsigned char)ch));
00071 }
00072
00073 using Xapian::Unicode::is_whitespace;
00074
00075 inline bool
00076 is_not_whitespace(unsigned ch) {
00077 return !is_whitespace(ch);
00078 }
00079
00080 using Xapian::Unicode::is_wordchar;
00081
00082 inline bool
00083 is_not_wordchar(unsigned ch) {
00084 return !is_wordchar(ch);
00085 }
00086
00087 inline bool
00088 is_digit(unsigned ch) {
00089 return (Unicode::get_category(ch) == Unicode::DECIMAL_DIGIT_NUMBER);
00090 }
00091
00092
00093
00094 inline bool
00095 is_suffix(unsigned ch) {
00096 return ch == '+' || ch == '#';
00097 }
00098
00099 inline bool
00100 prefix_needs_colon(const string & prefix, unsigned ch)
00101 {
00102 if (!U_isupper(ch)) return false;
00103 string::size_type len = prefix.length();
00104 return (len > 1 && prefix[len - 1] != ':');
00105 }
00106
00107 using Unicode::is_currency;
00108
00109 inline bool
00110 is_positional(Xapian::Query::op op)
00111 {
00112 return (op == Xapian::Query::OP_PHRASE || op == Xapian::Query::OP_NEAR);
00113 }
00114
00116 struct filter_group_id {
00121 const PrefixInfo *prefix_info;
00122
00127 Xapian::valueno slot;
00128
00130 explicit filter_group_id(const PrefixInfo * prefix_info_)
00131 : prefix_info(prefix_info_), slot(Xapian::BAD_VALUENO) {}
00132
00134 explicit filter_group_id(Xapian::valueno slot_)
00135 : prefix_info(NULL), slot(slot_) {}
00136
00138 bool operator<(const filter_group_id & other) const {
00139
00140 if (slot != other.slot)
00141 return slot < other.slot;
00142 if (!prefix_info || prefix_info == other.prefix_info)
00143 return false;
00144 if (!other.prefix_info)
00145 return true;
00146 return prefix_info->prefixes < other.prefix_info->prefixes;
00147 }
00148 };
00149
00150 class Terms;
00151
00158 class Term {
00159 State * state;
00160
00161 public:
00162 string name;
00163 const PrefixInfo * prefix_info;
00164 string unstemmed;
00165 QueryParser::stem_strategy stem;
00166 termpos pos;
00167
00168 Term(const string &name_, termpos pos_) : name(name_), stem(QueryParser::STEM_NONE), pos(pos_) { }
00169 Term(const string &name_) : name(name_), stem(QueryParser::STEM_NONE), pos(0) { }
00170 Term(const string &name_, const PrefixInfo * prefix_info_)
00171 : name(name_), prefix_info(prefix_info_),
00172 stem(QueryParser::STEM_NONE), pos(0) { }
00173 Term(termpos pos_) : stem(QueryParser::STEM_NONE), pos(pos_) { }
00174 Term(State * state_, const string &name_, const PrefixInfo * prefix_info_,
00175 const string &unstemmed_,
00176 QueryParser::stem_strategy stem_ = QueryParser::STEM_NONE,
00177 termpos pos_ = 0)
00178 : state(state_), name(name_), prefix_info(prefix_info_),
00179 unstemmed(unstemmed_), stem(stem_), pos(pos_) { }
00180
00181 Term(valueno slot, const string &a, const string &b)
00182 : name(a), unstemmed(b), pos(slot) { }
00183
00184 string make_term(const string & prefix) const;
00185
00186 void need_positions() {
00187 if (stem == QueryParser::STEM_SOME) stem = QueryParser::STEM_NONE;
00188 }
00189
00190 termpos get_termpos() const { return pos; }
00191
00192 filter_group_id get_filter_group_id() const {
00193 return filter_group_id(prefix_info);
00194 }
00195
00196 Query * as_wildcarded_query(State * state) const;
00197
00206 Query * as_partial_query(State * state_) const;
00207
00209 Query * as_cjk_query() const;
00210
00212 void as_positional_cjk_term(Terms * terms) const;
00213
00215 Query as_value_range_query() const;
00216
00217 Query get_query() const;
00218
00219 Query get_query_with_synonyms() const;
00220
00221 Query get_query_with_auto_synonyms() const;
00222 };
00223
00225 class State {
00226 QueryParser::Internal * qpi;
00227
00228 public:
00229 Query query;
00230 const char * error;
00231 unsigned flags;
00232
00233 State(QueryParser::Internal * qpi_, unsigned flags_)
00234 : qpi(qpi_), error(NULL), flags(flags_) { }
00235
00236 string stem_term(const string &term) {
00237 return qpi->stemmer(term);
00238 }
00239
00240 void add_to_stoplist(const Term * term) {
00241 qpi->stoplist.push_back(term->name);
00242 }
00243
00244 void add_to_unstem(const string & term, const string & unstemmed) {
00245 qpi->unstem.insert(make_pair(term, unstemmed));
00246 }
00247
00248 Term * value_range(const string &a, const string &b) {
00249 list<ValueRangeProcessor *>::const_iterator i;
00250 for (i = qpi->valrangeprocs.begin(); i != qpi->valrangeprocs.end(); ++i) {
00251 string start = a;
00252 string end = b;
00253 Xapian::valueno slot = (**i)(start, end);
00254 if (slot != Xapian::BAD_VALUENO) {
00255 return new Term(slot, start, end);
00256 }
00257 }
00258 return NULL;
00259 }
00260
00261 Query::op default_op() const { return qpi->default_op; }
00262
00263 bool is_stopword(const Term *term) const {
00264 return qpi->stopper && (*qpi->stopper)(term->name);
00265 }
00266
00267 Database get_database() const {
00268 return qpi->db;
00269 }
00270
00271 const Stopper * get_stopper() const {
00272 return qpi->stopper;
00273 }
00274
00275 size_t stoplist_size() const {
00276 return qpi->stoplist.size();
00277 }
00278
00279 void stoplist_resize(size_t s) {
00280 qpi->stoplist.resize(s);
00281 }
00282
00283 Xapian::termcount get_max_wildcard_expansion() const {
00284 return qpi->max_wildcard_expansion;
00285 }
00286 };
00287
00288 string
00289 Term::make_term(const string & prefix) const
00290 {
00291 string term;
00292 if (stem == QueryParser::STEM_SOME) term += 'Z';
00293 if (!prefix.empty()) {
00294 term += prefix;
00295 if (prefix_needs_colon(prefix, name[0])) term += ':';
00296 }
00297 if (stem != QueryParser::STEM_NONE) {
00298 term += state->stem_term(name);
00299 } else {
00300 term += name;
00301 }
00302
00303 if (!unstemmed.empty())
00304 state->add_to_unstem(term, unstemmed);
00305 return term;
00306 }
00307
00308 Query
00309 Term::get_query_with_synonyms() const
00310 {
00311 Query q = get_query();
00312
00313
00314 const list<string> & prefixes = prefix_info->prefixes;
00315 list<string>::const_iterator piter;
00316 for (piter = prefixes.begin(); piter != prefixes.end(); ++piter) {
00317
00318 string term;
00319 if (!piter->empty()) {
00320 term += *piter;
00321 if (prefix_needs_colon(*piter, name[0])) term += ':';
00322 }
00323 term += name;
00324
00325 Xapian::Database db = state->get_database();
00326 Xapian::TermIterator syn = db.synonyms_begin(term);
00327 Xapian::TermIterator end = db.synonyms_end(term);
00328 if (syn == end && stem != QueryParser::STEM_NONE) {
00329
00330 term = 'Z';
00331 if (!piter->empty()) {
00332 term += *piter;
00333 if (prefix_needs_colon(*piter, name[0])) term += ':';
00334 }
00335 term += state->stem_term(name);
00336 syn = db.synonyms_begin(term);
00337 end = db.synonyms_end(term);
00338 }
00339 while (syn != end) {
00340 q = Query(Query::OP_SYNONYM, q, Query(*syn, 1, pos));
00341 ++syn;
00342 }
00343 }
00344 return q;
00345 }
00346
00347 Query
00348 Term::get_query_with_auto_synonyms() const
00349 {
00350 if (state->flags & QueryParser::FLAG_AUTO_SYNONYMS)
00351 return get_query_with_synonyms();
00352
00353 return get_query();
00354 }
00355
00356 static void
00357 add_to_query(Query *& q, Query::op op, Query * term)
00358 {
00359 Assert(term);
00360 if (q) {
00361 *q = Query(op, *q, *term);
00362 delete term;
00363 } else {
00364 q = term;
00365 }
00366 }
00367
00368 static void
00369 add_to_query(Query *& q, Query::op op, const Query & term)
00370 {
00371 if (q) {
00372 *q = Query(op, *q, term);
00373 } else {
00374 q = new Query(term);
00375 }
00376 }
00377
00378 Query
00379 Term::get_query() const
00380 {
00381 const list<string> & prefixes = prefix_info->prefixes;
00382 Assert(prefixes.size() >= 1);
00383 list<string>::const_iterator piter = prefixes.begin();
00384 Query q(make_term(*piter), 1, pos);
00385 while (++piter != prefixes.end()) {
00386 q = Query(Query::OP_OR, q, Query(make_term(*piter), 1, pos));
00387 }
00388 return q;
00389 }
00390
00391 Query *
00392 Term::as_wildcarded_query(State * state_) const
00393 {
00394 const Database & db = state_->get_database();
00395 vector<Query> subqs;
00396
00397 const list<string> & prefixes = prefix_info->prefixes;
00398 list<string>::const_iterator piter;
00399 Xapian::termcount expansion_count = 0;
00400 Xapian::termcount max = state_->get_max_wildcard_expansion();
00401 for (piter = prefixes.begin(); piter != prefixes.end(); ++piter) {
00402 string root = *piter;
00403 root += name;
00404 TermIterator t = db.allterms_begin(root);
00405 while (t != db.allterms_end(root)) {
00406 if (max != 0 && ++expansion_count > max) {
00407 string msg("Wildcard ");
00408 msg += unstemmed;
00409 msg += "* expands to more than ";
00410 msg += str(max);
00411 msg += " terms";
00412 throw Xapian::QueryParserError(msg);
00413 }
00414 subqs.push_back(Query(*t, 1, pos));
00415 ++t;
00416 }
00417 }
00418 Query * q = new Query(Query::OP_SYNONYM, subqs.begin(), subqs.end());
00419 delete this;
00420 return q;
00421 }
00422
00423 Query *
00424 Term::as_partial_query(State * state_) const
00425 {
00426 const Database & db = state_->get_database();
00427 vector<Query> subqs_partial;
00428 vector<Query> subqs_full;
00429
00430 const list<string> & prefixes = prefix_info->prefixes;
00431 list<string>::const_iterator piter;
00432 for (piter = prefixes.begin(); piter != prefixes.end(); ++piter) {
00433 string root = *piter;
00434 root += name;
00435 TermIterator t = db.allterms_begin(root);
00436 while (t != db.allterms_end(root)) {
00437 subqs_partial.push_back(Query(*t, 1, pos));
00438 ++t;
00439 }
00440
00441 subqs_full.push_back(Query(make_term(*piter), 1, pos));
00442 }
00443 Query * q = new Query(Query::OP_OR,
00444 Query(Query::OP_SYNONYM,
00445 subqs_partial.begin(), subqs_partial.end()),
00446 Query(Query::OP_SYNONYM,
00447 subqs_full.begin(), subqs_full.end()));
00448 delete this;
00449 return q;
00450 }
00451
00452 Query *
00453 Term::as_cjk_query() const
00454 {
00455 vector<Query> prefix_cjk;
00456 const list<string> & prefixes = prefix_info->prefixes;
00457 list<string>::const_iterator piter;
00458 for (CJKTokenIterator tk(name); tk != CJKTokenIterator(); ++tk) {
00459 for (piter = prefixes.begin(); piter != prefixes.end(); ++piter) {
00460 string cjk = *piter;
00461 cjk += *tk;
00462 prefix_cjk.push_back(Query(cjk, 1, pos));
00463 }
00464 }
00465 Query * q = new Query(Query::OP_AND, prefix_cjk.begin(), prefix_cjk.end());
00466 delete this;
00467 return q;
00468 }
00469
00470 Query
00471 Term::as_value_range_query() const
00472 {
00473 Query q;
00474 if (unstemmed.empty())
00475 q = Query(Query::OP_VALUE_GE, pos, name);
00476 else
00477 q = Query(Query::OP_VALUE_RANGE, pos, name, unstemmed);
00478 delete this;
00479 return q;
00480 }
00481
00482 inline bool
00483 is_phrase_generator(unsigned ch)
00484 {
00485
00486
00487
00488 return (ch && ch < 128 && strchr(".-/:\\@", ch) != NULL);
00489 }
00490
00491 inline bool
00492 is_stem_preventer(unsigned ch)
00493 {
00494 return (ch && ch < 128 && strchr("(/\\@<>=*[{\"", ch) != NULL);
00495 }
00496
00497 inline bool
00498 should_stem(const string & term)
00499 {
00500 const unsigned int SHOULD_STEM_MASK =
00501 (1 << Unicode::LOWERCASE_LETTER) |
00502 (1 << Unicode::TITLECASE_LETTER) |
00503 (1 << Unicode::MODIFIER_LETTER) |
00504 (1 << Unicode::OTHER_LETTER);
00505 Utf8Iterator u(term);
00506 return ((SHOULD_STEM_MASK >> Unicode::get_category(*u)) & 1);
00507 }
00508
00512 const unsigned UNICODE_IGNORE = numeric_limits<unsigned>::max();
00513
00514 inline unsigned check_infix(unsigned ch) {
00515 if (ch == '\'' || ch == '&' || ch == 0xb7 || ch == 0x5f4 || ch == 0x2027) {
00516
00517
00518
00519
00520 return ch;
00521 }
00522
00523
00524 if (ch == 0x2019 || ch == 0x201b) return '\'';
00525 if (ch >= 0x200b && (ch <= 0x200d || ch == 0x2060 || ch == 0xfeff))
00526 return UNICODE_IGNORE;
00527 return 0;
00528 }
00529
00530 inline unsigned check_infix_digit(unsigned ch) {
00531
00532 switch (ch) {
00533 case ',':
00534 case '.':
00535 case ';':
00536 case 0x037e:
00537 case 0x0589:
00538 case 0x060D:
00539 case 0x07F8:
00540 case 0x2044:
00541 case 0xFE10:
00542 case 0xFE13:
00543 case 0xFE14:
00544 return ch;
00545 }
00546 if (ch >= 0x200b && (ch <= 0x200d || ch == 0x2060 || ch == 0xfeff))
00547 return UNICODE_IGNORE;
00548 return 0;
00549 }
00550
00551 struct yyParser;
00552
00553
00554 static yyParser *ParseAlloc();
00555 static void ParseFree(yyParser *);
00556 static void Parse(yyParser *, int, Term *, State *);
00557 static void yy_parse_failed(yyParser *);
00558
00559 void
00560 QueryParser::Internal::add_prefix(const string &field, const string &prefix,
00561 filter_type type)
00562 {
00563 map<string, PrefixInfo>::iterator p = prefixmap.find(field);
00564 if (p == prefixmap.end()) {
00565 prefixmap.insert(make_pair(field, PrefixInfo(type, prefix)));
00566 } else {
00567
00568 if (p->second.type != type) {
00569 throw Xapian::InvalidOperationError("Can't use add_prefix() and add_boolean_prefix() on the same field name, or add_boolean_prefix() with different values of the 'exclusive' parameter");
00570 }
00571 p->second.prefixes.push_back(prefix);
00572 }
00573 }
00574
00575 string
00576 QueryParser::Internal::parse_term(Utf8Iterator &it, const Utf8Iterator &end,
00577 bool cjk_ngram, bool & is_cjk_term,
00578 bool &was_acronym)
00579 {
00580 string term;
00581
00582
00583 if (U_isupper(*it)) {
00584 string t;
00585 Utf8Iterator p = it;
00586 do {
00587 Unicode::append_utf8(t, *p++);
00588 } while (p != end && *p == '.' && ++p != end && U_isupper(*p));
00589
00590
00591 if (t.length() > 1) {
00592
00593
00594
00595 if (p == end || !is_wordchar(*p)) {
00596 it = p;
00597 swap(term, t);
00598 }
00599 }
00600 }
00601 was_acronym = !term.empty();
00602
00603 if (cjk_ngram && term.empty() && CJK::codepoint_is_cjk(*it)) {
00604 term = CJK::get_cjk(it);
00605 is_cjk_term = true;
00606 }
00607
00608 if (term.empty()) {
00609 unsigned prevch = *it;
00610 Unicode::append_utf8(term, prevch);
00611 while (++it != end) {
00612 if (cjk_ngram && CJK::codepoint_is_cjk(*it)) break;
00613 unsigned ch = *it;
00614 if (!is_wordchar(ch)) {
00615
00616
00617
00618 Utf8Iterator p = it;
00619 ++p;
00620 if (p == end || !is_wordchar(*p)) break;
00621 unsigned nextch = *p;
00622 if (is_digit(prevch) && is_digit(nextch)) {
00623 ch = check_infix_digit(ch);
00624 } else {
00625 ch = check_infix(ch);
00626 }
00627 if (!ch) break;
00628 if (ch == UNICODE_IGNORE)
00629 continue;
00630 }
00631 Unicode::append_utf8(term, ch);
00632 prevch = ch;
00633 }
00634 if (it != end && is_suffix(*it)) {
00635 string suff_term = term;
00636 Utf8Iterator p = it;
00637
00638 do {
00639 if (suff_term.size() - term.size() == 3) {
00640 suff_term.resize(0);
00641 break;
00642 }
00643 suff_term += *p;
00644 } while (is_suffix(*++p));
00645 if (!suff_term.empty() && (p == end || !is_wordchar(*p))) {
00646
00647
00648
00649
00650 bool use_suff_term = false;
00651 string lc = Unicode::tolower(suff_term);
00652 if (db.term_exists(lc)) {
00653 use_suff_term = true;
00654 } else {
00655 lc = Unicode::tolower(term);
00656 if (!db.term_exists(lc)) use_suff_term = true;
00657 }
00658 if (use_suff_term) {
00659 term = suff_term;
00660 it = p;
00661 }
00662 }
00663 }
00664 }
00665 return term;
00666 }
00667
00668 class ParserHandler {
00669 yyParser * parser;
00670
00671 public:
00672 explicit ParserHandler(yyParser * parser_) : parser(parser_) { }
00673 operator yyParser*() { return parser; }
00674 ~ParserHandler() { ParseFree(parser); }
00675 };
00676
00677 Query
00678 QueryParser::Internal::parse_query(const string &qs, unsigned flags,
00679 const string &default_prefix)
00680 {
00681 bool cjk_ngram = CJK::is_cjk_enabled();
00682
00683
00684 bool value_ranges;
00685 value_ranges = !valrangeprocs.empty() && (qs.find("..") != string::npos);
00686
00687 termpos term_pos = 1;
00688 Utf8Iterator it(qs), end;
00689
00690 State state(this, flags);
00691
00692
00693
00694 int correction_offset = 0;
00695 corrected_query.resize(0);
00696
00697
00698 list<const PrefixInfo *> prefix_stack;
00699
00700
00701
00702 const PrefixInfo def_pfx(NON_BOOLEAN, default_prefix);
00703 {
00704 const PrefixInfo * default_prefix_info = &def_pfx;
00705 if (default_prefix.empty()) {
00706 map<string, PrefixInfo>::const_iterator f = prefixmap.find("");
00707 if (f != prefixmap.end()) default_prefix_info = &(f->second);
00708 }
00709
00710
00711 prefix_stack.push_back(default_prefix_info);
00712 }
00713
00714 ParserHandler pParser(ParseAlloc());
00715
00716 unsigned newprev = ' ';
00717 main_lex_loop:
00718 enum {
00719 DEFAULT, IN_QUOTES, IN_PREFIXED_QUOTES, IN_PHRASED_TERM, IN_GROUP,
00720 IN_GROUP2, EXPLICIT_SYNONYM
00721 } mode = DEFAULT;
00722 while (it != end && !state.error) {
00723 bool last_was_operator = false;
00724 bool last_was_operator_needing_term = false;
00725 if (mode == EXPLICIT_SYNONYM) mode = DEFAULT;
00726 if (false) {
00727 just_had_operator:
00728 if (it == end) break;
00729 mode = DEFAULT;
00730 last_was_operator_needing_term = false;
00731 last_was_operator = true;
00732 }
00733 if (false) {
00734 just_had_operator_needing_term:
00735 last_was_operator_needing_term = true;
00736 last_was_operator = true;
00737 }
00738 if (mode == IN_PHRASED_TERM) mode = DEFAULT;
00739 if (is_whitespace(*it)) {
00740 newprev = ' ';
00741 ++it;
00742 it = find_if(it, end, is_not_whitespace);
00743 if (it == end) break;
00744 }
00745
00746 if (value_ranges &&
00747 (mode == DEFAULT || mode == IN_GROUP || mode == IN_GROUP2)) {
00748
00749
00750
00751
00752 Utf8Iterator it_initial = it;
00753 Utf8Iterator p = it;
00754 unsigned ch = 0;
00755 while (p != end) {
00756 if (ch == '.' && *p == '.') {
00757 string a;
00758 while (it != p) {
00759 Unicode::append_utf8(a, *it++);
00760 }
00761
00762 a.resize(a.size() - 1);
00763 ++p;
00764
00765
00766 if (!a.empty() || (p != end && *p > ' ' && *p != ')')) {
00767 string b;
00768
00769
00770
00771 while (p != end && *p > ' ' && *p != ')') {
00772 Unicode::append_utf8(b, *p++);
00773 }
00774 Term * range = state.value_range(a, b);
00775 if (!range) {
00776 state.error = "Unknown range operation";
00777 if (a.find(':', 1) == string::npos) {
00778 goto done;
00779 }
00780
00781
00782 it = it_initial;
00783 break;
00784 }
00785 Parse(pParser, RANGE, range, &state);
00786 }
00787 it = p;
00788 goto main_lex_loop;
00789 }
00790 ch = *p;
00791 if (!(is_wordchar(ch) || is_currency(ch) ||
00792 (ch < 128 && strchr("%,-./:@", ch)))) break;
00793 ++p;
00794 }
00795 }
00796
00797 if (!is_wordchar(*it)) {
00798 unsigned prev = newprev;
00799 unsigned ch = *it++;
00800 newprev = ch;
00801
00802 if (mode == IN_GROUP || mode == IN_GROUP2)
00803 mode = DEFAULT;
00804 switch (ch) {
00805 case '"':
00806 if (mode == DEFAULT) {
00807
00808 it = find_if(it, end, is_not_whitespace);
00809 if (it == end) {
00810
00811
00812
00813 goto done;
00814 }
00815 if (*it == '"') {
00816
00817
00818
00819 newprev = *it++;
00820 break;
00821 }
00822 }
00823 if (flags & QueryParser::FLAG_PHRASE) {
00824 Parse(pParser, QUOTE, NULL, &state);
00825 if (mode == DEFAULT) {
00826 mode = IN_QUOTES;
00827 } else {
00828
00829 if (mode == IN_PREFIXED_QUOTES)
00830 prefix_stack.pop_back();
00831 mode = DEFAULT;
00832 }
00833 }
00834 break;
00835
00836 case '+': case '-':
00837
00838 if (it == end) goto done;
00839 if (prev > ' ' && prev != '(') {
00840
00841 break;
00842 }
00843 if (is_whitespace(*it) || *it == '+' || *it == '-') {
00844
00845
00846
00847 newprev = *it++;
00848 break;
00849 }
00850 if (mode == DEFAULT && (flags & FLAG_LOVEHATE)) {
00851 int token;
00852 if (ch == '+') {
00853 token = LOVE;
00854 } else if (last_was_operator) {
00855 token = HATE_AFTER_AND;
00856 } else {
00857 token = HATE;
00858 }
00859 Parse(pParser, token, NULL, &state);
00860 goto just_had_operator_needing_term;
00861 }
00862
00863
00864 break;
00865
00866 case '(':
00867
00868 it = find_if(it, end, is_not_whitespace);
00869
00870 if (it == end) goto done;
00871 if (prev > ' ' && strchr("()+-", prev) == NULL) {
00872
00873 break;
00874 }
00875 if (*it == ')') {
00876
00877 newprev = *it++;
00878 break;
00879 }
00880 if (mode == DEFAULT && (flags & FLAG_BOOLEAN)) {
00881 prefix_stack.push_back(prefix_stack.back());
00882 Parse(pParser, BRA, NULL, &state);
00883 }
00884 break;
00885
00886 case ')':
00887 if (mode == DEFAULT && (flags & FLAG_BOOLEAN)) {
00888
00889
00890
00891 if (prefix_stack.size() > 1) prefix_stack.pop_back();
00892 Parse(pParser, KET, NULL, &state);
00893 }
00894 break;
00895
00896 case '~':
00897
00898 if (it == end) goto done;
00899 if (mode == DEFAULT && (flags & FLAG_SYNONYM)) {
00900 if (prev > ' ' && strchr("+-(", prev) == NULL) {
00901
00902 break;
00903 }
00904 if (!is_wordchar(*it)) {
00905
00906 break;
00907 }
00908 Parse(pParser, SYNONYM, NULL, &state);
00909 mode = EXPLICIT_SYNONYM;
00910 goto just_had_operator_needing_term;
00911 }
00912 break;
00913 }
00914
00915 continue;
00916 }
00917
00918 Assert(is_wordchar(*it));
00919
00920 size_t term_start_index = it.raw() - qs.data();
00921
00922 newprev = 'A';
00923
00924
00925 const PrefixInfo * prefix_info = NULL;
00926 if ((mode == DEFAULT || mode == IN_GROUP || mode == IN_GROUP2 || mode == EXPLICIT_SYNONYM) &&
00927 !prefixmap.empty()) {
00928
00929 Utf8Iterator p = find_if(it, end, is_not_wordchar);
00930 if (p != end && *p == ':' && ++p != end && *p > ' ' && *p != ')') {
00931 string field;
00932 p = it;
00933 while (*p != ':')
00934 Unicode::append_utf8(field, *p++);
00935 map<string, PrefixInfo>::const_iterator f;
00936 f = prefixmap.find(field);
00937 if (f != prefixmap.end()) {
00938
00939
00940 unsigned ch = *++p;
00941 prefix_info = &(f->second);
00942
00943 if (prefix_info->type != NON_BOOLEAN) {
00944
00945 if (mode == IN_GROUP || mode == IN_GROUP2)
00946 mode = DEFAULT;
00947 it = p;
00948 string name;
00949 if (it != end && *it == '"') {
00950
00951 ++it;
00952 while (it != end) {
00953 if (*it == '"') {
00954
00955 if (++it == end || *it != '"')
00956 break;
00957 }
00958 Unicode::append_utf8(name, *it++);
00959 }
00960 } else {
00961
00962
00963
00964
00965 while (it != end && *it > ' ' && *it != ')')
00966 Unicode::append_utf8(name, *it++);
00967 }
00968
00969 field += ':';
00970 field += name;
00971
00972 state.error = NULL;
00973 Term * token = new Term(&state, name, prefix_info, field);
00974 Parse(pParser, BOOLEAN_FILTER, token, &state);
00975 continue;
00976 }
00977
00978 if (ch == '"' && (flags & FLAG_PHRASE)) {
00979
00980 mode = IN_PREFIXED_QUOTES;
00981 Parse(pParser, QUOTE, NULL, &state);
00982 it = p;
00983 newprev = ch;
00984 ++it;
00985 prefix_stack.push_back(prefix_info);
00986 continue;
00987 }
00988
00989 if (ch == '(' && (flags & FLAG_BOOLEAN)) {
00990
00991 mode = DEFAULT;
00992 Parse(pParser, BRA, NULL, &state);
00993 it = p;
00994 newprev = ch;
00995 ++it;
00996 prefix_stack.push_back(prefix_info);
00997 continue;
00998 }
00999
01000 if (ch != ':') {
01001
01002 while (is_phrase_generator(ch)) {
01003 if (++p == end)
01004 goto not_prefix;
01005 ch = *p;
01006 }
01007 }
01008
01009 if (is_wordchar(ch)) {
01010
01011 it = p;
01012 } else {
01013 not_prefix:
01014
01015
01016 prefix_info = NULL;
01017 }
01018 }
01019 }
01020 }
01021
01022 phrased_term:
01023 bool was_acronym;
01024 bool is_cjk_term = false;
01025 string term = parse_term(it, end, cjk_ngram, is_cjk_term, was_acronym);
01026
01027
01028 if ((mode == DEFAULT || mode == IN_GROUP || mode == IN_GROUP2) &&
01029 (flags & FLAG_BOOLEAN) &&
01030
01031 !was_acronym &&
01032 !prefix_info &&
01033 term.size() >= 2 && term.size() <= 4 && U_isalpha(term[0])) {
01034
01035 string op = term;
01036 if (flags & FLAG_BOOLEAN_ANY_CASE) {
01037 for (string::iterator i = op.begin(); i != op.end(); ++i) {
01038 *i = C_toupper(*i);
01039 }
01040 }
01041 if (op.size() == 3) {
01042 if (op == "AND") {
01043 Parse(pParser, AND, NULL, &state);
01044 goto just_had_operator;
01045 }
01046 if (op == "NOT") {
01047 Parse(pParser, NOT, NULL, &state);
01048 goto just_had_operator;
01049 }
01050 if (op == "XOR") {
01051 Parse(pParser, XOR, NULL, &state);
01052 goto just_had_operator;
01053 }
01054 if (op == "ADJ") {
01055 if (it != end && *it == '/') {
01056 size_t width = 0;
01057 Utf8Iterator p = it;
01058 while (++p != end && U_isdigit(*p)) {
01059 width = (width * 10) + (*p - '0');
01060 }
01061 if (width && (p == end || is_whitespace(*p))) {
01062 it = p;
01063 Parse(pParser, ADJ, new Term(width), &state);
01064 goto just_had_operator;
01065 }
01066 } else {
01067 Parse(pParser, ADJ, NULL, &state);
01068 goto just_had_operator;
01069 }
01070 }
01071 } else if (op.size() == 2) {
01072 if (op == "OR") {
01073 Parse(pParser, OR, NULL, &state);
01074 goto just_had_operator;
01075 }
01076 } else if (op.size() == 4) {
01077 if (op == "NEAR") {
01078 if (it != end && *it == '/') {
01079 size_t width = 0;
01080 Utf8Iterator p = it;
01081 while (++p != end && U_isdigit(*p)) {
01082 width = (width * 10) + (*p - '0');
01083 }
01084 if (width && (p == end || is_whitespace(*p))) {
01085 it = p;
01086 Parse(pParser, NEAR, new Term(width), &state);
01087 goto just_had_operator;
01088 }
01089 } else {
01090 Parse(pParser, NEAR, NULL, &state);
01091 goto just_had_operator;
01092 }
01093 }
01094 }
01095 }
01096
01097
01098 if (!prefix_info) prefix_info = prefix_stack.back();
01099
01100 Assert(prefix_info->type == NON_BOOLEAN);
01101
01102 {
01103 string unstemmed_term(term);
01104 term = Unicode::tolower(term);
01105
01106
01107
01108 stem_strategy stem_term = stem_action;
01109 if (stem_term != STEM_NONE) {
01110 if (!stemmer.internal.get()) {
01111
01112 stem_term = STEM_NONE;
01113 } else if (stem_term == STEM_SOME) {
01114 if (!should_stem(unstemmed_term) ||
01115 (it != end && is_stem_preventer(*it))) {
01116
01117 stem_term = STEM_NONE;
01118 }
01119 }
01120 }
01121
01122 Term * term_obj = new Term(&state, term, prefix_info,
01123 unstemmed_term, stem_term, term_pos++);
01124
01125 if (is_cjk_term) {
01126 Parse(pParser, CJKTERM, term_obj, &state);
01127 if (it == end) break;
01128 continue;
01129 }
01130
01131 if (mode == DEFAULT || mode == IN_GROUP || mode == IN_GROUP2) {
01132 if (it != end) {
01133 if ((flags & FLAG_WILDCARD) && *it == '*') {
01134 Utf8Iterator p(it);
01135 ++p;
01136 if (p == end || !is_wordchar(*p)) {
01137 it = p;
01138 if (mode == IN_GROUP || mode == IN_GROUP2) {
01139
01140
01141 if (mode == IN_GROUP2)
01142 Parse(pParser, EMPTY_GROUP_OK, NULL, &state);
01143 mode = DEFAULT;
01144 }
01145
01146
01147 Parse(pParser, WILD_TERM, term_obj, &state);
01148 continue;
01149 }
01150 }
01151 } else {
01152 if (flags & FLAG_PARTIAL) {
01153 if (mode == IN_GROUP || mode == IN_GROUP2) {
01154
01155
01156 if (mode == IN_GROUP2)
01157 Parse(pParser, EMPTY_GROUP_OK, NULL, &state);
01158 mode = DEFAULT;
01159 }
01160
01161
01162 Parse(pParser, PARTIAL_TERM, term_obj, &state);
01163 continue;
01164 }
01165 }
01166 }
01167
01168
01169
01170 if ((flags & FLAG_SPELLING_CORRECTION) && !was_acronym) {
01171 const list<string> & pfxes = prefix_info->prefixes;
01172 list<string>::const_iterator pfx_it;
01173 for (pfx_it = pfxes.begin(); pfx_it != pfxes.end(); ++pfx_it) {
01174 if (!pfx_it->empty())
01175 continue;
01176 const string & suggest = db.get_spelling_suggestion(term);
01177 if (!suggest.empty()) {
01178 if (corrected_query.empty()) corrected_query = qs;
01179 size_t term_end_index = it.raw() - qs.data();
01180 size_t n = term_end_index - term_start_index;
01181 size_t pos = term_start_index + correction_offset;
01182 corrected_query.replace(pos, n, suggest);
01183 correction_offset += suggest.size();
01184 correction_offset -= n;
01185 }
01186 break;
01187 }
01188 }
01189
01190 if (mode == IN_PHRASED_TERM) {
01191 Parse(pParser, PHR_TERM, term_obj, &state);
01192 } else {
01193
01194
01195 if ((mode == IN_GROUP || mode == IN_GROUP2) &&
01196 is_phrase_generator(*it)) {
01197
01198 Utf8Iterator p = it;
01199 do {
01200 ++p;
01201 } while (p != end && is_phrase_generator(*p));
01202
01203
01204 if (p != end && is_wordchar(*p)) {
01205 mode = DEFAULT;
01206 }
01207 }
01208
01209 int token = TERM;
01210 if (mode == IN_GROUP || mode == IN_GROUP2) {
01211 mode = IN_GROUP2;
01212 token = GROUP_TERM;
01213 }
01214 Parse(pParser, token, term_obj, &state);
01215 if (token == TERM && mode != DEFAULT)
01216 continue;
01217 }
01218 }
01219
01220 if (it == end) break;
01221
01222 if (is_phrase_generator(*it)) {
01223
01224 do {
01225 ++it;
01226 } while (it != end && is_phrase_generator(*it));
01227
01228
01229 if (it != end && is_wordchar(*it)) {
01230 mode = IN_PHRASED_TERM;
01231 term_start_index = it.raw() - qs.data();
01232 goto phrased_term;
01233 }
01234 } else if (mode == DEFAULT || mode == IN_GROUP || mode == IN_GROUP2) {
01235 int old_mode = mode;
01236 mode = DEFAULT;
01237 if (!last_was_operator_needing_term && is_whitespace(*it)) {
01238 newprev = ' ';
01239
01240 do {
01241 ++it;
01242 } while (it != end && is_whitespace(*it));
01243
01244
01245 if (it != end && is_wordchar(*it)) {
01246 if (old_mode == IN_GROUP || old_mode == IN_GROUP2) {
01247 mode = IN_GROUP2;
01248 } else {
01249 mode = IN_GROUP;
01250 }
01251 }
01252 }
01253 }
01254 }
01255 done:
01256 if (!state.error) {
01257
01258 if (mode == IN_QUOTES || mode == IN_PREFIXED_QUOTES)
01259 Parse(pParser, QUOTE, NULL, &state);
01260 Parse(pParser, 0, NULL, &state);
01261 }
01262
01263 errmsg = state.error;
01264 return state.query;
01265 }
01266
01267 struct ProbQuery {
01268 Query * query;
01269 Query * love;
01270 Query * hate;
01271
01272
01273
01274 map<filter_group_id, Query> filter;
01275
01276 ProbQuery() : query(0), love(0), hate(0) { }
01277 ~ProbQuery() {
01278 delete query;
01279 delete love;
01280 delete hate;
01281 }
01282
01283 void add_filter(const filter_group_id & id, const Query & q) {
01284 filter[id] = q;
01285 }
01286
01287 void append_filter(const filter_group_id & id, const Query & qnew) {
01288 Query & q = filter[id];
01289
01290
01291 bool exclusive = (id.prefix_info->type == BOOLEAN_EXCLUSIVE);
01292 Query::op op = exclusive ? Query::OP_OR : Query::OP_AND;
01293 q = Query(op, q, qnew);
01294 }
01295
01296 void add_filter_range(Xapian::valueno slot, const Query & range) {
01297 filter[filter_group_id(slot)] = range;
01298 }
01299
01300 void append_filter_range(Xapian::valueno slot, const Query & range) {
01301 Query & q = filter[filter_group_id(slot)];
01302 q = Query(Query::OP_OR, q, range);
01303 }
01304
01305 Query merge_filters() const {
01306 map<filter_group_id, Query>::const_iterator i = filter.begin();
01307 Assert(i != filter.end());
01308 Query q = i->second;
01309 while (++i != filter.end()) {
01310 q = Query(Query::OP_AND, q, i->second);
01311 }
01312 return q;
01313 }
01314 };
01315
01317 class TermGroup {
01318 vector<Term *> terms;
01319
01325 bool empty_ok;
01326
01327 public:
01328 TermGroup() : empty_ok(false) { }
01329
01331 void add_term(Term * term) {
01332 terms.push_back(term);
01333 }
01334
01336 void set_empty_ok() { empty_ok = true; }
01337
01339 Query * as_group(State *state) const;
01340
01344 void destroy() { delete this; }
01345
01346 protected:
01350 ~TermGroup() {
01351 vector<Term*>::const_iterator i;
01352 for (i = terms.begin(); i != terms.end(); ++i) {
01353 delete *i;
01354 }
01355 }
01356 };
01357
01358 Query *
01359 TermGroup::as_group(State *state) const
01360 {
01361 const Xapian::Stopper * stopper = state->get_stopper();
01362 size_t stoplist_size = state->stoplist_size();
01363 bool default_op_is_positional = is_positional(state->default_op());
01364 reprocess:
01365 Query::op default_op = state->default_op();
01366 vector<Query> subqs;
01367 subqs.reserve(terms.size());
01368
01369
01370
01371 const unsigned ENABLE_AUTO_MULTIWORD_SYNONYMS = 1024;
01372 if (state->flags & ENABLE_AUTO_MULTIWORD_SYNONYMS) {
01373
01374 Database db = state->get_database();
01375
01376 string key;
01377 vector<Term*>::const_iterator begin = terms.begin();
01378 vector<Term*>::const_iterator i = begin;
01379 while (i != terms.end()) {
01380 TermIterator synkey(db.synonym_keys_begin((*i)->name));
01381 TermIterator synend(db.synonym_keys_end((*i)->name));
01382 if (synkey == synend) {
01383
01384 if (stopper && (*stopper)((*i)->name)) {
01385 state->add_to_stoplist(*i);
01386 } else {
01387 if (default_op_is_positional)
01388 (*i)->need_positions();
01389 subqs.push_back((*i)->get_query_with_auto_synonyms());
01390 }
01391 begin = ++i;
01392 continue;
01393 }
01394 key.resize(0);
01395 while (i != terms.end()) {
01396 if (!key.empty()) key += ' ';
01397 key += (*i)->name;
01398 ++i;
01399 synkey.skip_to(key);
01400 if (synkey == synend || !startswith(*synkey, key)) break;
01401 }
01402
01403 TermIterator syn, end;
01404 while (true) {
01405 syn = db.synonyms_begin(key);
01406 end = db.synonyms_end(key);
01407 if (syn != end) break;
01408 if (--i == begin) break;
01409 key.resize(key.size() - (*i)->name.size() - 1);
01410 }
01411 if (i == begin) {
01412
01413 if (stopper && (*stopper)((*i)->name)) {
01414 state->add_to_stoplist(*i);
01415 } else {
01416 if (default_op_is_positional)
01417 (*i)->need_positions();
01418 subqs.push_back((*i)->get_query_with_auto_synonyms());
01419 }
01420 begin = ++i;
01421 continue;
01422 }
01423
01424 vector<Query> subqs2;
01425 vector<Term*>::const_iterator j;
01426 for (j = begin; j != i; ++j) {
01427 if (stopper && (*stopper)((*j)->name)) {
01428 state->add_to_stoplist(*j);
01429 } else {
01430 if (default_op_is_positional)
01431 (*i)->need_positions();
01432 subqs2.push_back((*j)->get_query());
01433 }
01434 }
01435 Query q_original_terms;
01436 if (default_op_is_positional) {
01437 q_original_terms = Query(default_op,
01438 subqs2.begin(), subqs2.end(),
01439 subqs2.size() + 9);
01440 } else {
01441 q_original_terms = Query(default_op,
01442 subqs2.begin(), subqs2.end());
01443 }
01444 subqs2.clear();
01445
01446
01447 Xapian::termpos pos = (*begin)->pos;
01448 begin = i;
01449 while (syn != end) {
01450 subqs2.push_back(Query(*syn, 1, pos));
01451 ++syn;
01452 }
01453 Query q_synonym_terms(Query::OP_SYNONYM, subqs2.begin(), subqs2.end());
01454 subqs2.clear();
01455 subqs.push_back(Query(Query::OP_SYNONYM,
01456 q_original_terms, q_synonym_terms));
01457 }
01458 } else {
01459 vector<Term*>::const_iterator i;
01460 for (i = terms.begin(); i != terms.end(); ++i) {
01461 if (stopper && (*stopper)((*i)->name)) {
01462 state->add_to_stoplist(*i);
01463 } else {
01464 if (default_op_is_positional)
01465 (*i)->need_positions();
01466 subqs.push_back((*i)->get_query_with_auto_synonyms());
01467 }
01468 }
01469 }
01470
01471 if (!empty_ok && stopper && subqs.empty() &&
01472 stoplist_size < state->stoplist_size()) {
01473
01474
01475 state->stoplist_resize(stoplist_size);
01476 stopper = NULL;
01477 goto reprocess;
01478 }
01479
01480 Query * q = NULL;
01481 if (!subqs.empty()) {
01482 if (default_op_is_positional) {
01483 q = new Query(default_op, subqs.begin(), subqs.end(),
01484 subqs.size() + 9);
01485 } else {
01486 q = new Query(default_op, subqs.begin(), subqs.end());
01487 }
01488 }
01489 delete this;
01490 return q;
01491 }
01492
01494 class Terms {
01495 vector<Term *> terms;
01496 size_t window;
01497
01507 bool uniform_prefixes;
01508
01512 const list<string> * prefixes;
01513
01515 Query * as_opwindow_query(Query::op op, Xapian::termcount w_delta) const {
01516 Query * q = NULL;
01517 size_t n_terms = terms.size();
01518 Xapian::termcount w = w_delta + terms.size();
01519 if (uniform_prefixes) {
01520 if (prefixes) {
01521 list<string>::const_iterator piter;
01522 for (piter = prefixes->begin(); piter != prefixes->end(); ++piter) {
01523 vector<Query> subqs;
01524 subqs.reserve(n_terms);
01525 vector<Term *>::const_iterator titer;
01526 for (titer = terms.begin(); titer != terms.end(); ++titer) {
01527 Term * t = *titer;
01528 subqs.push_back(Query(t->make_term(*piter), 1, t->pos));
01529 }
01530 add_to_query(q, Query::OP_OR,
01531 Query(op, subqs.begin(), subqs.end(), w));
01532 }
01533 }
01534 } else {
01535 vector<Query> subqs;
01536 subqs.reserve(n_terms);
01537 vector<Term *>::const_iterator titer;
01538 for (titer = terms.begin(); titer != terms.end(); ++titer) {
01539 subqs.push_back((*titer)->get_query());
01540 }
01541 q = new Query(op, subqs.begin(), subqs.end(), w);
01542 }
01543
01544 delete this;
01545 return q;
01546 }
01547
01548 public:
01549 Terms() : window(0), uniform_prefixes(true), prefixes(NULL) { }
01550
01552 void add_positional_term(Term * term) {
01553 const list<string> & term_prefixes = term->prefix_info->prefixes;
01554 if (terms.empty()) {
01555 prefixes = &term_prefixes;
01556 } else if (uniform_prefixes && prefixes != &term_prefixes) {
01557 if (*prefixes != term_prefixes) {
01558 prefixes = NULL;
01559 uniform_prefixes = false;
01560 }
01561 }
01562 term->need_positions();
01563 terms.push_back(term);
01564 }
01565
01566 void adjust_window(size_t alternative_window) {
01567 if (alternative_window > window) window = alternative_window;
01568 }
01569
01571 Query * as_phrase_query() const {
01572 return as_opwindow_query(Query::OP_PHRASE, 0);
01573 }
01574
01576 Query * as_near_query() const {
01577
01578
01579
01580 size_t w = window;
01581 if (w == 0) w = 10;
01582 return as_opwindow_query(Query::OP_NEAR, w - 1);
01583 }
01584
01586 Query * as_adj_query() const {
01587
01588
01589
01590 size_t w = window;
01591 if (w == 0) w = 10;
01592 return as_opwindow_query(Query::OP_PHRASE, w - 1);
01593 }
01594
01598 void destroy() { delete this; }
01599
01600 protected:
01604 ~Terms() {
01605 vector<Term *>::const_iterator t;
01606 for (t = terms.begin(); t != terms.end(); ++t) {
01607 delete *t;
01608 }
01609 }
01610 };
01611
01612 void
01613 Term::as_positional_cjk_term(Terms * terms) const
01614 {
01615
01616 string t;
01617 for (Utf8Iterator it(name); it != Utf8Iterator(); ++it) {
01618 Unicode::append_utf8(t, *it);
01619 Term * c = new Term(state, t, prefix_info, unstemmed, stem, pos);
01620 terms->add_positional_term(c);
01621 t.resize(0);
01622 }
01623
01624
01625
01626 delete this;
01627 }
01628
01629
01630 #define BOOL_OP_TO_QUERY(E, A, OP, B, OP_TXT) \
01631 do {\
01632 if (!A || !B) {\
01633 state->error = "Syntax: <expression> "OP_TXT" <expression>";\
01634 yy_parse_failed(yypParser);\
01635 return;\
01636 }\
01637 E = new Query(OP, *A, *B);\
01638 delete A;\
01639 delete B;\
01640 } while (0)
01641
01642 #line 1643 "queryparser/queryparser_internal.cc"
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655 #ifndef INTERFACE
01656 # define INTERFACE 1
01657 #endif
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692 #define YYCODETYPE unsigned char
01693 #define YYNOCODE 40
01694 #define YYACTIONTYPE unsigned char
01695 #define ParseTOKENTYPE Term *
01696 typedef union {
01697 int yyinit;
01698 ParseTOKENTYPE yy0;
01699 TermGroup * yy14;
01700 Terms * yy32;
01701 Query * yy39;
01702 ProbQuery * yy40;
01703 int yy46;
01704 } YYMINORTYPE;
01705 #ifndef YYSTACKDEPTH
01706 #define YYSTACKDEPTH 100
01707 #endif
01708 #define ParseARG_SDECL State * state;
01709 #define ParseARG_PDECL ,State * state
01710 #define ParseARG_FETCH State * state = yypParser->state
01711 #define ParseARG_STORE yypParser->state = state
01712 #define YYNSTATE 77
01713 #define YYNRULE 56
01714 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
01715 #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
01716 #define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726 #ifndef yytestcase
01727 # define yytestcase(X)
01728 #endif
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777 static const YYACTIONTYPE yy_action[] = {
01778 134, 25, 35, 17, 8, 58, 19, 13, 16, 42,
01779 28, 24, 29, 31, 6, 1, 2, 11, 12, 7,
01780 34, 15, 22, 77, 45, 46, 74, 59, 14, 5,
01781 78, 65, 43, 3, 4, 1, 2, 55, 11, 12,
01782 52, 34, 15, 30, 56, 45, 46, 74, 59, 14,
01783 5, 50, 65, 38, 35, 36, 8, 58, 19, 13,
01784 16, 51, 28, 24, 29, 31, 38, 35, 37, 8,
01785 58, 19, 13, 16, 32, 28, 24, 29, 31, 38,
01786 35, 21, 8, 58, 19, 13, 16, 64, 28, 24,
01787 29, 31, 38, 35, 23, 8, 58, 19, 13, 16,
01788 135, 28, 24, 29, 31, 33, 35, 17, 8, 58,
01789 19, 13, 16, 135, 28, 24, 29, 31, 38, 35,
01790 75, 8, 58, 19, 13, 16, 135, 28, 24, 29,
01791 31, 38, 35, 76, 8, 58, 19, 13, 16, 53,
01792 28, 24, 29, 31, 11, 12, 57, 34, 15, 54,
01793 135, 45, 46, 74, 59, 14, 5, 135, 65, 135,
01794 104, 104, 135, 34, 18, 135, 135, 45, 46, 104,
01795 104, 14, 5, 108, 65, 108, 108, 108, 108, 26,
01796 27, 26, 27, 48, 135, 135, 41, 40, 41, 40,
01797 47, 34, 20, 49, 108, 45, 46, 62, 135, 14,
01798 5, 135, 65, 34, 20, 135, 135, 45, 46, 67,
01799 135, 14, 5, 135, 65, 34, 20, 135, 135, 45,
01800 46, 71, 135, 14, 5, 135, 65, 34, 20, 135,
01801 135, 45, 46, 73, 135, 14, 5, 135, 65, 34,
01802 18, 135, 135, 45, 46, 135, 135, 14, 5, 135,
01803 65, 135, 39, 44, 135, 28, 24, 29, 31, 61,
01804 135, 135, 63, 135, 28, 24, 29, 31, 135, 66,
01805 135, 135, 63, 135, 28, 24, 29, 31, 70, 135,
01806 135, 63, 135, 28, 24, 29, 31, 72, 135, 135,
01807 63, 135, 28, 24, 29, 31, 135, 69, 44, 135,
01808 28, 24, 29, 31, 109, 135, 109, 109, 109, 109,
01809 9, 10, 4, 1, 2, 135, 135, 135, 135, 68,
01810 60, 135, 135, 135, 135, 109,
01811 };
01812 static const YYCODETYPE yy_lookahead[] = {
01813 25, 26, 27, 28, 29, 30, 31, 32, 33, 12,
01814 35, 36, 37, 38, 5, 4, 5, 8, 9, 10,
01815 11, 12, 34, 0, 15, 16, 17, 18, 19, 20,
01816 0, 22, 12, 2, 3, 4, 5, 12, 8, 9,
01817 14, 11, 12, 6, 12, 15, 16, 17, 18, 19,
01818 20, 12, 22, 26, 27, 28, 29, 30, 31, 32,
01819 33, 22, 35, 36, 37, 38, 26, 27, 28, 29,
01820 30, 31, 32, 33, 7, 35, 36, 37, 38, 26,
01821 27, 28, 29, 30, 31, 32, 33, 12, 35, 36,
01822 37, 38, 26, 27, 28, 29, 30, 31, 32, 33,
01823 39, 35, 36, 37, 38, 26, 27, 28, 29, 30,
01824 31, 32, 33, 39, 35, 36, 37, 38, 26, 27,
01825 28, 29, 30, 31, 32, 33, 39, 35, 36, 37,
01826 38, 26, 27, 28, 29, 30, 31, 32, 33, 13,
01827 35, 36, 37, 38, 8, 9, 21, 11, 12, 23,
01828 39, 15, 16, 17, 18, 19, 20, 39, 22, 39,
01829 8, 9, 39, 11, 12, 39, 39, 15, 16, 17,
01830 18, 19, 20, 0, 22, 2, 3, 4, 5, 6,
01831 7, 6, 7, 12, 39, 39, 13, 14, 13, 14,
01832 19, 11, 12, 22, 21, 15, 16, 17, 39, 19,
01833 20, 39, 22, 11, 12, 39, 39, 15, 16, 17,
01834 39, 19, 20, 39, 22, 11, 12, 39, 39, 15,
01835 16, 17, 39, 19, 20, 39, 22, 11, 12, 39,
01836 39, 15, 16, 17, 39, 19, 20, 39, 22, 11,
01837 12, 39, 39, 15, 16, 39, 39, 19, 20, 39,
01838 22, 39, 32, 33, 39, 35, 36, 37, 38, 30,
01839 39, 39, 33, 39, 35, 36, 37, 38, 39, 30,
01840 39, 39, 33, 39, 35, 36, 37, 38, 30, 39,
01841 39, 33, 39, 35, 36, 37, 38, 30, 39, 39,
01842 33, 39, 35, 36, 37, 38, 39, 32, 33, 39,
01843 35, 36, 37, 38, 0, 39, 2, 3, 4, 5,
01844 8, 9, 3, 4, 5, 39, 39, 39, 39, 17,
01845 18, 39, 39, 39, 39, 21,
01846 };
01847 #define YY_SHIFT_USE_DFLT (-4)
01848 #define YY_SHIFT_MAX 34
01849 static const short yy_shift_ofst[] = {
01850 30, 9, 136, 136, 136, 136, 136, 136, 152, 180,
01851 192, 204, 216, 228, 39, 173, 304, 31, 175, 302,
01852 175, 309, 171, 11, 126, 23, -3, 20, 26, 37,
01853 25, 67, 32, 125, 75,
01854 };
01855 #define YY_REDUCE_USE_DFLT (-26)
01856 #define YY_REDUCE_MAX 14
01857 static const short yy_reduce_ofst[] = {
01858 -25, 27, 40, 53, 66, 79, 92, 105, 220, 229,
01859 239, 248, 257, 265, -12,
01860 };
01861 static const YYACTIONTYPE yy_default[] = {
01862 87, 87, 87, 87, 87, 87, 87, 87, 88, 133,
01863 133, 133, 133, 105, 133, 106, 107, 133, 106, 133,
01864 108, 84, 133, 85, 114, 86, 133, 133, 113, 115,
01865 133, 116, 133, 86, 133, 79, 80, 81, 86, 93,
01866 124, 126, 129, 131, 107, 110, 111, 112, 122, 123,
01867 120, 121, 125, 127, 128, 130, 132, 117, 89, 90,
01868 91, 95, 103, 109, 118, 119, 97, 99, 101, 92,
01869 94, 102, 96, 98, 100, 82, 83,
01870 };
01871 #define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883 #ifdef YYFALLBACK
01884 static const YYCODETYPE yyFallback[] = {
01885 };
01886 #endif
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900 struct yyStackEntry {
01901 yyStackEntry() {
01902 stateno = 0;
01903 major = 0;
01904 }
01905 yyStackEntry(YYACTIONTYPE stateno_, YYCODETYPE major_, YYMINORTYPE minor_) {
01906 stateno = stateno_;
01907 major = major_;
01908 minor = minor_;
01909 }
01910 YYACTIONTYPE stateno;
01911 YYCODETYPE major;
01912
01913 YYMINORTYPE minor;
01914
01915 };
01916
01917
01918
01919 struct yyParser {
01920 int yyerrcnt;
01921 ParseARG_SDECL
01922 vector<yyStackEntry> yystack;
01923 };
01924 typedef struct yyParser yyParser;
01925
01926 #include "omassert.h"
01927 #include "debuglog.h"
01928
01929 #ifdef XAPIAN_DEBUG_LOG
01930
01931
01932 static const char *const yyTokenName[] = {
01933 "$", "ERROR", "OR", "XOR",
01934 "AND", "NOT", "NEAR", "ADJ",
01935 "LOVE", "HATE", "HATE_AFTER_AND", "SYNONYM",
01936 "TERM", "GROUP_TERM", "PHR_TERM", "WILD_TERM",
01937 "PARTIAL_TERM", "BOOLEAN_FILTER", "RANGE", "QUOTE",
01938 "BRA", "KET", "CJKTERM", "EMPTY_GROUP_OK",
01939 "error", "query", "expr", "prob_expr",
01940 "bool_arg", "prob", "term", "stop_prob",
01941 "stop_term", "compound_term", "phrase", "phrased_term",
01942 "group", "near_expr", "adj_expr",
01943 };
01944
01945
01946
01947 static const char *const yyRuleName[] = {
01948 "query ::= expr",
01949 "query ::=",
01950 "expr ::= prob_expr",
01951 "expr ::= bool_arg AND bool_arg",
01952 "expr ::= bool_arg NOT bool_arg",
01953 "expr ::= bool_arg AND NOT bool_arg",
01954 "expr ::= bool_arg AND HATE_AFTER_AND bool_arg",
01955 "expr ::= bool_arg OR bool_arg",
01956 "expr ::= bool_arg XOR bool_arg",
01957 "bool_arg ::= expr",
01958 "bool_arg ::=",
01959 "prob_expr ::= prob",
01960 "prob_expr ::= term",
01961 "prob ::= RANGE",
01962 "prob ::= stop_prob RANGE",
01963 "prob ::= stop_term stop_term",
01964 "prob ::= prob stop_term",
01965 "prob ::= LOVE term",
01966 "prob ::= stop_prob LOVE term",
01967 "prob ::= HATE term",
01968 "prob ::= stop_prob HATE term",
01969 "prob ::= HATE BOOLEAN_FILTER",
01970 "prob ::= stop_prob HATE BOOLEAN_FILTER",
01971 "prob ::= BOOLEAN_FILTER",
01972 "prob ::= stop_prob BOOLEAN_FILTER",
01973 "prob ::= LOVE BOOLEAN_FILTER",
01974 "prob ::= stop_prob LOVE BOOLEAN_FILTER",
01975 "stop_prob ::= prob",
01976 "stop_prob ::= stop_term",
01977 "stop_term ::= TERM",
01978 "stop_term ::= compound_term",
01979 "term ::= TERM",
01980 "term ::= compound_term",
01981 "compound_term ::= WILD_TERM",
01982 "compound_term ::= PARTIAL_TERM",
01983 "compound_term ::= QUOTE phrase QUOTE",
01984 "compound_term ::= phrased_term",
01985 "compound_term ::= group",
01986 "compound_term ::= near_expr",
01987 "compound_term ::= adj_expr",
01988 "compound_term ::= BRA expr KET",
01989 "compound_term ::= SYNONYM TERM",
01990 "compound_term ::= CJKTERM",
01991 "phrase ::= TERM",
01992 "phrase ::= CJKTERM",
01993 "phrase ::= phrase TERM",
01994 "phrase ::= phrase CJKTERM",
01995 "phrased_term ::= TERM PHR_TERM",
01996 "phrased_term ::= phrased_term PHR_TERM",
01997 "group ::= TERM GROUP_TERM",
01998 "group ::= group GROUP_TERM",
01999 "group ::= group EMPTY_GROUP_OK",
02000 "near_expr ::= TERM NEAR TERM",
02001 "near_expr ::= near_expr NEAR TERM",
02002 "adj_expr ::= TERM ADJ TERM",
02003 "adj_expr ::= adj_expr ADJ TERM",
02004 };
02005
02006
02007
02008
02009
02010 static const char *ParseTokenName(int tokenType){
02011 if( tokenType>=0 && tokenType<(int)(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
02012 return yyTokenName[tokenType];
02013 }
02014 return "Unknown";
02015 }
02016
02017
02018
02019
02020
02021 static const char *ParseRuleName(int ruleNum){
02022 if( ruleNum>=0 && ruleNum<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
02023 return yyRuleName[ruleNum];
02024 }
02025 return "Unknown";
02026 }
02027 #endif
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041 static yyParser *ParseAlloc(){
02042 return new yyParser;
02043 }
02044
02045
02046
02047
02048
02049
02050 static void yy_destructor(
02051 yyParser *yypParser,
02052 YYCODETYPE yymajor,
02053 YYMINORTYPE *yypminor
02054 ){
02055 ParseARG_FETCH;
02056 switch( yymajor ){
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068 case 1:
02069 case 2:
02070 case 3:
02071 case 4:
02072 case 5:
02073 case 6:
02074 case 7:
02075 case 8:
02076 case 9:
02077 case 10:
02078 case 11:
02079 case 12:
02080 case 13:
02081 case 14:
02082 case 15:
02083 case 16:
02084 case 17:
02085 case 18:
02086 case 19:
02087 case 20:
02088 case 21:
02089 case 22:
02090 case 23:
02091 {
02092 #line 1636 "queryparser/queryparser.lemony"
02093 delete (yypminor->yy0);
02094 #line 2095 "queryparser/queryparser_internal.cc"
02095 }
02096 break;
02097 case 26:
02098 case 27:
02099 case 28:
02100 case 30:
02101 case 32:
02102 case 33:
02103 {
02104 #line 1711 "queryparser/queryparser.lemony"
02105 delete (yypminor->yy39);
02106 #line 2107 "queryparser/queryparser_internal.cc"
02107 }
02108 break;
02109 case 29:
02110 case 31:
02111 {
02112 #line 1806 "queryparser/queryparser.lemony"
02113 delete (yypminor->yy40);
02114 #line 2115 "queryparser/queryparser_internal.cc"
02115 }
02116 break;
02117 case 34:
02118 case 35:
02119 case 37:
02120 case 38:
02121 {
02122 #line 2011 "queryparser/queryparser.lemony"
02123 (yypminor->yy32)->destroy();
02124 #line 2125 "queryparser/queryparser_internal.cc"
02125 }
02126 break;
02127 case 36:
02128 {
02129 #line 2055 "queryparser/queryparser.lemony"
02130 (yypminor->yy14)->destroy();
02131 #line 2132 "queryparser/queryparser_internal.cc"
02132 }
02133 break;
02134 default: break;
02135 }
02136 ParseARG_STORE;
02137 }
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147 static int yy_pop_parser_stack(yyParser *pParser){
02148 YYCODETYPE yymajor;
02149 if( pParser->yystack.empty() ) return 0;
02150 yyStackEntry *yytos = &pParser->yystack.back();
02151
02152 LOGLINE(QUERYPARSER, "Popping " << ParseTokenName(yytos->major));
02153 yymajor = (YYCODETYPE)yytos->major;
02154 yy_destructor(pParser, yymajor, &yytos->minor);
02155 pParser->yystack.pop_back();
02156 return yymajor;
02157 }
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167 static void ParseFree(
02168 yyParser *pParser
02169 ){
02170 if( pParser==0 ) return;
02171 while( !pParser->yystack.empty() ) yy_pop_parser_stack(pParser);
02172 delete pParser;
02173 }
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183 static int yy_find_shift_action(
02184 yyParser *pParser,
02185 YYCODETYPE iLookAhead
02186 ){
02187 int i;
02188 int stateno = pParser->yystack.back().stateno;
02189
02190 if( stateno>YY_SHIFT_MAX || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
02191 return yy_default[stateno];
02192 }
02193 Assert( iLookAhead!=YYNOCODE );
02194 i += iLookAhead;
02195 if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
02196 if( iLookAhead>0 ){
02197 #ifdef YYFALLBACK
02198 YYCODETYPE iFallback;
02199 if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
02200 && (iFallback = yyFallback[iLookAhead])!=0 ){
02201 LOGLINE(QUERYPARSER,
02202 "FALLBACK " << ParseTokenName(iLookAhead) << " => " <<
02203 ParseTokenName(iFallback));
02204 return yy_find_shift_action(pParser, iFallback);
02205 }
02206 #endif
02207 #ifdef YYWILDCARD
02208 {
02209 int j = i - iLookAhead + YYWILDCARD;
02210 if( j>=0 && j<YY_SZ_ACTTAB && yy_lookahead[j]==YYWILDCARD ){
02211 LOGLINE(QUERYPARSER,
02212 "WILDCARD " << ParseTokenName(iLookAhead) << " => " <<
02213 ParseTokenName(YYWILDCARD));
02214 return yy_action[j];
02215 }
02216 }
02217 #endif
02218 }
02219 return yy_default[stateno];
02220 }else{
02221 return yy_action[i];
02222 }
02223 }
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233 static int yy_find_reduce_action(
02234 int stateno,
02235 YYCODETYPE iLookAhead
02236 ){
02237 int i;
02238 #ifdef YYERRORSYMBOL
02239 if( stateno>YY_REDUCE_MAX ){
02240 return yy_default[stateno];
02241 }
02242 #else
02243 Assert( stateno<=YY_REDUCE_MAX );
02244 #endif
02245 i = yy_reduce_ofst[stateno];
02246 Assert( i!=YY_REDUCE_USE_DFLT );
02247 Assert( iLookAhead!=YYNOCODE );
02248 i += iLookAhead;
02249 #ifdef YYERRORSYMBOL
02250 if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
02251 return yy_default[stateno];
02252 }
02253 #else
02254 Assert( i>=0 && i<YY_SZ_ACTTAB );
02255 Assert( yy_lookahead[i]==iLookAhead );
02256 #endif
02257 return yy_action[i];
02258 }
02259
02260
02261
02262
02263 static void yy_shift(
02264 yyParser *yypParser,
02265 int yyNewState,
02266 int yyMajor,
02267 YYMINORTYPE *yypMinor
02268 ){
02269
02270
02271
02272
02273 #if 0
02274 #endif
02275 #ifdef XAPIAN_DEBUG_LOG
02276 unsigned i;
02277 LOGLINE(QUERYPARSER, "Shift " << yyNewState);
02278 string stack("Stack:");
02279 for (i = 0; i < yypParser->yystack.size(); i++) {
02280 stack += ' ';
02281 stack += ParseTokenName(yypParser->yystack[i].major);
02282 }
02283 LOGLINE(QUERYPARSER, stack);
02284 #endif
02285 yypParser->yystack.push_back(yyStackEntry(yyNewState, yyMajor, *yypMinor));
02286 }
02287
02288
02289
02290
02291 static const struct {
02292 YYCODETYPE lhs;
02293 unsigned char nrhs;
02294 } yyRuleInfo[] = {
02295 { 25, 1 },
02296 { 25, 0 },
02297 { 26, 1 },
02298 { 26, 3 },
02299 { 26, 3 },
02300 { 26, 4 },
02301 { 26, 4 },
02302 { 26, 3 },
02303 { 26, 3 },
02304 { 28, 1 },
02305 { 28, 0 },
02306 { 27, 1 },
02307 { 27, 1 },
02308 { 29, 1 },
02309 { 29, 2 },
02310 { 29, 2 },
02311 { 29, 2 },
02312 { 29, 2 },
02313 { 29, 3 },
02314 { 29, 2 },
02315 { 29, 3 },
02316 { 29, 2 },
02317 { 29, 3 },
02318 { 29, 1 },
02319 { 29, 2 },
02320 { 29, 2 },
02321 { 29, 3 },
02322 { 31, 1 },
02323 { 31, 1 },
02324 { 32, 1 },
02325 { 32, 1 },
02326 { 30, 1 },
02327 { 30, 1 },
02328 { 33, 1 },
02329 { 33, 1 },
02330 { 33, 3 },
02331 { 33, 1 },
02332 { 33, 1 },
02333 { 33, 1 },
02334 { 33, 1 },
02335 { 33, 3 },
02336 { 33, 2 },
02337 { 33, 1 },
02338 { 34, 1 },
02339 { 34, 1 },
02340 { 34, 2 },
02341 { 34, 2 },
02342 { 35, 2 },
02343 { 35, 2 },
02344 { 36, 2 },
02345 { 36, 2 },
02346 { 36, 2 },
02347 { 37, 3 },
02348 { 37, 3 },
02349 { 38, 3 },
02350 { 38, 3 },
02351 };
02352
02353 static void yy_accept(yyParser*);
02354
02355
02356
02357
02358
02359 static void yy_reduce(
02360 yyParser *yypParser,
02361 int yyruleno
02362 ){
02363 int yygoto;
02364 int yyact;
02365 YYMINORTYPE yygotominor;
02366 yyStackEntry *yymsp;
02367 int yysize;
02368 ParseARG_FETCH;
02369 yymsp = &yypParser->yystack.back();
02370 #ifdef XAPIAN_DEBUG_LOG
02371 LOGLINE(QUERYPARSER, "Reduce [" << ParseRuleName(yyruleno) << "].");
02372 #endif
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393 switch( yyruleno ){
02394
02395
02396
02397
02398
02399
02400
02401
02402 case 0:
02403 #line 1693 "queryparser/queryparser.lemony"
02404 {
02405
02406 if (yymsp[0].minor.yy39) {
02407 state->query = *yymsp[0].minor.yy39;
02408 delete yymsp[0].minor.yy39;
02409 } else {
02410 state->query = Query();
02411 }
02412 }
02413 #line 2414 "queryparser/queryparser_internal.cc"
02414 break;
02415 case 1:
02416 #line 1703 "queryparser/queryparser.lemony"
02417 {
02418
02419 state->query = Query();
02420 }
02421 #line 2422 "queryparser/queryparser_internal.cc"
02422 break;
02423 case 2:
02424 case 9: yytestcase(yyruleno==9);
02425 #line 1714 "queryparser/queryparser.lemony"
02426 { yygotominor.yy39 = yymsp[0].minor.yy39; }
02427 #line 2428 "queryparser/queryparser_internal.cc"
02428 break;
02429 case 3:
02430 #line 1717 "queryparser/queryparser.lemony"
02431 { BOOL_OP_TO_QUERY(yygotominor.yy39, yymsp[-2].minor.yy39, Query::OP_AND, yymsp[0].minor.yy39, "AND"); yy_destructor(yypParser,4,&yymsp[-1].minor);
02432 }
02433 #line 2434 "queryparser/queryparser_internal.cc"
02434 break;
02435 case 4:
02436 #line 1719 "queryparser/queryparser.lemony"
02437 {
02438
02439 if (!yymsp[-2].minor.yy39 && (state->flags & QueryParser::FLAG_PURE_NOT)) {
02440 yymsp[-2].minor.yy39 = new Query("", 1, 0);
02441 }
02442 BOOL_OP_TO_QUERY(yygotominor.yy39, yymsp[-2].minor.yy39, Query::OP_AND_NOT, yymsp[0].minor.yy39, "NOT");
02443 yy_destructor(yypParser,5,&yymsp[-1].minor);
02444 }
02445 #line 2446 "queryparser/queryparser_internal.cc"
02446 break;
02447 case 5:
02448 #line 1728 "queryparser/queryparser.lemony"
02449 { BOOL_OP_TO_QUERY(yygotominor.yy39, yymsp[-3].minor.yy39, Query::OP_AND_NOT, yymsp[0].minor.yy39, "AND NOT"); yy_destructor(yypParser,4,&yymsp[-2].minor);
02450 yy_destructor(yypParser,5,&yymsp[-1].minor);
02451 }
02452 #line 2453 "queryparser/queryparser_internal.cc"
02453 break;
02454 case 6:
02455 #line 1731 "queryparser/queryparser.lemony"
02456 { BOOL_OP_TO_QUERY(yygotominor.yy39, yymsp[-3].minor.yy39, Query::OP_AND_NOT, yymsp[0].minor.yy39, "AND"); yy_destructor(yypParser,4,&yymsp[-2].minor);
02457 yy_destructor(yypParser,10,&yymsp[-1].minor);
02458 }
02459 #line 2460 "queryparser/queryparser_internal.cc"
02460 break;
02461 case 7:
02462 #line 1734 "queryparser/queryparser.lemony"
02463 { BOOL_OP_TO_QUERY(yygotominor.yy39, yymsp[-2].minor.yy39, Query::OP_OR, yymsp[0].minor.yy39, "OR"); yy_destructor(yypParser,2,&yymsp[-1].minor);
02464 }
02465 #line 2466 "queryparser/queryparser_internal.cc"
02466 break;
02467 case 8:
02468 #line 1737 "queryparser/queryparser.lemony"
02469 { BOOL_OP_TO_QUERY(yygotominor.yy39, yymsp[-2].minor.yy39, Query::OP_XOR, yymsp[0].minor.yy39, "XOR"); yy_destructor(yypParser,3,&yymsp[-1].minor);
02470 }
02471 #line 2472 "queryparser/queryparser_internal.cc"
02472 break;
02473 case 10:
02474 #line 1746 "queryparser/queryparser.lemony"
02475 {
02476
02477
02478
02479 yygotominor.yy39 = NULL;
02480 }
02481 #line 2482 "queryparser/queryparser_internal.cc"
02482 break;
02483 case 11:
02484 #line 1758 "queryparser/queryparser.lemony"
02485 {
02486 yygotominor.yy39 = yymsp[0].minor.yy40->query;
02487 yymsp[0].minor.yy40->query = NULL;
02488
02489 if (yymsp[0].minor.yy40->love) {
02490 if (yymsp[0].minor.yy40->love->empty()) {
02491
02492 delete yygotominor.yy39;
02493 yygotominor.yy39 = yymsp[0].minor.yy40->love;
02494 } else if (yygotominor.yy39) {
02495 swap(yygotominor.yy39, yymsp[0].minor.yy40->love);
02496 add_to_query(yygotominor.yy39, Query::OP_AND_MAYBE, yymsp[0].minor.yy40->love);
02497 } else {
02498 yygotominor.yy39 = yymsp[0].minor.yy40->love;
02499 }
02500 yymsp[0].minor.yy40->love = NULL;
02501 }
02502
02503 if (!yymsp[0].minor.yy40->filter.empty()) {
02504 if (yygotominor.yy39) {
02505 add_to_query(yygotominor.yy39, Query::OP_FILTER, yymsp[0].minor.yy40->merge_filters());
02506 } else {
02507
02508 yygotominor.yy39 = new Query(Query::OP_SCALE_WEIGHT, yymsp[0].minor.yy40->merge_filters(), 0.0);
02509 }
02510 }
02511
02512 if (yymsp[0].minor.yy40->hate && !yymsp[0].minor.yy40->hate->empty()) {
02513 if (!yygotominor.yy39) {
02514
02515 yy_parse_failed(yypParser);
02516 return;
02517 }
02518 *yygotominor.yy39 = Query(Query::OP_AND_NOT, *yygotominor.yy39, *yymsp[0].minor.yy40->hate);
02519 }
02520 delete yymsp[0].minor.yy40;
02521 }
02522 #line 2523 "queryparser/queryparser_internal.cc"
02523 break;
02524 case 12:
02525 case 30: yytestcase(yyruleno==30);
02526 case 32: yytestcase(yyruleno==32);
02527 #line 1796 "queryparser/queryparser.lemony"
02528 {
02529 yygotominor.yy39 = yymsp[0].minor.yy39;
02530 }
02531 #line 2532 "queryparser/queryparser_internal.cc"
02532 break;
02533 case 13:
02534 #line 1808 "queryparser/queryparser.lemony"
02535 {
02536 valueno slot = yymsp[0].minor.yy0->pos;
02537 const Query & range = yymsp[0].minor.yy0->as_value_range_query();
02538 yygotominor.yy40 = new ProbQuery;
02539 yygotominor.yy40->add_filter_range(slot, range);
02540 }
02541 #line 2542 "queryparser/queryparser_internal.cc"
02542 break;
02543 case 14:
02544 #line 1815 "queryparser/queryparser.lemony"
02545 {
02546 valueno slot = yymsp[0].minor.yy0->pos;
02547 const Query & range = yymsp[0].minor.yy0->as_value_range_query();
02548 yygotominor.yy40 = yymsp[-1].minor.yy40;
02549 yygotominor.yy40->append_filter_range(slot, range);
02550 }
02551 #line 2552 "queryparser/queryparser_internal.cc"
02552 break;
02553 case 15:
02554 #line 1822 "queryparser/queryparser.lemony"
02555 {
02556 yygotominor.yy40 = new ProbQuery;
02557 yygotominor.yy40->query = yymsp[-1].minor.yy39;
02558 if (yymsp[0].minor.yy39) {
02559 Query::op op = state->default_op();
02560 if (yygotominor.yy40->query && is_positional(op)) {
02561
02562
02563
02564 Query * subqs[2] = { yygotominor.yy40->query, yymsp[0].minor.yy39 };
02565 *(yygotominor.yy40->query) = Query(op, subqs, subqs + 2, 11);
02566 delete yymsp[0].minor.yy39;
02567 } else {
02568 add_to_query(yygotominor.yy40->query, op, yymsp[0].minor.yy39);
02569 }
02570 }
02571 }
02572 #line 2573 "queryparser/queryparser_internal.cc"
02573 break;
02574 case 16:
02575 #line 1840 "queryparser/queryparser.lemony"
02576 {
02577 yygotominor.yy40 = yymsp[-1].minor.yy40;
02578
02579 if (yymsp[0].minor.yy39) add_to_query(yygotominor.yy40->query, state->default_op(), yymsp[0].minor.yy39);
02580 }
02581 #line 2582 "queryparser/queryparser_internal.cc"
02582 break;
02583 case 17:
02584 #line 1846 "queryparser/queryparser.lemony"
02585 {
02586 yygotominor.yy40 = new ProbQuery;
02587 if (state->default_op() == Query::OP_AND) {
02588 yygotominor.yy40->query = yymsp[0].minor.yy39;
02589 } else {
02590 yygotominor.yy40->love = yymsp[0].minor.yy39;
02591 }
02592 yy_destructor(yypParser,8,&yymsp[-1].minor);
02593 }
02594 #line 2595 "queryparser/queryparser_internal.cc"
02595 break;
02596 case 18:
02597 #line 1855 "queryparser/queryparser.lemony"
02598 {
02599 yygotominor.yy40 = yymsp[-2].minor.yy40;
02600 if (state->default_op() == Query::OP_AND) {
02601
02602
02603
02604 add_to_query(yygotominor.yy40->query, Query::OP_AND, yymsp[0].minor.yy39);
02605 } else {
02606 add_to_query(yygotominor.yy40->love, Query::OP_AND, yymsp[0].minor.yy39);
02607 }
02608 yy_destructor(yypParser,8,&yymsp[-1].minor);
02609 }
02610 #line 2611 "queryparser/queryparser_internal.cc"
02611 break;
02612 case 19:
02613 #line 1867 "queryparser/queryparser.lemony"
02614 {
02615 yygotominor.yy40 = new ProbQuery;
02616 yygotominor.yy40->hate = yymsp[0].minor.yy39;
02617 yy_destructor(yypParser,9,&yymsp[-1].minor);
02618 }
02619 #line 2620 "queryparser/queryparser_internal.cc"
02620 break;
02621 case 20:
02622 #line 1872 "queryparser/queryparser.lemony"
02623 {
02624 yygotominor.yy40 = yymsp[-2].minor.yy40;
02625 add_to_query(yygotominor.yy40->hate, Query::OP_OR, yymsp[0].minor.yy39);
02626 yy_destructor(yypParser,9,&yymsp[-1].minor);
02627 }
02628 #line 2629 "queryparser/queryparser_internal.cc"
02629 break;
02630 case 21:
02631 #line 1877 "queryparser/queryparser.lemony"
02632 {
02633 yygotominor.yy40 = new ProbQuery;
02634 yygotominor.yy40->hate = new Query(yymsp[0].minor.yy0->get_query());
02635 delete yymsp[0].minor.yy0;
02636 yy_destructor(yypParser,9,&yymsp[-1].minor);
02637 }
02638 #line 2639 "queryparser/queryparser_internal.cc"
02639 break;
02640 case 22:
02641 #line 1883 "queryparser/queryparser.lemony"
02642 {
02643 yygotominor.yy40 = yymsp[-2].minor.yy40;
02644 add_to_query(yygotominor.yy40->hate, Query::OP_OR, yymsp[0].minor.yy0->get_query());
02645 delete yymsp[0].minor.yy0;
02646 yy_destructor(yypParser,9,&yymsp[-1].minor);
02647 }
02648 #line 2649 "queryparser/queryparser_internal.cc"
02649 break;
02650 case 23:
02651 #line 1889 "queryparser/queryparser.lemony"
02652 {
02653 yygotominor.yy40 = new ProbQuery;
02654 yygotominor.yy40->add_filter(yymsp[0].minor.yy0->get_filter_group_id(), yymsp[0].minor.yy0->get_query());
02655 delete yymsp[0].minor.yy0;
02656 }
02657 #line 2658 "queryparser/queryparser_internal.cc"
02658 break;
02659 case 24:
02660 #line 1895 "queryparser/queryparser.lemony"
02661 {
02662 yygotominor.yy40 = yymsp[-1].minor.yy40;
02663 yygotominor.yy40->append_filter(yymsp[0].minor.yy0->get_filter_group_id(), yymsp[0].minor.yy0->get_query());
02664 delete yymsp[0].minor.yy0;
02665 }
02666 #line 2667 "queryparser/queryparser_internal.cc"
02667 break;
02668 case 25:
02669 #line 1901 "queryparser/queryparser.lemony"
02670 {
02671
02672 yygotominor.yy40 = new ProbQuery;
02673 yygotominor.yy40->filter[yymsp[0].minor.yy0->get_filter_group_id()] = yymsp[0].minor.yy0->get_query();
02674 delete yymsp[0].minor.yy0;
02675 yy_destructor(yypParser,8,&yymsp[-1].minor);
02676 }
02677 #line 2678 "queryparser/queryparser_internal.cc"
02678 break;
02679 case 26:
02680 #line 1908 "queryparser/queryparser.lemony"
02681 {
02682
02683 yygotominor.yy40 = yymsp[-2].minor.yy40;
02684
02685 Query & q = yygotominor.yy40->filter[yymsp[0].minor.yy0->get_filter_group_id()];
02686 q = Query(Query::OP_OR, q, yymsp[0].minor.yy0->get_query());
02687 delete yymsp[0].minor.yy0;
02688 yy_destructor(yypParser,8,&yymsp[-1].minor);
02689 }
02690 #line 2691 "queryparser/queryparser_internal.cc"
02691 break;
02692 case 27:
02693 #line 1923 "queryparser/queryparser.lemony"
02694 { yygotominor.yy40 = yymsp[0].minor.yy40; }
02695 #line 2696 "queryparser/queryparser_internal.cc"
02696 break;
02697 case 28:
02698 #line 1925 "queryparser/queryparser.lemony"
02699 {
02700 yygotominor.yy40 = new ProbQuery;
02701 yygotominor.yy40->query = yymsp[0].minor.yy39;
02702 }
02703 #line 2704 "queryparser/queryparser_internal.cc"
02704 break;
02705 case 29:
02706 #line 1939 "queryparser/queryparser.lemony"
02707 {
02708 if (state->is_stopword(yymsp[0].minor.yy0)) {
02709 yygotominor.yy39 = NULL;
02710 state->add_to_stoplist(yymsp[0].minor.yy0);
02711 } else {
02712 yygotominor.yy39 = new Query(yymsp[0].minor.yy0->get_query_with_auto_synonyms());
02713 }
02714 delete yymsp[0].minor.yy0;
02715 }
02716 #line 2717 "queryparser/queryparser_internal.cc"
02717 break;
02718 case 31:
02719 #line 1958 "queryparser/queryparser.lemony"
02720 {
02721 yygotominor.yy39 = new Query(yymsp[0].minor.yy0->get_query_with_auto_synonyms());
02722 delete yymsp[0].minor.yy0;
02723 }
02724 #line 2725 "queryparser/queryparser_internal.cc"
02725 break;
02726 case 33:
02727 #line 1975 "queryparser/queryparser.lemony"
02728 { yygotominor.yy39 = yymsp[0].minor.yy0->as_wildcarded_query(state); }
02729 #line 2730 "queryparser/queryparser_internal.cc"
02730 break;
02731 case 34:
02732 #line 1978 "queryparser/queryparser.lemony"
02733 { yygotominor.yy39 = yymsp[0].minor.yy0->as_partial_query(state); }
02734 #line 2735 "queryparser/queryparser_internal.cc"
02735 break;
02736 case 35:
02737 #line 1981 "queryparser/queryparser.lemony"
02738 { yygotominor.yy39 = yymsp[-1].minor.yy32->as_phrase_query(); yy_destructor(yypParser,19,&yymsp[-2].minor);
02739 yy_destructor(yypParser,19,&yymsp[0].minor);
02740 }
02741 #line 2742 "queryparser/queryparser_internal.cc"
02742 break;
02743 case 36:
02744 #line 1984 "queryparser/queryparser.lemony"
02745 { yygotominor.yy39 = yymsp[0].minor.yy32->as_phrase_query(); }
02746 #line 2747 "queryparser/queryparser_internal.cc"
02747 break;
02748 case 37:
02749 #line 1987 "queryparser/queryparser.lemony"
02750 { yygotominor.yy39 = yymsp[0].minor.yy14->as_group(state); }
02751 #line 2752 "queryparser/queryparser_internal.cc"
02752 break;
02753 case 38:
02754 #line 1990 "queryparser/queryparser.lemony"
02755 { yygotominor.yy39 = yymsp[0].minor.yy32->as_near_query(); }
02756 #line 2757 "queryparser/queryparser_internal.cc"
02757 break;
02758 case 39:
02759 #line 1993 "queryparser/queryparser.lemony"
02760 { yygotominor.yy39 = yymsp[0].minor.yy32->as_adj_query(); }
02761 #line 2762 "queryparser/queryparser_internal.cc"
02762 break;
02763 case 40:
02764 #line 1996 "queryparser/queryparser.lemony"
02765 { yygotominor.yy39 = yymsp[-1].minor.yy39; yy_destructor(yypParser,20,&yymsp[-2].minor);
02766 yy_destructor(yypParser,21,&yymsp[0].minor);
02767 }
02768 #line 2769 "queryparser/queryparser_internal.cc"
02769 break;
02770 case 41:
02771 #line 1998 "queryparser/queryparser.lemony"
02772 {
02773 yygotominor.yy39 = new Query(yymsp[0].minor.yy0->get_query_with_synonyms());
02774 delete yymsp[0].minor.yy0;
02775 yy_destructor(yypParser,11,&yymsp[-1].minor);
02776 }
02777 #line 2778 "queryparser/queryparser_internal.cc"
02778 break;
02779 case 42:
02780 #line 2003 "queryparser/queryparser.lemony"
02781 {
02782 { yygotominor.yy39 = yymsp[0].minor.yy0->as_cjk_query(); }
02783 }
02784 #line 2785 "queryparser/queryparser_internal.cc"
02785 break;
02786 case 43:
02787 #line 2013 "queryparser/queryparser.lemony"
02788 {
02789 yygotominor.yy32 = new Terms;
02790 yygotominor.yy32->add_positional_term(yymsp[0].minor.yy0);
02791 }
02792 #line 2793 "queryparser/queryparser_internal.cc"
02793 break;
02794 case 44:
02795 #line 2018 "queryparser/queryparser.lemony"
02796 {
02797 yygotominor.yy32 = new Terms;
02798 yymsp[0].minor.yy0->as_positional_cjk_term(yygotominor.yy32);
02799 }
02800 #line 2801 "queryparser/queryparser_internal.cc"
02801 break;
02802 case 45:
02803 case 48: yytestcase(yyruleno==48);
02804 #line 2023 "queryparser/queryparser.lemony"
02805 {
02806 yygotominor.yy32 = yymsp[-1].minor.yy32;
02807 yygotominor.yy32->add_positional_term(yymsp[0].minor.yy0);
02808 }
02809 #line 2810 "queryparser/queryparser_internal.cc"
02810 break;
02811 case 46:
02812 #line 2028 "queryparser/queryparser.lemony"
02813 {
02814 yygotominor.yy32 = yymsp[-1].minor.yy32;
02815 yymsp[0].minor.yy0->as_positional_cjk_term(yygotominor.yy32);
02816 }
02817 #line 2818 "queryparser/queryparser_internal.cc"
02818 break;
02819 case 47:
02820 #line 2040 "queryparser/queryparser.lemony"
02821 {
02822 yygotominor.yy32 = new Terms;
02823 yygotominor.yy32->add_positional_term(yymsp[-1].minor.yy0);
02824 yygotominor.yy32->add_positional_term(yymsp[0].minor.yy0);
02825 }
02826 #line 2827 "queryparser/queryparser_internal.cc"
02827 break;
02828 case 49:
02829 #line 2057 "queryparser/queryparser.lemony"
02830 {
02831 yygotominor.yy14 = new TermGroup;
02832 yygotominor.yy14->add_term(yymsp[-1].minor.yy0);
02833 yygotominor.yy14->add_term(yymsp[0].minor.yy0);
02834 }
02835 #line 2836 "queryparser/queryparser_internal.cc"
02836 break;
02837 case 50:
02838 #line 2063 "queryparser/queryparser.lemony"
02839 {
02840 yygotominor.yy14 = yymsp[-1].minor.yy14;
02841 yygotominor.yy14->add_term(yymsp[0].minor.yy0);
02842 }
02843 #line 2844 "queryparser/queryparser_internal.cc"
02844 break;
02845 case 51:
02846 #line 2068 "queryparser/queryparser.lemony"
02847 {
02848 yygotominor.yy14 = yymsp[-1].minor.yy14;
02849 yygotominor.yy14->set_empty_ok();
02850 yy_destructor(yypParser,23,&yymsp[0].minor);
02851 }
02852 #line 2853 "queryparser/queryparser_internal.cc"
02853 break;
02854 case 52:
02855 case 54: yytestcase(yyruleno==54);
02856 #line 2079 "queryparser/queryparser.lemony"
02857 {
02858 yygotominor.yy32 = new Terms;
02859 yygotominor.yy32->add_positional_term(yymsp[-2].minor.yy0);
02860 yygotominor.yy32->add_positional_term(yymsp[0].minor.yy0);
02861 if (yymsp[-1].minor.yy0) {
02862 yygotominor.yy32->adjust_window(yymsp[-1].minor.yy0->get_termpos());
02863 delete yymsp[-1].minor.yy0;
02864 }
02865 }
02866 #line 2867 "queryparser/queryparser_internal.cc"
02867 break;
02868 case 53:
02869 case 55: yytestcase(yyruleno==55);
02870 #line 2089 "queryparser/queryparser.lemony"
02871 {
02872 yygotominor.yy32 = yymsp[-2].minor.yy32;
02873 yygotominor.yy32->add_positional_term(yymsp[0].minor.yy0);
02874 if (yymsp[-1].minor.yy0) {
02875 yygotominor.yy32->adjust_window(yymsp[-1].minor.yy0->get_termpos());
02876 delete yymsp[-1].minor.yy0;
02877 }
02878 }
02879 #line 2880 "queryparser/queryparser_internal.cc"
02880 break;
02881 default:
02882 break;
02883 }
02884 yygoto = yyRuleInfo[yyruleno].lhs;
02885 yysize = yyRuleInfo[yyruleno].nrhs;
02886 yypParser->yystack.resize(yypParser->yystack.size() - yysize);
02887 yyact = yy_find_reduce_action(yypParser->yystack.back().stateno,(YYCODETYPE)yygoto);
02888 if( yyact < YYNSTATE ){
02889 yy_shift(yypParser,yyact,yygoto,&yygotominor);
02890 }else{
02891 Assert( yyact == YYNSTATE + YYNRULE + 1 );
02892 yy_accept(yypParser);
02893 }
02894 }
02895
02896
02897
02898
02899 #ifndef YYNOERRORRECOVERY
02900 static void yy_parse_failed(
02901 yyParser *yypParser
02902 ){
02903 ParseARG_FETCH;
02904 LOGLINE(QUERYPARSER, "Fail!");
02905 while( !yypParser->yystack.empty() ) yy_pop_parser_stack(yypParser);
02906
02907
02908 #line 1640 "queryparser/queryparser.lemony"
02909
02910
02911 if (!state->error) state->error = "parse error";
02912 #line 2913 "queryparser/queryparser_internal.cc"
02913 ParseARG_STORE;
02914 }
02915 #endif
02916
02917
02918
02919
02920 static void yy_syntax_error(
02921 yyParser *yypParser,
02922 int yymajor,
02923 YYMINORTYPE yyminor
02924 ){
02925 ParseARG_FETCH;
02926 (void)yymajor;
02927 (void)yyminor;
02928 #define TOKEN (yyminor.yy0)
02929 #line 1645 "queryparser/queryparser.lemony"
02930
02931 yy_parse_failed(yypParser);
02932 #line 2933 "queryparser/queryparser_internal.cc"
02933 ParseARG_STORE;
02934 }
02935
02936
02937
02938
02939 static void yy_accept(
02940 yyParser *yypParser
02941 ){
02942 ParseARG_FETCH;
02943 LOGLINE(QUERYPARSER, "Accept!");
02944 while( !yypParser->yystack.empty() ) yy_pop_parser_stack(yypParser);
02945
02946
02947 ParseARG_STORE;
02948 }
02949
02950
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966
02967
02968
02969 static void Parse(
02970 yyParser *yypParser,
02971 int yymajor,
02972 ParseTOKENTYPE yyminor
02973 ParseARG_PDECL
02974 ){
02975 YYMINORTYPE yyminorunion;
02976 int yyact;
02977 int yyendofinput;
02978 #ifdef YYERRORSYMBOL
02979 int yyerrorhit = 0;
02980 #endif
02981
02982
02983 if( yypParser->yystack.empty() ){
02984 yypParser->yystack.push_back(yyStackEntry());
02985 yypParser->yyerrcnt = -1;
02986 }
02987 yyminorunion.yy0 = yyminor;
02988 yyendofinput = (yymajor==0);
02989 ParseARG_STORE;
02990
02991 LOGLINE(QUERYPARSER, "Input " << ParseTokenName(yymajor) << " " <<
02992 (yyminor ? yyminor->name : "<<null>>"));
02993
02994 do{
02995 yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
02996 if( yyact<YYNSTATE ){
02997 Assert( !yyendofinput );
02998 yy_shift(yypParser,yyact,yymajor,&yyminorunion);
02999 yypParser->yyerrcnt--;
03000 yymajor = YYNOCODE;
03001 }else if( yyact < YYNSTATE + YYNRULE ){
03002 yy_reduce(yypParser,yyact-YYNSTATE);
03003 }else{
03004 Assert( yyact == YY_ERROR_ACTION );
03005 #ifdef YYERRORSYMBOL
03006 int yymx;
03007 #endif
03008 LOGLINE(QUERYPARSER, "Syntax Error!");
03009 #ifdef YYERRORSYMBOL
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029 if( yypParser->yyerrcnt<0 ){
03030 yy_syntax_error(yypParser,yymajor,yyminorunion);
03031 }
03032 yymx = yypParser->yystack.back().major;
03033 if( yymx==YYERRORSYMBOL || yyerrorhit ){
03034 LOGLINE(QUERYPARSER, "Discard input token " << ParseTokenName(yymajor));
03035 yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion);
03036 yymajor = YYNOCODE;
03037 }else{
03038 while(
03039 !yypParser->yystack.empty() &&
03040 yymx != YYERRORSYMBOL &&
03041 (yyact = yy_find_reduce_action(
03042 yypParser->yystack.back().stateno,
03043 YYERRORSYMBOL)) >= YYNSTATE
03044 ){
03045 yy_pop_parser_stack(yypParser);
03046 }
03047 if( yypParser->yystack.empty() || yymajor==0 ){
03048 yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion);
03049 yy_parse_failed(yypParser);
03050 yymajor = YYNOCODE;
03051 }else if( yymx!=YYERRORSYMBOL ){
03052 YYMINORTYPE u2;
03053 u2.YYERRSYMDT = 0;
03054 yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
03055 }
03056 }
03057 yypParser->yyerrcnt = 3;
03058 yyerrorhit = 1;
03059 #elif defined(YYNOERRORRECOVERY)
03060
03061
03062
03063
03064
03065
03066
03067 yy_syntax_error(yypParser,yymajor,yyminorunion);
03068 yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
03069 yymajor = YYNOCODE;
03070
03071 #else
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081 if( yypParser->yyerrcnt<=0 ){
03082 yy_syntax_error(yypParser,yymajor,yyminorunion);
03083 }
03084 yypParser->yyerrcnt = 3;
03085 yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
03086 if( yyendofinput ){
03087 yy_parse_failed(yypParser);
03088 }
03089 yymajor = YYNOCODE;
03090 #endif
03091 }
03092 }while( yymajor!=YYNOCODE && !yypParser->yystack.empty() );
03093 return;
03094 }
03095
03096