jmohr-blir 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
+