beawesomeinstead-explore 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.
data/explore.gemspec ADDED
@@ -0,0 +1,13 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "explore"
3
+ s.version = "0.1.0"
4
+ s.date = "2008-07-11"
5
+ s.summary = "Simple conditions parser."
6
+ s.email = "beawesomeinstead@yahoo.com"
7
+ s.homepage = "http://github.com/beawesomeinstead/explore/wikis"
8
+ s.description = s.summary
9
+ s.authors = ["beawesomeinstead"]
10
+ s.has_rdoc = false
11
+ s.require_paths = ["libraries"]
12
+ s.files = ["libraries/explore", "libraries/explore/definition.rb", "libraries/explore/search.rl", "libraries/explore/keyword.rb", "libraries/explore/search.rb", "libraries/explore.rb", "specifications/spec_helper.rb", "specifications/integration", "specifications/integration/explore_spec.rb", "rakefile", "readme", "explore.gemspec"]
13
+ end
@@ -0,0 +1,4 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ %w(explore/definition explore/keyword explore/search).map { |x| require x }
@@ -0,0 +1,28 @@
1
+ module Explore #:nodoc:
2
+ class Definition #:nodoc:
3
+ def initialize
4
+ @default_keyword = nil
5
+ yield self if block_given?
6
+ end
7
+
8
+ def keywords
9
+ @keywords ||= []
10
+ end
11
+
12
+ def keyword(name, description = nil, &block)
13
+ keywords << Keyword.new(name, description, &block)
14
+ end
15
+
16
+ def default_keyword(name)
17
+ @default_keyword = name
18
+ end
19
+
20
+ def handle(key, values)
21
+ key = @default_keyword if key == :default
22
+ return false unless key
23
+ if k = keywords.detect { |kw| kw.name == key.to_sym }
24
+ k.handle(values)
25
+ end
26
+ end
27
+ end # class Definition
28
+ end # module Keyword
@@ -0,0 +1,14 @@
1
+ module Explore #:nodoc:
2
+ class Keyword #:nodoc:
3
+ attr_reader :name, :description, :handler
4
+
5
+ def initialize(name, description = nil, &handler)
6
+ @name, @description = name, description
7
+ @handler = handler
8
+ end
9
+
10
+ def handle(value)
11
+ handler.call(value)
12
+ end
13
+ end # class Keyword
14
+ end # module Keyword
@@ -0,0 +1,281 @@
1
+ module Explore
2
+
3
+ class ParseError < ::SyntaxError; end
4
+
5
+ class << self
6
+
7
+ # line 54 "lib/keyword_search.rl"
8
+
9
+
10
+ def search(input_string, definition=nil, &block)
11
+ definition ||= Definition.new(&block)
12
+ results = parse(input_string)
13
+ results.each do |key, terms|
14
+ definition.handle(key, terms)
15
+ end
16
+ results
17
+ end
18
+
19
+ #######
20
+ private
21
+ #######
22
+
23
+ def parse(input) #:nodoc:
24
+ data = input + ' '
25
+
26
+ # line 30 "lib/keyword_search.rb"
27
+ class << self
28
+ attr_accessor :_parser_actions
29
+ private :_parser_actions, :_parser_actions=
30
+ end
31
+ self._parser_actions = [
32
+ 0, 1, 3, 1, 5, 1, 6, 2,
33
+ 0, 2, 2, 1, 0, 3, 0, 2,
34
+ 4, 3, 1, 0, 4
35
+ ]
36
+
37
+ class << self
38
+ attr_accessor :_parser_key_offsets
39
+ private :_parser_key_offsets, :_parser_key_offsets=
40
+ end
41
+ self._parser_key_offsets = [
42
+ 0, 0, 6, 10, 15, 19, 20, 21,
43
+ 22, 23
44
+ ]
45
+
46
+ class << self
47
+ attr_accessor :_parser_trans_keys
48
+ private :_parser_trans_keys, :_parser_trans_keys=
49
+ end
50
+ self._parser_trans_keys = [
51
+ 0, 32, 34, 39, 40, 58, 32, 34,
52
+ 41, 58, 32, 34, 39, 40, 58, 32,
53
+ 34, 41, 58, 34, 32, 39, 41, 32,
54
+ 34, 41, 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, 6, 4, 5, 4, 1, 1, 1,
63
+ 1, 4
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, 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, 7, 12, 18, 23, 25, 27,
81
+ 29, 31
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
+ 9, 0, 5, 7, 8, 0, 2, 1,
90
+ 0, 0, 3, 2, 0, 5, 7, 8,
91
+ 0, 4, 1, 0, 0, 0, 4, 6,
92
+ 5, 1, 0, 6, 7, 6, 8, 1,
93
+ 0, 0, 3, 2, 0
94
+ ]
95
+
96
+ class << self
97
+ attr_accessor :_parser_trans_actions_wi
98
+ private :_parser_trans_actions_wi, :_parser_trans_actions_wi=
99
+ end
100
+ self._parser_trans_actions_wi = [
101
+ 7, 5, 13, 13, 13, 5, 7, 1,
102
+ 0, 0, 0, 0, 0, 17, 17, 17,
103
+ 0, 10, 1, 0, 0, 0, 0, 3,
104
+ 0, 1, 0, 3, 0, 3, 0, 1,
105
+ 0, 0, 0, 0, 0
106
+ ]
107
+
108
+ class << self
109
+ attr_accessor :parser_start
110
+ end
111
+ self.parser_start = 1;
112
+ class << self
113
+ attr_accessor :parser_first_final
114
+ end
115
+ self.parser_first_final = 9;
116
+ class << self
117
+ attr_accessor :parser_error
118
+ end
119
+ self.parser_error = 0;
120
+
121
+ class << self
122
+ attr_accessor :parser_en_main
123
+ end
124
+ self.parser_en_main = 1;
125
+
126
+ # line 72 "lib/keyword_search.rl"
127
+ p = 0
128
+ pe = data.length
129
+ key = nil
130
+ tokstart = nil
131
+ results = {}
132
+ quotes = 0
133
+
134
+ # line 138 "lib/keyword_search.rb"
135
+ begin
136
+ cs = parser_start
137
+ end
138
+ # line 79 "lib/keyword_search.rl"
139
+
140
+ # line 144 "lib/keyword_search.rb"
141
+ begin
142
+ _klen, _trans, _keys, _acts, _nacts = nil
143
+ if p != pe
144
+ if cs != 0
145
+ while true
146
+ _break_resume = false
147
+ begin
148
+ _break_again = false
149
+ _keys = _parser_key_offsets[cs]
150
+ _trans = _parser_index_offsets[cs]
151
+ _klen = _parser_single_lengths[cs]
152
+ _break_match = false
153
+
154
+ begin
155
+ if _klen > 0
156
+ _lower = _keys
157
+ _upper = _keys + _klen - 1
158
+
159
+ loop do
160
+ break if _upper < _lower
161
+ _mid = _lower + ( (_upper - _lower) >> 1 )
162
+
163
+ if data[p] < _parser_trans_keys[_mid]
164
+ _upper = _mid - 1
165
+ elsif data[p] > _parser_trans_keys[_mid]
166
+ _lower = _mid + 1
167
+ else
168
+ _trans += (_mid - _keys)
169
+ _break_match = true
170
+ break
171
+ end
172
+ end # loop
173
+ break if _break_match
174
+ _keys += _klen
175
+ _trans += _klen
176
+ end
177
+ _klen = _parser_range_lengths[cs]
178
+ if _klen > 0
179
+ _lower = _keys
180
+ _upper = _keys + (_klen << 1) - 2
181
+ loop do
182
+ break if _upper < _lower
183
+ _mid = _lower + (((_upper-_lower) >> 1) & ~1)
184
+ if data[p] < _parser_trans_keys[_mid]
185
+ _upper = _mid - 2
186
+ elsif data[p] > _parser_trans_keys[_mid+1]
187
+ _lower = _mid + 2
188
+ else
189
+ _trans += ((_mid - _keys) >> 1)
190
+ _break_match = true
191
+ break
192
+ end
193
+ end # loop
194
+ break if _break_match
195
+ _trans += _klen
196
+ end
197
+ end while false
198
+ cs = _parser_trans_targs_wi[_trans]
199
+ break if _parser_trans_actions_wi[_trans] == 0
200
+ _acts = _parser_trans_actions_wi[_trans]
201
+ _nacts = _parser_actions[_acts]
202
+ _acts += 1
203
+ while _nacts > 0
204
+ _nacts -= 1
205
+ _acts += 1
206
+ case _parser_actions[_acts - 1]
207
+ when 0:
208
+ # line 13 "lib/keyword_search.rl"
209
+ begin
210
+
211
+ tokstart = p;
212
+ end
213
+ # line 13 "lib/keyword_search.rl"
214
+ when 1:
215
+ # line 17 "lib/keyword_search.rl"
216
+ begin
217
+
218
+ key = data[tokstart...p-1]
219
+ results[key] ||= []
220
+ end
221
+ # line 17 "lib/keyword_search.rl"
222
+ when 2:
223
+ # line 22 "lib/keyword_search.rl"
224
+ begin
225
+
226
+ key = nil
227
+ end
228
+ # line 22 "lib/keyword_search.rl"
229
+ when 3:
230
+ # line 26 "lib/keyword_search.rl"
231
+ begin
232
+
233
+ value = data[tokstart..p-1]
234
+ if ["("].include?(value[0,1])
235
+ value = parse(value[1..-2])[:default]
236
+ elsif ["'", '"'].include?(value[0,1])
237
+ value = value[1..-2]
238
+ end
239
+ (results[key || :default] ||= []) << value
240
+ end
241
+ # line 26 "lib/keyword_search.rl"
242
+ when 4:
243
+ # line 36 "lib/keyword_search.rl"
244
+ begin
245
+ quotes += 1 end
246
+ # line 36 "lib/keyword_search.rl"
247
+ when 5:
248
+ # line 38 "lib/keyword_search.rl"
249
+ begin
250
+ quotes -= 1 end
251
+ # line 38 "lib/keyword_search.rl"
252
+ when 6:
253
+ # line 52 "lib/keyword_search.rl"
254
+ begin
255
+ raise ParseError, "At offset #{p}, near: '#{data[p,10]}'" end
256
+ # line 52 "lib/keyword_search.rl"
257
+ # line 261 "lib/keyword_search.rb"
258
+ end # action switch
259
+ end
260
+ end while false
261
+ break if _break_resume
262
+ break if cs == 0
263
+ p += 1
264
+ break if p == pe
265
+ end
266
+ end
267
+ end
268
+ end
269
+ # line 80 "lib/keyword_search.rl"
270
+
271
+ # line 275 "lib/keyword_search.rb"
272
+ # line 81 "lib/keyword_search.rl"
273
+ unless quotes.zero?
274
+ raise ParseError, "Unclosed quotes"
275
+ end
276
+ results
277
+ end
278
+
279
+ end
280
+
281
+ end
@@ -0,0 +1,80 @@
1
+ module Explore
2
+ class ParseError < ::SyntaxError; end
3
+
4
+ class << self
5
+ %%{
6
+ machine parser;
7
+
8
+ action start {
9
+ tokstart = p;
10
+ }
11
+
12
+ action key {
13
+ key = data[tokstart...p-1]
14
+ results[key] ||= []
15
+ }
16
+
17
+ action default {
18
+ key = nil
19
+ }
20
+
21
+ action value {
22
+ value = data[tokstart..p-1]
23
+ if ["("].include?(value[0,1])
24
+ value = parse(value[1..-2])[:default]
25
+ elsif ["'", '"'].include?(value[0,1])
26
+ value = value[1..-2]
27
+ end
28
+ (results[key || :default] ||= []) << value
29
+ }
30
+
31
+ action quote { quotes += 1 }
32
+
33
+ action unquote { quotes -= 1 }
34
+
35
+ bareword = [^ '"(:] [^ "):]*; # allow apostrophes
36
+ grouped = '(' @ quote any* :>> ')' @ unquote;
37
+ dquoted = '"' @ quote any* :>> '"' @ unquote;
38
+ squoted = '\'' @ quote any* :>> '\'' @ unquote;
39
+
40
+ value = ( grouped | 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
+ def search(input_string, definition=nil, &block)
50
+ definition ||= Definition.new(&block)
51
+ results = parse(input_string)
52
+ results.each do |key, terms|
53
+ definition.handle(key, terms)
54
+ end
55
+ results
56
+ end
57
+
58
+ #######
59
+ private
60
+ #######
61
+
62
+ def parse(input) #:nodoc:
63
+ data = input + ' '
64
+ %% write data;
65
+ p = 0
66
+ pe = data.length
67
+ key = nil
68
+ tokstart = nil
69
+ results = {}
70
+ quotes = 0
71
+ %% write init;
72
+ %% write exec;
73
+ %% write eof;
74
+ unless quotes.zero?
75
+ raise ParseError, "Unclosed quotes"
76
+ end
77
+ results
78
+ end
79
+ end
80
+ end
data/rakefile ADDED
@@ -0,0 +1,6 @@
1
+ %w(rubygems rake/gempackagetask spec/rake/spectask).each { |x| require x }
2
+
3
+ Spec::Rake::SpecTask.new("specs") do |t|
4
+ t.spec_opts << '--format' << 'specdoc' << '--colour'
5
+ t.spec_files = Dir.glob("specifications/**/*_spec.rb")
6
+ end
data/readme ADDED
File without changes
@@ -0,0 +1,204 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
+
3
+ describe Explore do
4
+ NAME_AND_AGE = %<bruce williams age:26>
5
+ NAME_QUOTED_AND_AGE = %<"bruce williams" age:26>
6
+ NAME_AND_QUOTED_AGE = %<bruce williams age:"26">
7
+ DEFAULT_AGE_WITH_QUOTED_AGE = %<26 name:"bruce williams">
8
+ DEFAULT_AGE_WITH_SINGLE_QUOTED_AGE = %<26 name:'bruce williams'>
9
+ NAME_WITH_NESTED_SINGLE_QUOTES = %<"d'arcy d'uberville" age:28>
10
+ NAME_AND_GROUPED_AGE = %<coda hale age:(27)>
11
+ NAME_AND_GROUPED_QUOTED_AGE = %<coda hale age:("27")>
12
+ NAME_AND_GROUPED_QUOTED_AGES = %<coda hale age:("27" 34 '48')>
13
+ GROUPED_NAMES_AND_AGE = %<(coda bruce 'hale' "williams") age:20>
14
+
15
+ before(:each) do
16
+ @result = nil
17
+ end
18
+
19
+ it "should parse grouped default keywords properly" do
20
+ Explore.search(NAME_AND_AGE) do |with|
21
+ with.default_keyword :name
22
+ with.keyword :name do |values|
23
+ @result = values.join(' ')
24
+ end
25
+ end
26
+ @result.should == "bruce williams"
27
+ end
28
+
29
+ it "should parse grouped default keywords properly" do
30
+ Explore.search(GROUPED_NAMES_AND_AGE) do |with|
31
+ with.default_keyword :name
32
+ with.keyword :name do |values|
33
+ @result = values.first
34
+ end
35
+ end
36
+ @result.should == ['coda', 'bruce', 'hale', 'williams']
37
+ end
38
+
39
+ it "should parse unquoted keyword term properly" do
40
+ Explore.search(NAME_AND_AGE) do |with|
41
+ with.keyword :age do |values|
42
+ @result = Integer(values.first)
43
+ end
44
+ end
45
+ @result.should == 26
46
+ end
47
+
48
+ it "should parse unquoted grouped keyword term properly" do
49
+ Explore.search(NAME_AND_GROUPED_AGE) do |with|
50
+ with.keyword :age do |values|
51
+ @result = Integer(values.first.first)
52
+ end
53
+ end
54
+ @result.should == 27
55
+ end
56
+
57
+ it "should parse quoted grouped keyword term properly" do
58
+ Explore.search(NAME_AND_GROUPED_QUOTED_AGE) do |with|
59
+ with.keyword :age do |values|
60
+ @result = Integer(values.first.first)
61
+ end
62
+ end
63
+ @result.should == 27
64
+ end
65
+
66
+ it "should parse mixed grouped keyword terms properly" do
67
+ Explore.search(NAME_AND_GROUPED_QUOTED_AGES) do |with|
68
+ with.keyword :age do |values|
69
+ @result = values.first.map { |v| v.to_i }
70
+ end
71
+ end
72
+ @result.should == [27, 34, 48]
73
+ end
74
+
75
+ it "should parse quoted default keyword term properly" do
76
+ Explore.search(NAME_QUOTED_AND_AGE) do |with|
77
+ with.default_keyword :name
78
+ with.keyword :name do |values|
79
+ @result = values.join(' ')
80
+ end
81
+ end
82
+ @result.should == "bruce williams"
83
+ end
84
+
85
+ it "should parse quoted keyword term properly" do
86
+ Explore.search(NAME_AND_QUOTED_AGE) do |with|
87
+ with.keyword :age do |values|
88
+ @result = Integer(values.first)
89
+ end
90
+ end
91
+ @result.should == 26
92
+ end
93
+
94
+ it "should parse quoted keyword term with whitespace properly" do
95
+ Explore.search(DEFAULT_AGE_WITH_QUOTED_AGE) do |with|
96
+ with.default_keyword :age
97
+ with.keyword :name do |values|
98
+ @result = values.first
99
+ end
100
+ end
101
+ @result.should == "bruce williams"
102
+ end
103
+
104
+ it "should parse single quoted keyword term with whitespace" do
105
+ Explore.search(DEFAULT_AGE_WITH_SINGLE_QUOTED_AGE) do |with|
106
+ with.default_keyword :age
107
+ with.keyword :name do |values|
108
+ @result = values.first
109
+ end
110
+ end
111
+ @result.should == "bruce williams"
112
+ end
113
+
114
+ it "should parse nested single quote is accumulated" do
115
+ Explore.search(NAME_WITH_NESTED_SINGLE_QUOTES) do |with|
116
+ with.default_keyword :name
117
+ with.keyword :name do |values|
118
+ @result = values.first
119
+ end
120
+ end
121
+ @result.should == %<d'arcy d'uberville>
122
+ end
123
+
124
+ it "should parse nested single quote is accumulated" do
125
+ Explore.search(%<'he was called "jake"'>) do |with|
126
+ with.default_keyword :text
127
+ with.keyword :text do |values|
128
+ @result = values.first
129
+ end
130
+ end
131
+ @result.should == %<he was called "jake">
132
+ end
133
+
134
+ it "should parse bare single quote in unquoted literal is accumulated" do
135
+ Explore.search(%<bruce's age:27>) do |with|
136
+ with.default_keyword :text
137
+ with.keyword :text do |values|
138
+ @result = values.first
139
+ end
140
+ end
141
+ @result.should == %<bruce's>
142
+ end
143
+
144
+ it "should parse single quoted literal is accumulated" do
145
+ Explore.search(%<foo 'bruce williams' age:27>) do |with|
146
+ with.default_keyword :text
147
+ with.keyword :text do |values|
148
+ @result = values.last
149
+ end
150
+ end
151
+ @result.should == %<bruce williams>
152
+ end
153
+
154
+ it "should parse period in literal is accumulated" do
155
+ Explore.search(%<okay... age:27>) do |with|
156
+ with.default_keyword :text
157
+ with.keyword :text do |values|
158
+ @result = values.first
159
+ end
160
+ end
161
+ @result.should == %<okay...>
162
+ end
163
+
164
+ it "should parse data with apostrophes in unquoted literal" do
165
+ Explore.search(%<d'correct>) do |with|
166
+ with.default_keyword :text
167
+ with.keyword :text do |values|
168
+ @result = values.first
169
+ end
170
+ end
171
+ @result.should == "d'correct"
172
+ end
173
+
174
+ it "should parse data with apostrophes in unquoted literal values" do
175
+ Explore.search(%<text:d'correct>) do |with|
176
+ with.default_keyword :text
177
+ with.keyword :text do |values|
178
+ @result = values.first
179
+ end
180
+ end
181
+ @result.should == "d'correct"
182
+ end
183
+
184
+ it "should parse case-sensitive keywords" do
185
+ Explore.search(%<Text:justtesting>) do |with|
186
+ with.keyword :text do |values|
187
+ @result = :small
188
+ end
189
+ with.keyword :Text do |values|
190
+ @result = :big
191
+ end
192
+ end
193
+ @result.should == :big
194
+ end
195
+
196
+ it "should parse case-sensitive values" do
197
+ Explore.search(%<text:Big>) do |with|
198
+ with.keyword :text do |values|
199
+ @result = values.first
200
+ end
201
+ end
202
+ @result.should == "Big"
203
+ end
204
+ end
@@ -0,0 +1,2 @@
1
+ %w(rubygems spec).each { |x| require x }
2
+ require File.join(File.dirname(__FILE__), "..", "libraries", "explore")
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: beawesomeinstead-explore
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - beawesomeinstead
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-07-11 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Simple conditions parser.
17
+ email: beawesomeinstead@yahoo.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - libraries/explore
26
+ - libraries/explore/definition.rb
27
+ - libraries/explore/search.rl
28
+ - libraries/explore/keyword.rb
29
+ - libraries/explore/search.rb
30
+ - libraries/explore.rb
31
+ - specifications/spec_helper.rb
32
+ - specifications/integration
33
+ - specifications/integration/explore_spec.rb
34
+ - rakefile
35
+ - readme
36
+ - explore.gemspec
37
+ has_rdoc: false
38
+ homepage: http://github.com/beawesomeinstead/explore/wikis
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - libraries
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.2.0
60
+ signing_key:
61
+ specification_version: 2
62
+ summary: Simple conditions parser.
63
+ test_files: []
64
+