ferret 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README +109 -0
  3. data/Rakefile +275 -0
  4. data/TODO +9 -0
  5. data/TUTORIAL +197 -0
  6. data/ext/extconf.rb +3 -0
  7. data/ext/ferret.c +23 -0
  8. data/ext/ferret.h +85 -0
  9. data/ext/index_io.c +543 -0
  10. data/ext/priority_queue.c +227 -0
  11. data/ext/ram_directory.c +316 -0
  12. data/ext/segment_merge_queue.c +41 -0
  13. data/ext/string_helper.c +42 -0
  14. data/ext/tags +240 -0
  15. data/ext/term.c +261 -0
  16. data/ext/term_buffer.c +299 -0
  17. data/ext/util.c +12 -0
  18. data/lib/ferret.rb +41 -0
  19. data/lib/ferret/analysis.rb +11 -0
  20. data/lib/ferret/analysis/analyzers.rb +93 -0
  21. data/lib/ferret/analysis/standard_tokenizer.rb +65 -0
  22. data/lib/ferret/analysis/token.rb +79 -0
  23. data/lib/ferret/analysis/token_filters.rb +86 -0
  24. data/lib/ferret/analysis/token_stream.rb +26 -0
  25. data/lib/ferret/analysis/tokenizers.rb +107 -0
  26. data/lib/ferret/analysis/word_list_loader.rb +27 -0
  27. data/lib/ferret/document.rb +2 -0
  28. data/lib/ferret/document/document.rb +152 -0
  29. data/lib/ferret/document/field.rb +304 -0
  30. data/lib/ferret/index.rb +26 -0
  31. data/lib/ferret/index/compound_file_io.rb +343 -0
  32. data/lib/ferret/index/document_writer.rb +288 -0
  33. data/lib/ferret/index/field_infos.rb +259 -0
  34. data/lib/ferret/index/fields_io.rb +175 -0
  35. data/lib/ferret/index/index.rb +228 -0
  36. data/lib/ferret/index/index_file_names.rb +33 -0
  37. data/lib/ferret/index/index_reader.rb +462 -0
  38. data/lib/ferret/index/index_writer.rb +488 -0
  39. data/lib/ferret/index/multi_reader.rb +363 -0
  40. data/lib/ferret/index/multiple_term_doc_pos_enum.rb +105 -0
  41. data/lib/ferret/index/segment_infos.rb +130 -0
  42. data/lib/ferret/index/segment_merge_info.rb +47 -0
  43. data/lib/ferret/index/segment_merge_queue.rb +16 -0
  44. data/lib/ferret/index/segment_merger.rb +337 -0
  45. data/lib/ferret/index/segment_reader.rb +380 -0
  46. data/lib/ferret/index/segment_term_enum.rb +178 -0
  47. data/lib/ferret/index/segment_term_vector.rb +58 -0
  48. data/lib/ferret/index/term.rb +49 -0
  49. data/lib/ferret/index/term_buffer.rb +88 -0
  50. data/lib/ferret/index/term_doc_enum.rb +283 -0
  51. data/lib/ferret/index/term_enum.rb +52 -0
  52. data/lib/ferret/index/term_info.rb +41 -0
  53. data/lib/ferret/index/term_infos_io.rb +312 -0
  54. data/lib/ferret/index/term_vector_offset_info.rb +20 -0
  55. data/lib/ferret/index/term_vectors_io.rb +552 -0
  56. data/lib/ferret/query_parser.rb +274 -0
  57. data/lib/ferret/query_parser/query_parser.tab.rb +819 -0
  58. data/lib/ferret/search.rb +49 -0
  59. data/lib/ferret/search/boolean_clause.rb +100 -0
  60. data/lib/ferret/search/boolean_query.rb +303 -0
  61. data/lib/ferret/search/boolean_scorer.rb +294 -0
  62. data/lib/ferret/search/caching_wrapper_filter.rb +40 -0
  63. data/lib/ferret/search/conjunction_scorer.rb +99 -0
  64. data/lib/ferret/search/disjunction_sum_scorer.rb +203 -0
  65. data/lib/ferret/search/exact_phrase_scorer.rb +32 -0
  66. data/lib/ferret/search/explanation.rb +41 -0
  67. data/lib/ferret/search/field_cache.rb +216 -0
  68. data/lib/ferret/search/field_doc.rb +31 -0
  69. data/lib/ferret/search/field_sorted_hit_queue.rb +184 -0
  70. data/lib/ferret/search/filter.rb +11 -0
  71. data/lib/ferret/search/filtered_query.rb +130 -0
  72. data/lib/ferret/search/filtered_term_enum.rb +79 -0
  73. data/lib/ferret/search/fuzzy_query.rb +153 -0
  74. data/lib/ferret/search/fuzzy_term_enum.rb +244 -0
  75. data/lib/ferret/search/hit_collector.rb +34 -0
  76. data/lib/ferret/search/hit_queue.rb +11 -0
  77. data/lib/ferret/search/index_searcher.rb +173 -0
  78. data/lib/ferret/search/match_all_docs_query.rb +104 -0
  79. data/lib/ferret/search/multi_phrase_query.rb +204 -0
  80. data/lib/ferret/search/multi_term_query.rb +65 -0
  81. data/lib/ferret/search/non_matching_scorer.rb +22 -0
  82. data/lib/ferret/search/phrase_positions.rb +55 -0
  83. data/lib/ferret/search/phrase_query.rb +217 -0
  84. data/lib/ferret/search/phrase_scorer.rb +153 -0
  85. data/lib/ferret/search/prefix_query.rb +47 -0
  86. data/lib/ferret/search/query.rb +111 -0
  87. data/lib/ferret/search/query_filter.rb +51 -0
  88. data/lib/ferret/search/range_filter.rb +103 -0
  89. data/lib/ferret/search/range_query.rb +139 -0
  90. data/lib/ferret/search/req_excl_scorer.rb +125 -0
  91. data/lib/ferret/search/req_opt_sum_scorer.rb +70 -0
  92. data/lib/ferret/search/score_doc.rb +38 -0
  93. data/lib/ferret/search/score_doc_comparator.rb +114 -0
  94. data/lib/ferret/search/scorer.rb +91 -0
  95. data/lib/ferret/search/similarity.rb +278 -0
  96. data/lib/ferret/search/sloppy_phrase_scorer.rb +47 -0
  97. data/lib/ferret/search/sort.rb +105 -0
  98. data/lib/ferret/search/sort_comparator.rb +60 -0
  99. data/lib/ferret/search/sort_field.rb +87 -0
  100. data/lib/ferret/search/spans.rb +12 -0
  101. data/lib/ferret/search/spans/near_spans_enum.rb +304 -0
  102. data/lib/ferret/search/spans/span_first_query.rb +79 -0
  103. data/lib/ferret/search/spans/span_near_query.rb +108 -0
  104. data/lib/ferret/search/spans/span_not_query.rb +130 -0
  105. data/lib/ferret/search/spans/span_or_query.rb +176 -0
  106. data/lib/ferret/search/spans/span_query.rb +25 -0
  107. data/lib/ferret/search/spans/span_scorer.rb +74 -0
  108. data/lib/ferret/search/spans/span_term_query.rb +105 -0
  109. data/lib/ferret/search/spans/span_weight.rb +84 -0
  110. data/lib/ferret/search/spans/spans_enum.rb +44 -0
  111. data/lib/ferret/search/term_query.rb +128 -0
  112. data/lib/ferret/search/term_scorer.rb +181 -0
  113. data/lib/ferret/search/top_docs.rb +24 -0
  114. data/lib/ferret/search/top_field_docs.rb +17 -0
  115. data/lib/ferret/search/weight.rb +54 -0
  116. data/lib/ferret/search/wildcard_query.rb +26 -0
  117. data/lib/ferret/search/wildcard_term_enum.rb +61 -0
  118. data/lib/ferret/stemmers.rb +1 -0
  119. data/lib/ferret/stemmers/porter_stemmer.rb +218 -0
  120. data/lib/ferret/store.rb +5 -0
  121. data/lib/ferret/store/buffered_index_io.rb +191 -0
  122. data/lib/ferret/store/directory.rb +139 -0
  123. data/lib/ferret/store/fs_store.rb +338 -0
  124. data/lib/ferret/store/index_io.rb +259 -0
  125. data/lib/ferret/store/ram_store.rb +282 -0
  126. data/lib/ferret/utils.rb +7 -0
  127. data/lib/ferret/utils/bit_vector.rb +105 -0
  128. data/lib/ferret/utils/date_tools.rb +138 -0
  129. data/lib/ferret/utils/number_tools.rb +91 -0
  130. data/lib/ferret/utils/parameter.rb +41 -0
  131. data/lib/ferret/utils/priority_queue.rb +120 -0
  132. data/lib/ferret/utils/string_helper.rb +47 -0
  133. data/lib/ferret/utils/weak_key_hash.rb +51 -0
  134. data/rake_utils/code_statistics.rb +106 -0
  135. data/setup.rb +1551 -0
  136. data/test/benchmark/tb_ram_store.rb +76 -0
  137. data/test/benchmark/tb_rw_vint.rb +26 -0
  138. data/test/longrunning/tc_numbertools.rb +60 -0
  139. data/test/longrunning/tm_store.rb +19 -0
  140. data/test/test_all.rb +9 -0
  141. data/test/test_helper.rb +6 -0
  142. data/test/unit/analysis/tc_analyzer.rb +21 -0
  143. data/test/unit/analysis/tc_letter_tokenizer.rb +20 -0
  144. data/test/unit/analysis/tc_lower_case_filter.rb +20 -0
  145. data/test/unit/analysis/tc_lower_case_tokenizer.rb +27 -0
  146. data/test/unit/analysis/tc_per_field_analyzer_wrapper.rb +39 -0
  147. data/test/unit/analysis/tc_porter_stem_filter.rb +16 -0
  148. data/test/unit/analysis/tc_standard_analyzer.rb +20 -0
  149. data/test/unit/analysis/tc_standard_tokenizer.rb +20 -0
  150. data/test/unit/analysis/tc_stop_analyzer.rb +20 -0
  151. data/test/unit/analysis/tc_stop_filter.rb +14 -0
  152. data/test/unit/analysis/tc_white_space_analyzer.rb +21 -0
  153. data/test/unit/analysis/tc_white_space_tokenizer.rb +20 -0
  154. data/test/unit/analysis/tc_word_list_loader.rb +32 -0
  155. data/test/unit/document/tc_document.rb +47 -0
  156. data/test/unit/document/tc_field.rb +80 -0
  157. data/test/unit/index/tc_compound_file_io.rb +107 -0
  158. data/test/unit/index/tc_field_infos.rb +119 -0
  159. data/test/unit/index/tc_fields_io.rb +167 -0
  160. data/test/unit/index/tc_index.rb +140 -0
  161. data/test/unit/index/tc_index_reader.rb +622 -0
  162. data/test/unit/index/tc_index_writer.rb +57 -0
  163. data/test/unit/index/tc_multiple_term_doc_pos_enum.rb +80 -0
  164. data/test/unit/index/tc_segment_infos.rb +74 -0
  165. data/test/unit/index/tc_segment_term_docs.rb +17 -0
  166. data/test/unit/index/tc_segment_term_enum.rb +60 -0
  167. data/test/unit/index/tc_segment_term_vector.rb +71 -0
  168. data/test/unit/index/tc_term.rb +22 -0
  169. data/test/unit/index/tc_term_buffer.rb +57 -0
  170. data/test/unit/index/tc_term_info.rb +19 -0
  171. data/test/unit/index/tc_term_infos_io.rb +192 -0
  172. data/test/unit/index/tc_term_vector_offset_info.rb +18 -0
  173. data/test/unit/index/tc_term_vectors_io.rb +108 -0
  174. data/test/unit/index/th_doc.rb +244 -0
  175. data/test/unit/query_parser/tc_query_parser.rb +84 -0
  176. data/test/unit/search/tc_filter.rb +113 -0
  177. data/test/unit/search/tc_fuzzy_query.rb +136 -0
  178. data/test/unit/search/tc_index_searcher.rb +188 -0
  179. data/test/unit/search/tc_search_and_sort.rb +98 -0
  180. data/test/unit/search/tc_similarity.rb +37 -0
  181. data/test/unit/search/tc_sort.rb +48 -0
  182. data/test/unit/search/tc_sort_field.rb +27 -0
  183. data/test/unit/search/tc_spans.rb +153 -0
  184. data/test/unit/store/tc_fs_store.rb +84 -0
  185. data/test/unit/store/tc_ram_store.rb +35 -0
  186. data/test/unit/store/tm_store.rb +180 -0
  187. data/test/unit/store/tm_store_lock.rb +68 -0
  188. data/test/unit/ts_analysis.rb +16 -0
  189. data/test/unit/ts_document.rb +4 -0
  190. data/test/unit/ts_index.rb +18 -0
  191. data/test/unit/ts_query_parser.rb +3 -0
  192. data/test/unit/ts_search.rb +10 -0
  193. data/test/unit/ts_store.rb +6 -0
  194. data/test/unit/ts_utils.rb +10 -0
  195. data/test/unit/utils/tc_bit_vector.rb +65 -0
  196. data/test/unit/utils/tc_date_tools.rb +50 -0
  197. data/test/unit/utils/tc_number_tools.rb +59 -0
  198. data/test/unit/utils/tc_parameter.rb +40 -0
  199. data/test/unit/utils/tc_priority_queue.rb +62 -0
  200. data/test/unit/utils/tc_string_helper.rb +21 -0
  201. data/test/unit/utils/tc_weak_key_hash.rb +25 -0
  202. metadata +251 -0
