keyword_search 1.2.0 → 1.3.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.
data/History.txt CHANGED
@@ -1,3 +1,11 @@
1
+ = 1.3.0 / 2007-10-09
2
+
3
+ * Conversion to Ragel-based parser (faster, less resource-intensive)
4
+ * Better support for other character sets, allow apostrophes in
5
+ unquoted words
6
+ * Test suite now uses test/spec
7
+ * API Should be backwards compatible
8
+
1
9
  = 1.2.0 / 2007-05-09
2
10
 
3
11
  * Raises KeywordSearch::ParseError instead of returning an empty Hash if an error occurs during parsing
data/Manifest.txt CHANGED
@@ -3,9 +3,6 @@ Manifest.txt
3
3
  README.txt
4
4
  Rakefile
5
5
  lib/keyword_search.rb
6
+ lib/keyword_search.rl
6
7
  lib/keyword_search/definition.rb
7
- lib/keyword_search/evaluator.rb
8
- lib/keyword_search/grammar.rb
9
- lib/keyword_search/parser.rb
10
- lib/keyword_search/tokenizer.rb
11
8
  test/test_keyword_search.rb
data/README.txt CHANGED
@@ -17,8 +17,6 @@ Various notes:
17
17
  * Input is automatically downcased (both keywords and values should be assumed to be in lowercase)
18
18
 
19
19
  Development Roadmap:
20
- 1.1:: Expand supported character set for keywords and values
21
- (currently supports a-z)
22
20
  2.0:: Add negation and grouping (will break API backwards compatibility)
23
21
 
24
22
  == SYNOPSIS:
@@ -59,7 +57,6 @@ Here's an example of usage from Rails (though the library is generic, and could
59
57
 
60
58
  == REQUIREMENTS:
61
59
 
62
- * dhaka
63
60
  * hoe
64
61
 
65
62
  == INSTALL:
data/Rakefile CHANGED
@@ -2,9 +2,8 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'hoe'
5
- require './lib/keyword_search.rb'
6
5
 
7
- Hoe.new('keyword_search', KeywordSearch::VERSION) do |p|
6
+ Hoe.new('keyword_search', '1.3.0') do |p|
8
7
  p.rubyforge_name = 'codefluency'
9
8
  p.summary = 'Generic support for extracting GMail-style search keywords/values from strings'
10
9
  p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
@@ -12,31 +11,10 @@ Hoe.new('keyword_search', KeywordSearch::VERSION) do |p|
12
11
  p.author = 'Bruce Williams'
13
12
  p.email = 'bruce@codefluency.com'
14
13
  p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
15
- p.extra_deps = [['dhaka', '= 2.1.0']]
16
14
  end
17
15
 
18
- task :rebuild_parser do
19
- require 'dhaka'
20
- parser = Dhaka::Parser.new(KeywordSearch::Grammar)
21
- File.open('lib/keyword_search/parser.rb', 'w') do |file|
22
- file << parser.compile_to_ruby_source_as('KeywordSearch::Parser')
23
- end
16
+ rule '.rb' => '.rl' do |t|
17
+ sh "ragel -R #{t.source} | rlgen-ruby -o #{t.name}"
24
18
  end
25
19
 
26
- task :rebuild_lexer do
27
- require 'dhaka'
28
- lexer = Dhaka::Lexer.new(KeywordSearch::LexerSpec)
29
- File.open('lib/keyword_search/lexer.rb', 'w') do |file|
30
- file << lexer.compile_to_ruby_source_as('KeywordSearch::Lexer')
31
- end
32
- end
33
-
34
- task :rebuild_lexer do
35
- require 'dhaka'
36
- lexer = Dhaka::Lexer.new(KeywordSearch::LexerSpec)
37
- File.open('lib/keyword_search/lexer.rb', 'w') do |file|
38
- file << lexer.compile_to_ruby_source_as('KeywordSearch::Lexer')
39
- end
40
- end
41
-
42
- # vim: syntax=Ruby
20
+ task :ragel => 'lib/keyword_search.rb'
@@ -1,31 +1,265 @@
1
- require 'dhaka'
2
-
3
- dirname = File.join(File.dirname(__FILE__), 'keyword_search')
4
- %w|grammar parser lexer_spec lexer evaluator definition|.each do |dependency|
5
- require File.join(dirname, dependency)
6
- end
1
+ # line 1 "lib/keyword_search.rl"
2
+ require File.dirname(__FILE__) << '/keyword_search/definition.rb'
7
3
 
