jk-ferret 0.11.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (228) hide show
  1. data/CHANGELOG +24 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README +90 -0
  4. data/RELEASE_CHANGES +137 -0
  5. data/RELEASE_NOTES +60 -0
  6. data/Rakefile +443 -0
  7. data/TODO +109 -0
  8. data/TUTORIAL +231 -0
  9. data/bin/ferret-browser +79 -0
  10. data/ext/BZLIB_blocksort.c +1094 -0
  11. data/ext/BZLIB_bzlib.c +1578 -0
  12. data/ext/BZLIB_compress.c +672 -0
  13. data/ext/BZLIB_crctable.c +104 -0
  14. data/ext/BZLIB_decompress.c +626 -0
  15. data/ext/BZLIB_huffman.c +205 -0
  16. data/ext/BZLIB_randtable.c +84 -0
  17. data/ext/STEMMER_api.c +66 -0
  18. data/ext/STEMMER_libstemmer.c +93 -0
  19. data/ext/STEMMER_stem_ISO_8859_1_danish.c +337 -0
  20. data/ext/STEMMER_stem_ISO_8859_1_dutch.c +624 -0
  21. data/ext/STEMMER_stem_ISO_8859_1_english.c +1117 -0
  22. data/ext/STEMMER_stem_ISO_8859_1_finnish.c +762 -0
  23. data/ext/STEMMER_stem_ISO_8859_1_french.c +1246 -0
  24. data/ext/STEMMER_stem_ISO_8859_1_german.c +503 -0
  25. data/ext/STEMMER_stem_ISO_8859_1_hungarian.c +1230 -0
  26. data/ext/STEMMER_stem_ISO_8859_1_italian.c +1065 -0
  27. data/ext/STEMMER_stem_ISO_8859_1_norwegian.c +297 -0
  28. data/ext/STEMMER_stem_ISO_8859_1_porter.c +749 -0
  29. data/ext/STEMMER_stem_ISO_8859_1_portuguese.c +1017 -0
  30. data/ext/STEMMER_stem_ISO_8859_1_spanish.c +1093 -0
  31. data/ext/STEMMER_stem_ISO_8859_1_swedish.c +307 -0
  32. data/ext/STEMMER_stem_ISO_8859_2_romanian.c +998 -0
  33. data/ext/STEMMER_stem_KOI8_R_russian.c +700 -0
  34. data/ext/STEMMER_stem_UTF_8_danish.c +339 -0
  35. data/ext/STEMMER_stem_UTF_8_dutch.c +634 -0
  36. data/ext/STEMMER_stem_UTF_8_english.c +1125 -0
  37. data/ext/STEMMER_stem_UTF_8_finnish.c +768 -0
  38. data/ext/STEMMER_stem_UTF_8_french.c +1256 -0
  39. data/ext/STEMMER_stem_UTF_8_german.c +509 -0
  40. data/ext/STEMMER_stem_UTF_8_hungarian.c +1234 -0
  41. data/ext/STEMMER_stem_UTF_8_italian.c +1073 -0
  42. data/ext/STEMMER_stem_UTF_8_norwegian.c +299 -0
  43. data/ext/STEMMER_stem_UTF_8_porter.c +755 -0
  44. data/ext/STEMMER_stem_UTF_8_portuguese.c +1023 -0
  45. data/ext/STEMMER_stem_UTF_8_romanian.c +1004 -0
  46. data/ext/STEMMER_stem_UTF_8_russian.c +694 -0
  47. data/ext/STEMMER_stem_UTF_8_spanish.c +1097 -0
  48. data/ext/STEMMER_stem_UTF_8_swedish.c +309 -0
  49. data/ext/STEMMER_stem_UTF_8_turkish.c +2205 -0
  50. data/ext/STEMMER_utilities.c +478 -0
  51. data/ext/analysis.c +1710 -0
  52. data/ext/analysis.h +266 -0
  53. data/ext/api.h +26 -0
  54. data/ext/array.c +125 -0
  55. data/ext/array.h +62 -0
  56. data/ext/bitvector.c +96 -0
  57. data/ext/bitvector.h +594 -0
  58. data/ext/bzlib.h +282 -0
  59. data/ext/bzlib_private.h +503 -0
  60. data/ext/compound_io.c +384 -0
  61. data/ext/config.h +52 -0
  62. data/ext/document.c +159 -0
  63. data/ext/document.h +63 -0
  64. data/ext/except.c +102 -0
  65. data/ext/except.h +176 -0
  66. data/ext/extconf.rb +15 -0
  67. data/ext/ferret.c +416 -0
  68. data/ext/ferret.h +94 -0
  69. data/ext/field_index.c +262 -0
  70. data/ext/field_index.h +52 -0
  71. data/ext/filter.c +157 -0
  72. data/ext/fs_store.c +493 -0
  73. data/ext/global.c +458 -0
  74. data/ext/global.h +302 -0
  75. data/ext/hash.c +524 -0
  76. data/ext/hash.h +515 -0
  77. data/ext/hashset.c +192 -0
  78. data/ext/hashset.h +215 -0
  79. data/ext/header.h +58 -0
  80. data/ext/helper.c +63 -0
  81. data/ext/helper.h +21 -0
  82. data/ext/index.c +6804 -0
  83. data/ext/index.h +935 -0
  84. data/ext/internal.h +1019 -0
  85. data/ext/lang.c +10 -0
  86. data/ext/lang.h +68 -0
  87. data/ext/libstemmer.h +79 -0
  88. data/ext/mempool.c +88 -0
  89. data/ext/mempool.h +43 -0
  90. data/ext/modules.h +190 -0
  91. data/ext/multimapper.c +351 -0
  92. data/ext/multimapper.h +60 -0
  93. data/ext/posh.c +1006 -0
  94. data/ext/posh.h +973 -0
  95. data/ext/priorityqueue.c +149 -0
  96. data/ext/priorityqueue.h +155 -0
  97. data/ext/q_boolean.c +1621 -0
  98. data/ext/q_const_score.c +162 -0
  99. data/ext/q_filtered_query.c +212 -0
  100. data/ext/q_fuzzy.c +280 -0
  101. data/ext/q_match_all.c +149 -0
  102. data/ext/q_multi_term.c +673 -0
  103. data/ext/q_parser.c +3103 -0
  104. data/ext/q_phrase.c +1206 -0
  105. data/ext/q_prefix.c +98 -0
  106. data/ext/q_range.c +682 -0
  107. data/ext/q_span.c +2390 -0
  108. data/ext/q_term.c +337 -0
  109. data/ext/q_wildcard.c +167 -0
  110. data/ext/r_analysis.c +2626 -0
  111. data/ext/r_index.c +3468 -0
  112. data/ext/r_qparser.c +635 -0
  113. data/ext/r_search.c +4490 -0
  114. data/ext/r_store.c +513 -0
  115. data/ext/r_utils.c +1131 -0
  116. data/ext/ram_store.c +476 -0
  117. data/ext/scanner.c +895 -0
  118. data/ext/scanner.h +36 -0
  119. data/ext/scanner_mb.c +6701 -0
  120. data/ext/scanner_utf8.c +4415 -0
  121. data/ext/search.c +1864 -0
  122. data/ext/search.h +953 -0
  123. data/ext/similarity.c +151 -0
  124. data/ext/similarity.h +89 -0
  125. data/ext/sort.c +786 -0
  126. data/ext/stem_ISO_8859_1_danish.h +16 -0
  127. data/ext/stem_ISO_8859_1_dutch.h +16 -0
  128. data/ext/stem_ISO_8859_1_english.h +16 -0
  129. data/ext/stem_ISO_8859_1_finnish.h +16 -0
  130. data/ext/stem_ISO_8859_1_french.h +16 -0
  131. data/ext/stem_ISO_8859_1_german.h +16 -0
  132. data/ext/stem_ISO_8859_1_hungarian.h +16 -0
  133. data/ext/stem_ISO_8859_1_italian.h +16 -0
  134. data/ext/stem_ISO_8859_1_norwegian.h +16 -0
  135. data/ext/stem_ISO_8859_1_porter.h +16 -0
  136. data/ext/stem_ISO_8859_1_portuguese.h +16 -0
  137. data/ext/stem_ISO_8859_1_spanish.h +16 -0
  138. data/ext/stem_ISO_8859_1_swedish.h +16 -0
  139. data/ext/stem_ISO_8859_2_romanian.h +16 -0
  140. data/ext/stem_KOI8_R_russian.h +16 -0
  141. data/ext/stem_UTF_8_danish.h +16 -0
  142. data/ext/stem_UTF_8_dutch.h +16 -0
  143. data/ext/stem_UTF_8_english.h +16 -0
  144. data/ext/stem_UTF_8_finnish.h +16 -0
  145. data/ext/stem_UTF_8_french.h +16 -0
  146. data/ext/stem_UTF_8_german.h +16 -0
  147. data/ext/stem_UTF_8_hungarian.h +16 -0
  148. data/ext/stem_UTF_8_italian.h +16 -0
  149. data/ext/stem_UTF_8_norwegian.h +16 -0
  150. data/ext/stem_UTF_8_porter.h +16 -0
  151. data/ext/stem_UTF_8_portuguese.h +16 -0
  152. data/ext/stem_UTF_8_romanian.h +16 -0
  153. data/ext/stem_UTF_8_russian.h +16 -0
  154. data/ext/stem_UTF_8_spanish.h +16 -0
  155. data/ext/stem_UTF_8_swedish.h +16 -0
  156. data/ext/stem_UTF_8_turkish.h +16 -0
  157. data/ext/stopwords.c +410 -0
  158. data/ext/store.c +698 -0
  159. data/ext/store.h +799 -0
  160. data/ext/symbol.c +10 -0
  161. data/ext/symbol.h +23 -0
  162. data/ext/term_vectors.c +73 -0
  163. data/ext/threading.h +31 -0
  164. data/ext/win32.h +62 -0
  165. data/lib/ferret.rb +30 -0
  166. data/lib/ferret/browser.rb +246 -0
  167. data/lib/ferret/browser/s/global.js +192 -0
  168. data/lib/ferret/browser/s/style.css +148 -0
  169. data/lib/ferret/browser/views/document/list.rhtml +49 -0
  170. data/lib/ferret/browser/views/document/show.rhtml +27 -0
  171. data/lib/ferret/browser/views/error/index.rhtml +7 -0
  172. data/lib/ferret/browser/views/help/index.rhtml +8 -0
  173. data/lib/ferret/browser/views/home/index.rhtml +29 -0
  174. data/lib/ferret/browser/views/layout.rhtml +22 -0
  175. data/lib/ferret/browser/views/term-vector/index.rhtml +4 -0
  176. data/lib/ferret/browser/views/term/index.rhtml +199 -0
  177. data/lib/ferret/browser/views/term/termdocs.rhtml +1 -0
  178. data/lib/ferret/browser/webrick.rb +14 -0
  179. data/lib/ferret/document.rb +130 -0
  180. data/lib/ferret/field_infos.rb +44 -0
  181. data/lib/ferret/field_symbol.rb +87 -0
  182. data/lib/ferret/index.rb +973 -0
  183. data/lib/ferret/number_tools.rb +157 -0
  184. data/lib/ferret/version.rb +3 -0
  185. data/setup.rb +1555 -0
  186. data/test/long_running/largefile/tc_largefile.rb +46 -0
  187. data/test/test_all.rb +5 -0
  188. data/test/test_helper.rb +29 -0
  189. data/test/test_installed.rb +1 -0
  190. data/test/threading/number_to_spoken.rb +132 -0
  191. data/test/threading/thread_safety_index_test.rb +88 -0
  192. data/test/threading/thread_safety_read_write_test.rb +73 -0
  193. data/test/threading/thread_safety_test.rb +133 -0
  194. data/test/unit/analysis/tc_analyzer.rb +550 -0
  195. data/test/unit/analysis/tc_token_stream.rb +653 -0
  196. data/test/unit/index/tc_index.rb +867 -0
  197. data/test/unit/index/tc_index_reader.rb +699 -0
  198. data/test/unit/index/tc_index_writer.rb +447 -0
  199. data/test/unit/index/th_doc.rb +332 -0
  200. data/test/unit/query_parser/tc_query_parser.rb +238 -0
  201. data/test/unit/search/tc_filter.rb +156 -0
  202. data/test/unit/search/tc_fuzzy_query.rb +147 -0
  203. data/test/unit/search/tc_index_searcher.rb +67 -0
  204. data/test/unit/search/tc_multi_searcher.rb +128 -0
  205. data/test/unit/search/tc_multiple_search_requests.rb +58 -0
  206. data/test/unit/search/tc_search_and_sort.rb +179 -0
  207. data/test/unit/search/tc_sort.rb +49 -0
  208. data/test/unit/search/tc_sort_field.rb +27 -0
  209. data/test/unit/search/tc_spans.rb +190 -0
  210. data/test/unit/search/tm_searcher.rb +436 -0
  211. data/test/unit/store/tc_fs_store.rb +115 -0
  212. data/test/unit/store/tc_ram_store.rb +35 -0
  213. data/test/unit/store/tm_store.rb +34 -0
  214. data/test/unit/store/tm_store_lock.rb +68 -0
  215. data/test/unit/tc_document.rb +81 -0
  216. data/test/unit/tc_field_symbol.rb +26 -0
  217. data/test/unit/ts_analysis.rb +2 -0
  218. data/test/unit/ts_index.rb +2 -0
  219. data/test/unit/ts_largefile.rb +4 -0
  220. data/test/unit/ts_query_parser.rb +2 -0
  221. data/test/unit/ts_search.rb +2 -0
  222. data/test/unit/ts_store.rb +2 -0
  223. data/test/unit/ts_utils.rb +2 -0
  224. data/test/unit/utils/tc_bit_vector.rb +295 -0
  225. data/test/unit/utils/tc_number_tools.rb +117 -0
  226. data/test/unit/utils/tc_priority_queue.rb +106 -0
  227. data/test/utils/content_generator.rb +226 -0
  228. metadata +319 -0