@@ -0,0 +1,274 @@
1
+ require 'racc/parser'
2
+ module Ferret
3
+ # = QueryParser
4
+ #
5
+ # The Ferret::QueryParser is used to parse Ferret Query Language (FQL) into
6
+ # a Ferret Query. FQL is described Bellow.
7
+ #
8
+ # == Ferret Query Language
9
+ #
10
+ # === Preamble
11
+ #
12
+ # The following characters are special characters in FQL;
13
+ #
14
+ # :, (, ), [, ], {, }, !, +, ", ~, ^, -, |, <, >, =, *, ?, \
15
+ #
16
+ # If you want to use one of these characters in one of your terms you need
17
+ # to escape it with a \ character. \ escapes itself. The exception to this
18
+ # rule is within Phrases which a strings surrounded by double quotes (and
19
+ # will be explained further bellow in the section on PhraseQueries). In
20
+ # Phrases, only ", | and <> have special meaning and need to be escaped if
21
+ # you want the literal value. <> is escaped \<\>.
22
+ #
23
+ # In the following examples I have only written the query string. This would
24
+ # be parse like;
25
+ #
26
+ # query = query_parser.parse("pet:(dog AND cat)")
27
+ # puts query # => "+pet:dog +pet:cat"
28
+ #
29
+ # === TermQuery
30
+ #
31
+ # A term query is the most basic query of all and is what most of the other
32
+ # queries are built upon. The term consists of a single word. eg;
33
+ #
34
+ # 'term'
35
+ #
36
+ # Note that the analyzer will be run on the term and if it splits the term
37
+ # in two then it will be turned into a phrase query. For example, with the
38
+ # plain Ferret::Analysis::Analyzer, the following;
39
+ #
40
+ # 'dave12balmain'
41
+ #
42
+ # is equivalent to;
43
+ #
44
+ # '"dave balmain"'
45
+ #
46
+ # Which we will explain now...
47
+ #
48
+ # === PhraseQuery
49
+ #
50
+ # A phrase query is a string of terms surrounded by double quotes. For
51
+ # example you could write;
52
+ #
53
+ # '"quick brown fox"'
54
+ #
55
+ # But if a "fast" fox is just as good as a quick one you could use the |
56
+ # character to specify alternate terms.
57
+ #
58
+ # '"quick|speedy|fast brown fox"'
59
+ #
60
+ # What if we don't care what colour the fox is. We can use the <> to specify
61
+ # a place setter. eg;
62
+ #
63
+ # '"quick|speedy|fast <> fox"'
64
+ #
65
+ # This will match any word in between quick and fox. Alternatively we could
66
+ # set the "slop" for the phrase which allows a certain variation in the
67
+ # match of the phrase. The slop for a phrase is an integer indicating how
68
+ # many positions you are allowed to move the terms to get a match. Read more
69
+ # about the slop factor in Ferret::Search::PhraseQuery. To set the slop
70
+ # factor for a phrase you can type;
71
+ #
72
+ # '"big house"~2'
73
+ #
74
+ # This would match "big house", "big red house", "big red brick house" and
75
+ # even "house big". That's right, you don't need to have th terms in order
76
+ # if you allow some slop in your phrases. (See Ferret::Search::Spans if you
77
+ # need a phrase type query with ordered terms.)
78
+ #
79
+ # These basic queries will be run on the default field which is set when you
80
+ # create the query_parser. But what if you want to search a different field.
81
+ # You'll be needing a ...
82
+ #
83
+ # === FieldQuery
84
+ #
85
+ # A field query is any field prefixed by <fieldname>:. For example, to
86
+ # search for all instances of the term "ski" in field "sport", you'd write;
87
+ #
88
+ # 'sport:ski'
89
+ # Or we can apply a field to phrase;
90
+ #
91
+ # 'sport:"skiing is fun"'
92
+ #
93
+ # Now we have a few types of queries, we'll be needing to glue them together
94
+ # with a ...
95
+ #
96
+ # === BooleanQuery
97
+ #
98
+ # There are a couple of ways of writing boolean queries. Firstly you can
99
+ # specify which terms are required, optional or required not to exist (not).
100
+ #
101
+ # * '+' or "REQ" can be used to indicate a required query. "REQ" must be
102
+ # surrounded by white space.
103
+ # * '-', '!' or "NOT" are used to indicate query that is required to be
104
+ # false. "NOT" must be surrounded by white space.
105
+ # * all other queries are optional if the above symbols are used.
106
+ #
107
+ # Some examples;
108
+ #
109
+ # '+sport:ski -sport:snowboard sport:taboggen'
110
+ # '+ingredient:chocolate +ingredient:strawberries -ingredient:wheat'
111
+ #
112
+ # You may also use the boolean operators "AND", "&&", "OR" and "||". eg;
113
+ #
114
+ # 'sport:ski AND NOT sport:snowboard OR sport:taboggen'
115
+ # 'ingredient:chocolate AND ingredient:strawberries AND NOT ingredient:wheat'
116
+ #
117
+ # You can set the default operator when you create the query parse.
118
+ #
119
+ # === RangeQuery
120
+ #
121
+ # A range query finds all documents with terms between the two query terms.
122
+ # This can be very useful in particular for dates. eg;
123
+ #
124
+ # 'date:[20050725 20050905]' # all dates >= 20050725 and <= 20050905
125
+ # 'date:[20050725 20050905}' # all dates >= 20050725 and < 20050905
126
+ # 'date:{20050725 20050905]' # all dates > 20050725 and <= 20050905
127
+ # 'date:{20050725 20050905}' # all dates > 20050725 and < 20050905
128
+ #
129
+ # You can also do open ended queries like this;
130
+ #
131
+ # 'date:[20050725|' # all dates >= 20050725
132
+ # 'date:{20050725|' # all dates > 20050725
133
+ # 'date:|20050905]' # all dates <= 20050905
134
+ # 'date:|20050905}' # all dates < 20050905
135
+ #
136
+ # Or like this;
137
+ #
138
+ # 'date: >= 20050725'
139
+ # 'date: > 20050725'
140
+ # 'date: <= 20050905'
141
+ # 'date: < 20050905'
142
+ #
143
+ # If you prefer the above style you could use a boolean query but like this;
144
+ #
145
+ # 'date:( >= 20050725 AND <= 20050905)'
146
+ #
147
+ # But rangequery only solution shown first will be faster.
148
+ #
149
+ # === WildQuery
150
+ #
151
+ # A wild query is a query using the pattern matching characters * and ?. *
152
+ # matchs 0 or more characters while ? matchs a single character. This type
153
+ # of query can be really useful for matching heirarchical categories for
154
+ # example. Let's say we had this structure;
155
+ #
156
+ # /sport/skiing
157
+ # /sport/cycling
158
+ # /coding1/ruby
159
+ # /coding1/c
160
+ # /coding2/python
161
+ # /coding2/perl
162
+ #
163
+ # If you wanted all categories with programming languages you could use the
164
+ # query;
165
+ #
166
+ # 'category:/coding?/*'
167
+ #
168
+ # Note that this query can be quite expensive if not used carefully. In the
169
+ # example above there would be no problem but you should be careful not use
170
+ # the wild characters at the beginning of the query as it'll have to iterate
171
+ # through every term in that field. Having said that, some fields like the
172
+ # category field above will only have a small number of distinct fields so
173
+ # this could be ok.
174
+ #
175
+ # === FuzzyQuery
176
+ #
177
+ # This is like the sloppy phrase query above, except you are now adding slop
178
+ # to a term. Basically it measures the Levenshtein distance between two
179
+ # terms and if the value is below the slop threshold the term is a match.
180
+ # This time though the slop must be a float between 0 and 1.0, 1.0 being a
181
+ # perfect match and 0 being far from a match. The default is set to 0.5 so
182
+ # you don't need to give a slop value if you don't want to. You can set the
183
+ # default in the Ferret::Search::FuzzyQuery class. Here are a couple of
184
+ # examples;
185
+ #
186
+ # 'content:ferret~'
187
+ # 'content:Ostralya~0.4'
188
+ #
189
+ # Note that this query can be quite expensive. If you'd like to use this
190
+ # query, you may want to set a mininum prefix length in the FuzzyQuery
191
+ # class. This can substantially reduce the number of terms that the query
192
+ # will iterate over.
193
+ #
194
+ # Well, that's it for the query language. Next we have...
195
+ #
196
+ # == Extending the Query Parser
197
+ #
198
+ # The query parser has a number of methods which you may want to subclass if
199
+ # you are interested in extending the query parser.
200
+ #
201
+ # get_term_query:: Called for each term in the query. You may want
202
+ # to discard all but the first token instead or
203
+ # doing a phrase query.
204
+ #
205
+ # get_fuzzy_query:: These are expensive. You could set the default
206
+ # prefix or perhaps disallow these all together by
207
+ # raising an exception.
208
+ #
209
+ # get_range_query:: You'll probably want to leave this as is.
210
+ #
211
+ # get_phrase_query:: This method is passed an array of terms or
212
+ # perhaps an array of arrays of terms in the case
213
+ # of a multi-term phrase query as well as the slop
214
+ # and it returns a phrase query. Perhaps you'd
215
+ # like to use a span query instead of the standard
216
+ # phrase query to ensure the order of the terms
217
+ # remains intact.
218
+ #
219
+ # get_normal_phrase_query:: Called for phrases without any multi-terms. This
220
+ # method is called by the standard
221
+ # get_phrase_query.
222
+ #
223
+ # get_multi_phrase_query:: Called for phrases with multi-terms. This method
224
+ # is called by the standard get_phrase_query.
225
+ #
226
+ # get_boolean_query:: Called with an array of clauses.
227
+ #
228
+ class QueryParser < Racc::Parser
229
+ include Ferret::Search
230
+ include Ferret::Index
231
+
232
+ # Create a new QueryParser.
233
+ #
234
+ # default_field:: all queries without a specified query string are run on
235
+ # this field.
236
+ # options:: the following options exist;
237
+ #
238
+ # * *analyzer* the analyzer is used to break phrases up into terms and
239
+ # to turn terms in tokens recognized in the index. Analysis::Analyzer
240
+ # is the default
241
+ # * *occur_default* Set to either BooleanClause::Occur::SHOULD (default)
242
+ # or BooleanClause::Occur::MUST to specify the default Occur operator.
243
+ # * *wild_lower* Set to false if you don't want the terms in fuzzy and
244
+ # wild queries to be set to lower case. You should do this if your
245
+ # analyzer doesn't downcase. The default is true.
246
+ # * *default_slop* Set the default slop for phrase queries. This defaults
247
+ # to 0.
248
+ def initialize(default_field = "", options = {})
249
+ end
250
+
251
+ # parses a string into a Ferret::Search::Query. The string needs to be
252
+ # parseable FQL.
253
+ def parse(str)
254
+ end
255
+
256
+ # Set to false if you don't want the terms in fuzzy and wild queries to be
257
+ # set to lower case. You should do this if your analyzer doesn't downcase.
258
+ def wild_lower()
259
+ end
260
+
261
+ # Returns the value of wild_lower. See #wild_lower.
262
+ def wild_lower?()
263
+ end
264
+
265
+ # Processes the query string escaping all special characters within
266
+ # phrases and making sure that double quotes and brackets are matching.
267
+ # This class will be called by the parse method so you should subclass it
268
+ # if you'd like to do your own query string cleaning.
269
+ def clean_string(str)
270
+ end
271
+ end
272
+ end
273
+
274
+ require 'ferret/query_parser/query_parser.tab.rb'
@@ -0,0 +1,819 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by racc 1.4.4
4
+ # from racc grammer file "lib/ferret/query_parser/query_parser.y".
5
+ #
6
+
7
+ require 'racc/parser'
8
+
9
+
10
+ module Ferret
11
+
12
+ class QueryParser < Racc::Parser
13
+
14
+ module_eval <<'..end lib/ferret/query_parser/query_parser.y modeval..id4dd1430e53', 'lib/ferret/query_parser/query_parser.y', 121
15
+ attr_accessor :default_field
16
+
17
+ # true if you want to downcase wild card queries. This is set to try by
18
+ # default.
19
+ attr_accessor :wild_lower
20
+
21
+ def wild_lower?() @wild_lower end
22
+
23
+
24
+ def initialize(default_field = "", options = {})
25
+ @yydebug = true
26
+ @field = @default_field = default_field
27
+ @analyzer = options[:analyzer] || Analysis::Analyzer.new
28
+ @wild_lower = options[:wild_lower].nil? ? true : options[:wild_lower]
29
+ @occur_default = options[:occur_default] || BooleanClause::Occur::SHOULD
30
+ @default_slop = options[:default_slop] || 0
31
+ end
32
+
33
+ RESERVED = {
34
+ 'AND' => :AND,
35
+ '&&' => :AND,
36
+ 'OR' => :OR,
37
+ '||' => :OR,
38
+ 'NOT' => :NOT,
39
+ '!' => :NOT,
40
+ '-' => :NOT,
41
+ 'REQ' => :REQ,
42
+ '+' => :REQ
43
+ }
44
+
45
+ ECHR = %q,:()\[\]{}!+"~^\-\|<>\=\*\?,
46
+ EWCHR = %q,:()\[\]{}!+"~^\-\|<>\=,
47
+
48
+ def parse(str)
49
+ str = clean_string(str)
50
+ str.strip!
51
+ @q = []
52
+
53
+ until str.empty? do
54
+ case str
55
+ when /\A\s+/
56
+ ;
57
+ when /\A[#{ECHR}]/
58
+ @q.push [ RESERVED[$&]||$&, $& ]
59
+ when /\A(\&\&|\|\|)/
60
+ @q.push [ RESERVED[$&], $& ]
61
+ when /\A(\\[#{ECHR}]|[^\s#{ECHR}])+[?*](\\[#{EWCHR}]|[^\s#{EWCHR}])*/
62
+ str = $'
63
+ unescaped = $&.gsub(/\\(?!\\)/,"")
64
+ @q.push [ :WILD_STRING, unescaped ]
65
+ next
66
+ when /\A(\\[#{ECHR}]|[^\s#{ECHR}])+/
67
+ symbol = RESERVED[$&]
68
+ if symbol
69
+ @q.push [ symbol, $& ]
70
+ else
71
+ str = $'
72
+ unescaped = $&.gsub(/\\(?!\\)/,"")
73
+ @q.push [ :WORD, unescaped ]
74
+ next
75
+ end
76
+ else
77
+ raise RuntimeError, "shouldn't happen"
78
+ end
79
+ str = $'
80
+ end
81
+ @q.push [ false, '$' ]
82
+ #p @q
83
+
84
+ do_parse
85
+ end
86
+
87
+ def next_token
88
+ @q.shift
89
+ end
90
+
91
+ PHRASE_CHARS = [?<, ?>, ?|, ?"] # these chars have meaning within phrases
92
+ def clean_string(str)
93
+ escape_chars = ECHR.gsub(/\\/,"").unpack("c*")
94
+ pb = nil
95
+ br_stack = []
96
+ quote_open = false
97
+ # leave a little extra
98
+ new_str = []
99
+
100
+ str.each_byte do |b|
101
+ # ignore escaped characters
102
+ if pb == ?\\
103
+ if quote_open and PHRASE_CHARS.index(b)
104
+ new_str << ?\\ # this was left off the first time through
105
+ end
106
+
107
+ new_str << b
108
+ pb = (b == ?\\ ? ?: : b) # \\ has escaped itself so does nothing more
109
+ next
110
+ end
111
+ case b
112
+ when ?\\
113
+ new_str << b if !quote_open # We do our own escaping below
114
+ when ?"
115
+ quote_open = !quote_open
116
+ new_str << b
117
+ when ?(
118
+ if !quote_open
119
+ br_stack << b
120
+ else
121
+ new_str << ?\\
122
+ end
123
+ new_str << b
124
+ when ?)
125
+ if !quote_open
126
+ if br_stack.size == 0
127
+ new_str.unshift(?()
128
+ else
129
+ br_stack.pop
130
+ end
131
+ else
132
+ new_str << ?\\
133
+ end
134
+ new_str << b
135
+ when ?>
136
+ if quote_open
137
+ if pb == ?<
138
+ new_str.delete_at(-2)
139
+ else
140
+ new_str << ?\\
141
+ end
142
+ end
143
+ new_str << b
144
+ else
145
+ if quote_open
146
+ if escape_chars.index(b) and b != ?|
147
+ new_str << ?\\
148
+ end
149
+ end
150
+ new_str << b
151
+ end
152
+ pb = b
153
+ end
154
+ new_str << ?" if quote_open
155
+ br_stack.each { |b| new_str << ?) }
156
+ return new_str.pack("c*")
157
+ end
158
+
159
+ def get_range_query(start_word, end_word, inc_upper, inc_lower)
160
+ return RangeQuery.new(@field, start_word, end_word, inc_upper, inc_lower)
161
+ end
162
+
163
+ def get_term_query(word)
164
+ tokens = []
165
+ stream = @analyzer.token_stream(@field, word)
166
+ while token = stream.next
167
+ tokens << token
168
+ end
169
+ if tokens.length == 0
170
+ return nil
171
+ elsif tokens.length == 1
172
+ return TermQuery.new(Term.new(@field, tokens[0].term_text))
173
+ else
174
+ pq = PhraseQuery.new()
175
+ tokens.each do |token|
176
+ pq.add(Term.new(@field, token.term_text), nil, token.position_increment)
177
+ end
178
+ return pq
179
+ end
180
+ end
181
+
182
+ def get_fuzzy_query(word, min_sim = nil)
183
+ tokens = []
184
+ stream = @analyzer.token_stream(@field, word)
185
+ if token = stream.next # only makes sense to look at one term for fuzzy
186
+ if min_sim
187
+ return FuzzyQuery.new(Term.new(@field, token.term_text), min_sim.to_f)
188
+ else
189
+ return FuzzyQuery.new(Term.new(@field, token.term_text))
190
+ end
191
+ else
192
+ return nil
193
+ end
194
+ end
195
+
196
+ def add_multi_word(words, word)
197
+ last_word = words[-1]
198
+ if not last_word.is_a?(Array)
199
+ last_word = words[-1] = [words[-1]]
200
+ end
201
+ last_word << word
202
+ return words
203
+ end
204
+
205
+ def get_normal_phrase_query(positions)
206
+ pq = PhraseQuery.new()
207
+ pq.slop = @default_slop
208
+ pos_inc = 0
209
+
210
+ positions.each do |position|
211
+ if position.nil?
212
+ pos_inc += 1
213
+ next
214
+ end
215
+ stream = @analyzer.token_stream(@field, position)
216
+ tokens = []
217
+ while token = stream.next
218
+ tokens << token
219
+ end
220
+ tokens.each do |token|
221
+ pq.add(Term.new(@field, token.term_text), nil,
222
+ token.position_increment + pos_inc)
223
+ pos_inc = 0
224
+ end
225
+ end
226
+ return pq
227
+ end
228
+
229
+ def get_multi_phrase_query(positions)
230
+ mpq = MultiPhraseQuery.new()
231
+ mpq.slop = @default_slop
232
+ pos_inc = 0
233
+
234
+ positions.each do |position|
235
+ if position.nil?
236
+ pos_inc += 1
237
+ next
238
+ end
239
+ if position.is_a?(Array)
240
+ position.compact! # it doesn't make sense to have an empty spot here
241
+ terms = []
242
+ position.each do |word|
243
+ stream = @analyzer.token_stream(@field, word)
244
+ if token = stream.next # only put one term per word
245
+ terms << Term.new(@field, token.term_text)
246
+ end
247
+ end
248
+ mpq.add(terms, nil, pos_inc + 1) # must go at least one forward
249
+ pos_inc = 0
250
+ else
251
+ stream = @analyzer.token_stream(@field, position)
252
+ tokens = []
253
+ while token = stream.next
254
+ tokens << token
255
+ end
256
+ tokens.each do |token|
257
+ mpq.add([Term.new(@field, token.term_text)], nil,
258
+ token.position_increment + pos_inc)
259
+ pos_inc = 0
260
+ end
261
+ end
262
+ end
263
+ return mpq
264
+ end
265
+
266
+ def get_phrase_query(positions, slop = nil)
267
+ if positions.size == 1 and not positions[0].is_a?(Array)
268
+ return get_term_query(words[0])
269
+ end
270
+
271
+ multi_phrase = false
272
+ positions.each do |position|
273
+ if position.is_a?(Array)
274
+ position.compact!
275
+ if position.size > 1
276
+ multi_phrase = true
277
+ end
278
+ end
279
+ end
280
+
281
+ q = nil
282
+ if not multi_phrase
283
+ q = get_normal_phrase_query(positions.flatten)
284
+ else
285
+ q = get_multi_phrase_query(positions)
286
+ end
287
+ q.slop = slop if slop
288
+ return q
289
+ end
290
+
291
+ def add_and_clause(clauses, clause)
292
+ clauses.compact!
293
+ if (clauses.length == 1)
294
+ last_cl = clauses[0]
295
+ last_cl.occur = BooleanClause::Occur::MUST if not last_cl.prohibited?
296
+ end
297
+
298
+ return if clause.nil? # incase a query got destroyed by the analyzer
299
+
300
+ clause.occur = BooleanClause::Occur::MUST if not clause.prohibited?
301
+ clauses << clause
302
+ end
303
+
304
+ def add_or_clause(clauses, clause)
305
+ clauses << clause
306
+ end
307
+
308
+ def add_default_clause(clauses, clause)
309
+ if @occur_default == BooleanClause::Occur::MUST
310
+ add_and_clause(clauses, clause)
311
+ else
312
+ add_or_clause(clauses, clause)
313
+ end
314
+ end
315
+
316
+ def get_boolean_query(clauses)
317
+ # possible that we got all nil clauses so check
318
+ return nil if clauses.nil?
319
+ clauses.compact!
320
+ return nil if clauses.size == 0
321
+
322
+ if clauses.size == 1 and not clauses[0].prohibited?
323
+ return clauses[0].query
324
+ end
325
+ bq = BooleanQuery.new()
326
+ clauses.each {|clause| bq << clause }
327
+ return bq
328
+ end
329
+
330
+ def get_boolean_clause(query, occur)
331
+ return nil if query.nil?
332
+ return BooleanClause.new(query, occur)
333
+ end
334
+
335
+ ..end lib/ferret/query_parser/query_parser.y modeval..id4dd1430e53
336
+
337
+ ##### racc 1.4.4 generates ###
338
+
339
+ racc_reduce_table = [
340
+ 0, 0, :racc_error,
341
+ 1, 25, :_reduce_1,
342
+ 1, 26, :_reduce_2,
343
+ 3, 26, :_reduce_3,
344
+ 3, 26, :_reduce_4,
345
+ 2, 26, :_reduce_5,
346
+ 2, 27, :_reduce_6,
347
+ 2, 27, :_reduce_7,
348
+ 1, 27, :_reduce_8,
349
+ 1, 29, :_reduce_none,
350
+ 3, 29, :_reduce_10,
351
+ 1, 28, :_reduce_none,
352
+ 3, 28, :_reduce_12,
353
+ 1, 28, :_reduce_none,
354
+ 1, 28, :_reduce_none,
355
+ 1, 28, :_reduce_none,
356
+ 1, 28, :_reduce_none,
357
+ 1, 30, :_reduce_17,
358
+ 3, 30, :_reduce_18,
359
+ 2, 30, :_reduce_19,
360
+ 1, 34, :_reduce_20,
361
+ 0, 36, :_reduce_21,
362
+ 4, 31, :_reduce_22,
363
+ 1, 35, :_reduce_23,
364
+ 3, 32, :_reduce_24,
365
+ 5, 32, :_reduce_25,
366
+ 2, 32, :_reduce_26,
367
+ 4, 32, :_reduce_27,
368
+ 1, 37, :_reduce_28,
369
+ 2, 37, :_reduce_29,
370
+ 3, 37, :_reduce_30,
371
+ 3, 37, :_reduce_31,
372
+ 4, 33, :_reduce_32,
373
+ 4, 33, :_reduce_33,
374
+ 4, 33, :_reduce_34,
375
+ 4, 33, :_reduce_35,
376
+ 3, 33, :_reduce_36,
377
+ 3, 33, :_reduce_37,
378
+ 3, 33, :_reduce_38,
379
+ 3, 33, :_reduce_39,
380
+ 2, 33, :_reduce_40,
381
+ 3, 33, :_reduce_41,
382
+ 3, 33, :_reduce_42,
383
+ 2, 33, :_reduce_43 ]
384
+
385
+ racc_reduce_n = 44
386
+
387
+ racc_shift_n = 73
388
+
389
+ racc_action_table = [
390
+ 7, 10, 61, 47, 38, 36, 48, 21, 3, 41,
391
+ 60, 6, 9, 12, 14, 16, 18, 37, 35, 1,
392
+ 7, 10, 33, 34, 58, 59, 40, 21, 3, 45,
393
+ -23, 6, 9, 12, 14, 16, 18, 7, 10, 1,
394
+ 55, 42, 30, 56, 21, 3, 44, 28, 6, 9,
395
+ 12, 14, 16, 18, 43, 57, 1, 7, 10, 33,
396
+ 34, 70, 71, 39, 21, 3, 63, 64, 6, 9,
397
+ 12, 14, 16, 18, 7, 10, 1, 27, 62, 25,
398
+ 66, 21, 3, 67, 68, 6, 9, 12, 14, 16,
399
+ 18, 7, 10, 1, 69, 23, 72, nil, 21, 3,
400
+ nil, nil, 6, 9, 12, 14, 16, 18, 21, 3,
401
+ 1, nil, 6, 9, 12, 14, 16, 18, 21, 3,
402
+ 1, nil, 6, 9, 12, 14, 16, 18, 21, 3,
403
+ 1, nil, 6, 9, 12, 14, 16, 18, 52, nil,
404
+ 1, nil, nil, 49, 50, nil, 51 ]
405
+
406
+ racc_action_check = [
407
+ 0, 0, 41, 27, 14, 12, 28, 0, 0, 18,
408
+ 41, 0, 0, 0, 0, 0, 0, 14, 12, 0,
409
+ 24, 24, 24, 24, 40, 40, 16, 24, 24, 24,
410
+ 21, 24, 24, 24, 24, 24, 24, 3, 3, 24,
411
+ 35, 21, 9, 37, 3, 3, 23, 9, 3, 3,
412
+ 3, 3, 3, 3, 23, 39, 3, 11, 11, 11,
413
+ 11, 61, 61, 15, 11, 11, 44, 44, 11, 11,
414
+ 11, 11, 11, 11, 34, 34, 11, 8, 42, 5,
415
+ 48, 34, 34, 49, 50, 34, 34, 34, 34, 34,
416
+ 34, 33, 33, 34, 51, 1, 67, nil, 33, 33,
417
+ nil, nil, 33, 33, 33, 33, 33, 33, 10, 10,
418
+ 33, nil, 10, 10, 10, 10, 10, 10, 25, 25,
419
+ 10, nil, 25, 25, 25, 25, 25, 25, 7, 7,
420
+ 25, nil, 7, 7, 7, 7, 7, 7, 29, nil,
421
+ 7, nil, nil, 29, 29, nil, 29 ]
422
+
423
+ racc_action_pointer = [
424
+ -3, 85, nil, 34, nil, 77, nil, 118, 77, 32,
425
+ 98, 54, -5, nil, -6, 54, 16, nil, -1, nil,
426
+ nil, 28, nil, 36, 17, 108, nil, 3, -7, 128,
427
+ nil, nil, nil, 88, 71, 30, nil, 33, nil, 45,
428
+ 4, -8, 68, nil, 46, nil, nil, nil, 70, 70,
429
+ 67, 84, nil, nil, nil, nil, nil, nil, nil, nil,
430
+ nil, 41, nil, nil, nil, nil, nil, 86, nil, nil,
431
+ nil, nil, nil ]
432
+
433
+ racc_action_default = [
434
+ -44, -44, -15, -44, -16, -44, -20, -44, -44, -44,
435
+ -44, -1, -44, -2, -44, -9, -44, -8, -44, -11,
436
+ -13, -17, -14, -44, -44, -44, -6, -44, -26, -44,
437
+ -28, -7, -5, -44, -44, -44, -40, -44, -43, -44,
438
+ -44, -44, -19, -39, -44, -12, -21, 73, -44, -24,
439
+ -44, -44, -29, -3, -4, -41, -42, -10, -37, -36,
440
+ -38, -44, -18, -34, -35, -22, -27, -44, -30, -31,
441
+ -32, -33, -25 ]
442
+
443
+ racc_goto_table = [
444
+ 32, 26, 11, 8, 31, 24, 65, 29, nil, nil,
445
+ nil, nil, nil, 32, nil, nil, nil, nil, nil, 46,
446
+ nil, nil, 53, 54 ]
447
+
448
+ racc_goto_check = [
449
+ 3, 4, 2, 1, 4, 2, 12, 13, nil, nil,
450
+ nil, nil, nil, 3, nil, nil, nil, nil, nil, 4,
451
+ nil, nil, 3, 3 ]
452
+
453
+ racc_goto_pointer = [
454
+ nil, 3, 2, -11, -6, nil, nil, nil, nil, nil,
455
+ nil, nil, -40, -2 ]
456
+
457
+ racc_goto_default = [
458
+ nil, nil, nil, 13, 15, 17, 19, 20, 22, 2,
459
+ 4, 5, nil, nil ]
460
+
461
+ racc_token_table = {
462
+ false => 0,
463
+ Object.new => 1,
464
+ ":" => 2,
465
+ :REQ => 3,
466
+ :NOT => 4,
467
+ :AND => 5,
468
+ :OR => 6,
469
+ :HIGH => 7,
470
+ :LOW => 8,
471
+ "^" => 9,
472
+ :WORD => 10,
473
+ "(" => 11,
474
+ ")" => 12,
475
+ "~" => 13,
476
+ :WILD_STRING => 14,
477
+ "\"" => 15,
478
+ "<" => 16,
479
+ ">" => 17,
480
+ "|" => 18,
481
+ "[" => 19,
482
+ "]" => 20,
483
+ "}" => 21,
484
+ "{" => 22,
485
+ "=" => 23 }
486
+
487
+ racc_use_result_var = false
488
+
489
+ racc_nt_base = 24
490
+
491
+ Racc_arg = [
492
+ racc_action_table,
493
+ racc_action_check,
494
+ racc_action_default,
495
+ racc_action_pointer,
496
+ racc_goto_table,
497
+ racc_goto_check,
498
+ racc_goto_default,
499
+ racc_goto_pointer,
500
+ racc_nt_base,
501
+ racc_reduce_table,
502
+ racc_token_table,
503
+ racc_shift_n,
504
+ racc_reduce_n,
505
+ racc_use_result_var ]
506
+
507
+ Racc_token_to_s_table = [
508
+ '$end',
509
+ 'error',
510
+ '":"',
511
+ 'REQ',
512
+ 'NOT',
513
+ 'AND',
514
+ 'OR',
515
+ 'HIGH',
516
+ 'LOW',
517
+ '"^"',
518
+ 'WORD',
519
+ '"("',
520
+ '")"',
521
+ '"~"',
522
+ 'WILD_STRING',
523
+ '"\""',
524
+ '"<"',
525
+ '">"',
526
+ '"|"',
527
+ '"["',
528
+ '"]"',
529
+ '"}"',
530
+ '"{"',
531
+ '"="',
532
+ '$start',
533
+ 'top_query',
534
+ 'bool_query',
535
+ 'bool_clause',
536
+ 'query',
537
+ 'boosted_query',
538
+ 'term_query',
539
+ 'field_query',
540
+ 'phrase_query',
541
+ 'range_query',
542
+ 'wild_query',
543
+ 'field_name',
544
+ '@1',
545
+ 'phrase_words']
546
+
547
+ Racc_debug_parser = false
548
+
549
+ ##### racc system variables end #####
550
+
551
+ # reduce 0 omitted
552
+
553
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 19
554
+ def _reduce_1( val, _values)
555
+ get_boolean_query(val[0])
556
+ end
557
+ .,.,
558
+
559
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 24
560
+ def _reduce_2( val, _values)
561
+ [val[0]]
562
+ end
563
+ .,.,
564
+
565
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 28
566
+ def _reduce_3( val, _values)
567
+ add_and_clause(val[0], val[2])
568
+ end
569
+ .,.,
570
+
571
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 32
572
+ def _reduce_4( val, _values)
573
+ add_or_clause(val[0], val[2])
574
+ end
575
+ .,.,
576
+
577
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 36
578
+ def _reduce_5( val, _values)
579
+ add_default_clause(val[0], val[1])
580
+ end
581
+ .,.,
582
+
583
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 41
584
+ def _reduce_6( val, _values)
585
+ get_boolean_clause(val[1], BooleanClause::Occur::MUST)
586
+ end
587
+ .,.,
588
+
589
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 45
590
+ def _reduce_7( val, _values)
591
+ get_boolean_clause(val[1], BooleanClause::Occur::MUST_NOT)
592
+ end
593
+ .,.,
594
+
595
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 49
596
+ def _reduce_8( val, _values)
597
+ get_boolean_clause(val[0], BooleanClause::Occur::SHOULD)
598
+ end
599
+ .,.,
600
+
601
+ # reduce 9 omitted
602
+
603
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 51
604
+ def _reduce_10( val, _values)
605
+ val[0].boost = val[2].to_f; return val[0]
606
+ end
607
+ .,.,
608
+
609
+ # reduce 11 omitted
610
+
611
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 58
612
+ def _reduce_12( val, _values)
613
+ get_boolean_query(val[1])
614
+ end
615
+ .,.,
616
+
617
+ # reduce 13 omitted
618
+
619
+ # reduce 14 omitted
620
+
621
+ # reduce 15 omitted
622
+
623
+ # reduce 16 omitted
624
+
625
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 67
626
+ def _reduce_17( val, _values)
627
+ get_term_query(val[0])
628
+ end
629
+ .,.,
630
+
631
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 71
632
+ def _reduce_18( val, _values)
633
+ get_fuzzy_query(val[0], val[2])
634
+ end
635
+ .,.,
636
+
637
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 75
638
+ def _reduce_19( val, _values)
639
+ get_fuzzy_query(val[0])
640
+ end
641
+ .,.,
642
+
643
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 80
644
+ def _reduce_20( val, _values)
645
+ WildcardQuery.new(Term.new(@field, val[0]))
646
+ end
647
+ .,.,
648
+
649
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 81
650
+ def _reduce_21( val, _values)
651
+ @field = @default_field
652
+ end
653
+ .,.,
654
+
655
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 85
656
+ def _reduce_22( val, _values)
657
+ val[2]
658
+ end
659
+ .,.,
660
+
661
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 86
662
+ def _reduce_23( val, _values)
663
+ @field = val[0]
664
+ end
665
+ .,.,
666
+
667
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 92
668
+ def _reduce_24( val, _values)
669
+ get_phrase_query(val[1])
670
+ end
671
+ .,.,
672
+
673
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 96
674
+ def _reduce_25( val, _values)
675
+ get_phrase_query(val[1], val[4].to_i)
676
+ end
677
+ .,.,
678
+
679
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 96
680
+ def _reduce_26( val, _values)
681
+ nil
682
+ end
683
+ .,.,
684
+
685
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 97
686
+ def _reduce_27( val, _values)
687
+ nil
688
+ end
689
+ .,.,
690
+
691
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 99
692
+ def _reduce_28( val, _values)
693
+ [val[0]]
694
+ end
695
+ .,.,
696
+
697
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 100
698
+ def _reduce_29( val, _values)
699
+ val[0] << val[1]
700
+ end
701
+ .,.,
702
+
703
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 101
704
+ def _reduce_30( val, _values)
705
+ val[0] << nil
706
+ end
707
+ .,.,
708
+
709
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 102
710
+ def _reduce_31( val, _values)
711
+ add_multi_word(val[0], val[2])
712
+ end
713
+ .,.,
714
+
715
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 104
716
+ def _reduce_32( val, _values)
717
+ get_range_query(val[1], val[2], true, true)
718
+ end
719
+ .,.,
720
+
721
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 105
722
+ def _reduce_33( val, _values)
723
+ get_range_query(val[1], val[2], true, false)
724
+ end
725
+ .,.,
726
+
727
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 106
728
+ def _reduce_34( val, _values)
729
+ get_range_query(val[1], val[2], false, true)
730
+ end
731
+ .,.,
732
+
733
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 107
734
+ def _reduce_35( val, _values)
735
+ get_range_query(val[1], val[2], false, false)
736
+ end
737
+ .,.,
738
+
739
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 108
740
+ def _reduce_36( val, _values)
741
+ get_range_query(nil, val[1], false, false)
742
+ end
743
+ .,.,
744
+
745
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 109
746
+ def _reduce_37( val, _values)
747
+ get_range_query(nil, val[1], false, true)
748
+ end
749
+ .,.,
750
+
751
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 110
752
+ def _reduce_38( val, _values)
753
+ get_range_query(val[1], nil, true, false)
754
+ end
755
+ .,.,
756
+
757
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 111
758
+ def _reduce_39( val, _values)
759
+ get_range_query(val[1], nil, false, false)
760
+ end
761
+ .,.,
762
+
763
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 112
764
+ def _reduce_40( val, _values)
765
+ get_range_query(nil, val[1], false, false)
766
+ end
767
+ .,.,
768
+
769
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 113
770
+ def _reduce_41( val, _values)
771
+ get_range_query(nil, val[2], false, true)
772
+ end
773
+ .,.,
774
+
775
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 114
776
+ def _reduce_42( val, _values)
777
+ get_range_query(val[2], nil, true, false)
778
+ end
779
+ .,.,
780
+
781
+ module_eval <<'.,.,', 'lib/ferret/query_parser/query_parser.y', 115
782
+ def _reduce_43( val, _values)
783
+ get_range_query(val[1], nil, false, false)
784
+ end
785
+ .,.,
786
+
787
+ def _reduce_none( val, _values)
788
+ val[0]
789
+ end
790
+
791
+ end # class QueryParser
792
+
793
+ end # module Ferret
794
+
795
+
796
+ if __FILE__ == $0
797
+ $:.unshift File.join(File.dirname(__FILE__), '..')
798
+ require 'utils'
799
+ require 'analysis'
800
+ require 'document'
801
+ require 'store'
802
+ require 'index'
803
+ require 'search'
804
+
805
+ st = "\033[7m"
806
+ en = "\033[m"
807
+
808
+ parser = Ferret::QueryParser.new("default")
809
+
810
+ $stdin.each do |line|
811
+ query = parser.parse(line)
812
+ if query
813
+ puts "#{query.class}"
814
+ puts query.to_s(parser.default_field)
815
+ else
816
+ puts "No query was returned"
817
+ end
818
+ end
819
+ end