8
4
  module KeywordSearch
9
-
10
- class ParseError < ::SyntaxError; end
11
-
12
- VERSION = '1.2.0'
13
-
5
+
6
+ class ParseError < ::SyntaxError; end
7
+
14
8
  class << self
9
+
10
+ # line 44 "lib/keyword_search.rl"
11
+
15
12
  def search(input_string, definition=nil, &block)
16
- @evaluator ||= Evaluator.new
17
13
  definition ||= Definition.new(&block)
18
- parse_result = Parser.parse(Lexer.lex(input_string))
19
- unless parse_result.has_error?
20
- results = @evaluator.evaluate(parse_result.parse_tree)
21
- results.each do |key, terms|
22
- definition.handle(key, terms)
23
- end
24
- results
25
- else
26
- raise ParseError, "Unexpected token #{parse_result.unexpected_token.inspect}"
14
+ results = parse(input_string)
15
+ results.each do |key, terms|
16
+ definition.handle(key, terms)
27
17
  end
18
+ results
19
+ end
20
+
21
+ #######
22
+ private
23
+ #######
24
+
25
+ def parse(input) #:nodoc:
26
+ data = input + ' '
27
+
28
+ # line 30 "lib/keyword_search.rb"
29
+ class << self
30
+ attr_accessor :_parser_actions
31
+ private :_parser_actions, :_parser_actions=
32
+ end
33
+ self._parser_actions = [
34
+ 0, 1, 3, 1, 4, 2, 0, 2,
35
+ 2, 1, 0
36
+ ]
37
+
38
+ class << self
39
+ attr_accessor :_parser_key_offsets
40
+ private :_parser_key_offsets, :_parser_key_offsets=
41
+ end
42
+ self._parser_key_offsets = [
43
+ 0, 0, 5, 8, 12, 15, 16, 17,
44
+ 18
45
+ ]
46
+
47
+ class << self
48
+ attr_accessor :_parser_trans_keys
49
+ private :_parser_trans_keys, :_parser_trans_keys=
50
+ end
51
+ self._parser_trans_keys = [
52
+ 0, 32, 34, 39, 58, 32, 34, 58,
53
+ 32, 34, 39, 58, 32, 34, 58, 34,
54
+ 32, 39, 32, 34, 58, 0
55
+ ]
56
+
57
+ class << self
58
+ attr_accessor :_parser_single_lengths
59
+ private :_parser_single_lengths, :_parser_single_lengths=
60
+ end
61
+ self._parser_single_lengths = [
62
+ 0, 5, 3, 4, 3, 1, 1, 1,
63
+ 3
64
+ ]
65
+
66
+ class << self
67
+ attr_accessor :_parser_range_lengths
68
+ private :_parser_range_lengths, :_parser_range_lengths=
69
+ end
70
+ self._parser_range_lengths = [
71
+ 0, 0, 0, 0, 0, 0, 0, 0,
72
+ 0
73
+ ]
74
+
75
+ class << self
76
+ attr_accessor :_parser_index_offsets
77
+ private :_parser_index_offsets, :_parser_index_offsets=
78
+ end
79
+ self._parser_index_offsets = [
80
+ 0, 0, 6, 10, 15, 19, 21, 23,
81
+ 25
82
+ ]
83
+
84
+ class << self
85
+ attr_accessor :_parser_trans_targs_wi
86
+ private :_parser_trans_targs_wi, :_parser_trans_targs_wi=
87
+ end
88
+ self._parser_trans_targs_wi = [
89
+ 8, 0, 5, 7, 0, 2, 1, 0,
90
+ 3, 2, 0, 5, 7, 0, 4, 1,
91
+ 0, 0, 4, 6, 5, 1, 0, 6,
92
+ 7, 1, 0, 3, 2, 0
93
+ ]
94
+
95
+ class << self
96
+ attr_accessor :_parser_trans_actions_wi
97
+ private :_parser_trans_actions_wi, :_parser_trans_actions_wi=
98
+ end
99
+ self._parser_trans_actions_wi = [
100
+ 5, 3, 5, 5, 3, 5, 1, 0,
101
+ 0, 0, 0, 8, 8, 0, 8, 1,
102
+ 0, 0, 0, 0, 0, 1, 0, 0,
103
+ 0, 1, 0, 0, 0, 0
104
+ ]
105
+
106
+ class << self
107
+ attr_accessor :parser_start
108
+ end
109
+ self.parser_start = 1;
110
+ class << self
111
+ attr_accessor :parser_first_final
112
+ end
113
+ self.parser_first_final = 8;
114
+ class << self
115
+ attr_accessor :parser_error
116
+ end
117
+ self.parser_error = 0;
118
+
119
+ class << self
120
+ attr_accessor :parser_en_main
121
+ end
122
+ self.parser_en_main = 1;
123
+
124
+ # line 62 "lib/keyword_search.rl"
125
+ p = 0
126
+ pe = data.length
127
+ key = nil
128
+ tokstart = nil
129
+ results = {}
130
+
131
+ # line 133 "lib/keyword_search.rb"
132
+ begin
133
+ p ||= 0
134
+ pe ||= data.length
135
+ cs = parser_start
136
+ end
137
+ # line 68 "lib/keyword_search.rl"
138
+
139
+ # line 141 "lib/keyword_search.rb"
140
+ begin
141
+ _klen, _trans, _keys, _acts, _nacts = nil
142
+ if p != pe
143
+ if cs != 0
144
+ while true
145
+ _break_resume = false
146
+ begin
147
+ _break_again = false
148
+ _keys = _parser_key_offsets[cs]
149
+ _trans = _parser_index_offsets[cs]
150
+ _klen = _parser_single_lengths[cs]
151
+ _break_match = false
152
+
153
+ begin
154
+ if _klen > 0
155
+ _lower = _keys
156
+ _upper = _keys + _klen - 1
157
+
158
+ loop do
159
+ break if _upper < _lower
160
+ _mid = _lower + ( (_upper - _lower) >> 1 )
161
+
162
+ if data[p] < _parser_trans_keys[_mid]
163
+ _upper = _mid - 1
164
+ elsif data[p] > _parser_trans_keys[_mid]
165
+ _lower = _mid + 1
166
+ else
167
+ _trans += (_mid - _keys)
168
+ _break_match = true
169
+ break
170
+ end
171
+ end # loop
172
+ break if _break_match
173
+ _keys += _klen
174
+ _trans += _klen
175
+ end
176
+ _klen = _parser_range_lengths[cs]
177
+ if _klen > 0
178
+ _lower = _keys
179
+ _upper = _keys + (_klen << 1) - 2
180
+ loop do
181
+ break if _upper < _lower
182
+ _mid = _lower + (((_upper-_lower) >> 1) & ~1)
183
+ if data[p] < _parser_trans_keys[_mid]
184
+ _upper = _mid - 2
185
+ elsif data[p] > _parser_trans_keys[_mid+1]
186
+ _lower = _mid + 2
187
+ else
188
+ _trans += ((_mid - _keys) >> 1)
189
+ _break_match = true
190
+ break
191
+ end
192
+ end # loop
193
+ break if _break_match
194
+ _trans += _klen
195
+ end
196
+ end while false
197
+ cs = _parser_trans_targs_wi[_trans]
198
+ break if _parser_trans_actions_wi[_trans] == 0
199
+ _acts = _parser_trans_actions_wi[_trans]
200
+ _nacts = _parser_actions[_acts]
201
+ _acts += 1
202
+ while _nacts > 0
203
+ _nacts -= 1
204
+ _acts += 1
205
+ case _parser_actions[_acts - 1]
206
+ when 0:
207
+ # line 13 "lib/keyword_search.rl"
208
+ begin
209
+
210
+ tokstart = p;
211
+ end
212
+ # line 13 "lib/keyword_search.rl"
213
+ when 1:
214
+ # line 17 "lib/keyword_search.rl"
215
+ begin
216
+
217
+ key = data[tokstart...p-1]
218
+ results[key] ||= []
219
+ end
220
+ # line 17 "lib/keyword_search.rl"
221
+ when 2:
222
+ # line 22 "lib/keyword_search.rl"
223
+ begin
224
+
225
+ key = nil
226
+ end
227
+ # line 22 "lib/keyword_search.rl"
228
+ when 3:
229
+ # line 26 "lib/keyword_search.rl"
230
+ begin
231
+
232
+ value = data[tokstart..p-1]
233
+ value = value[1..-2] if ["'", '"'].include?(value[0,1])
234
+ (results[key || :default] ||= []) << value
235
+ end
236
+ # line 26 "lib/keyword_search.rl"
237
+ when 4:
238
+ # line 42 "lib/keyword_search.rl"
239
+ begin
240
+ raise ParseError, "At offset #{p}, near: '#{data[p,10]}'" end
241
+ # line 42 "lib/keyword_search.rl"
242
+ # line 244 "lib/keyword_search.rb"
243
+ end # action switch
244
+ end
245
+ end while false
246
+ break if _break_resume
247
+ break if cs == 0
248
+ p += 1
249
+ break if p == pe
250
+ end
251
+ end
252
+ end
253
+ end
254
+ # line 69 "lib/keyword_search.rl"
255
+
256
+ # line 258 "lib/keyword_search.rb"
257
+ # line 70 "lib/keyword_search.rl"
258
+ results
28
259
  end
