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.
- data/README +0 -0
- data/lib/Regexp/generate.rb +291 -0
- 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
|
+
|