data/ext/q_parser.c ADDED
@@ -0,0 +1,3103 @@
1
+ /* A Bison parser, made by GNU Bison 2.3. */
2
+
3
+ /* Skeleton implementation for Bison's Yacc-like parsers in C
4
+
5
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
6
+ Free Software Foundation, Inc.
7
+
8
+ This program is free software; you can redistribute it and/or modify
9
+ it under the terms of the GNU General Public License as published by
10
+ the Free Software Foundation; either version 2, or (at your option)
11
+ any later version.
12
+
13
+ This program is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU General Public License for more details.
17
+
18
+ You should have received a copy of the GNU General Public License
19
+ along with this program; if not, write to the Free Software
20
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
21
+ Boston, MA 02110-1301, USA. */
22
+
23
+ /* As a special exception, you may create a larger work that contains
24
+ part or all of the Bison parser skeleton and distribute that work
25
+ under terms of your choice, so long as that work isn't itself a
26
+ parser generator using the skeleton or a modified version thereof
27
+ as a parser skeleton. Alternatively, if you modify or redistribute
28
+ the parser skeleton itself, you may (at your option) remove this
29
+ special exception, which will cause the skeleton and the resulting
30
+ Bison output files to be licensed under the GNU General Public
31
+ License without this special exception.
32
+
33
+ This special exception was added by the Free Software Foundation in
34
+ version 2.2 of Bison. */
35
+
36
+ /* C LALR(1) parser skeleton written by Richard Stallman, by
37
+ simplifying the original so-called "semantic" parser. */
38
+
39
+ /* All symbols defined below should begin with yy or YY, to avoid
40
+ infringing on user name space. This should be done even for local
41
+ variables, as they might otherwise be expanded by user macros.
42
+ There are some unavoidable exceptions within include files to
43
+ define necessary library symbols; they are noted "INFRINGES ON
44
+ USER NAME SPACE" below. */
45
+
46
+ /* Identify Bison output. */
47
+ #define YYBISON 1
48
+
49
+ /* Bison version. */
50
+ #define YYBISON_VERSION "2.3"
51
+
52
+ /* Skeleton name. */
53
+ #define YYSKELETON_NAME "yacc.c"
54
+
55
+ /* Pure parsers. */
56
+ #define YYPURE 1
57
+
58
+ /* Using locations. */
59
+ #define YYLSP_NEEDED 0
60
+
61
+ /* Substitute the variable and function names. */
62
+ #define yyparse frt_parse
63
+ #define yylex frt_lex
64
+ #define yyerror frt_error
65
+ #define yylval frt_lval
66
+ #define yychar frt_char
67
+ #define yydebug frt_debug
68
+ #define yynerrs frt_nerrs
69
+
70
+
71
+ /* Tokens. */
72
+ #ifndef YYTOKENTYPE
73
+ # define YYTOKENTYPE
74
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
75
+ know about them. */
76
+ enum yytokentype {
77
+ QWRD = 258,
78
+ WILD_STR = 259,
79
+ LOW = 260,
80
+ OR = 261,
81
+ AND = 262,
82
+ NOT = 263,
83
+ REQ = 264,
84
+ HIGH = 265
85
+ };
86
+ #endif
87
+ /* Tokens. */
88
+ #define QWRD 258
89
+ #define WILD_STR 259
90
+ #define LOW 260
91
+ #define OR 261
92
+ #define AND 262
93
+ #define NOT 263
94
+ #define REQ 264
95
+ #define HIGH 265
96
+
97
+
98
+
99
+
100
+ /* Copy the first part of user declarations. */
101
+ #line 84 "src/q_parser.y"
102
+
103
+ #include <string.h>
104
+ #include <ctype.h>
105
+ #include <wctype.h>
106
+ #include <assert.h>
107
+ #include "except.h"
108
+ #include "search.h"
109
+ #include "array.h"
110
+ #include "symbol.h"
111
+ #include "internal.h"
112
+
113
+ typedef struct Phrase {
114
+ int size;
115
+ int capa;
116
+ int pos_inc;
117
+ PhrasePosition *positions;
118
+ } Phrase;
119
+
120
+ #define BCA_INIT_CAPA 4
121
+ typedef struct BCArray {
122
+ int size;
123
+ int capa;
124
+ BooleanClause **clauses;
125
+ } BCArray;
126
+
127
+ float qp_default_fuzzy_min_sim = 0.5;
128
+ int qp_default_fuzzy_pre_len = 0;
129
+
130
+
131
+
132
+ /* Enabling traces. */
133
+ #ifndef YYDEBUG
134
+ # define YYDEBUG 0
135
+ #endif
136
+
137
+ /* Enabling verbose error messages. */
138
+ #ifdef YYERROR_VERBOSE
139
+ # undef YYERROR_VERBOSE
140
+ # define YYERROR_VERBOSE 1
141
+ #else
142
+ # define YYERROR_VERBOSE 0
143
+ #endif
144
+
145
+ /* Enabling the token table. */
146
+ #ifndef YYTOKEN_TABLE
147
+ # define YYTOKEN_TABLE 0
148
+ #endif
149
+
150
+ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
151
+ typedef union YYSTYPE
152
+ #line 113 "src/q_parser.y"
153
+ {
154
+ Query *query;
155
+ BooleanClause *bcls;
156
+ BCArray *bclss;
157
+ HashSet *hashset;
158
+ Phrase *phrase;
159
+ char *str;
160
+ }
161
+ /* Line 187 of yacc.c. */
162
+ #line 163 "src/q_parser.c"
163
+ YYSTYPE;
164
+ # define yystype YYSTYPE /* obsolescent; will be withdrawn */
165
+ # define YYSTYPE_IS_DECLARED 1
166
+ # define YYSTYPE_IS_TRIVIAL 1
167
+ #endif
168
+
169
+
170
+
171
+ /* Copy the second part of user declarations. */
172
+ #line 121 "src/q_parser.y"
173
+
174
+ static int yylex(YYSTYPE *lvalp, QParser *qp);
175
+ static int yyerror(QParser *qp, char const *msg);
176
+
177
+ #define PHRASE_INIT_CAPA 4
178
+ static Query *get_bool_q(BCArray *bca);
179
+
180
+ static BCArray *first_cls(BooleanClause *boolean_clause);
181
+ static BCArray *add_and_cls(BCArray *bca, BooleanClause *clause);
182
+ static BCArray *add_or_cls(BCArray *bca, BooleanClause *clause);
183
+ static BCArray *add_default_cls(QParser *qp, BCArray *bca,
184
+ BooleanClause *clause);
185
+ static void bca_destroy(BCArray *bca);
186
+
187
+ static BooleanClause *get_bool_cls(Query *q, BCType occur);
188
+
189
+ static Query *get_term_q(QParser *qp, Symbol field, char *word);
190
+ static Query *get_fuzzy_q(QParser *qp, Symbol field, char *word,
191
+ char *slop);
192
+ static Query *get_wild_q(QParser *qp, Symbol field, char *pattern);
193
+
194
+ static HashSet *first_field(QParser *qp, const char *field);
195
+ static HashSet *add_field(QParser *qp, const char *field);
196
+
197
+ static Query *get_phrase_q(QParser *qp, Phrase *phrase, char *slop);
198
+
199
+ static Phrase *ph_first_word(char *word);
200
+ static Phrase *ph_add_word(Phrase *self, char *word);
201
+ static Phrase *ph_add_multi_word(Phrase *self, char *word);
202
+ static void ph_destroy(Phrase *self);
203
+
204
+ static Query *get_r_q(QParser *qp, Symbol field, char *from, char *to,
205
+ bool inc_lower, bool inc_upper);
206
+
207
+ static void qp_push_fields(QParser *self, HashSet *fields, bool destroy);
208
+ static void qp_pop_fields(QParser *self);
209
+
210
+ /**
211
+ * +FLDS+ calls +func+ for all fields on top of the field stack. +func+
212
+ * must return a query. If there is more than one field on top of FieldStack
213
+ * then +FLDS+ will combing all the queries returned by +func+ into a single
214
+ * BooleanQuery which it than assigns to +q+. If there is only one field, the
215
+ * return value of +func+ is assigned to +q+ directly.
216
+ */
217
+ #define FLDS(q, func) do {\
218
+ TRY {\
219
+ Symbol field;\
220
+ if (qp->fields->size == 0) {\
221
+ q = NULL;\
222
+ } else if (qp->fields->size == 1) {\
223
+ field = (Symbol)qp->fields->first->elem;\
224
+ q = func;\
225
+ } else {\
226
+ Query *volatile sq; HashSetEntry *volatile hse;\
227
+ q = bq_new_max(false, qp->max_clauses);\
228
+ for (hse = qp->fields->first; hse; hse = hse->next) {\
229
+ field = (Symbol)hse->elem;\
230
+ sq = func;\
231
+ TRY\
232
+ if (sq) bq_add_query_nr(q, sq, BC_SHOULD);\
233
+ XCATCHALL\
234
+ if (sq) q_deref(sq);\
235
+ XENDTRY\
236
+ }\
237
+ if (((BooleanQuery *)q)->clause_cnt == 0) {\
238
+ q_deref(q);\
239
+ q = NULL;\
240
+ }\
241
+ }\
242
+ } XCATCHALL\
243
+ qp->destruct = true;\
244
+ HANDLED();\
245
+ XENDTRY\
246
+ if (qp->destruct && !qp->recovering && q) {q_deref(q); q = NULL;}\
247
+ } while (0)
248
+
249
+ #define Y if (qp->destruct) goto yyerrorlab;
250
+ #define T TRY
251
+ #define E\
252
+ XCATCHALL\
253
+ qp->destruct = true;\
254
+ HANDLED();\
255
+ XENDTRY\
256
+ if (qp->destruct) Y;
257
+
258
+
259
+ /* Line 216 of yacc.c. */
260
+ #line 261 "src/q_parser.c"
261
+
262
+ #ifdef short
263
+ # undef short
264
+ #endif
265
+
266
+ #ifdef YYTYPE_UINT8
267
+ typedef YYTYPE_UINT8 yytype_uint8;
268
+ #else
269
+ typedef unsigned char yytype_uint8;
270
+ #endif
271
+
272
+ #ifdef YYTYPE_INT8
273
+ typedef YYTYPE_INT8 yytype_int8;
274
+ #elif (defined __STDC__ || defined __C99__FUNC__ \
275
+ || defined __cplusplus || defined _MSC_VER)
276
+ typedef signed char yytype_int8;
277
+ #else
278
+ typedef short int yytype_int8;
279
+ #endif
280
+
281
+ #ifdef YYTYPE_UINT16
282
+ typedef YYTYPE_UINT16 yytype_uint16;
283
+ #else
284
+ typedef unsigned short int yytype_uint16;
285
+ #endif
286
+
287
+ #ifdef YYTYPE_INT16
288
+ typedef YYTYPE_INT16 yytype_int16;
289
+ #else
290
+ typedef short int yytype_int16;
291
+ #endif
292
+
293
+ #ifndef YYSIZE_T
294
+ # ifdef __SIZE_TYPE__
295
+ # define YYSIZE_T __SIZE_TYPE__
296
+ # elif defined size_t
297
+ # define YYSIZE_T size_t
298
+ # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
299
+ || defined __cplusplus || defined _MSC_VER)
300
+ # include <stddef.h> /* INFRINGES ON USER NAME SPACE */
301
+ # define YYSIZE_T size_t
302
+ # else
303
+ # define YYSIZE_T unsigned int
304
+ # endif
305
+ #endif
306
+
307
+ #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
308
+
309
+ #ifndef YY_
310
+ # if YYENABLE_NLS
311
+ # if ENABLE_NLS
312
+ # include <libintl.h> /* INFRINGES ON USER NAME SPACE */
313
+ # define YY_(msgid) dgettext ("bison-runtime", msgid)
314
+ # endif
315
+ # endif
316
+ # ifndef YY_
317
+ # define YY_(msgid) msgid
318
+ # endif
319
+ #endif
320
+
321
+ /* Suppress unused-variable warnings by "using" E. */
322
+ #if ! defined lint || defined __GNUC__
323
+ # define YYUSE(e) ((void) (e))
324
+ #else
325
+ # define YYUSE(e) /* empty */
326
+ #endif
327
+
328
+ /* Identity function, used to suppress warnings about constant conditions. */
329
+ #ifndef lint
330
+ # define YYID(n) (n)
331
+ #else
332
+ #if (defined __STDC__ || defined __C99__FUNC__ \
333
+ || defined __cplusplus || defined _MSC_VER)
334
+ static int
335
+ YYID (int i)
336
+ #else
337
+ static int
338
+ YYID (i)
339
+ int i;
340
+ #endif
341
+ {
342
+ return i;
343
+ }
344
+ #endif
345
+
346
+ #if ! defined yyoverflow || YYERROR_VERBOSE
347
+
348
+ /* The parser invokes alloca or malloc; define the necessary symbols. */
349
+
350
+ # ifdef YYSTACK_USE_ALLOCA
351
+ # if YYSTACK_USE_ALLOCA
352
+ # ifdef __GNUC__
353
+ # define YYSTACK_ALLOC __builtin_alloca
354
+ # elif defined __BUILTIN_VA_ARG_INCR
355
+ # include <alloca.h> /* INFRINGES ON USER NAME SPACE */
356
+ # elif defined _AIX
357
+ # define YYSTACK_ALLOC __alloca
358
+ # elif defined _MSC_VER
359
+ # include <malloc.h> /* INFRINGES ON USER NAME SPACE */
360
+ # define alloca _alloca
361
+ # else
362
+ # define YYSTACK_ALLOC alloca
363
+ # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
364
+ || defined __cplusplus || defined _MSC_VER)
365
+ # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
366
+ # ifndef _STDLIB_H
367
+ # define _STDLIB_H 1
368
+ # endif
369
+ # endif
370
+ # endif
371
+ # endif
372
+ # endif
373
+
374
+ # ifdef YYSTACK_ALLOC
375
+ /* Pacify GCC's `empty if-body' warning. */
376
+ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
377
+ # ifndef YYSTACK_ALLOC_MAXIMUM
378
+ /* The OS might guarantee only one guard page at the bottom of the stack,
379
+ and a page size can be as small as 4096 bytes. So we cannot safely
380
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
381
+ to allow for a few compiler-allocated temporary stack slots. */
382
+ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
383
+ # endif
384
+ # else
385
+ # define YYSTACK_ALLOC YYMALLOC
386
+ # define YYSTACK_FREE YYFREE
387
+ # ifndef YYSTACK_ALLOC_MAXIMUM
388
+ # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
389
+ # endif
390
+ # if (defined __cplusplus && ! defined _STDLIB_H \
391
+ && ! ((defined YYMALLOC || defined malloc) \
392
+ && (defined YYFREE || defined free)))
393
+ # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
394
+ # ifndef _STDLIB_H
395
+ # define _STDLIB_H 1
396
+ # endif
397
+ # endif
398
+ # ifndef YYMALLOC
399
+ # define YYMALLOC malloc
400
+ # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
401
+ || defined __cplusplus || defined _MSC_VER)
402
+ void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
403
+ # endif
404
+ # endif
405
+ # ifndef YYFREE
406
+ # define YYFREE free
407
+ # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
408
+ || defined __cplusplus || defined _MSC_VER)
409
+ void free (void *); /* INFRINGES ON USER NAME SPACE */
410
+ # endif
411
+ # endif
412
+ # endif
413
+ #endif /* ! defined yyoverflow || YYERROR_VERBOSE */
414
+
415
+
416
+ #if (! defined yyoverflow \
417
+ && (! defined __cplusplus \
418
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
419
+
420
+ /* A type that is properly aligned for any stack member. */
421
+ union yyalloc
422
+ {
423
+ yytype_int16 yyss;
424
+ YYSTYPE yyvs;
425
+ };
426
+
427
+ /* The size of the maximum gap between one aligned stack and the next. */
428
+ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
429
+
430
+ /* The size of an array large to enough to hold all stacks, each with
431
+ N elements. */
432
+ # define YYSTACK_BYTES(N) \
433
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
434
+ + YYSTACK_GAP_MAXIMUM)
435
+
436
+ /* Copy COUNT objects from FROM to TO. The source and destination do
437
+ not overlap. */
438
+ # ifndef YYCOPY
439
+ # if defined __GNUC__ && 1 < __GNUC__
440
+ # define YYCOPY(To, From, Count) \
441
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
442
+ # else
443
+ # define YYCOPY(To, From, Count) \
444
+ do \
445
+ { \
446
+ YYSIZE_T yyi; \
447
+ for (yyi = 0; yyi < (Count); yyi++) \
448
+ (To)[yyi] = (From)[yyi]; \
449
+ } \
450
+ while (YYID (0))
451
+ # endif
452
+ # endif
453
+
454
+ /* Relocate STACK from its old location to the new one. The
455
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
456
+ elements in the stack, and YYPTR gives the new location of the
457
+ stack. Advance YYPTR to a properly aligned location for the next
458
+ stack. */
459
+ # define YYSTACK_RELOCATE(Stack) \
460
+ do \
461
+ { \
462
+ YYSIZE_T yynewbytes; \
463
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
464
+ Stack = &yyptr->Stack; \
465
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
466
+ yyptr += yynewbytes / sizeof (*yyptr); \
467
+ } \
468
+ while (YYID (0))
469
+
470
+ #endif
471
+
472
+ /* YYFINAL -- State number of the termination state. */
473
+ #define YYFINAL 39
474
+ /* YYLAST -- Last index in YYTABLE. */
475
+ #define YYLAST 126
476
+
477
+ /* YYNTOKENS -- Number of terminals. */
478
+ #define YYNTOKENS 26
479
+ /* YYNNTS -- Number of nonterminals. */
480
+ #define YYNNTS 16
481
+ /* YYNRULES -- Number of rules. */
482
+ #define YYNRULES 51
483
+ /* YYNRULES -- Number of states. */
484
+ #define YYNSTATES 80
485
+
486
+ /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
487
+ #define YYUNDEFTOK 2
488
+ #define YYMAXUTOK 265
489
+
490
+ #define YYTRANSLATE(YYX) \
491
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
492
+
493
+ /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
494
+ static const yytype_uint8 yytranslate[] =
495
+ {
496
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
497
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
498
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
499
+ 2, 2, 2, 2, 18, 2, 2, 2, 2, 2,
500
+ 13, 14, 16, 2, 2, 2, 2, 2, 2, 2,
501
+ 2, 2, 2, 2, 2, 2, 2, 2, 10, 2,
502
+ 19, 25, 20, 2, 2, 2, 2, 2, 2, 2,
503
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
504
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
505
+ 2, 21, 2, 22, 12, 2, 2, 2, 2, 2,
506
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
507
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
508
+ 2, 2, 2, 24, 17, 23, 15, 2, 2, 2,
509
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
510
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
511
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
512
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
513
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
514
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
515
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
516
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
517
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
518
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
519
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
520
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
521
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
522
+ 5, 6, 7, 8, 9, 11
523
+ };
524
+
525
+ #if YYDEBUG
526
+ /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
527
+ YYRHS. */
528
+ static const yytype_uint8 yyprhs[] =
529
+ {
530
+ 0, 0, 3, 4, 6, 8, 12, 16, 19, 22,
531
+ 25, 27, 29, 33, 35, 38, 42, 44, 46, 48,
532
+ 50, 52, 56, 59, 61, 62, 67, 68, 69, 75,
533
+ 77, 81, 85, 91, 94, 99, 101, 104, 107, 111,
534
+ 115, 120, 125, 130, 135, 139, 143, 147, 151, 154,
535
+ 158, 162
536
+ };
537
+
538
+ /* YYRHS -- A `-1'-separated list of the rules' RHS. */
539
+ static const yytype_int8 yyrhs[] =
540
+ {
541
+ 27, 0, -1, -1, 28, -1, 29, -1, 28, 7,
542
+ 29, -1, 28, 6, 29, -1, 28, 29, -1, 9,
543
+ 30, -1, 8, 30, -1, 30, -1, 31, -1, 31,
544
+ 12, 3, -1, 32, -1, 13, 14, -1, 13, 28,
545
+ 14, -1, 34, -1, 39, -1, 41, -1, 33, -1,
546
+ 3, -1, 3, 15, 3, -1, 3, 15, -1, 4,
547
+ -1, -1, 38, 10, 31, 35, -1, -1, -1, 16,
548
+ 36, 10, 31, 37, -1, 3, -1, 38, 17, 3,
549
+ -1, 18, 40, 18, -1, 18, 40, 18, 15, 3,
550
+ -1, 18, 18, -1, 18, 18, 15, 3, -1, 3,
551
+ -1, 19, 20, -1, 40, 3, -1, 40, 19, 20,
552
+ -1, 40, 17, 3, -1, 21, 3, 3, 22, -1,
553
+ 21, 3, 3, 23, -1, 24, 3, 3, 22, -1,
554
+ 24, 3, 3, 23, -1, 19, 3, 23, -1, 19,
555
+ 3, 22, -1, 21, 3, 20, -1, 24, 3, 20,
556
+ -1, 19, 3, -1, 19, 25, 3, -1, 20, 25,
557
+ 3, -1, 20, 3, -1
558
+ };
559
+
560
+ /* YYRLINE[YYN] -- source line where rule number YYN was defined. */
561
+ static const yytype_uint16 yyrline[] =
562
+ {
563
+ 0, 226, 226, 227, 229, 230, 231, 232, 234, 235,
564
+ 236, 238, 239, 241, 242, 243, 244, 245, 246, 247,
565
+ 249, 250, 251, 253, 255, 255, 257, 257, 257, 260,
566
+ 261, 263, 264, 265, 266, 268, 269, 270, 271, 272,
567
+ 274, 275, 276, 277, 278, 279, 280, 281, 282, 283,
568
+ 284, 285
569
+ };
570
+ #endif
571
+
572
+ #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
573
+ /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
574
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
575
+ static const char *const yytname[] =
576
+ {
577
+ "$end", "error", "$undefined", "QWRD", "WILD_STR", "LOW", "OR", "AND",
578
+ "NOT", "REQ", "':'", "HIGH", "'^'", "'('", "')'", "'~'", "'*'", "'|'",
579
+ "'\"'", "'<'", "'>'", "'['", "']'", "'}'", "'{'", "'='", "$accept",
580
+ "bool_q", "bool_clss", "bool_cls", "boosted_q", "q", "term_q", "wild_q",
581
+ "field_q", "@1", "@2", "@3", "field", "phrase_q", "ph_words", "range_q", 0
582
+ };
583
+ #endif
584
+
585
+ # ifdef YYPRINT
586
+ /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
587
+ token YYLEX-NUM. */
588
+ static const yytype_uint16 yytoknum[] =
589
+ {
590
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
591
+ 58, 265, 94, 40, 41, 126, 42, 124, 34, 60,
592
+ 62, 91, 93, 125, 123, 61
593
+ };
594
+ # endif
595
+
596
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
597
+ static const yytype_uint8 yyr1[] =
598
+ {
599
+ 0, 26, 27, 27, 28, 28, 28, 28, 29, 29,
600
+ 29, 30, 30, 31, 31, 31, 31, 31, 31, 31,
601
+ 32, 32, 32, 33, 35, 34, 36, 37, 34, 38,
602
+ 38, 39, 39, 39, 39, 40, 40, 40, 40, 40,
603
+ 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
604
+ 41, 41
605
+ };
606
+
607
+ /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
608
+ static const yytype_uint8 yyr2[] =
609
+ {
610
+ 0, 2, 0, 1, 1, 3, 3, 2, 2, 2,
611
+ 1, 1, 3, 1, 2, 3, 1, 1, 1, 1,
612
+ 1, 3, 2, 1, 0, 4, 0, 0, 5, 1,
613
+ 3, 3, 5, 2, 4, 1, 2, 2, 3, 3,
614
+ 4, 4, 4, 4, 3, 3, 3, 3, 2, 3,
615
+ 3, 2
616
+ };
617
+
618
+ /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
619
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
620
+ means the default is an error. */
621
+ static const yytype_uint8 yydefact[] =
622
+ {
623
+ 2, 20, 23, 0, 0, 0, 26, 0, 0, 0,
624
+ 0, 0, 0, 3, 4, 10, 11, 13, 19, 16,
625
+ 0, 17, 18, 22, 9, 8, 14, 0, 0, 35,
626
+ 33, 0, 0, 48, 0, 51, 0, 0, 0, 1,
627
+ 0, 0, 7, 0, 0, 0, 21, 15, 0, 0,
628
+ 36, 37, 0, 31, 0, 45, 44, 49, 50, 0,
629
+ 46, 0, 47, 6, 5, 12, 24, 30, 27, 34,
630
+ 39, 0, 38, 40, 41, 42, 43, 25, 28, 32
631
+ };
632
+
633
+ /* YYDEFGOTO[NTERM-NUM]. */
634
+ static const yytype_int8 yydefgoto[] =
635
+ {
636
+ -1, 12, 13, 14, 15, 16, 17, 18, 19, 77,
637
+ 28, 78, 20, 21, 32, 22
638
+ };
639
+
640
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
641
+ STATE-NUM. */
642
+ #define YYPACT_NINF -30
643
+ static const yytype_int8 yypact[] =
644
+ {
645
+ 83, -4, -30, 102, 102, 64, -30, 7, -2, -1,
646
+ 6, 15, 31, 45, -30, -30, 29, -30, -30, -30,
647
+ -5, -30, -30, 40, -30, -30, -30, 26, 47, -30,
648
+ 55, 42, 19, -15, 68, -30, 71, 0, 1, -30,
649
+ 83, 83, -30, 72, 102, 73, -30, -30, 102, 76,
650
+ -30, -30, 78, 74, 70, -30, -30, -30, -30, -6,
651
+ -30, 33, -30, -30, -30, -30, -30, -30, -30, -30,
652
+ -30, 90, -30, -30, -30, -30, -30, -30, -30, -30
653
+ };
654
+
655
+ /* YYPGOTO[NTERM-NUM]. */
656
+ static const yytype_int8 yypgoto[] =
657
+ {
658
+ -30, -30, 89, -13, 56, -29, -30, -30, -30, -30,
659
+ -30, -30, -30, -30, -30, -30
660
+ };
661
+
662
+ /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
663
+ positive, shift that token. If negative, reduce the rule which
664
+ number is the opposite. If zero, do what YYDEFACT says.
665
+ If YYTABLE_NINF, syntax error. */
666
+ #define YYTABLE_NINF -30
667
+ static const yytype_int8 yytable[] =
668
+ {
669
+ 42, 33, 35, 59, 61, 44, -29, 55, 56, 37,
670
+ 29, 23, 45, -29, 42, 66, 73, 74, 38, 68,
671
+ 60, 62, 51, 34, 36, 30, 31, 63, 64, 1,
672
+ 2, 39, 40, 41, 3, 4, 52, 53, 54, 5,
673
+ 47, 43, 6, 46, 7, 8, 9, 10, 1, 2,
674
+ 11, 40, 41, 3, 4, 75, 76, 48, 5, 24,
675
+ 25, 6, 50, 7, 8, 9, 10, 1, 2, 11,
676
+ 49, 57, 3, 4, 58, 65, 67, 5, 26, 69,
677
+ 6, 70, 7, 8, 9, 10, 1, 2, 11, 71,
678
+ 72, 3, 4, 79, 27, 0, 5, 0, 0, 6,
679
+ 0, 7, 8, 9, 10, 1, 2, 11, 0, 0,
680
+ 0, 0, 0, 0, 0, 5, 0, 0, 6, 0,
681
+ 7, 8, 9, 10, 0, 0, 11
682
+ };
683
+
684
+ static const yytype_int8 yycheck[] =
685
+ {
686
+ 13, 3, 3, 3, 3, 10, 10, 22, 23, 3,
687
+ 3, 15, 17, 17, 27, 44, 22, 23, 3, 48,
688
+ 20, 20, 3, 25, 25, 18, 19, 40, 41, 3,
689
+ 4, 0, 6, 7, 8, 9, 17, 18, 19, 13,
690
+ 14, 12, 16, 3, 18, 19, 20, 21, 3, 4,
691
+ 24, 6, 7, 8, 9, 22, 23, 10, 13, 3,
692
+ 4, 16, 20, 18, 19, 20, 21, 3, 4, 24,
693
+ 15, 3, 8, 9, 3, 3, 3, 13, 14, 3,
694
+ 16, 3, 18, 19, 20, 21, 3, 4, 24, 15,
695
+ 20, 8, 9, 3, 5, -1, 13, -1, -1, 16,
696
+ -1, 18, 19, 20, 21, 3, 4, 24, -1, -1,
697
+ -1, -1, -1, -1, -1, 13, -1, -1, 16, -1,
698
+ 18, 19, 20, 21, -1, -1, 24
699
+ };
700
+
701
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
702
+ symbol of state STATE-NUM. */
703
+ static const yytype_uint8 yystos[] =
704
+ {
705
+ 0, 3, 4, 8, 9, 13, 16, 18, 19, 20,
706
+ 21, 24, 27, 28, 29, 30, 31, 32, 33, 34,
707
+ 38, 39, 41, 15, 30, 30, 14, 28, 36, 3,
708
+ 18, 19, 40, 3, 25, 3, 25, 3, 3, 0,
709
+ 6, 7, 29, 12, 10, 17, 3, 14, 10, 15,
710
+ 20, 3, 17, 18, 19, 22, 23, 3, 3, 3,
711
+ 20, 3, 20, 29, 29, 3, 31, 3, 31, 3,
712
+ 3, 15, 20, 22, 23, 22, 23, 35, 37, 3
713
+ };
714
+
715
+ #define yyerrok (yyerrstatus = 0)
716
+ #define yyclearin (yychar = YYEMPTY)
717
+ #define YYEMPTY (-2)
718
+ #define YYEOF 0
719
+
720
+ #define YYACCEPT goto yyacceptlab
721
+ #define YYABORT goto yyabortlab
722
+ #define YYERROR goto yyerrorlab
723
+
724
+
725
+ /* Like YYERROR except do call yyerror. This remains here temporarily
726
+ to ease the transition to the new meaning of YYERROR, for GCC.
727
+ Once GCC version 2 has supplanted version 1, this can go. */
728
+
729
+ #define YYFAIL goto yyerrlab
730
+
731
+ #define YYRECOVERING() (!!yyerrstatus)
732
+
733
+ #define YYBACKUP(Token, Value) \
734
+ do \
735
+ if (yychar == YYEMPTY && yylen == 1) \
736
+ { \
737
+ yychar = (Token); \
738
+ yylval = (Value); \
739
+ yytoken = YYTRANSLATE (yychar); \
740
+ YYPOPSTACK (1); \
741
+ goto yybackup; \
742
+ } \
743
+ else \
744
+ { \
745
+ yyerror (qp, YY_("syntax error: cannot back up")); \
746
+ YYERROR; \
747
+ } \
748
+ while (YYID (0))
749
+
750
+
751
+ #define YYTERROR 1
752
+ #define YYERRCODE 256
753
+
754
+
755
+ /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
756
+ If N is 0, then set CURRENT to the empty location which ends
757
+ the previous symbol: RHS[0] (always defined). */
758
+
759
+ #define YYRHSLOC(Rhs, K) ((Rhs)[K])
760
+ #ifndef YYLLOC_DEFAULT
761
+ # define YYLLOC_DEFAULT(Current, Rhs, N) \
762
+ do \
763
+ if (YYID (N)) \
764
+ { \
765
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
766
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
767
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
768
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
769
+ } \
770
+ else \
771
+ { \
772
+ (Current).first_line = (Current).last_line = \
773
+ YYRHSLOC (Rhs, 0).last_line; \
774
+ (Current).first_column = (Current).last_column = \
775
+ YYRHSLOC (Rhs, 0).last_column; \
776
+ } \
777
+ while (YYID (0))
778
+ #endif
779
+
780
+
781
+ /* YY_LOCATION_PRINT -- Print the location on the stream.
782
+ This macro was not mandated originally: define only if we know
783
+ we won't break user code: when these are the locations we know. */
784
+
785
+ #ifndef YY_LOCATION_PRINT
786
+ # if YYLTYPE_IS_TRIVIAL
787
+ # define YY_LOCATION_PRINT(File, Loc) \
788
+ fprintf (File, "%d.%d-%d.%d", \
789
+ (Loc).first_line, (Loc).first_column, \
790
+ (Loc).last_line, (Loc).last_column)
791
+ # else
792
+ # define YY_LOCATION_PRINT(File, Loc) ((void) 0)
793
+ # endif
794
+ #endif
795
+
796
+
797
+ /* YYLEX -- calling `yylex' with the right arguments. */
798
+
799
+ #ifdef YYLEX_PARAM
800
+ # define YYLEX yylex (&yylval, YYLEX_PARAM)
801
+ #else
802
+ # define YYLEX yylex (&yylval, qp)
803
+ #endif
804
+
805
+ /* Enable debugging if requested. */
806
+ #if YYDEBUG
807
+
808
+ # ifndef YYFPRINTF
809
+ # include <stdio.h> /* INFRINGES ON USER NAME SPACE */
810
+ # define YYFPRINTF fprintf
811
+ # endif
812
+
813
+ # define YYDPRINTF(Args) \
814
+ do { \
815
+ if (yydebug) \
816
+ YYFPRINTF Args; \
817
+ } while (YYID (0))
818
+
819
+ # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
820
+ do { \
821
+ if (yydebug) \
822
+ { \
823
+ YYFPRINTF (stderr, "%s ", Title); \
824
+ yy_symbol_print (stderr, \
825
+ Type, Value, qp); \
826
+ YYFPRINTF (stderr, "\n"); \
827
+ } \
828
+ } while (YYID (0))
829
+
830
+
831
+ /*--------------------------------.
832
+ | Print this symbol on YYOUTPUT. |
833
+ `--------------------------------*/
834
+
835
+ /*ARGSUSED*/
836
+ #if (defined __STDC__ || defined __C99__FUNC__ \
837
+ || defined __cplusplus || defined _MSC_VER)
838
+ static void
839
+ yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, QParser *qp)
840
+ #else
841
+ static void
842
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, qp)
843
+ FILE *yyoutput;
844
+ int yytype;
845
+ YYSTYPE const * const yyvaluep;
846
+ QParser *qp;
847
+ #endif
848
+ {
849
+ if (!yyvaluep)
850
+ return;
851
+ YYUSE (qp);
852
+ # ifdef YYPRINT
853
+ if (yytype < YYNTOKENS)
854
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
855
+ # else
856
+ YYUSE (yyoutput);
857
+ # endif
858
+ switch (yytype)
859
+ {
860
+ default:
861
+ break;
862
+ }
863
+ }
864
+
865
+
866
+ /*--------------------------------.
867
+ | Print this symbol on YYOUTPUT. |
868
+ `--------------------------------*/
869
+
870
+ #if (defined __STDC__ || defined __C99__FUNC__ \
871
+ || defined __cplusplus || defined _MSC_VER)
872
+ static void
873
+ yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, QParser *qp)
874
+ #else
875
+ static void
876
+ yy_symbol_print (yyoutput, yytype, yyvaluep, qp)
877
+ FILE *yyoutput;
878
+ int yytype;
879
+ YYSTYPE const * const yyvaluep;
880
+ QParser *qp;
881
+ #endif
882
+ {
883
+ if (yytype < YYNTOKENS)
884
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
885
+ else
886
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
887
+
888
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, qp);
889
+ YYFPRINTF (yyoutput, ")");
890
+ }
891
+
892
+ /*------------------------------------------------------------------.
893
+ | yy_stack_print -- Print the state stack from its BOTTOM up to its |
894
+ | TOP (included). |
895
+ `------------------------------------------------------------------*/
896
+
897
+ #if (defined __STDC__ || defined __C99__FUNC__ \
898
+ || defined __cplusplus || defined _MSC_VER)
899
+ static void
900
+ yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
901
+ #else
902
+ static void
903
+ yy_stack_print (bottom, top)
904
+ yytype_int16 *bottom;
905
+ yytype_int16 *top;
906
+ #endif
907
+ {
908
+ YYFPRINTF (stderr, "Stack now");
909
+ for (; bottom <= top; ++bottom)
910
+ YYFPRINTF (stderr, " %d", *bottom);
911
+ YYFPRINTF (stderr, "\n");
912
+ }
913
+
914
+ # define YY_STACK_PRINT(Bottom, Top) \
915
+ do { \
916
+ if (yydebug) \
917
+ yy_stack_print ((Bottom), (Top)); \
918
+ } while (YYID (0))
919
+
920
+
921
+ /*------------------------------------------------.
922
+ | Report that the YYRULE is going to be reduced. |
923
+ `------------------------------------------------*/
924
+
925
+ #if (defined __STDC__ || defined __C99__FUNC__ \
926
+ || defined __cplusplus || defined _MSC_VER)
927
+ static void
928
+ yy_reduce_print (YYSTYPE *yyvsp, int yyrule, QParser *qp)
929
+ #else
930
+ static void
931
+ yy_reduce_print (yyvsp, yyrule, qp)
932
+ YYSTYPE *yyvsp;
933
+ int yyrule;
934
+ QParser *qp;
935
+ #endif
936
+ {
937
+ int yynrhs = yyr2[yyrule];
938
+ int yyi;
939
+ unsigned long int yylno = yyrline[yyrule];
940
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
941
+ yyrule - 1, yylno);
942
+ /* The symbols being reduced. */
943
+ for (yyi = 0; yyi < yynrhs; yyi++)
944
+ {
945
+ fprintf (stderr, " $%d = ", yyi + 1);
946
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
947
+ &(yyvsp[(yyi + 1) - (yynrhs)])
948
+ , qp);
949
+ fprintf (stderr, "\n");
950
+ }
951
+ }
952
+
953
+ # define YY_REDUCE_PRINT(Rule) \
954
+ do { \
955
+ if (yydebug) \
956
+ yy_reduce_print (yyvsp, Rule, qp); \
957
+ } while (YYID (0))
958
+
959
+ /* Nonzero means print parse trace. It is left uninitialized so that
960
+ multiple parsers can coexist. */
961
+ int yydebug;
962
+ #else /* !YYDEBUG */
963
+ # define YYDPRINTF(Args)
964
+ # define YY_SYMBOL_PRINT(Title, Type, Value, Location)
965
+ # define YY_STACK_PRINT(Bottom, Top)
966
+ # define YY_REDUCE_PRINT(Rule)
967
+ #endif /* !YYDEBUG */
968
+
969
+
970
+ /* YYINITDEPTH -- initial size of the parser's stacks. */
971
+ #ifndef YYINITDEPTH
972
+ # define YYINITDEPTH 200
973
+ #endif
974
+
975
+ /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
976
+ if the built-in stack extension method is used).
977
+
978
+ Do not make this value too large; the results are undefined if
979
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
980
+ evaluated with infinite-precision integer arithmetic. */
981
+
982
+ #ifndef YYMAXDEPTH
983
+ # define YYMAXDEPTH 10000
984
+ #endif
985
+
986
+
987
+
988
+ #if YYERROR_VERBOSE
989
+
990
+ # ifndef yystrlen
991
+ # if defined __GLIBC__ && defined _STRING_H
992
+ # define yystrlen strlen
993
+ # else
994
+ /* Return the length of YYSTR. */
995
+ #if (defined __STDC__ || defined __C99__FUNC__ \
996
+ || defined __cplusplus || defined _MSC_VER)
997
+ static YYSIZE_T
998
+ yystrlen (const char *yystr)
999
+ #else
1000
+ static YYSIZE_T
1001
+ yystrlen (yystr)
1002
+ const char *yystr;
1003
+ #endif
1004
+ {
1005
+ YYSIZE_T yylen;
1006
+ for (yylen = 0; yystr[yylen]; yylen++)
1007
+ continue;
1008
+ return yylen;
1009
+ }
1010
+ # endif
1011
+ # endif
1012
+
1013
+ # ifndef yystpcpy
1014
+ # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
1015
+ # define yystpcpy stpcpy
1016
+ # else
1017
+ /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
1018
+ YYDEST. */
1019
+ #if (defined __STDC__ || defined __C99__FUNC__ \
1020
+ || defined __cplusplus || defined _MSC_VER)
1021
+ static char *
1022
+ yystpcpy (char *yydest, const char *yysrc)
1023
+ #else
1024
+ static char *
1025
+ yystpcpy (yydest, yysrc)
1026
+ char *yydest;
1027
+ const char *yysrc;
1028
+ #endif
1029
+ {
1030
+ char *yyd = yydest;
1031
+ const char *yys = yysrc;
1032
+
1033
+ while ((*yyd++ = *yys++) != '\0')
1034
+ continue;
1035
+
1036
+ return yyd - 1;
1037
+ }
1038
+ # endif
1039
+ # endif
1040
+
1041
+ # ifndef yytnamerr
1042
+ /* Copy to YYRES the contents of YYSTR after stripping away unnecessary
1043
+ quotes and backslashes, so that it's suitable for yyerror. The
1044
+ heuristic is that double-quoting is unnecessary unless the string
1045
+ contains an apostrophe, a comma, or backslash (other than
1046
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
1047
+ null, do not copy; instead, return the length of what the result
1048
+ would have been. */
1049
+ static YYSIZE_T
1050
+ yytnamerr (char *yyres, const char *yystr)
1051
+ {
1052
+ if (*yystr == '"')
1053
+ {
1054
+ YYSIZE_T yyn = 0;
1055
+ char const *yyp = yystr;
1056
+
1057
+ for (;;)
1058
+ switch (*++yyp)
1059
+ {
1060
+ case '\'':
1061
+ case ',':
1062
+ goto do_not_strip_quotes;
1063
+
1064
+ case '\\':
1065
+ if (*++yyp != '\\')
1066
+ goto do_not_strip_quotes;
1067
+ /* Fall through. */
1068
+ default:
1069
+ if (yyres)
1070
+ yyres[yyn] = *yyp;
1071
+ yyn++;
1072
+ break;
1073
+
1074
+ case '"':
1075
+ if (yyres)
1076
+ yyres[yyn] = '\0';
1077
+ return yyn;
1078
+ }
1079
+ do_not_strip_quotes: ;
1080
+ }
1081
+
1082
+ if (! yyres)
1083
+ return yystrlen (yystr);
1084
+
1085
+ return yystpcpy (yyres, yystr) - yyres;
1086
+ }
1087
+ # endif
1088
+
1089
+ /* Copy into YYRESULT an error message about the unexpected token
1090
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
1091
+ including the terminating null byte. If YYRESULT is null, do not
1092
+ copy anything; just return the number of bytes that would be
1093
+ copied. As a special case, return 0 if an ordinary "syntax error"
1094
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
1095
+ size calculation. */
1096
+ static YYSIZE_T
1097
+ yysyntax_error (char *yyresult, int yystate, int yychar)
1098
+ {
1099
+ int yyn = yypact[yystate];
1100
+
1101
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
1102
+ return 0;
1103
+ else
1104
+ {
1105
+ int yytype = YYTRANSLATE (yychar);
1106
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
1107
+ YYSIZE_T yysize = yysize0;
1108
+ YYSIZE_T yysize1;
1109
+ int yysize_overflow = 0;
1110
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
1111
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
1112
+ int yyx;
1113
+
1114
+ # if 0
1115
+ /* This is so xgettext sees the translatable formats that are
1116
+ constructed on the fly. */
1117
+ YY_("syntax error, unexpected %s");
1118
+ YY_("syntax error, unexpected %s, expecting %s");
1119
+ YY_("syntax error, unexpected %s, expecting %s or %s");
1120
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
1121
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
1122
+ # endif
1123
+ char *yyfmt;
1124
+ char const *yyf;
1125
+ static char const yyunexpected[] = "syntax error, unexpected %s";
1126
+ static char const yyexpecting[] = ", expecting %s";
1127
+ static char const yyor[] = " or %s";
1128
+ char yyformat[sizeof yyunexpected
1129
+ + sizeof yyexpecting - 1
1130
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
1131
+ * (sizeof yyor - 1))];
1132
+ char const *yyprefix = yyexpecting;
1133
+
1134
+ /* Start YYX at -YYN if negative to avoid negative indexes in
1135
+ YYCHECK. */
1136
+ int yyxbegin = yyn < 0 ? -yyn : 0;
1137
+
1138
+ /* Stay within bounds of both yycheck and yytname. */
1139
+ int yychecklim = YYLAST - yyn + 1;
1140
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
1141
+ int yycount = 1;
1142
+
1143
+ yyarg[0] = yytname[yytype];
1144
+ yyfmt = yystpcpy (yyformat, yyunexpected);
1145
+
1146
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
1147
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
1148
+ {
1149
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
1150
+ {
1151
+ yycount = 1;
1152
+ yysize = yysize0;
1153
+ yyformat[sizeof yyunexpected - 1] = '\0';
1154
+ break;
1155
+ }
1156
+ yyarg[yycount++] = yytname[yyx];
1157
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
1158
+ yysize_overflow |= (yysize1 < yysize);
1159
+ yysize = yysize1;
1160
+ yyfmt = yystpcpy (yyfmt, yyprefix);
1161
+ yyprefix = yyor;
1162
+ }
1163
+
1164
+ yyf = YY_(yyformat);
1165
+ yysize1 = yysize + yystrlen (yyf);
1166
+ yysize_overflow |= (yysize1 < yysize);
1167
+ yysize = yysize1;
1168
+
1169
+ if (yysize_overflow)
1170
+ return YYSIZE_MAXIMUM;
1171
+
1172
+ if (yyresult)
1173
+ {
1174
+ /* Avoid sprintf, as that infringes on the user's name space.
1175
+ Don't have undefined behavior even if the translation
1176
+ produced a string with the wrong number of "%s"s. */
1177
+ char *yyp = yyresult;
1178
+ int yyi = 0;
1179
+ while ((*yyp = *yyf) != '\0')
1180
+ {
1181
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
1182
+ {
1183
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
1184
+ yyf += 2;
1185
+ }
1186
+ else
1187
+ {
1188
+ yyp++;
1189
+ yyf++;
1190
+ }
1191
+ }
1192
+ }
1193
+ return yysize;
1194
+ }
1195
+ }
1196
+ #endif /* YYERROR_VERBOSE */
1197
+
1198
+
1199
+ /*-----------------------------------------------.
1200
+ | Release the memory associated to this symbol. |
1201
+ `-----------------------------------------------*/
1202
+
1203
+ /*ARGSUSED*/
1204
+ #if (defined __STDC__ || defined __C99__FUNC__ \
1205
+ || defined __cplusplus || defined _MSC_VER)
1206
+ static void
1207
+ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, QParser *qp)
1208
+ #else
1209
+ static void
1210
+ yydestruct (yymsg, yytype, yyvaluep, qp)
1211
+ const char *yymsg;
1212
+ int yytype;
1213
+ YYSTYPE *yyvaluep;
1214
+ QParser *qp;
1215
+ #endif
1216
+ {
1217
+ YYUSE (yyvaluep);
1218
+ YYUSE (qp);
1219
+
1220
+ if (!yymsg)
1221
+ yymsg = "Deleting";
1222
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
1223
+
1224
+ switch (yytype)
1225
+ {
1226
+ case 27: /* "bool_q" */
1227
+ #line 221 "src/q_parser.y"
1228
+ { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); };
1229
+ #line 1230 "src/q_parser.c"
1230
+ break;
1231
+ case 28: /* "bool_clss" */
1232
+ #line 223 "src/q_parser.y"
1233
+ { if ((yyvaluep->bclss) && qp->destruct) bca_destroy((yyvaluep->bclss)); };
1234
+ #line 1235 "src/q_parser.c"
1235
+ break;
1236
+ case 29: /* "bool_cls" */
1237
+ #line 222 "src/q_parser.y"
1238
+ { if ((yyvaluep->bcls) && qp->destruct) bc_deref((yyvaluep->bcls)); };
1239
+ #line 1240 "src/q_parser.c"
1240
+ break;
1241
+ case 30: /* "boosted_q" */
1242
+ #line 221 "src/q_parser.y"
1243
+ { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); };
1244
+ #line 1245 "src/q_parser.c"
1245
+ break;
1246
+ case 31: /* "q" */
1247
+ #line 221 "src/q_parser.y"
1248
+ { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); };
1249
+ #line 1250 "src/q_parser.c"
1250
+ break;
1251
+ case 32: /* "term_q" */
1252
+ #line 221 "src/q_parser.y"
1253
+ { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); };
1254
+ #line 1255 "src/q_parser.c"
1255
+ break;
1256
+ case 33: /* "wild_q" */
1257
+ #line 221 "src/q_parser.y"
1258
+ { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); };
1259
+ #line 1260 "src/q_parser.c"
1260
+ break;
1261
+ case 34: /* "field_q" */
1262
+ #line 221 "src/q_parser.y"
1263
+ { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); };
1264
+ #line 1265 "src/q_parser.c"
1265
+ break;
1266
+ case 39: /* "phrase_q" */
1267
+ #line 221 "src/q_parser.y"
1268
+ { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); };
1269
+ #line 1270 "src/q_parser.c"
1270
+ break;
1271
+ case 40: /* "ph_words" */
1272
+ #line 224 "src/q_parser.y"
1273
+ { if ((yyvaluep->phrase) && qp->destruct) ph_destroy((yyvaluep->phrase)); };
1274
+ #line 1275 "src/q_parser.c"
1275
+ break;
1276
+ case 41: /* "range_q" */
1277
+ #line 221 "src/q_parser.y"
1278
+ { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); };
1279
+ #line 1280 "src/q_parser.c"
1280
+ break;
1281
+
1282
+ default:
1283
+ break;
1284
+ }
1285
+ }
1286
+
1287
+
1288
+ /* Prevent warnings from -Wmissing-prototypes. */
1289
+
1290
+ #ifdef YYPARSE_PARAM
1291
+ #if defined __STDC__ || defined __cplusplus
1292
+ int yyparse (void *YYPARSE_PARAM);
1293
+ #else
1294
+ int yyparse ();
1295
+ #endif
1296
+ #else /* ! YYPARSE_PARAM */
1297
+ #if defined __STDC__ || defined __cplusplus
1298
+ int yyparse (QParser *qp);
1299
+ #else
1300
+ int yyparse ();
1301
+ #endif
1302
+ #endif /* ! YYPARSE_PARAM */
1303
+
1304
+
1305
+
1306
+
1307
+
1308
+
1309
+ /*----------.
1310
+ | yyparse. |
1311
+ `----------*/
1312
+
1313
+ #ifdef YYPARSE_PARAM
1314
+ #if (defined __STDC__ || defined __C99__FUNC__ \
1315
+ || defined __cplusplus || defined _MSC_VER)
1316
+ int
1317
+ yyparse (void *YYPARSE_PARAM)
1318
+ #else
1319
+ int
1320
+ yyparse (YYPARSE_PARAM)
1321
+ void *YYPARSE_PARAM;
1322
+ #endif
1323
+ #else /* ! YYPARSE_PARAM */
1324
+ #if (defined __STDC__ || defined __C99__FUNC__ \
1325
+ || defined __cplusplus || defined _MSC_VER)
1326
+ int
1327
+ yyparse (QParser *qp)
1328
+ #else
1329
+ int
1330
+ yyparse (qp)
1331
+ QParser *qp;
1332
+ #endif
1333
+ #endif
1334
+ {
1335
+ /* The look-ahead symbol. */
1336
+ int yychar;
1337
+
1338
+ /* The semantic value of the look-ahead symbol. */
1339
+ YYSTYPE yylval;
1340
+
1341
+ /* Number of syntax errors so far. */
1342
+ int yynerrs;
1343
+
1344
+ int yystate;
1345
+ int yyn;
1346
+ int yyresult;
1347
+ /* Number of tokens to shift before error messages enabled. */
1348
+ int yyerrstatus;
1349
+ /* Look-ahead token as an internal (translated) token number. */
1350
+ int yytoken = 0;
1351
+ #if YYERROR_VERBOSE
1352
+ /* Buffer for error messages, and its allocated size. */
1353
+ char yymsgbuf[128];
1354
+ char *yymsg = yymsgbuf;
1355
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
1356
+ #endif
1357
+
1358
+ /* Three stacks and their tools:
1359
+ `yyss': related to states,
1360
+ `yyvs': related to semantic values,
1361
+ `yyls': related to locations.
1362
+
1363
+ Refer to the stacks thru separate pointers, to allow yyoverflow
1364
+ to reallocate them elsewhere. */
1365
+
1366
+ /* The state stack. */
1367
+ yytype_int16 yyssa[YYINITDEPTH];
1368
+ yytype_int16 *yyss = yyssa;
1369
+ yytype_int16 *yyssp;
1370
+
1371
+ /* The semantic value stack. */
1372
+ YYSTYPE yyvsa[YYINITDEPTH];
1373
+ YYSTYPE *yyvs = yyvsa;
1374
+ YYSTYPE *yyvsp;
1375
+
1376
+
1377
+
1378
+ #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
1379
+
1380
+ YYSIZE_T yystacksize = YYINITDEPTH;
1381
+
1382
+ /* The variables used to return semantic value and location from the
1383
+ action routines. */
1384
+ YYSTYPE yyval;
1385
+
1386
+
1387
+ /* The number of symbols on the RHS of the reduced rule.
1388
+ Keep to zero when no symbol should be popped. */
1389
+ int yylen = 0;
1390
+
1391
+ YYDPRINTF ((stderr, "Starting parse\n"));
1392
+
1393
+ yystate = 0;
1394
+ yyerrstatus = 0;
1395
+ yynerrs = 0;
1396
+ yychar = YYEMPTY; /* Cause a token to be read. */
1397
+
1398
+ /* Initialize stack pointers.
1399
+ Waste one element of value and location stack
1400
+ so that they stay on the same level as the state stack.
1401
+ The wasted elements are never initialized. */
1402
+
1403
+ yyssp = yyss;
1404
+ yyvsp = yyvs;
1405
+
1406
+ goto yysetstate;
1407
+
1408
+ /*------------------------------------------------------------.
1409
+ | yynewstate -- Push a new state, which is found in yystate. |
1410
+ `------------------------------------------------------------*/
1411
+ yynewstate:
1412
+ /* In all cases, when you get here, the value and location stacks
1413
+ have just been pushed. So pushing a state here evens the stacks. */
1414
+ yyssp++;
1415
+
1416
+ yysetstate:
1417
+ *yyssp = yystate;
1418
+
1419
+ if (yyss + yystacksize - 1 <= yyssp)
1420
+ {
1421
+ /* Get the current used size of the three stacks, in elements. */
1422
+ YYSIZE_T yysize = yyssp - yyss + 1;
1423
+
1424
+ #ifdef yyoverflow
1425
+ {
1426
+ /* Give user a chance to reallocate the stack. Use copies of
1427
+ these so that the &'s don't force the real ones into
1428
+ memory. */
1429
+ YYSTYPE *yyvs1 = yyvs;
1430
+ yytype_int16 *yyss1 = yyss;
1431
+
1432
+
1433
+ /* Each stack pointer address is followed by the size of the
1434
+ data in use in that stack, in bytes. This used to be a
1435
+ conditional around just the two extra args, but that might
1436
+ be undefined if yyoverflow is a macro. */
1437
+ yyoverflow (YY_("memory exhausted"),
1438
+ &yyss1, yysize * sizeof (*yyssp),
1439
+ &yyvs1, yysize * sizeof (*yyvsp),
1440
+
1441
+ &yystacksize);
1442
+
1443
+ yyss = yyss1;
1444
+ yyvs = yyvs1;
1445
+ }
1446
+ #else /* no yyoverflow */
1447
+ # ifndef YYSTACK_RELOCATE
1448
+ goto yyexhaustedlab;
1449
+ # else
1450
+ /* Extend the stack our own way. */
1451
+ if (YYMAXDEPTH <= yystacksize)
1452
+ goto yyexhaustedlab;
1453
+ yystacksize *= 2;
1454
+ if (YYMAXDEPTH < yystacksize)
1455
+ yystacksize = YYMAXDEPTH;
1456
+
1457
+ {
1458
+ yytype_int16 *yyss1 = yyss;
1459
+ union yyalloc *yyptr =
1460
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
1461
+ if (! yyptr)
1462
+ goto yyexhaustedlab;
1463
+ YYSTACK_RELOCATE (yyss);
1464
+ YYSTACK_RELOCATE (yyvs);
1465
+
1466
+ # undef YYSTACK_RELOCATE
1467
+ if (yyss1 != yyssa)
1468
+ YYSTACK_FREE (yyss1);
1469
+ }
1470
+ # endif
1471
+ #endif /* no yyoverflow */
1472
+
1473
+ yyssp = yyss + yysize - 1;
1474
+ yyvsp = yyvs + yysize - 1;
1475
+
1476
+
1477
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
1478
+ (unsigned long int) yystacksize));
1479
+
1480
+ if (yyss + yystacksize - 1 <= yyssp)
1481
+ YYABORT;
1482
+ }
1483
+
1484
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
1485
+
1486
+ goto yybackup;
1487
+
1488
+ /*-----------.
1489
+ | yybackup. |
1490
+ `-----------*/
1491
+ yybackup:
1492
+
1493
+ /* Do appropriate processing given the current state. Read a
1494
+ look-ahead token if we need one and don't already have one. */
1495
+
1496
+ /* First try to decide what to do without reference to look-ahead token. */
1497
+ yyn = yypact[yystate];
1498
+ if (yyn == YYPACT_NINF)
1499
+ goto yydefault;
1500
+
1501
+ /* Not known => get a look-ahead token if don't already have one. */
1502
+
1503
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
1504
+ if (yychar == YYEMPTY)
1505
+ {
1506
+ YYDPRINTF ((stderr, "Reading a token: "));
1507
+ yychar = YYLEX;
1508
+ }
1509
+
1510
+ if (yychar <= YYEOF)
1511
+ {
1512
+ yychar = yytoken = YYEOF;
1513
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
1514
+ }
1515
+ else
1516
+ {
1517
+ yytoken = YYTRANSLATE (yychar);
1518
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
1519
+ }
1520
+
1521
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
1522
+ detect an error, take that action. */
1523
+ yyn += yytoken;
1524
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
1525
+ goto yydefault;
1526
+ yyn = yytable[yyn];
1527
+ if (yyn <= 0)
1528
+ {
1529
+ if (yyn == 0 || yyn == YYTABLE_NINF)
1530
+ goto yyerrlab;
1531
+ yyn = -yyn;
1532
+ goto yyreduce;
1533
+ }
1534
+
1535
+ if (yyn == YYFINAL)
1536
+ YYACCEPT;
1537
+
1538
+ /* Count tokens shifted since error; after three, turn off error
1539
+ status. */
1540
+ if (yyerrstatus)
1541
+ yyerrstatus--;
1542
+
1543
+ /* Shift the look-ahead token. */
1544
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
1545
+
1546
+ /* Discard the shifted token unless it is eof. */
1547
+ if (yychar != YYEOF)
1548
+ yychar = YYEMPTY;
1549
+
1550
+ yystate = yyn;
1551
+ *++yyvsp = yylval;
1552
+
1553
+ goto yynewstate;
1554
+
1555
+
1556
+ /*-----------------------------------------------------------.
1557
+ | yydefault -- do the default action for the current state. |
1558
+ `-----------------------------------------------------------*/
1559
+ yydefault:
1560
+ yyn = yydefact[yystate];
1561
+ if (yyn == 0)
1562
+ goto yyerrlab;
1563
+ goto yyreduce;
1564
+
1565
+
1566
+ /*-----------------------------.
1567
+ | yyreduce -- Do a reduction. |
1568
+ `-----------------------------*/
1569
+ yyreduce:
1570
+ /* yyn is the number of a rule to reduce with. */
1571
+ yylen = yyr2[yyn];
1572
+
1573
+ /* If YYLEN is nonzero, implement the default value of the action:
1574
+ `$$ = $1'.
1575
+
1576
+ Otherwise, the following line sets YYVAL to garbage.
1577
+ This behavior is undocumented and Bison
1578
+ users should not rely upon it. Assigning to YYVAL
1579
+ unconditionally makes the parser a bit smaller, and it avoids a
1580
+ GCC warning that YYVAL may be used uninitialized. */
1581
+ yyval = yyvsp[1-yylen];
1582
+
1583
+
1584
+ YY_REDUCE_PRINT (yyn);
1585
+ switch (yyn)
1586
+ {
1587
+ case 2:
1588
+ #line 226 "src/q_parser.y"
1589
+ { qp->result = (yyval.query) = NULL; }
1590
+ break;
1591
+
1592
+ case 3:
1593
+ #line 227 "src/q_parser.y"
1594
+ { T qp->result = (yyval.query) = get_bool_q((yyvsp[(1) - (1)].bclss)); E }
1595
+ break;
1596
+
1597
+ case 4:
1598
+ #line 229 "src/q_parser.y"
1599
+ { T (yyval.bclss) = first_cls((yyvsp[(1) - (1)].bcls)); E }
1600
+ break;
1601
+
1602
+ case 5:
1603
+ #line 230 "src/q_parser.y"
1604
+ { T (yyval.bclss) = add_and_cls((yyvsp[(1) - (3)].bclss), (yyvsp[(3) - (3)].bcls)); E }
1605
+ break;
1606
+
1607
+ case 6:
1608
+ #line 231 "src/q_parser.y"
1609
+ { T (yyval.bclss) = add_or_cls((yyvsp[(1) - (3)].bclss), (yyvsp[(3) - (3)].bcls)); E }
1610
+ break;
1611
+
1612
+ case 7:
1613
+ #line 232 "src/q_parser.y"
1614
+ { T (yyval.bclss) = add_default_cls(qp, (yyvsp[(1) - (2)].bclss), (yyvsp[(2) - (2)].bcls)); E }
1615
+ break;
1616
+
1617
+ case 8:
1618
+ #line 234 "src/q_parser.y"
1619
+ { T (yyval.bcls) = get_bool_cls((yyvsp[(2) - (2)].query), BC_MUST); E }
1620
+ break;
1621
+
1622
+ case 9:
1623
+ #line 235 "src/q_parser.y"
1624
+ { T (yyval.bcls) = get_bool_cls((yyvsp[(2) - (2)].query), BC_MUST_NOT); E }
1625
+ break;
1626
+
1627
+ case 10:
1628
+ #line 236 "src/q_parser.y"
1629
+ { T (yyval.bcls) = get_bool_cls((yyvsp[(1) - (1)].query), BC_SHOULD); E }
1630
+ break;
1631
+
1632
+ case 12:
1633
+ #line 239 "src/q_parser.y"
1634
+ { T if ((yyvsp[(1) - (3)].query)) sscanf((yyvsp[(3) - (3)].str),"%f",&((yyvsp[(1) - (3)].query)->boost)); (yyval.query)=(yyvsp[(1) - (3)].query); E }
1635
+ break;
1636
+
1637
+ case 14:
1638
+ #line 242 "src/q_parser.y"
1639
+ { T (yyval.query) = bq_new_max(true, qp->max_clauses); E }
1640
+ break;
1641
+
1642
+ case 15:
1643
+ #line 243 "src/q_parser.y"
1644
+ { T (yyval.query) = get_bool_q((yyvsp[(2) - (3)].bclss)); E }
1645
+ break;
1646
+
1647
+ case 20:
1648
+ #line 249 "src/q_parser.y"
1649
+ { FLDS((yyval.query), get_term_q(qp, field, (yyvsp[(1) - (1)].str))); Y}
1650
+ break;
1651
+
1652
+ case 21:
1653
+ #line 250 "src/q_parser.y"
1654
+ { FLDS((yyval.query), get_fuzzy_q(qp, field, (yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str))); Y}
1655
+ break;
1656
+
1657
+ case 22:
1658
+ #line 251 "src/q_parser.y"
1659
+ { FLDS((yyval.query), get_fuzzy_q(qp, field, (yyvsp[(1) - (2)].str), NULL)); Y}
1660
+ break;
1661
+
1662
+ case 23:
1663
+ #line 253 "src/q_parser.y"
1664
+ { FLDS((yyval.query), get_wild_q(qp, field, (yyvsp[(1) - (1)].str))); Y}
1665
+ break;
1666
+
1667
+ case 24:
1668
+ #line 255 "src/q_parser.y"
1669
+ { qp_pop_fields(qp); }
1670
+ break;
1671
+
1672
+ case 25:
1673
+ #line 256 "src/q_parser.y"
1674
+ { (yyval.query) = (yyvsp[(3) - (4)].query); }
1675
+ break;
1676
+
1677
+ case 26:
1678
+ #line 257 "src/q_parser.y"
1679
+ { qp_push_fields(qp, qp->all_fields, false); }
1680
+ break;
1681
+
1682
+ case 27:
1683
+ #line 257 "src/q_parser.y"
1684
+ { qp_pop_fields(qp); }
1685
+ break;
1686
+
1687
+ case 28:
1688
+ #line 258 "src/q_parser.y"
1689
+ { (yyval.query) = (yyvsp[(4) - (5)].query); }
1690
+ break;
1691
+
1692
+ case 29:
1693
+ #line 260 "src/q_parser.y"
1694
+ { (yyval.hashset) = first_field(qp, (yyvsp[(1) - (1)].str)); }
1695
+ break;
1696
+
1697
+ case 30:
1698
+ #line 261 "src/q_parser.y"
1699
+ { (yyval.hashset) = add_field(qp, (yyvsp[(3) - (3)].str));}
1700
+ break;
1701
+
1702
+ case 31:
1703
+ #line 263 "src/q_parser.y"
1704
+ { (yyval.query) = get_phrase_q(qp, (yyvsp[(2) - (3)].phrase), NULL); }
1705
+ break;
1706
+
1707
+ case 32:
1708
+ #line 264 "src/q_parser.y"
1709
+ { (yyval.query) = get_phrase_q(qp, (yyvsp[(2) - (5)].phrase), (yyvsp[(5) - (5)].str)); }
1710
+ break;
1711
+
1712
+ case 33:
1713
+ #line 265 "src/q_parser.y"
1714
+ { (yyval.query) = NULL; }
1715
+ break;
1716
+
1717
+ case 34:
1718
+ #line 266 "src/q_parser.y"
1719
+ { (yyval.query) = NULL; (void)(yyvsp[(4) - (4)].str);}
1720
+ break;
1721
+
1722
+ case 35:
1723
+ #line 268 "src/q_parser.y"
1724
+ { (yyval.phrase) = ph_first_word((yyvsp[(1) - (1)].str)); }
1725
+ break;
1726
+
1727
+ case 36:
1728
+ #line 269 "src/q_parser.y"
1729
+ { (yyval.phrase) = ph_first_word(NULL); }
1730
+ break;
1731
+
1732
+ case 37:
1733
+ #line 270 "src/q_parser.y"
1734
+ { (yyval.phrase) = ph_add_word((yyvsp[(1) - (2)].phrase), (yyvsp[(2) - (2)].str)); }
1735
+ break;
1736
+
1737
+ case 38:
1738
+ #line 271 "src/q_parser.y"
1739
+ { (yyval.phrase) = ph_add_word((yyvsp[(1) - (3)].phrase), NULL); }
1740
+ break;
1741
+
1742
+ case 39:
1743
+ #line 272 "src/q_parser.y"
1744
+ { (yyval.phrase) = ph_add_multi_word((yyvsp[(1) - (3)].phrase), (yyvsp[(3) - (3)].str)); }
1745
+ break;
1746
+
1747
+ case 40:
1748
+ #line 274 "src/q_parser.y"
1749
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].str), true, true)); Y}
1750
+ break;
1751
+
1752
+ case 41:
1753
+ #line 275 "src/q_parser.y"
1754
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].str), true, false)); Y}
1755
+ break;
1756
+
1757
+ case 42:
1758
+ #line 276 "src/q_parser.y"
1759
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].str), false, true)); Y}
1760
+ break;
1761
+
1762
+ case 43:
1763
+ #line 277 "src/q_parser.y"
1764
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].str), false, false)); Y}
1765
+ break;
1766
+
1767
+ case 44:
1768
+ #line 278 "src/q_parser.y"
1769
+ { FLDS((yyval.query), get_r_q(qp, field, NULL,(yyvsp[(2) - (3)].str), false, false)); Y}
1770
+ break;
1771
+
1772
+ case 45:
1773
+ #line 279 "src/q_parser.y"
1774
+ { FLDS((yyval.query), get_r_q(qp, field, NULL,(yyvsp[(2) - (3)].str), false, true)); Y}
1775
+ break;
1776
+
1777
+ case 46:
1778
+ #line 280 "src/q_parser.y"
1779
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (3)].str), NULL,true, false)); Y}
1780
+ break;
1781
+
1782
+ case 47:
1783
+ #line 281 "src/q_parser.y"
1784
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (3)].str), NULL,false, false)); Y}
1785
+ break;
1786
+
1787
+ case 48:
1788
+ #line 282 "src/q_parser.y"
1789
+ { FLDS((yyval.query), get_r_q(qp, field, NULL,(yyvsp[(2) - (2)].str), false, false)); Y}
1790
+ break;
1791
+
1792
+ case 49:
1793
+ #line 283 "src/q_parser.y"
1794
+ { FLDS((yyval.query), get_r_q(qp, field, NULL,(yyvsp[(3) - (3)].str), false, true)); Y}
1795
+ break;
1796
+
1797
+ case 50:
1798
+ #line 284 "src/q_parser.y"
1799
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(3) - (3)].str), NULL,true, false)); Y}
1800
+ break;
1801
+
1802
+ case 51:
1803
+ #line 285 "src/q_parser.y"
1804
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (2)].str), NULL,false, false)); Y}
1805
+ break;
1806
+
1807
+
1808
+ /* Line 1267 of yacc.c. */
1809
+ #line 1810 "src/q_parser.c"
1810
+ default: break;
1811
+ }
1812
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
1813
+
1814
+ YYPOPSTACK (yylen);
1815
+ yylen = 0;
1816
+ YY_STACK_PRINT (yyss, yyssp);
1817
+
1818
+ *++yyvsp = yyval;
1819
+
1820
+
1821
+ /* Now `shift' the result of the reduction. Determine what state
1822
+ that goes to, based on the state we popped back to and the rule
1823
+ number reduced by. */
1824
+
1825
+ yyn = yyr1[yyn];
1826
+
1827
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
1828
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1829
+ yystate = yytable[yystate];
1830
+ else
1831
+ yystate = yydefgoto[yyn - YYNTOKENS];
1832
+
1833
+ goto yynewstate;
1834
+
1835
+
1836
+ /*------------------------------------.
1837
+ | yyerrlab -- here on detecting error |
1838
+ `------------------------------------*/
1839
+ yyerrlab:
1840
+ /* If not already recovering from an error, report this error. */
1841
+ if (!yyerrstatus)
1842
+ {
1843
+ ++yynerrs;
1844
+ #if ! YYERROR_VERBOSE
1845
+ yyerror (qp, YY_("syntax error"));
1846
+ #else
1847
+ {
1848
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
1849
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
1850
+ {
1851
+ YYSIZE_T yyalloc = 2 * yysize;
1852
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
1853
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
1854
+ if (yymsg != yymsgbuf)
1855
+ YYSTACK_FREE (yymsg);
1856
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
1857
+ if (yymsg)
1858
+ yymsg_alloc = yyalloc;
1859
+ else
1860
+ {
1861
+ yymsg = yymsgbuf;
1862
+ yymsg_alloc = sizeof yymsgbuf;
1863
+ }
1864
+ }
1865
+
1866
+ if (0 < yysize && yysize <= yymsg_alloc)
1867
+ {
1868
+ (void) yysyntax_error (yymsg, yystate, yychar);
1869
+ yyerror (qp, yymsg);
1870
+ }
1871
+ else
1872
+ {
1873
+ yyerror (qp, YY_("syntax error"));
1874
+ if (yysize != 0)
1875
+ goto yyexhaustedlab;
1876
+ }
1877
+ }
1878
+ #endif
1879
+ }
1880
+
1881
+
1882
+
1883
+ if (yyerrstatus == 3)
1884
+ {
1885
+ /* If just tried and failed to reuse look-ahead token after an
1886
+ error, discard it. */
1887
+
1888
+ if (yychar <= YYEOF)
1889
+ {
1890
+ /* Return failure if at end of input. */
1891
+ if (yychar == YYEOF)
1892
+ YYABORT;
1893
+ }
1894
+ else
1895
+ {
1896
+ yydestruct ("Error: discarding",
1897
+ yytoken, &yylval, qp);
1898
+ yychar = YYEMPTY;
1899
+ }
1900
+ }
1901
+
1902
+ /* Else will try to reuse look-ahead token after shifting the error
1903
+ token. */
1904
+ goto yyerrlab1;
1905
+
1906
+
1907
+ /*---------------------------------------------------.
1908
+ | yyerrorlab -- error raised explicitly by YYERROR. |
1909
+ `---------------------------------------------------*/
1910
+ yyerrorlab:
1911
+
1912
+ /* Pacify compilers like GCC when the user code never invokes
1913
+ YYERROR and the label yyerrorlab therefore never appears in user
1914
+ code. */
1915
+ if (/*CONSTCOND*/ 0)
1916
+ goto yyerrorlab;
1917
+
1918
+ /* Do not reclaim the symbols of the rule which action triggered
1919
+ this YYERROR. */
1920
+ YYPOPSTACK (yylen);
1921
+ yylen = 0;
1922
+ YY_STACK_PRINT (yyss, yyssp);
1923
+ yystate = *yyssp;
1924
+ goto yyerrlab1;
1925
+
1926
+
1927
+ /*-------------------------------------------------------------.
1928
+ | yyerrlab1 -- common code for both syntax error and YYERROR. |
1929
+ `-------------------------------------------------------------*/
1930
+ yyerrlab1:
1931
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
1932
+
1933
+ for (;;)
1934
+ {
1935
+ yyn = yypact[yystate];
1936
+ if (yyn != YYPACT_NINF)
1937
+ {
1938
+ yyn += YYTERROR;
1939
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
1940
+ {
1941
+ yyn = yytable[yyn];
1942
+ if (0 < yyn)
1943
+ break;
1944
+ }
1945
+ }
1946
+
1947
+ /* Pop the current state because it cannot handle the error token. */
1948
+ if (yyssp == yyss)
1949
+ YYABORT;
1950
+
1951
+
1952
+ yydestruct ("Error: popping",
1953
+ yystos[yystate], yyvsp, qp);
1954
+ YYPOPSTACK (1);
1955
+ yystate = *yyssp;
1956
+ YY_STACK_PRINT (yyss, yyssp);
1957
+ }
1958
+
1959
+ if (yyn == YYFINAL)
1960
+ YYACCEPT;
1961
+
1962
+ *++yyvsp = yylval;
1963
+
1964
+
1965
+ /* Shift the error token. */
1966
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
1967
+
1968
+ yystate = yyn;
1969
+ goto yynewstate;
1970
+
1971
+
1972
+ /*-------------------------------------.
1973
+ | yyacceptlab -- YYACCEPT comes here. |
1974
+ `-------------------------------------*/
1975
+ yyacceptlab:
1976
+ yyresult = 0;
1977
+ goto yyreturn;
1978
+
1979
+ /*-----------------------------------.
1980
+ | yyabortlab -- YYABORT comes here. |
1981
+ `-----------------------------------*/
1982
+ yyabortlab:
1983
+ yyresult = 1;
1984
+ goto yyreturn;
1985
+
1986
+ #ifndef yyoverflow
1987
+ /*-------------------------------------------------.
1988
+ | yyexhaustedlab -- memory exhaustion comes here. |
1989
+ `-------------------------------------------------*/
1990
+ yyexhaustedlab:
1991
+ yyerror (qp, YY_("memory exhausted"));
1992
+ yyresult = 2;
1993
+ /* Fall through. */
1994
+ #endif
1995
+
1996
+ yyreturn:
1997
+ if (yychar != YYEOF && yychar != YYEMPTY)
1998
+ yydestruct ("Cleanup: discarding lookahead",
1999
+ yytoken, &yylval, qp);
2000
+ /* Do not reclaim the symbols of the rule which action triggered
2001
+ this YYABORT or YYACCEPT. */
2002
+ YYPOPSTACK (yylen);
2003
+ YY_STACK_PRINT (yyss, yyssp);
2004
+ while (yyssp != yyss)
2005
+ {
2006
+ yydestruct ("Cleanup: popping",
2007
+ yystos[*yyssp], yyvsp, qp);
2008
+ YYPOPSTACK (1);
2009
+ }
2010
+ #ifndef yyoverflow
2011
+ if (yyss != yyssa)
2012
+ YYSTACK_FREE (yyss);
2013
+ #endif
2014
+ #if YYERROR_VERBOSE
2015
+ if (yymsg != yymsgbuf)
2016
+ YYSTACK_FREE (yymsg);
2017
+ #endif
2018
+ /* Make sure YYID is used. */
2019
+ return YYID (yyresult);
2020
+ }
2021
+
2022
+
2023
+ #line 287 "src/q_parser.y"
2024
+
2025
+
2026
+ static const char *special_char = "&:()[]{}!\"~^|<>=*?+-";
2027
+ static const char *not_word = " \t()[]{}!\"~^|<>=";
2028
+
2029
+ /**
2030
+ * +get_word+ gets the next query-word from the query string. A query-word is
2031
+ * basically a string of non-special or escaped special characters. It is
2032
+ * Analyzer agnostic. It is up to the get_*_q methods to tokenize the word and
2033
+ * turn it into a +Query+. See the documentation for each get_*_q method to
2034
+ * see how it handles tokenization.
2035
+ *
2036
+ * Note that +get_word+ is also responsible for returning field names and
2037
+ * matching the special tokens 'AND', 'NOT', 'REQ' and 'OR'.
2038
+ */
2039
+ static int get_word(YYSTYPE *lvalp, QParser *qp)
2040
+ {
2041
+ bool is_wild = false;
2042
+ int len;
2043
+ char c;
2044
+ char *buf = qp->buf[qp->buf_index];
2045
+ char *bufp = buf;
2046
+ qp->buf_index = (qp->buf_index + 1) % QP_CONC_WORDS;
2047
+
2048
+ if (qp->dynbuf) {
2049
+ free(qp->dynbuf);
2050
+ qp->dynbuf = NULL;
2051
+ }
2052
+
2053
+ qp->qstrp--; /* need to back up one character */
2054
+
2055
+ while (!strchr(not_word, (c = *qp->qstrp++))) {
2056
+ switch (c) {
2057
+ case '\\':
2058
+ if ((c = *qp->qstrp) == '\0') {
2059
+ *bufp++ = '\\';
2060
+ }
2061
+ else {
2062
+ *bufp++ = c;
2063
+ qp->qstrp++;
2064
+ }
2065
+ break;
2066
+ case ':':
2067
+ if ((*qp->qstrp) == ':') {
2068
+ qp->qstrp++;
2069
+ *bufp++ = ':';
2070
+ *bufp++ = ':';
2071
+ }
2072
+ else {
2073
+ goto get_word_done;
2074
+ }
2075
+ break;
2076
+ case '*': case '?':
2077
+ is_wild = true;
2078
+ /* fall through */
2079
+ default:
2080
+ *bufp++ = c;
2081
+ }
2082
+ /* we've exceeded the static buffer. switch to the dynamic one. The
2083
+ * dynamic buffer is allocated enough space to hold the whole query
2084
+ * string so it's capacity doesn't need to be checked again once
2085
+ * allocated. */
2086
+ if (!qp->dynbuf && ((bufp - buf) == MAX_WORD_SIZE)) {
2087
+ qp->dynbuf = ALLOC_AND_ZERO_N(char, strlen(qp->qstr) + 1);
2088
+ strncpy(qp->dynbuf, buf, MAX_WORD_SIZE);
2089
+ buf = qp->dynbuf;
2090
+ bufp = buf + MAX_WORD_SIZE;
2091
+ }
2092
+ }
2093
+ get_word_done:
2094
+ qp->qstrp--;
2095
+ /* check for keywords. There are only four so we have a bit of a hack
2096
+ * which just checks for all of them. */
2097
+ *bufp = '\0';
2098
+ len = (int)(bufp - buf);
2099
+ if (qp->use_keywords) {
2100
+ if (len == 3) {
2101
+ if (buf[0] == 'A' && buf[1] == 'N' && buf[2] == 'D') return AND;
2102
+ if (buf[0] == 'N' && buf[1] == 'O' && buf[2] == 'T') return NOT;
2103
+ if (buf[0] == 'R' && buf[1] == 'E' && buf[2] == 'Q') return REQ;
2104
+ }
2105
+ if (len == 2 && buf[0] == 'O' && buf[1] == 'R') return OR;
2106
+ }
2107
+
2108
+ /* found a word so return it. */
2109
+ lvalp->str = buf;
2110
+ if (is_wild) {
2111
+ return WILD_STR;
2112
+ }
2113
+ return QWRD;
2114
+ }
2115
+
2116
+ /**
2117
+ * +yylex+ is the lexing method called by the QueryParser. It breaks the
2118
+ * query up into special characters;
2119
+ *
2120
+ * ( "&:()[]{}!\"~^|<>=*?+-" )
2121
+ *
2122
+ * and tokens;
2123
+ *
2124
+ * - QWRD
2125
+ * - WILD_STR
2126
+ * - AND['AND', '&&']
2127
+ * - OR['OR', '||']
2128
+ * - REQ['REQ', '+']
2129
+ * - NOT['NOT', '-', '~']
2130
+ *
2131
+ * QWRD tokens are query word tokens which are made up of characters other
2132
+ * than the special characters. They can also contain special characters when
2133
+ * escaped with a backslash '\'. WILD_STR is the same as QWRD except that it
2134
+ * may also contain '?' and '*' characters.
2135
+ *
2136
+ * If any of the special chars are seen they will usually be returned straight
2137
+ * away. The exceptions are the wild chars '*' and '?', and '&' which will be
2138
+ * treated as a plain old word character unless followed by another '&'.
2139
+ *
2140
+ * If no special characters or tokens are found then yylex delegates to
2141
+ * +get_word+ which will fetch the next query-word.
2142
+ */
2143
+ static int yylex(YYSTYPE *lvalp, QParser *qp)
2144
+ {
2145
+ char c, nc;
2146
+
2147
+ while ((c=*qp->qstrp++) == ' ' || c == '\t') {
2148
+ }
2149
+
2150
+ if (c == '\0') return 0;
2151
+
2152
+ if (strchr(special_char, c)) { /* comment */
2153
+ nc = *qp->qstrp;
2154
+ switch (c) {
2155
+ case '-': case '!': return NOT;
2156
+ case '+': return REQ;
2157
+ case '*':
2158
+ if (nc == ':') return c;
2159
+ break;
2160
+ case '?':
2161
+ break;
2162
+ case '&':
2163
+ if (nc == '&') {
2164
+ qp->qstrp++;
2165
+ return AND;
2166
+ }
2167
+ break; /* Don't return single & character. Use in word. */
2168
+ case '|':
2169
+ if (nc == '|') {
2170
+ qp->qstrp++;
2171
+ return OR;
2172
+ }
2173
+ default:
2174
+ return c;
2175
+ }
2176
+ }
2177
+
2178
+ return get_word(lvalp, qp);
2179
+ }
2180
+
2181
+ /**
2182
+ * yyerror gets called if there is an parse error with the yacc parser.
2183
+ * It is responsible for clearing any memory that was allocated during the
2184
+ * parsing process.
2185
+ */
2186
+ static int yyerror(QParser *qp, char const *msg)
2187
+ {
2188
+ qp->destruct = true;
2189
+ if (!qp->handle_parse_errors) {
2190
+ char buf[1024];
2191
+ buf[1023] = '\0';
2192
+ strncpy(buf, qp->qstr, 1023);
2193
+ if (qp->clean_str) {
2194
+ free(qp->qstr);
2195
+ }
2196
+ mutex_unlock(&qp->mutex);
2197
+ snprintf(xmsg_buffer, XMSG_BUFFER_SIZE,
2198
+ "couldn't parse query ``%s''. Error message "
2199
+ " was %s", buf, (char *)msg);
2200
+ }
2201
+ while (qp->fields_top->next != NULL) {
2202
+ qp_pop_fields(qp);
2203
+ }
2204
+ return 0;
2205
+ }
2206
+
2207
+ #define BQ(query) ((BooleanQuery *)(query))
2208
+
2209
+ /**
2210
+ * The QueryParser caches a tokenizer for each field so that it doesn't need
2211
+ * to allocate a new tokenizer for each term in the query. This would be quite
2212
+ * expensive as tokenizers use quite a large hunk of memory.
2213
+ *
2214
+ * This method returns the query parser for a particular field and sets it up
2215
+ * with the text to be tokenized.
2216
+ */
2217
+ static TokenStream *get_cached_ts(QParser *qp, Symbol field, char *text)
2218
+ {
2219
+ TokenStream *ts;
2220
+ if (hs_exists(qp->tokenized_fields, field)) {
2221
+ ts = (TokenStream *)h_get(qp->ts_cache, field);
2222
+ if (!ts) {
2223
+ ts = a_get_ts(qp->analyzer, field, text);
2224
+ h_set(qp->ts_cache, field, ts);
2225
+ }
2226
+ else {
2227
+ ts->reset(ts, text);
2228
+ }
2229
+ }
2230
+ else {
2231
+ ts = qp->non_tokenizer;
2232
+ ts->reset(ts, text);
2233
+ }
2234
+ return ts;
2235
+ }
2236
+
2237
+ /**
2238
+ * Turns a BooleanClause array into a BooleanQuery. It will optimize the query
2239
+ * if 0 or 1 clauses are present to NULL or the actual query in the clause
2240
+ * respectively.
2241
+ */
2242
+ static Query *get_bool_q(BCArray *bca)
2243
+ {
2244
+ Query *q;
2245
+ const int clause_count = bca->size;
2246
+
2247
+ if (clause_count == 0) {
2248
+ q = NULL;
2249
+ free(bca->clauses);
2250
+ }
2251
+ else if (clause_count == 1) {
2252
+ BooleanClause *bc = bca->clauses[0];
2253
+ if (bc->is_prohibited) {
2254
+ q = bq_new(false);
2255
+ bq_add_query_nr(q, bc->query, BC_MUST_NOT);
2256
+ bq_add_query_nr(q, maq_new(), BC_MUST);
2257
+ }
2258
+ else {
2259
+ q = bc->query;
2260
+ }
2261
+ free(bc);
2262
+ free(bca->clauses);
2263
+ }
2264
+ else {
2265
+ q = bq_new(false);
2266
+ /* copy clauses into query */
2267
+
2268
+ BQ(q)->clause_cnt = clause_count;
2269
+ BQ(q)->clause_capa = bca->capa;
2270
+ free(BQ(q)->clauses);
2271
+ BQ(q)->clauses = bca->clauses;
2272
+ }
2273
+ free(bca);
2274
+ return q;
2275
+ }
2276
+
2277
+ /**
2278
+ * Base method for appending BooleanClauses to a BooleanClause array. This
2279
+ * method doesn't care about the type of clause (MUST, SHOULD, MUST_NOT).
2280
+ */
2281
+ static void bca_add_clause(BCArray *bca, BooleanClause *clause)
2282
+ {
2283
+ if (bca->size >= bca->capa) {
2284
+ bca->capa <<= 1;
2285
+ REALLOC_N(bca->clauses, BooleanClause *, bca->capa);
2286
+ }
2287
+ bca->clauses[bca->size] = clause;
2288
+ bca->size++;
2289
+ }
2290
+
2291
+ /**
2292
+ * Add the first clause to a BooleanClause array. This method is also
2293
+ * responsible for allocating a new BooleanClause array.
2294
+ */
2295
+ static BCArray *first_cls(BooleanClause *clause)
2296
+ {
2297
+ BCArray *bca = ALLOC_AND_ZERO(BCArray);
2298
+ bca->capa = BCA_INIT_CAPA;
2299
+ bca->clauses = ALLOC_N(BooleanClause *, BCA_INIT_CAPA);
2300
+ if (clause) {
2301
+ bca_add_clause(bca, clause);
2302
+ }
2303
+ return bca;
2304
+ }
2305
+
2306
+ /**
2307
+ * Add AND clause to the BooleanClause array. The means that it will set the
2308
+ * clause being added and the previously added clause from SHOULD clauses to
2309
+ * MUST clauses. (If they are currently MUST_NOT clauses they stay as they
2310
+ * are.)
2311
+ */
2312
+ static BCArray *add_and_cls(BCArray *bca, BooleanClause *clause)
2313
+ {
2314
+ if (clause) {
2315
+ if (bca->size == 1) {
2316
+ if (!bca->clauses[0]->is_prohibited) {
2317
+ bc_set_occur(bca->clauses[0], BC_MUST);
2318
+ }
2319
+ }
2320
+ if (!clause->is_prohibited) {
2321
+ bc_set_occur(clause, BC_MUST);
2322
+ }
2323
+ bca_add_clause(bca, clause);
2324
+ }
2325
+ return bca;
2326
+ }
2327
+
2328
+ /**
2329
+ * Add SHOULD clause to the BooleanClause array.
2330
+ */
2331
+ static BCArray *add_or_cls(BCArray *bca, BooleanClause *clause)
2332
+ {
2333
+ if (clause) {
2334
+ bca_add_clause(bca, clause);
2335
+ }
2336
+ return bca;
2337
+ }
2338
+
2339
+ /**
2340
+ * Add AND or OR clause to the BooleanClause array, depending on the default
2341
+ * clause type.
2342
+ */
2343
+ static BCArray *add_default_cls(QParser *qp, BCArray *bca,
2344
+ BooleanClause *clause)
2345
+ {
2346
+ if (qp->or_default) {
2347
+ add_or_cls(bca, clause);
2348
+ }
2349
+ else {
2350
+ add_and_cls(bca, clause);
2351
+ }
2352
+ return bca;
2353
+ }
2354
+
2355
+ /**
2356
+ * destroy array of BooleanClauses
2357
+ */
2358
+ static void bca_destroy(BCArray *bca)
2359
+ {
2360
+ int i;
2361
+ for (i = 0; i < bca->size; i++) {
2362
+ bc_deref(bca->clauses[i]);
2363
+ }
2364
+ free(bca->clauses);
2365
+ free(bca);
2366
+ }
2367
+
2368
+ /**
2369
+ * Turn a query into a BooleanClause for addition to a BooleanQuery.
2370
+ */
2371
+ static BooleanClause *get_bool_cls(Query *q, BCType occur)
2372
+ {
2373
+ if (q) {
2374
+ return bc_new(q, occur);
2375
+ }
2376
+ else {
2377
+ return NULL;
2378
+ }
2379
+ }
2380
+
2381
+ /**
2382
+ * Create a TermQuery. The word will be tokenized and if the tokenization
2383
+ * produces more than one token, a PhraseQuery will be returned. For example,
2384
+ * if the word is dbalmain@gmail.com and a LetterTokenizer is used then a
2385
+ * PhraseQuery "dbalmain gmail com" will be returned which is actually exactly
2386
+ * what we want as it will match any documents containing the same email
2387
+ * address and tokenized with the same tokenizer.
2388
+ */
2389
+ static Query *get_term_q(QParser *qp, Symbol field, char *word)
2390
+ {
2391
+ Query *q;
2392
+ Token *token;
2393
+ TokenStream *stream = get_cached_ts(qp, field, word);
2394
+
2395
+ if ((token = ts_next(stream)) == NULL) {
2396
+ q = NULL;
2397
+ }
2398
+ else {
2399
+ q = tq_new(field, token->text);
2400
+ if ((token = ts_next(stream)) != NULL) {
2401
+ /* Less likely case, destroy the term query and create a
2402
+ * phrase query instead */
2403
+ Query *phq = phq_new(field);
2404
+ phq_add_term(phq, ((TermQuery *)q)->term, 0);
2405
+ q->destroy_i(q);
2406
+ q = phq;
2407
+ do {
2408
+ if (token->pos_inc) {
2409
+ phq_add_term(q, token->text, token->pos_inc);
2410
+ /* add some slop since single term was expected */
2411
+ ((PhraseQuery *)q)->slop++;
2412
+ }
2413
+ else {
2414
+ phq_append_multi_term(q, token->text);
2415
+ }
2416
+ } while ((token = ts_next(stream)) != NULL);
2417
+ }
2418
+ }
2419
+ return q;
2420
+ }
2421
+
2422
+ /**
2423
+ * Create a FuzzyQuery. The word will be tokenized and only the first token
2424
+ * will be used. If there are any more tokens after tokenization, they will be
2425
+ * ignored.
2426
+ */
2427
+ static Query *get_fuzzy_q(QParser *qp, Symbol field, char *word,
2428
+ char *slop_str)
2429
+ {
2430
+ Query *q;
2431
+ Token *token;
2432
+ TokenStream *stream = get_cached_ts(qp, field, word);
2433
+
2434
+ if ((token = ts_next(stream)) == NULL) {
2435
+ q = NULL;
2436
+ }
2437
+ else {
2438
+ /* it only makes sense to find one term in a fuzzy query */
2439
+ float slop = qp_default_fuzzy_min_sim;
2440
+ if (slop_str) {
2441
+ sscanf(slop_str, "%f", &slop);
2442
+ }
2443
+ q = fuzq_new_conf(field, token->text, slop, qp_default_fuzzy_pre_len,
2444
+ qp->max_clauses);
2445
+ }
2446
+ return q;
2447
+ }
2448
+
2449
+ /**
2450
+ * Downcase a string taking locale into account and works for multibyte
2451
+ * character sets.
2452
+ */
2453
+ static char *lower_str(char *str)
2454
+ {
2455
+ const int max_len = (int)strlen(str) + 1;
2456
+ int cnt;
2457
+ wchar_t *wstr = ALLOC_N(wchar_t, max_len);
2458
+ if ((cnt = mbstowcs(wstr, str, max_len)) > 0) {
2459
+ wchar_t *w = wstr;
2460
+ while (*w) {
2461
+ *w = towlower(*w);
2462
+ w++;
2463
+ }
2464
+ wcstombs(str, wstr, max_len);
2465
+ }
2466
+ else {
2467
+ char *s = str;
2468
+ while (*s) {
2469
+ *s = tolower(*s);
2470
+ s++;
2471
+ }
2472
+ }
2473
+ free(wstr);
2474
+ str[max_len] = '\0';
2475
+ return str;
2476
+ }
2477
+
2478
+ /**
2479
+ * Create a WildCardQuery. No tokenization will be performed on the pattern
2480
+ * but the pattern will be downcased if +qp->wild_lower+ is set to true and
2481
+ * the field in question is a tokenized field.
2482
+ *
2483
+ * Note: this method will not always return a WildCardQuery. It could be
2484
+ * optimized to a MatchAllQuery if the pattern is '*' or a PrefixQuery if the
2485
+ * only wild char (*, ?) in the pattern is a '*' at the end of the pattern.
2486
+ */
2487
+ static Query *get_wild_q(QParser *qp, Symbol field, char *pattern)
2488
+ {
2489
+ Query *q;
2490
+ bool is_prefix = false;
2491
+ char *p;
2492
+ int len = (int)strlen(pattern);
2493
+
2494
+ if (qp->wild_lower
2495
+ && (!qp->tokenized_fields || hs_exists(qp->tokenized_fields, field))) {
2496
+ lower_str(pattern);
2497
+ }
2498
+
2499
+ /* simplify the wildcard query to a prefix query if possible. Basically a
2500
+ * prefix query is any wildcard query that has a '*' as the last character
2501
+ * and no other wildcard characters before it. "*" by itself will expand
2502
+ * to a MatchAllQuery */
2503
+ if (strcmp(pattern, "*") == 0) {
2504
+ return maq_new();
2505
+ }
2506
+ if (pattern[len - 1] == '*') {
2507
+ is_prefix = true;
2508
+ for (p = &pattern[len - 2]; p >= pattern; p--) {
2509
+ if (*p == '*' || *p == '?') {
2510
+ is_prefix = false;
2511
+ break;
2512
+ }
2513
+ }
2514
+ }
2515
+ if (is_prefix) {
2516
+ /* chop off the '*' temporarily to create the query */
2517
+ pattern[len - 1] = 0;
2518
+ q = prefixq_new(field, pattern);
2519
+ pattern[len - 1] = '*';
2520
+ }
2521
+ else {
2522
+ q = wcq_new(field, pattern);
2523
+ }
2524
+ MTQMaxTerms(q) = qp->max_clauses;
2525
+ return q;
2526
+ }
2527
+
2528
+ /**
2529
+ * Adds another field to the top of the FieldStack.
2530
+ */
2531
+ static HashSet *add_field(QParser *qp, const char *field_name)
2532
+ {
2533
+ Symbol field = intern(field_name);
2534
+ if (qp->allow_any_fields || hs_exists(qp->all_fields, field)) {
2535
+ hs_add(qp->fields, field);
2536
+ }
2537
+ return qp->fields;
2538
+ }
2539
+
2540
+ /**
2541
+ * The method gets called when a field modifier ("field1|field2:") is seen. It
2542
+ * will push a new FieldStack object onto the stack and add +field+ to its
2543
+ * fields set.
2544
+ */
2545
+ static HashSet *first_field(QParser *qp, const char *field)
2546
+ {
2547
+ qp_push_fields(qp, hs_new_ptr(NULL), true);
2548
+ return add_field(qp, field);
2549
+ }
2550
+
2551
+ /**
2552
+ * Destroy a phrase object freeing all allocated memory.
2553
+ */
2554
+ static void ph_destroy(Phrase *self)
2555
+ {
2556
+ int i;
2557
+ for (i = 0; i < self->size; i++) {
2558
+ ary_destroy(self->positions[i].terms, &free);
2559
+ }
2560
+ free(self->positions);
2561
+ free(self);
2562
+ }
2563
+
2564
+
2565
+ /**
2566
+ * Allocate a new Phrase object
2567
+ */
2568
+ static Phrase *ph_new()
2569
+ {
2570
+ Phrase *self = ALLOC_AND_ZERO(Phrase);
2571
+ self->capa = PHRASE_INIT_CAPA;
2572
+ self->positions = ALLOC_AND_ZERO_N(PhrasePosition, PHRASE_INIT_CAPA);
2573
+ return self;
2574
+ }
2575
+
2576
+ /**
2577
+ * Add the first word to the phrase. This method is also in charge of
2578
+ * allocating a new Phrase object.
2579
+ */
2580
+ static Phrase *ph_first_word(char *word)
2581
+ {
2582
+ Phrase *self = ph_new();
2583
+ if (word) { /* no point in adding NULL in start */
2584
+ self->positions[0].terms = ary_new_type_capa(char *, 1);
2585
+ ary_push(self->positions[0].terms, estrdup(word));
2586
+ self->size = 1;
2587
+ }
2588
+ return self;
2589
+ }
2590
+
2591
+ /**
2592
+ * Add a new word to the Phrase
2593
+ */
2594
+ static Phrase *ph_add_word(Phrase *self, char *word)
2595
+ {
2596
+ if (word) {
2597
+ const int index = self->size;
2598
+ PhrasePosition *pp = self->positions;
2599
+ if (index >= self->capa) {
2600
+ self->capa <<= 1;
2601
+ REALLOC_N(pp, PhrasePosition, self->capa);
2602
+ self->positions = pp;
2603
+ }
2604
+ pp[index].pos = self->pos_inc;
2605
+ pp[index].terms = ary_new_type_capa(char *, 1);
2606
+ ary_push(pp[index].terms, estrdup(word));
2607
+ self->size++;
2608
+ self->pos_inc = 0;
2609
+ }
2610
+ else {
2611
+ self->pos_inc++;
2612
+ }
2613
+ return self;
2614
+ }
2615
+
2616
+ /**
2617
+ * Adds a word to the Phrase object in the same position as the previous word
2618
+ * added to the Phrase. This will later be turned into a multi-PhraseQuery.
2619
+ */
2620
+ static Phrase *ph_add_multi_word(Phrase *self, char *word)
2621
+ {
2622
+ const int index = self->size - 1;
2623
+ PhrasePosition *pp = self->positions;
2624
+
2625
+ if (word) {
2626
+ ary_push(pp[index].terms, estrdup(word));
2627
+ }
2628
+ return self;
2629
+ }
2630
+
2631
+ /**
2632
+ * Build a phrase query for a single field. It might seem like a better idea
2633
+ * to build the PhraseQuery once and duplicate it for each field but this
2634
+ * would be buggy in the case of PerFieldAnalyzers in which case a different
2635
+ * tokenizer could be used for each field.
2636
+ *
2637
+ * Note that the query object returned by this method is not always a
2638
+ * PhraseQuery. If there is only one term in the query then the query is
2639
+ * simplified to a TermQuery. If there are multiple terms but only a single
2640
+ * position, then a MultiTermQuery is retured.
2641
+ *
2642
+ * Note that each word in the query gets tokenized. Unlike get_term_q, if the
2643
+ * word gets tokenized into more than one token, the rest of the tokens are
2644
+ * ignored. For example, if you have the phrase;
2645
+ *
2646
+ * "email: dbalmain@gmail.com"
2647
+ *
2648
+ * the Phrase object will contain to positions with the words 'email:' and
2649
+ * 'dbalmain@gmail.com'. Now, if you are using a LetterTokenizer then the
2650
+ * second word will be tokenized into the tokens ['dbalmain', 'gmail', 'com']
2651
+ * and only the first token will be used, so the resulting phrase query will
2652
+ * actually look like this;
2653
+ *
2654
+ * "email dbalmain"
2655
+ *
2656
+ * This problem can easily be solved by using the StandardTokenizer or any
2657
+ * custom tokenizer which will leave dbalmain@gmail.com as a single token.
2658
+ */
2659
+ static Query *get_phrase_query(QParser *qp, Symbol field,
2660
+ Phrase *phrase, char *slop_str)
2661
+ {
2662
+ const int pos_cnt = phrase->size;
2663
+ Query *q = NULL;
2664
+
2665
+ if (pos_cnt == 1) {
2666
+ char **words = phrase->positions[0].terms;
2667
+ const int word_count = ary_size(words);
2668
+ if (word_count == 1) {
2669
+ q = get_term_q(qp, field, words[0]);
2670
+ }
2671
+ else {
2672
+ int i;
2673
+ int term_cnt = 0;
2674
+ Token *token;
2675
+ char *last_word = NULL;
2676
+
2677
+ for (i = 0; i < word_count; i++) {
2678
+ token = ts_next(get_cached_ts(qp, field, words[i]));
2679
+ if (token) {
2680
+ free(words[i]);
2681
+ last_word = words[i] = estrdup(token->text);
2682
+ ++term_cnt;
2683
+ }
2684
+ else {
2685
+ /* empty words will later be ignored */
2686
+ words[i][0] = '\0';
2687
+ }
2688
+ }
2689
+
2690
+ switch (term_cnt) {
2691
+ case 0:
2692
+ q = bq_new(false);
2693
+ break;
2694
+ case 1:
2695
+ q = tq_new(field, last_word);
2696
+ break;
2697
+ default:
2698
+ q = multi_tq_new_conf(field, term_cnt, 0.0);
2699
+ for (i = 0; i < word_count; i++) {
2700
+ /* ignore empty words */
2701
+ if (words[i][0]) {
2702
+ multi_tq_add_term(q, words[i]);
2703
+ }
2704
+ }
2705
+ break;
2706
+ }
2707
+ }
2708
+ }
2709
+ else if (pos_cnt > 1) {
2710
+ Token *token;
2711
+ TokenStream *stream;
2712
+ int i, j;
2713
+ int pos_inc = 0;
2714
+ q = phq_new(field);
2715
+ if (slop_str) {
2716
+ int slop;
2717
+ sscanf(slop_str,"%d",&slop);
2718
+ ((PhraseQuery *)q)->slop = slop;
2719
+ }
2720
+
2721
+ for (i = 0; i < pos_cnt; i++) {
2722
+ char **words = phrase->positions[i].terms;
2723
+ const int word_count = ary_size(words);
2724
+ if (pos_inc) {
2725
+ ((PhraseQuery *)q)->slop++;
2726
+ }
2727
+ pos_inc += phrase->positions[i].pos + 1; /* Actually holds pos_inc*/
2728
+
2729
+ if (word_count == 1) {
2730
+ stream = get_cached_ts(qp, field, words[0]);
2731
+ while ((token = ts_next(stream))) {
2732
+ if (token->pos_inc) {
2733
+ phq_add_term(q, token->text,
2734
+ pos_inc ? pos_inc : token->pos_inc);
2735
+ }
2736
+ else {
2737
+ phq_append_multi_term(q, token->text);
2738
+ ((PhraseQuery *)q)->slop++;
2739
+ }
2740
+ pos_inc = 0;
2741
+ }
2742
+ }
2743
+ else {
2744
+ bool added_position = false;
2745
+
2746
+ for (j = 0; j < word_count; j++) {
2747
+ stream = get_cached_ts(qp, field, words[j]);
2748
+ if ((token = ts_next(stream))) {
2749
+ if (!added_position) {
2750
+ phq_add_term(q, token->text,
2751
+ pos_inc ? pos_inc : token->pos_inc);
2752
+ added_position = true;
2753
+ pos_inc = 0;
2754
+ }
2755
+ else {
2756
+ phq_append_multi_term(q, token->text);
2757
+ }
2758
+ }
2759
+ }
2760
+ }
2761
+ }
2762
+ }
2763
+ return q;
2764
+ }
2765
+
2766
+ /**
2767
+ * Get a phrase query from the Phrase object. The Phrase object is built up by
2768
+ * the query parser as the all PhraseQuery didn't work well for this. Once the
2769
+ * PhraseQuery has been built the Phrase object needs to be destroyed.
2770
+ */
2771
+ static Query *get_phrase_q(QParser *qp, Phrase *phrase, char *slop_str)
2772
+ {
2773
+ Query *volatile q = NULL;
2774
+ FLDS(q, get_phrase_query(qp, field, phrase, slop_str));
2775
+ ph_destroy(phrase);
2776
+ return q;
2777
+ }
2778
+
2779
+ /**
2780
+ * Gets a RangeQuery object.
2781
+ *
2782
+ * Just like with WildCardQuery, RangeQuery needs to downcase its terms if the
2783
+ * tokenizer also downcased its terms.
2784
+ */
2785
+ static Query *get_r_q(QParser *qp, Symbol field, char *from, char *to,
2786
+ bool inc_lower, bool inc_upper)
2787
+ {
2788
+ Query *rq;
2789
+ if (qp->wild_lower
2790
+ && (!qp->tokenized_fields || hs_exists(qp->tokenized_fields, field))) {
2791
+ if (from) {
2792
+ lower_str(from);
2793
+ }
2794
+ if (to) {
2795
+ lower_str(to);
2796
+ }
2797
+ }
2798
+ /*
2799
+ * terms don't get tokenized as it doesn't really make sense to do so for
2800
+ * range queries.
2801
+
2802
+ if (from) {
2803
+ TokenStream *stream = get_cached_ts(qp, field, from);
2804
+ Token *token = ts_next(stream);
2805
+ from = token ? estrdup(token->text) : NULL;
2806
+ }
2807
+ if (to) {
2808
+ TokenStream *stream = get_cached_ts(qp, field, to);
2809
+ Token *token = ts_next(stream);
2810
+ to = token ? estrdup(token->text) : NULL;
2811
+ }
2812
+ */
2813
+
2814
+ rq = qp->use_typed_range_query ?
2815
+ trq_new(field, from, to, inc_lower, inc_upper) :
2816
+ rq_new(field, from, to, inc_lower, inc_upper);
2817
+ return rq;
2818
+ }
2819
+
2820
+ /**
2821
+ * Every time the query parser sees a new field modifier ("field1|field2:")
2822
+ * it pushes a new FieldStack object onto the stack and sets its fields to the
2823
+ * fields specified in the fields modifier. If the field modifier is '*',
2824
+ * fs->fields is set to all_fields. fs->fields is set to +qp->def_field+ at
2825
+ * the bottom of the stack (ie the very first set of fields pushed onto the
2826
+ * stack).
2827
+ */
2828
+ static void qp_push_fields(QParser *self, HashSet *fields, bool destroy)
2829
+ {
2830
+ FieldStack *fs = ALLOC(FieldStack);
2831
+
2832
+ fs->next = self->fields_top;
2833
+ fs->fields = fields;
2834
+ fs->destroy = destroy;
2835
+
2836
+ self->fields_top = fs;
2837
+ self->fields = fields;
2838
+ }
2839
+
2840
+ /**
2841
+ * Pops the top of the fields stack and frees any memory used by it. This will
2842
+ * get called when query modified by a field modifier ("field1|field2:") has
2843
+ * been fully parsed and the field specifier no longer applies.
2844
+ */
2845
+ static void qp_pop_fields(QParser *self)
2846
+ {
2847
+ FieldStack *fs = self->fields_top;
2848
+
2849
+ if (fs->destroy) {
2850
+ hs_destroy(fs->fields);
2851
+ }
2852
+ self->fields_top = fs->next;
2853
+ if (self->fields_top) {
2854
+ self->fields = self->fields_top->fields;
2855
+ }
2856
+ free(fs);
2857
+ }
2858
+
2859
+ /**
2860
+ * Free all memory allocated by the QueryParser.
2861
+ */
2862
+ void qp_destroy(QParser *self)
2863
+ {
2864
+ if (self->tokenized_fields != self->all_fields) {
2865
+ hs_destroy(self->tokenized_fields);
2866
+ }
2867
+ if (self->def_fields != self->all_fields) {
2868
+ hs_destroy(self->def_fields);
2869
+ }
2870
+ hs_destroy(self->all_fields);
2871
+
2872
+ qp_pop_fields(self);
2873
+ assert(NULL == self->fields_top);
2874
+
2875
+ h_destroy(self->ts_cache);
2876
+ tk_destroy(self->non_tokenizer);
2877
+ a_deref(self->analyzer);
2878
+ free(self);
2879
+ }
2880
+
2881
+ /**
2882
+ * Creates a new QueryParser setting all boolean parameters to their defaults.
2883
+ * If +def_fields+ is NULL then +all_fields+ is used in place of +def_fields+.
2884
+ * Not also that this method ensures that all fields that exist in
2885
+ * +def_fields+ must also exist in +all_fields+. This should make sense.
2886
+ */
2887
+ QParser *qp_new(Analyzer *analyzer)
2888
+ {
2889
+ QParser *self = ALLOC(QParser);
2890
+ self->or_default = true;
2891
+ self->wild_lower = true;
2892
+ self->clean_str = false;
2893
+ self->max_clauses = QP_MAX_CLAUSES;
2894
+ self->handle_parse_errors = false;
2895
+ self->allow_any_fields = false;
2896
+ self->use_keywords = true;
2897
+ self->use_typed_range_query = false;
2898
+ self->def_slop = 0;
2899
+
2900
+ self->tokenized_fields = hs_new_ptr(NULL);
2901
+ self->all_fields = hs_new_ptr(NULL);
2902
+ self->def_fields = hs_new_ptr(NULL);
2903
+
2904
+ self->fields_top = NULL;
2905
+ qp_push_fields(self, self->def_fields, false);
2906
+
2907
+ /* make sure all_fields contains the default fields */
2908
+ self->analyzer = analyzer;
2909
+ self->ts_cache = h_new_ptr((free_ft)&ts_deref);
2910
+ self->buf_index = 0;
2911
+ self->dynbuf = NULL;
2912
+ self->non_tokenizer = non_tokenizer_new();
2913
+ mutex_init(&self->mutex, NULL);
2914
+ return self;
2915
+ }
2916
+
2917
+ void qp_add_field(QParser *self,
2918
+ Symbol field,
2919
+ bool is_default,
2920
+ bool is_tokenized)
2921
+ {
2922
+ hs_add(self->all_fields, field);
2923
+ if (is_default) {
2924
+ hs_add(self->def_fields, field);
2925
+ }
2926
+ if (is_tokenized) {
2927
+ hs_add(self->tokenized_fields, field);
2928
+ }
2929
+ }
2930
+
2931
+ /* these chars have meaning within phrases */
2932
+ static const char *PHRASE_CHARS = "<>|\"";
2933
+
2934
+ /**
2935
+ * +str_insert_char+ inserts a character at the beginning of a string by
2936
+ * shifting the rest of the string right.
2937
+ */
2938
+ static void str_insert_char(char *str, int len, char chr)
2939
+ {
2940
+ memmove(str+1, str, len*sizeof(char));
2941
+ *str = chr;
2942
+ }
2943
+
2944
+ /**
2945
+ * +qp_clean_str+ basically scans the query string and ensures that all open
2946
+ * and close parentheses '()' and quotes '"' are balanced. It does this by
2947
+ * inserting or appending extra parentheses or quotes to the string. This
2948
+ * obviously won't necessarily be exactly what the user wanted but we are
2949
+ * never going to know that anyway. The main job of this method is to help the
2950
+ * query at least parse correctly.
2951
+ *
2952
+ * It also checks that all special characters within phrases (ie between
2953
+ * quotes) are escaped correctly unless they have meaning within a phrase
2954
+ * ( <>,|," ). Note that '<' and '>' will also be escaped unless the appear
2955
+ * together like so; '<>'.
2956
+ */
2957
+ char *qp_clean_str(char *str)
2958
+ {
2959
+ int b, pb = -1;
2960
+ int br_cnt = 0;
2961
+ bool quote_open = false;
2962
+ char *sp, *nsp;
2963
+
2964
+ /* leave a little extra */
2965
+ char *new_str = ALLOC_N(char, strlen(str)*2 + 1);
2966
+
2967
+ for (sp = str, nsp = new_str; *sp; sp++) {
2968
+ b = *sp;
2969
+ /* ignore escaped characters */
2970
+ if (pb == '\\') {
2971
+ if (quote_open && strrchr(PHRASE_CHARS, b)) {
2972
+ *nsp++ = '\\'; /* this was left off the first time through */
2973
+ }
2974
+ *nsp++ = b;
2975
+ /* \ has escaped itself so has no power. Assign pb random char 'r' */
2976
+ pb = ((b == '\\') ? 'r' : b);
2977
+ continue;
2978
+ }
2979
+ switch (b) {
2980
+ case '\\':
2981
+ if (!quote_open) { /* We do our own escaping below */
2982
+ *nsp++ = b;
2983
+ }
2984
+ break;
2985
+ case '"':
2986
+ quote_open = !quote_open;
2987
+ *nsp++ = b;
2988
+ break;
2989
+ case '(':
2990
+ if (!quote_open) {
2991
+ br_cnt++;
2992
+ }
2993
+ else {
2994
+ *nsp++ = '\\';
2995
+ }
2996
+ *nsp++ = b;
2997
+ break;
2998
+ case ')':
2999
+ if (!quote_open) {
3000
+ if (br_cnt == 0) {
3001
+ str_insert_char(new_str, (int)(nsp - new_str), '(');
3002
+ nsp++;
3003
+ }
3004
+ else {
3005
+ br_cnt--;
3006
+ }
3007
+ }
3008
+ else {
3009
+ *nsp++ = '\\';
3010
+ }
3011
+ *nsp++ = b;
3012
+ break;
3013
+ case '>':
3014
+ if (quote_open) {
3015
+ if (pb == '<') {
3016
+ /* remove the escape character */
3017
+ nsp--;
3018
+ nsp[-1] = '<';
3019
+ }
3020
+ else {
3021
+ *nsp++ = '\\';
3022
+ }
3023
+ }
3024
+ *nsp++ = b;
3025
+ break;
3026
+ default:
3027
+ if (quote_open) {
3028
+ if (strrchr(special_char, b) && b != '|') {
3029
+ *nsp++ = '\\';
3030
+ }
3031
+ }
3032
+ *nsp++ = b;
3033
+ }
3034
+ pb = b;
3035
+ }
3036
+ if (quote_open) {
3037
+ *nsp++ = '"';
3038
+ }
3039
+ for (;br_cnt > 0; br_cnt--) {
3040
+ *nsp++ = ')';
3041
+ }
3042
+ *nsp = '\0';
3043
+ return new_str;
3044
+ }
3045
+
3046
+ /**
3047
+ * Takes a string and finds whatever tokens it can using the QueryParser's
3048
+ * analyzer. It then turns these tokens (if any) into a boolean query. If it
3049
+ * fails to find any tokens, this method will return NULL.
3050
+ */
3051
+ static Query *qp_get_bad_query(QParser *qp, char *str)
3052
+ {
3053
+ Query *volatile q = NULL;
3054
+ qp->recovering = true;
3055
+ assert(qp->fields_top->next == NULL);
3056
+ FLDS(q, get_term_q(qp, field, str));
3057
+ return q;
3058
+ }
3059
+
3060
+ /**
3061
+ * +qp_parse+ takes a string and turns it into a Query object using Ferret's
3062
+ * query language. It must either raise an error or return a query object. It
3063
+ * must not return NULL. If the yacc parser fails it will use a very basic
3064
+ * boolean query parser which takes whatever tokens it can find in the query
3065
+ * and terns them into a boolean query on the default fields.
3066
+ */
3067
+ Query *qp_parse(QParser *self, char *qstr)
3068
+ {
3069
+ Query *result = NULL;
3070
+ mutex_lock(&self->mutex);
3071
+ /* if qp->fields_top->next is not NULL we have a left over field-stack
3072
+ * object that was not popped during the last query parse */
3073
+ assert(NULL == self->fields_top->next);
3074
+
3075
+ self->recovering = self->destruct = false;
3076
+ if (self->clean_str) {
3077
+ self->qstrp = self->qstr = qp_clean_str(qstr);
3078
+ }
3079
+ else {
3080
+ self->qstrp = self->qstr = qstr;
3081
+ }
3082
+ self->fields = self->def_fields;
3083
+ self->result = NULL;
3084
+
3085
+ if (0 == yyparse(self)) result = self->result;
3086
+ if (!result && self->handle_parse_errors) {
3087
+ self->destruct = false;
3088
+ result = qp_get_bad_query(self, self->qstr);
3089
+ }
3090
+ if (self->destruct && !self->handle_parse_errors) {
3091
+ xraise(PARSE_ERROR, xmsg_buffer);
3092
+ }
3093
+ if (!result) {
3094
+ result = bq_new(false);
3095
+ }
3096
+ if (self->clean_str) {
3097
+ free(self->qstr);
3098
+ }
3099
+
3100
+ mutex_unlock(&self->mutex);
3101
+ return result;
3102
+ }
3103
+