260
+
29
261
  end
30
262
 
31
- end
263
+ end
264
+
265
+
@@ -0,0 +1,85 @@
1
+ require File.dirname(__FILE__) << '/keyword_search/definition.rb'
2
+
3
+ module KeywordSearch
4
+
5
+ class ParseError < ::SyntaxError; end
6
+
7
+ class << self
8
+
9
+ %%{
10
+
11
+ machine parser;
12
+
13
+ action start {
14
+ tokstart = p;
15
+ }
16
+
17
+ action key {
18
+ key = data[tokstart...p-1]
19
+ results[key] ||= []
20
+ }
21
+
22
+ action default {
23
+ key = nil
24
+ }
25
+
26
+ action value {
27
+ value = data[tokstart..p-1]
28
+ value = value[1..-2] if ["'", '"'].include?(value[0,1])
29
+ (results[key || :default] ||= []) << value
30
+ }
31
+
32
+ action quote { quotes += 1 }
33
+
34
+ action unquote { quotes -= 1 }
35
+
36
+ bareword = [^ '":] [^ ":]*; # allow apostrophes
37
+ dquoted = '"' @ quote any* :>> '"' @ unquote;
38
+ squoted = '\'' @ quote any* :>> '\'' @ unquote;
39
+
40
+ value = ( dquoted | squoted | bareword );
41
+
42
+ pair = (bareword > start ':') % key value > start % value ;
43
+
44
+ definition = ( pair | value > start > default % value) ' ';
45
+ main := definition** 0
46
+ @!{ raise ParseError, "At offset #{p}, near: '#{data[p,10]}'" };
47
+
48
+ }%%
49
+
50
+ def search(input_string, definition=nil, &block)
51
+ definition ||= Definition.new(&block)
52
+ results = parse(input_string)
53
+ results.each do |key, terms|
54
+ definition.handle(key, terms)
55
+ end
56
+ results
57
+ end
58
+
59
+ #######
60
+ private
61
+ #######
62
+
63
+ def parse(input) #:nodoc:
64
+ data = input + ' '
65
+ %% write data;
66
+ p = 0
67
+ pe = data.length
68
+ key = nil
69
+ tokstart = nil
70
+ results = {}
71
+ quotes = 0
72
+ %% write init;
73
+ %% write exec;
74
+ %% write eof;
75
+ unless quotes.zero?
76
+ raise ParseError, "Unclosed quotes"
77
+ end
78
+ results
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+
@@ -4,28 +4,29 @@ module KeywordSearch
4
4
 
5
5
  class Keyword
6
6
 
7
- attr_reader :name, :description
8
-
7
+ attr_reader :name, :description, :handler
9
8
  def initialize(name, description=nil, &handler)
10
9
  @name, @description = name, description
11
10
  @handler = handler
12
11
  end
13
12
 
14
13
  def handle(value)
15
- @handler.call(value)
14
+ handler.call(value)
16
15
  end
17
16
 
18
17
  end
19
18
 
20
- attr_reader :keywords
21
19
  def initialize
22
- @keywords = []
23
20
  @default_keyword = nil
24
21
  yield self if block_given?
25
22
  end
23
+
24
+ def keywords
25
+ @keywords ||= []
26
+ end
26
27
 
27
28
  def keyword(name, description=nil, &block)
28
- @keywords << Keyword.new(name, description, &block)
29
+ keywords << Keyword.new(name, description, &block)
29
30
  end
30
31
 
31
32
  def default_keyword(name)
@@ -35,7 +36,7 @@ module KeywordSearch
35
36
  def handle(key, values)
36
37
  key = @default_keyword if key == :default
37
38
  return false unless key
38
- if k = @keywords.detect{|kw| kw.name == key.to_sym}
39
+ if k = keywords.detect { |kw| kw.name == key.to_sym}
39
40
  k.handle(values)
40
41
  end
41
42
  end
@@ -1,7 +1,11 @@
1
1
  require 'test/unit'
2
+
3
+ require 'rubygems' rescue nil
4
+ require 'test/spec'
5
+
2
6
  require File.dirname(__FILE__) + '/../lib/keyword_search'
3
7
 
4
- class TestKeywordSearch < Test::Unit::TestCase
8
+ context "KeywordSearch" do
5
9
 
6
10
  NAME_AND_AGE = %<bruce williams age:26>
7
11
  NAME_QUOTED_AND_AGE = %<"bruce williams" age:26>
@@ -10,7 +14,7 @@ class TestKeywordSearch < Test::Unit::TestCase
10
14
  DEFAULT_AGE_WITH_SINGLE_QUOTED_AGE = %<26 name:'bruce williams'>
11
15
  NAME_WITH_NESTED_SINGLE_QUOTES = %<"d'arcy d'uberville" age:28>
12
16
 
13
- def test_default_keyword
17
+ specify "default keyword" do
14
18
  result = nil
15
19
  KeywordSearch.search(NAME_AND_AGE) do |with|
16
20
  with.default_keyword :name
@@ -21,7 +25,7 @@ class TestKeywordSearch < Test::Unit::TestCase
21
25
  assert_equal 'bruce williams', result
22
26
  end
23
27
 
24
- def test_unquoted_keyword_term
28
+ specify "unquoted keyword term" do
25
29
  result = nil
26
30
  KeywordSearch.search(NAME_AND_AGE) do |with|
27
31
  with.keyword :age do |values|
@@ -31,7 +35,7 @@ class TestKeywordSearch < Test::Unit::TestCase
31
35
  assert_equal 26, result
32
36
  end
33
37
 
34
- def test_quoted_default_keyword_term
38
+ specify "quoted default keyword term" do
35
39
  result = nil
36
40
  KeywordSearch.search(NAME_QUOTED_AND_AGE) do |with|
37
41
  with.default_keyword :name
@@ -42,7 +46,7 @@ class TestKeywordSearch < Test::Unit::TestCase
42
46
  assert_equal 'bruce williams', result
43
47
  end
44
48
 
45
- def test_quoted_keyword_term
49
+ specify "quoted keyword term" do
46
50
  result = nil
47
51
  KeywordSearch.search(NAME_AND_QUOTED_AGE) do |with|
48
52
  with.keyword :age do |values|
@@ -52,7 +56,7 @@ class TestKeywordSearch < Test::Unit::TestCase
52
56
  assert_equal 26, result
53
57
  end
54
58
 
55
- def test_quoted_keyword_term_with_whitespace
59
+ specify "quoted keyword term with whitespace" do
56
60
  result = nil
57
61
  KeywordSearch.search(DEFAULT_AGE_WITH_QUOTED_AGE) do |with|
58
62
  with.default_keyword :age
@@ -63,9 +67,9 @@ class TestKeywordSearch < Test::Unit::TestCase
63
67
  assert_equal 'bruce williams', result
64
68
  end
65
69
 
66
- def test_single_quoted_keyword_term_with_whitespace
67
- result = nil
68
- KeywordSearch.search(DEFAULT_AGE_WITH_SINGLE_QUOTED_AGE) do |with|
70
+ specify "single quoted keyword term with whitespace" do
71
+ result = nil
72
+ r = KeywordSearch.search(DEFAULT_AGE_WITH_SINGLE_QUOTED_AGE) do |with|
69
73
  with.default_keyword :age
70
74
  with.keyword :name do |values|
71
75
  result = values.first
@@ -74,7 +78,7 @@ class TestKeywordSearch < Test::Unit::TestCase
74
78
  assert_equal 'bruce williams', result
75
79
  end
76
80
 
77
- def test_nested_single_quote_is_accumulated
81
+ specify "nested single quote is accumulated" do
78
82
  result = nil
79
83
  KeywordSearch.search(NAME_WITH_NESTED_SINGLE_QUOTES) do |with|
80
84
  with.default_keyword :name
@@ -85,7 +89,7 @@ class TestKeywordSearch < Test::Unit::TestCase
85
89
  assert_equal %<d'arcy d'uberville>, result
86
90
  end
87
91
 
88
- def test_nested_double_quote_is_accumulated
92
+ specify "nested double quote is accumulated" do
89
93
  result = nil
90
94
  KeywordSearch.search(%<'he was called "jake"'>) do |with|
91
95
  with.default_keyword :text
@@ -96,7 +100,7 @@ class TestKeywordSearch < Test::Unit::TestCase
96
100
  assert_equal %<he was called "jake">, result
97
101
  end
98
102
 
99
- def test_bare_single_quote_in_unquoted_literal_is_accumulated
103
+ specify "bare single quote in unquoted literal is accumulated" do
100
104
  result = nil
101
105
  KeywordSearch.search(%<bruce's age:27>) do |with|
102
106
  with.default_keyword :text
@@ -107,7 +111,7 @@ class TestKeywordSearch < Test::Unit::TestCase
107
111
  assert_equal %<bruce's>, result
108
112
  end
109
113
 
110
- def test_single_quoted_literal_is_accumulated
114
+ specify "single quoted literal is accumulated" do
111
115
  result = nil
112
116
  KeywordSearch.search(%<foo 'bruce williams' age:27>) do |with|
113
117
  with.default_keyword :text
@@ -118,7 +122,7 @@ class TestKeywordSearch < Test::Unit::TestCase
118
122
  assert_equal %<bruce williams>, result
119
123
  end
120
124
 
121
- def test_period_in_literal_is_accumulated
125
+ specify "period in literal is accumulated" do
122
126
  result = nil
123
127
  KeywordSearch.search(%<okay... age:27>) do |with|
124
128
  with.default_keyword :text
@@ -129,7 +133,7 @@ class TestKeywordSearch < Test::Unit::TestCase
129
133
  assert_equal %<okay...>, result
130
134
  end
131
135
 
132
- def test_parse_error_results_in_exception
136
+ specify "parse error results in exception" do
133
137
  assert_raises(KeywordSearch::ParseError) do
134
138
  KeywordSearch.search(%<we_do_not_allow:! or ::>) do |with|
135
139
  with.default_keyword :text
@@ -140,6 +144,38 @@ class TestKeywordSearch < Test::Unit::TestCase
140
144
  end
141
145
  end
142
146
 
147
+ specify "can use apostrophes in unquoted literal" do
148
+ result = nil
149
+ KeywordSearch.search(%<d'correct>) do |with|
150
+ with.default_keyword :text
151
+ with.keyword :text do |values|
152
+ result = values.first
153
+ end
154
+ end
155
+ assert_equal "d'correct", result
156
+ end
157
+
158
+ specify "can use apostrophes in unquoted literal values" do
159
+ result = nil
160
+ KeywordSearch.search(%<text:d'correct>) do |with|
161
+ with.default_keyword :text
162
+ with.keyword :text do |values|
163
+ result = values.first
164
+ end
165
+ end
166
+ assert_equal "d'correct", result
167
+ end
168
+
169
+ specify "cannot use an apostrophe at the beginning on an unquoted literal" do
170
+ assert_raises(KeywordSearch::ParseError) do
171
+ KeywordSearch.search(%<'thisiswrong>) do |with|
172
+ with.default_keyword :text
173
+ with.keyword :text do |values|
174
+ result = values.first
175
+ end
176
+ end
177
+ end
178
+ end
143
179
  end
144
180
 
145
181
 
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0
2
+ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: keyword_search
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.2.0
7
- date: 2007-05-09 00:00:00 -06:00
6
+ version: 1.3.0
7
+ date: 2007-10-09 00:00:00 -05:00
8
8
  summary: Generic support for extracting GMail-style search keywords/values from strings
9
9
  require_paths:
10
10
  - lib
11
11
  email: bruce@codefluency.com
12
12
  homepage: " http://codefluency.rubyforge.org/keyword_search"
13
13
  rubyforge_project: codefluency
14
- description: "== FEATURES/PROBLEMS: The library features a very simple, easy-to-use API. * Define handlers for supported keywords with blocks * Define the default keyword (values not part of a keyword/value pair) Various notes: * Quoted values are supported. * Input is automatically downcased (both keywords and values should be assumed to be in lowercase) Development Roadmap: 1.1:: Expand supported character set for keywords and values (currently supports a-z) 2.0:: Add negation and grouping (will break API backwards compatibility) == SYNOPSIS:"
14
+ description: "== FEATURES/PROBLEMS: The library features a very simple, easy-to-use API. * Define handlers for supported keywords with blocks * Define the default keyword (values not part of a keyword/value pair) Various notes: * Quoted values are supported. * Input is automatically downcased (both keywords and values should be assumed to be in lowercase) Development Roadmap: 2.0:: Add negation and grouping (will break API backwards compatibility) == SYNOPSIS:"
15
15
  autorequire:
16
16
  default_executable:
17
17
  bindir: bin
@@ -34,18 +34,18 @@ files:
34
34
  - README.txt
35
35
  - Rakefile
36
36
  - lib/keyword_search.rb
37
+ - lib/keyword_search.rl
37
38
  - lib/keyword_search/definition.rb
38
- - lib/keyword_search/evaluator.rb
39
- - lib/keyword_search/grammar.rb
40
- - lib/keyword_search/parser.rb
41
- - lib/keyword_search/tokenizer.rb
42
39
  - test/test_keyword_search.rb
43
40
  test_files:
44
41
  - test/test_keyword_search.rb
45
- rdoc_options: []
46
-
47
- extra_rdoc_files: []
48
-
42
+ rdoc_options:
43
+ - --main
44
+ - README.txt
45
+ extra_rdoc_files:
46
+ - History.txt
47
+ - Manifest.txt
48
+ - README.txt
49
49
  executables: []
50
50
 
51
51
  extensions: []
@@ -53,15 +53,6 @@ extensions: []
53
53
  requirements: []
54
54
 
55
55
  dependencies:
56
- - !ruby/object:Gem::Dependency
57
- name: dhaka
58
- version_requirement:
59
- version_requirements: !ruby/object:Gem::Version::Requirement
60
- requirements:
61
- - - "="
62
- - !ruby/object:Gem::Version
63
- version: 2.1.0
64
- version:
65
56
  - !ruby/object:Gem::Dependency
66
57
  name: hoe
67
58
  version_requirement:
@@ -69,5 +60,5 @@ dependencies:
69
60
  requirements:
70
61
  - - ">="
71
62
  - !ruby/object:Gem::Version
72
- version: 1.2.0
63
+ version: 1.3.0
73
64
  version:
@@ -1,35 +0,0 @@
1
- module KeywordSearch
2
-
3
- class Evaluator < Dhaka::Evaluator
4
-
5
- self.grammar = Grammar
6
-
7
- define_evaluation_rules do
8
-
9
- for_multiple_pairs do
10
- child_nodes.inject({}) do |result,child_node|
11
- evaluate(child_node).each do |key,value|
12
- result[key] ||= []
13
- result[key] += value
14
- end
15
- result
16
- end
17
- end
18
-
19
- for_one_pair do
20
- evaluate(child_nodes.first)
21
- end
22
-
23
- for_keyword_and_term do
24
- {child_nodes.first.tokens.first.value => [child_nodes.last.tokens.first.value]}
25
- end
26
-
27
- for_default_keyword_term do
28
- {:default => [child_nodes[0].tokens[0].value]}
29
- end
30
-
31
- end
32
-
33
- end
34
-
35
- end
@@ -1,21 +0,0 @@
1
- module KeywordSearch
2
-
3
- class Grammar < Dhaka::Grammar
4
-
5
- for_symbol(Dhaka::START_SYMBOL_NAME) do
6
- start ['Pairs']
7
- end
8
-
9
- for_symbol 'Pairs' do
10
- one_pair ['Pair']
11
- multiple_pairs ['Pairs', 'Pair']
12
- end
13
-
14
- for_symbol 'Pair' do
15
- keyword_and_term ['s', ':', 's']
16
- default_keyword_term ['s']
17
- end
18
-
19
- end
20
-
21
- end
@@ -1,40 +0,0 @@
1
- class KeywordSearch::Parser < Dhaka::CompiledParser
2
-
3
- self.grammar = KeywordSearch::Grammar
4
-
5
- start_with 0
6
-
7
- at_state(1) {
8
- for_symbols("_End_") { reduce_with "start" }
9
- for_symbols("s") { shift_to 3 }
10
- for_symbols("Pair") { shift_to 2 }
11
- }
12
-
13
- at_state(5) {
14
- for_symbols("_End_", "s") { reduce_with "keyword_and_term" }
15
- }
16
-
17
- at_state(4) {
18
- for_symbols("s") { shift_to 5 }
19
- }
20
-
21
- at_state(2) {
22
- for_symbols("_End_", "s") { reduce_with "multiple_pairs" }
23
- }
24
-
25
- at_state(0) {
26
- for_symbols("Pair") { shift_to 6 }
27
- for_symbols("s") { shift_to 3 }
28
- for_symbols("Pairs") { shift_to 1 }
29
- }
30
-
31
- at_state(6) {
32
- for_symbols("_End_", "s") { reduce_with "one_pair" }
33
- }
34
-
35
- at_state(3) {
36
- for_symbols(":") { shift_to 4 }
37
- for_symbols("_End_", "s") { reduce_with "default_keyword_term" }
38
- }
39
-
40
- end
File without changes