jmohr-blir 0.0.2

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 (3) hide show
  1. data/README +0 -0
  2. data/lib/Regexp/generate.rb +291 -0
  3. metadata +54 -0
data/README ADDED
File without changes
@@ -0,0 +1,291 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Number of times to repeat for Star and Plus repeaters
4
+ TIMES = 2
5
+
6
+ # Set of chars for Dot and negated [^] char groups
7
+ #CHARS = [("a".."z").to_a, ("A".."Z").to_a, ".", ",", ";"].flatten
8
+ CHARS = %w{a b c d e}
9
+
10
+ class OneTimeRepeater
11
+ def initialize(group)
12
+ @group = group
13
+ end
14
+
15
+ def result
16
+ @group.result
17
+ end
18
+ end
19
+
20
+ class StarRepeater
21
+ def initialize(group)
22
+ @group = group
23
+ end
24
+
25
+ def result
26
+ r = []
27
+ group_res = @group.result
28
+ group_res.unshift("")
29
+ TIMES.times do
30
+ r << group_res
31
+ end
32
+ combine(r).uniq
33
+ end
34
+ end
35
+
36
+ class PlusRepeater
37
+ def initialize(group)
38
+ @group = group
39
+ end
40
+
41
+ def result
42
+ group_res = @group.result
43
+ r = [group_res]
44
+ temp = [""].concat(group_res)
45
+ (TIMES - 1).times do
46
+ r << temp
47
+ end
48
+ combine(r).uniq
49
+ end
50
+ end
51
+
52
+ class QuestionMarkRepeater
53
+ def initialize(group)
54
+ @group = group
55
+ end
56
+
57
+ def result
58
+ @group.result.unshift("")
59
+ end
60
+ end
61
+
62
+ class RangeRepeater
63
+ def initialize(group,min,max)
64
+ @group = group
65
+ @min = min
66
+ @max = max
67
+ end
68
+
69
+ def result
70
+ result = @group.result
71
+ r = []
72
+ r << [""] if @min == 0
73
+ @min.times {r << result}
74
+ temp = result.dup.unshift("")
75
+ if @max
76
+ (@max - @min).times do
77
+ r << temp
78
+ end
79
+ end
80
+ combine(r).uniq
81
+ end
82
+ end
83
+
84
+ class SingleChar
85
+ def initialize(c)
86
+ @c = c
87
+ end
88
+ def result
89
+ [@c]
90
+ end
91
+ end
92
+
93
+ class CharGroup
94
+ def initialize(chars)
95
+ @chars = chars
96
+ if chars[0] == "^"
97
+ @negative = true
98
+ @chars = @chars[1..-1]
99
+ else
100
+ @negative = false
101
+ end
102
+
103
+ # Ranges a-b
104
+ # save first and last "-" if present
105
+ first = nil
106
+ last = nil
107
+ first = @chars.shift if @chars.first == "-"
108
+ last = @chars.pop if @chars.last == "-"
109
+ while i = @chars.index("-")
110
+ @chars[i-1..i+1] = (@chars[i-1]..@chars[i+1]).to_a
111
+ end
112
+ # restore them back
113
+ @chars.unshift(first) if first
114
+ @chars.push(last) if last
115
+ end
116
+ def result
117
+ if @negative
118
+ CHARS - @chars
119
+ else
120
+ @chars
121
+ end
122
+ end
123
+ end
124
+
125
+ class Dot
126
+ def result
127
+ CHARS
128
+ end
129
+ end
130
+
131
+ class MultiGroup
132
+ attr_reader :group_num
133
+ def initialize(groups, group_num)
134
+ @groups = groups
135
+ @group_num = group_num
136
+ end
137
+
138
+ # Generates the result of each contained group
139
+ # and adds the filled group of each result to
140
+ # itself
141
+ def result
142
+ strings = @groups.map {|x| x.result}
143
+ result = combine(strings)
144
+ result.each {|x| x.add_filled_group(@group_num, x)}
145
+ result
146
+ end
147
+ end
148
+
149
+ class OrGroup
150
+ def initialize(first_groupset, second_groupset)
151
+ @first = first_groupset
152
+ @second = second_groupset
153
+ end
154
+
155
+ def result
156
+ strings = @first.map {|x| x.result}
157
+ s = combine(strings)
158
+ strings = @second.map {|x| x.result}
159
+ s.concat(combine(strings))
160
+ end
161
+ end
162
+
163
+ class BackReference
164
+ attr_reader :num
165
+ def initialize(num)
166
+ @num = num
167
+ end
168
+
169
+ def result
170
+ ["__#{@num}__"]
171
+ end
172
+ end
173
+
174
+ # Combines arrays, concatenating each string
175
+ # merging the possible groups they have
176
+ # Starts combining the first two arrays, then goes on
177
+ # combining each other array to the result of the
178
+ # previous combination
179
+ def combine(arrays)
180
+ string = arrays.inject do |r, rep|
181
+ temp = []
182
+ r.each {|aa| rep.each {|bb| temp << (aa.concat_and_merge_groups(bb))}}
183
+ temp
184
+ end
185
+ string
186
+ end
187
+
188
+ class String
189
+ attr_accessor :filled_groups
190
+
191
+ def add_filled_group(num, group)
192
+ @filled_groups ||= {}
193
+ @filled_groups[num] = group
194
+ end
195
+
196
+ def concat_and_merge_groups(other)
197
+ temp = self + other
198
+ groups = {}
199
+ groups.merge!(self.filled_groups) if self.filled_groups
200
+ groups.merge!(other.filled_groups) if other.filled_groups
201
+ temp.filled_groups = groups
202
+ temp
203
+ end
204
+
205
+ end
206
+
207
+ class Regexp
208
+ attr_reader :num_groups
209
+ def parse(s, i = 0)
210
+ repeaters = []
211
+ group = nil
212
+ while i < s.length
213
+ char = s[i].chr
214
+ case char
215
+ when '('
216
+ num = @num_groups + 1
217
+ @num_groups += 1
218
+ groups, i = parse(s, i+1)
219
+ group = MultiGroup.new(groups, num)
220
+ when ')'
221
+ return repeaters,i
222
+ when '['
223
+ chars = []
224
+ i += 1
225
+ until s[i].chr == ']'
226
+ chars << s[i].chr
227
+ i += 1
228
+ end
229
+ group = CharGroup.new(chars)
230
+ when '.'
231
+ group = Dot.new
232
+ when '|'
233
+ groups, i = parse(s, i + 1)
234
+ group = OrGroup.new(repeaters, groups)
235
+ return [group], i
236
+ when '\\'
237
+ i += 1
238
+ p s[i..-1]
239
+ m = s[i..-1].match(/^(\d+)/)
240
+ if m
241
+ group = BackReference.new(m[0].to_i)
242
+ i += m[0].size - 1
243
+ end
244
+ else
245
+ group = SingleChar.new(char)
246
+ end
247
+
248
+ repeater = nil
249
+ i += 1
250
+ if i < s.length
251
+ case s[i].chr
252
+ when '*'
253
+ repeater = StarRepeater.new(group)
254
+ when '+'
255
+ repeater = PlusRepeater.new(group)
256
+ when '?'
257
+ repeater = QuestionMarkRepeater.new(group)
258
+ when '{'
259
+ m = s[i..-1].match(/\{(\d+)(,(\d+))?\}/)
260
+ first = m[1].to_i if m[1]
261
+ second = m[3].to_i if m[3]
262
+ repeater = RangeRepeater.new(group, first, second)
263
+ i += m[0].size - 1
264
+ else
265
+ repeater = OneTimeRepeater.new(group)
266
+ i -= 1
267
+ end
268
+ i += 1
269
+ else
270
+ repeater = OneTimeRepeater.new(group)
271
+ end
272
+ repeaters << repeater
273
+ end
274
+ return repeaters, i
275
+ end
276
+
277
+ def generate
278
+ @num_groups = 0
279
+ r = self.inspect[1..-2]
280
+ repeaters, _ = self.parse(r)
281
+ strings = repeaters.map {|x| x.result}
282
+ s = combine(strings)
283
+ # Makes a pass for the backreferences
284
+ s.each do |string|
285
+ string.gsub!(/__(\d+)__/) do |match|
286
+ string.filled_groups[$1.to_i]
287
+ end
288
+ end
289
+ s
290
+ end
291
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jmohr-blir
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Justin Mohr
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-03 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: BLIR is a bunch of random stuff I've collected over the years.
17
+ email: jmohr@bytepulse.net
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README
26
+ - lib/Regexp/generate.rb
27
+ has_rdoc: false
28
+ homepage: http://bytepulse.net
29
+ post_install_message:
30
+ rdoc_options: []
31
+
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: "0"
39
+ version:
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ requirements: []
47
+
48
+ rubyforge_project:
49
+ rubygems_version: 1.2.0
50
+ signing_key:
51
+ specification_version: 2
52
+ summary: BLIR is a bunch of random stuff I've collected over the years.
53
+ test_files: []
54
+