patm 1.0.0 → 2.0.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.
- checksums.yaml +4 -4
- data/README.md +24 -2
- data/lib/patm.rb +178 -43
- data/patm.gemspec +1 -1
- data/spec/patm_spec.rb +55 -6
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2a4036ae8e3a9b302bd189406ebb284f3efcc54
|
4
|
+
data.tar.gz: 10b6f6831b67755280f6e6ba5faf145a3ddf8910
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50f3198622f079bc716eb064a4e8cfbdad3f63bfd6f7c9f76c750fefd35e86301513c79542b777c5c4d7594165632acdcbb00e213661a544cc8e61fbf439ef72
|
7
|
+
data.tar.gz: 093665d2fcb727165d6fda3cd9c214805be766f70b15cf565ec7670aa585a21c280514687298dd2aa64558248633fbee7f815f836a9e6207c00ced7ece6e2b7e
|
data/README.md
CHANGED
@@ -102,21 +102,36 @@ end
|
|
102
102
|
|
103
103
|
## Patterns
|
104
104
|
|
105
|
-
###
|
105
|
+
### Value
|
106
106
|
|
107
|
-
|
107
|
+
Value patterns such as `1, :x, String, ...` matches if `pattern === target_value` is true.
|
108
108
|
|
109
109
|
### Array
|
110
110
|
|
111
|
+
`[1, 2, _any]` matches `[1, 2, 3]`, `[1, 2, :x]`, etc.
|
112
|
+
|
111
113
|
`[1, 2, _xs]` matches `[1, 2]`, `[1, 2, 3]`, `[1, 2, 3, 4]`, etc.
|
114
|
+
|
112
115
|
`[1, _xs, 2]` matches `[1, 2]`, `[1, 10, 2]`, etc.
|
113
116
|
|
114
117
|
Note: More than one `_xs` in same array is invalid.
|
115
118
|
|
119
|
+
### Hash
|
120
|
+
|
121
|
+
`{a: 1}` matches `{a: 1}`, `{a: 1, b: 2}`, etc.
|
122
|
+
|
123
|
+
`{a: 1, Patm.exact => true}` matches only `{a: 1}`.
|
124
|
+
|
125
|
+
`{a: 1, b: Patm.opt(2)}` matches `{a: 1}`, `{a: 1, b: 2}`.
|
126
|
+
|
116
127
|
### Capture
|
117
128
|
|
118
129
|
`_1`, `_2`, etc matches any value, and capture the value as correspond match group.
|
119
130
|
|
131
|
+
`Pattern#[capture_name]` also used for capture.`Patm._any[:foo]` capture any value as `foo`.
|
132
|
+
|
133
|
+
Captured values are accessible through `Match#_1, _2, ...` and `Match#[capture_name]`
|
134
|
+
|
120
135
|
### Compose
|
121
136
|
|
122
137
|
`_1&[_any, _any]` matches any two element array, and capture the array as _1.
|
@@ -125,6 +140,13 @@ Note: More than one `_xs` in same array is invalid.
|
|
125
140
|
|
126
141
|
## Changes
|
127
142
|
|
143
|
+
### 2.0.0(Unreleased)
|
144
|
+
|
145
|
+
- Named capture
|
146
|
+
- Patm::GROUPS is obsolete. Use `pattern[number_or_name]` or `Patm._1, _2, ...` instead.
|
147
|
+
- More optimize for compiled pattern.
|
148
|
+
- Hash patterns
|
149
|
+
|
128
150
|
### 1.0.0
|
129
151
|
|
130
152
|
- DSL
|
data/lib/patm.rb
CHANGED
@@ -5,7 +5,7 @@ module Patm
|
|
5
5
|
case plain
|
6
6
|
when Pattern
|
7
7
|
plain
|
8
|
-
when Array
|
8
|
+
when ::Array
|
9
9
|
array = plain.map{|a| build_from(a)}
|
10
10
|
rest_index = array.index(&:rest?)
|
11
11
|
if rest_index
|
@@ -16,13 +16,47 @@ module Patm
|
|
16
16
|
else
|
17
17
|
Arr.new(array)
|
18
18
|
end
|
19
|
+
when ::Hash
|
20
|
+
Hash.new(
|
21
|
+
plain.each_with_object({}) do|(k, v), h|
|
22
|
+
h[k] = build_from(v) if k != Patm.exact
|
23
|
+
end,
|
24
|
+
plain[Patm.exact]
|
25
|
+
)
|
19
26
|
else
|
20
27
|
Obj.new(plain)
|
21
28
|
end
|
22
29
|
end
|
23
30
|
|
31
|
+
module Util
|
32
|
+
def self.compile_value(value, free_index)
|
33
|
+
if value.is_a?(Numeric) || value.is_a?(String) || value.is_a?(Symbol)
|
34
|
+
[
|
35
|
+
value.inspect,
|
36
|
+
[],
|
37
|
+
free_index,
|
38
|
+
]
|
39
|
+
else
|
40
|
+
[
|
41
|
+
"_ctx[#{free_index}]",
|
42
|
+
[value],
|
43
|
+
free_index + 1,
|
44
|
+
]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Use in Hash pattern.
|
50
|
+
def opt
|
51
|
+
Opt.new(self)
|
52
|
+
end
|
53
|
+
|
24
54
|
def execute(match, obj); true; end
|
25
55
|
|
56
|
+
def opt?
|
57
|
+
false
|
58
|
+
end
|
59
|
+
|
26
60
|
def rest?
|
27
61
|
false
|
28
62
|
end
|
@@ -31,14 +65,18 @@ module Patm
|
|
31
65
|
And.new([self, rhs])
|
32
66
|
end
|
33
67
|
|
68
|
+
def [](name)
|
69
|
+
self & Named.new(name)
|
70
|
+
end
|
71
|
+
|
34
72
|
def compile
|
35
73
|
src, context, _ = self.compile_internal(0)
|
36
74
|
|
37
|
-
Compiled.new(self.inspect, src, context)
|
75
|
+
Compiled.new(self.inspect, src || "true", context)
|
38
76
|
end
|
39
77
|
|
40
|
-
# free_index:Numeric -> [src, context, free_index]
|
41
|
-
# variables: _ctx, _match,
|
78
|
+
# free_index:Numeric -> target_name:String -> [src:String|nil, context:Array, free_index:Numeric]
|
79
|
+
# variables: _ctx, _match, (target_name)
|
42
80
|
def compile_internal(free_index, target_name = "_obj")
|
43
81
|
[
|
44
82
|
"_ctx[#{free_index}].execute(_match, #{target_name})",
|
@@ -69,6 +107,82 @@ module Patm
|
|
69
107
|
def inspect; "<compiled>#{@desc}"; end
|
70
108
|
end
|
71
109
|
|
110
|
+
class Hash < self
|
111
|
+
def initialize(hash, exact)
|
112
|
+
@pat = hash
|
113
|
+
@exact = exact
|
114
|
+
@non_opt_count = @pat.values.count{|v| !v.opt? }
|
115
|
+
end
|
116
|
+
def execute(match, obj)
|
117
|
+
return false unless obj.is_a?(::Hash)
|
118
|
+
obj.size >= @non_opt_count &&
|
119
|
+
(!@exact || obj.keys.all?{|k| @pat.has_key?(k) }) &&
|
120
|
+
@pat.all? {|k, pat|
|
121
|
+
if obj.has_key?(k)
|
122
|
+
pat.execute(match, obj[k])
|
123
|
+
else
|
124
|
+
pat.opt?
|
125
|
+
end
|
126
|
+
}
|
127
|
+
end
|
128
|
+
def inspect; @pat.inspect; end
|
129
|
+
def compile_internal(free_index, target_name = "_obj")
|
130
|
+
i = free_index
|
131
|
+
ctxs = []
|
132
|
+
src = []
|
133
|
+
|
134
|
+
ctxs << [@pat]
|
135
|
+
i += 1
|
136
|
+
|
137
|
+
pat = "_ctx[#{free_index}]"
|
138
|
+
src << "#{target_name}.is_a?(::Hash)"
|
139
|
+
src << "#{target_name}.size >= #{@non_opt_count}"
|
140
|
+
if @exact
|
141
|
+
src << "#{target_name}.keys.all?{|k| #{pat}.has_key?(k) }"
|
142
|
+
end
|
143
|
+
tname = "#{target_name}_elm"
|
144
|
+
@pat.each do|k, v|
|
145
|
+
key_src, c, i = Util.compile_value(k, i)
|
146
|
+
ctxs << c
|
147
|
+
s, c, i = v.compile_internal(i, tname)
|
148
|
+
body =
|
149
|
+
if s
|
150
|
+
"(#{tname} = #{target_name}[#{key_src}]; #{s})"
|
151
|
+
else
|
152
|
+
"true"
|
153
|
+
end
|
154
|
+
src <<
|
155
|
+
if v.opt?
|
156
|
+
"(!#{target_name}.has_key?(#{key_src}) || #{body})"
|
157
|
+
else
|
158
|
+
"(#{target_name}.has_key?(#{key_src}) && #{body})"
|
159
|
+
end
|
160
|
+
ctxs << c
|
161
|
+
end
|
162
|
+
[
|
163
|
+
src.join(" &&\n"),
|
164
|
+
ctxs.flatten(1),
|
165
|
+
i,
|
166
|
+
]
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class Opt < self
|
171
|
+
def initialize(pat)
|
172
|
+
@pat = pat
|
173
|
+
end
|
174
|
+
def opt?
|
175
|
+
true
|
176
|
+
end
|
177
|
+
def execute(match, obj)
|
178
|
+
@pat.execute(match, obj)
|
179
|
+
end
|
180
|
+
def inspect; "?#{@pat.inspect}"; end
|
181
|
+
def compile_internal(free_index, target_name = "_obj")
|
182
|
+
@pat.compile_internal(free_index, target_name)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
72
186
|
class Arr < self
|
73
187
|
def initialize(head, rest = nil, tail = [])
|
74
188
|
@head = head
|
@@ -114,26 +228,28 @@ module Patm
|
|
114
228
|
elm_target_name = "#{target_name}_elm"
|
115
229
|
@head.each_with_index do|h, hi|
|
116
230
|
s, c, i = h.compile_internal(i, elm_target_name)
|
117
|
-
srcs << "(#{elm_target_name} = #{target_name}[#{hi}]; #{s})"
|
231
|
+
srcs << "(#{elm_target_name} = #{target_name}[#{hi}]; #{s})" if s
|
118
232
|
ctxs << c
|
119
233
|
end
|
120
234
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
235
|
+
unless @tail.empty?
|
236
|
+
srcs << "(#{target_name}_t = #{target_name}[(-#{@tail.size})..-1]; true)"
|
237
|
+
@tail.each_with_index do|t, ti|
|
238
|
+
s, c, i = t.compile_internal(i, elm_target_name)
|
239
|
+
srcs << "(#{elm_target_name} = #{target_name}_t[#{ti}]; #{s})" if s
|
240
|
+
ctxs << c
|
241
|
+
end
|
126
242
|
end
|
127
243
|
|
128
244
|
if @rest
|
129
245
|
tname = "#{target_name}_r"
|
130
246
|
s, c, i = @rest.compile_internal(i, tname)
|
131
|
-
srcs << "(#{tname} = #{target_name}[#{@head.size}..-(#{@tail.size+1})];#{s})"
|
247
|
+
srcs << "(#{tname} = #{target_name}[#{@head.size}..-(#{@tail.size+1})];#{s})" if s
|
132
248
|
ctxs << c
|
133
249
|
end
|
134
250
|
|
135
251
|
[
|
136
|
-
srcs.map{|s| "(#{s})"}.join(" &&\n"),
|
252
|
+
srcs.compact.map{|s| "(#{s})"}.join(" &&\n"),
|
137
253
|
ctxs.flatten(1),
|
138
254
|
i
|
139
255
|
]
|
@@ -150,7 +266,7 @@ module Patm
|
|
150
266
|
def inspect; "..."; end
|
151
267
|
def compile_internal(free_index, target_name = "_obj")
|
152
268
|
[
|
153
|
-
|
269
|
+
nil,
|
154
270
|
[],
|
155
271
|
free_index
|
156
272
|
]
|
@@ -171,10 +287,11 @@ module Patm
|
|
171
287
|
end
|
172
288
|
|
173
289
|
def compile_internal(free_index, target_name = "_obj")
|
290
|
+
val_src, c, i = Util.compile_value(@obj, free_index)
|
174
291
|
[
|
175
|
-
"
|
176
|
-
|
177
|
-
|
292
|
+
"#{val_src} === #{target_name}",
|
293
|
+
c,
|
294
|
+
i
|
178
295
|
]
|
179
296
|
end
|
180
297
|
end
|
@@ -184,26 +301,28 @@ module Patm
|
|
184
301
|
def inspect; 'ANY'; end
|
185
302
|
def compile_internal(free_index, target_name = "_obj")
|
186
303
|
[
|
187
|
-
|
304
|
+
nil,
|
188
305
|
[],
|
189
306
|
free_index
|
190
307
|
]
|
191
308
|
end
|
192
309
|
end
|
193
310
|
|
194
|
-
class
|
195
|
-
def initialize(
|
196
|
-
|
311
|
+
class Named < self
|
312
|
+
def initialize(name)
|
313
|
+
raise ::ArgumentError unless name.is_a?(Symbol) || name.is_a?(Numeric)
|
314
|
+
@name = name
|
197
315
|
end
|
198
|
-
attr_reader :
|
199
|
-
|
200
|
-
|
316
|
+
attr_reader :name
|
317
|
+
alias index name # compatibility
|
318
|
+
def execute(match, obj)
|
319
|
+
match[@name] = obj
|
201
320
|
true
|
202
321
|
end
|
203
|
-
def inspect; "
|
322
|
+
def inspect; "NAMED(#{@name})"; end
|
204
323
|
def compile_internal(free_index, target_name = "_obj")
|
205
324
|
[
|
206
|
-
"_match[#{@
|
325
|
+
"_match[#{@name.inspect}] = #{target_name}; true",
|
207
326
|
[],
|
208
327
|
free_index
|
209
328
|
]
|
@@ -226,11 +345,17 @@ module Patm
|
|
226
345
|
end
|
227
346
|
|
228
347
|
[
|
229
|
-
srcs.map{|s| "(#{s})" }.join(" #{@op_str}\n"),
|
348
|
+
srcs.compact.map{|s| "(#{s})" }.join(" #{@op_str}\n"),
|
230
349
|
ctxs.flatten(1),
|
231
350
|
i
|
232
351
|
]
|
233
352
|
end
|
353
|
+
def rest?
|
354
|
+
@pats.any?(&:rest?)
|
355
|
+
end
|
356
|
+
def opt?
|
357
|
+
@pats.any?(&:opt?)
|
358
|
+
end
|
234
359
|
end
|
235
360
|
|
236
361
|
class Or < LogicalOp
|
@@ -242,9 +367,6 @@ module Patm
|
|
242
367
|
pat.execute(mmatch, obj)
|
243
368
|
end
|
244
369
|
end
|
245
|
-
def rest?
|
246
|
-
@pats.any?(&:rest?)
|
247
|
-
end
|
248
370
|
def inspect
|
249
371
|
"OR(#{@pats.map(&:inspect).join(',')})"
|
250
372
|
end
|
@@ -259,17 +381,12 @@ module Patm
|
|
259
381
|
pat.execute(mmatch, obj)
|
260
382
|
end
|
261
383
|
end
|
262
|
-
def rest?
|
263
|
-
@pats.any?(&:rest?)
|
264
|
-
end
|
265
384
|
def inspect
|
266
385
|
"AND(#{@pats.map(&:inspect).join(',')})"
|
267
386
|
end
|
268
387
|
end
|
269
388
|
end
|
270
389
|
|
271
|
-
GROUP = 100.times.map{|i| Pattern::Group.new(i) }
|
272
|
-
|
273
390
|
def self.or(*pats)
|
274
391
|
Pattern::Or.new(pats.map{|p| Pattern.build_from(p) })
|
275
392
|
end
|
@@ -282,10 +399,28 @@ module Patm
|
|
282
399
|
@xs = Pattern::ArrRest.new
|
283
400
|
end
|
284
401
|
|
402
|
+
# Use in hash value.
|
403
|
+
# Mark this pattern is optional.
|
404
|
+
def self.opt(pat = _any)
|
405
|
+
Pattern::Opt.new(Pattern.build_from(pat))
|
406
|
+
end
|
407
|
+
|
408
|
+
EXACT = Object.new
|
409
|
+
def EXACT.inspect
|
410
|
+
"EXACT"
|
411
|
+
end
|
412
|
+
# Use in Hash key.
|
413
|
+
# Specify exact match or not.
|
414
|
+
def self.exact
|
415
|
+
EXACT
|
416
|
+
end
|
417
|
+
|
418
|
+
PREDEF_GROUP_SIZE = 100
|
419
|
+
|
285
420
|
class <<self
|
286
|
-
|
287
|
-
define_method "_#{
|
288
|
-
|
421
|
+
PREDEF_GROUP_SIZE.times do|i|
|
422
|
+
define_method "_#{i}" do
|
423
|
+
Pattern::Named.new(i)
|
289
424
|
end
|
290
425
|
end
|
291
426
|
end
|
@@ -349,9 +484,9 @@ module Patm
|
|
349
484
|
@group[i] = val
|
350
485
|
end
|
351
486
|
|
352
|
-
|
353
|
-
define_method "_#{
|
354
|
-
self[
|
487
|
+
PREDEF_GROUP_SIZE.times.each do|i|
|
488
|
+
define_method "_#{i}" do
|
489
|
+
self[i]
|
355
490
|
end
|
356
491
|
end
|
357
492
|
end
|
@@ -367,9 +502,9 @@ module Patm
|
|
367
502
|
end
|
368
503
|
|
369
504
|
def [](i); @match[i]; end
|
370
|
-
|
371
|
-
define_method "_#{
|
372
|
-
@match[
|
505
|
+
PREDEF_GROUP_SIZE.times do|i|
|
506
|
+
define_method "_#{i}" do
|
507
|
+
@match[i]
|
373
508
|
end
|
374
509
|
end
|
375
510
|
end
|
data/patm.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.platform = Gem::Platform::RUBY
|
3
3
|
s.name = 'patm'
|
4
|
-
s.version = '
|
4
|
+
s.version = '2.0.0'
|
5
5
|
s.summary = 'PATtern Matching library'
|
6
6
|
s.description = 'Pattern matching library for plain data structure'
|
7
7
|
s.required_ruby_version = '>= 1.9.0'
|
data/spec/patm_spec.rb
CHANGED
@@ -24,14 +24,20 @@ module PatmHelper
|
|
24
24
|
|
25
25
|
def and_capture(g1, g2 = nil, g3 = nil, g4 = nil)
|
26
26
|
these_matches(
|
27
|
-
self, _capture(self, g1, g2, g3, g4)
|
27
|
+
self, _capture(self, {1 => g1, 2 => g2, 3 => g3, 4 => g4})
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
def and_named_capture(capture)
|
32
|
+
these_matches(
|
33
|
+
self, _capture(self, capture)
|
28
34
|
)
|
29
35
|
end
|
30
36
|
end
|
31
37
|
|
32
|
-
matcher :_capture do|m,
|
38
|
+
matcher :_capture do|m, capture|
|
33
39
|
match do|_|
|
34
|
-
[m.match[1], m.match[2], m.match[3], m.match[4]] ==
|
40
|
+
[m.match[1], m.match[2], m.match[3], m.match[4]] == capture.values_at(1,2,3,4)
|
35
41
|
end
|
36
42
|
end
|
37
43
|
|
@@ -206,9 +212,9 @@ describe Patm::Pattern do
|
|
206
212
|
it { should match_to([0, 1, 2, 3]).and_capture([2, 3]) }
|
207
213
|
end
|
208
214
|
|
209
|
-
pattern [0, 1, Patm._xs, 2] do
|
210
|
-
it { should match_to([0,1,2]) }
|
211
|
-
it { should match_to([0,1,10,20,30,2]) }
|
215
|
+
pattern [0, 1, Patm._xs[1], 2] do
|
216
|
+
it { should match_to([0,1,2]).and_capture([]) }
|
217
|
+
it { should match_to([0,1,10,20,30,2]).and_capture([10,20,30]) }
|
212
218
|
it { should_not match_to([0,1]) }
|
213
219
|
end
|
214
220
|
|
@@ -217,6 +223,45 @@ describe Patm::Pattern do
|
|
217
223
|
it { should_not match_to [0, [1, 3]] }
|
218
224
|
end
|
219
225
|
|
226
|
+
pattern Patm._any[:x] do
|
227
|
+
it { should match_to("aaa").and_named_capture(:x => "aaa") }
|
228
|
+
end
|
229
|
+
|
230
|
+
pattern(a: Patm._any[1]) do
|
231
|
+
it { should_not match_to {} }
|
232
|
+
it { should match_to(a: 1).and_capture(1) }
|
233
|
+
it { should match_to(a: 1, b: 2).and_capture(1) }
|
234
|
+
end
|
235
|
+
|
236
|
+
pattern(a: Patm._any, Patm.exact => false) do
|
237
|
+
it { should_not match_to(b: 1) }
|
238
|
+
it { should match_to(a: 1) }
|
239
|
+
it { should match_to(a: 1, b: 2) }
|
240
|
+
end
|
241
|
+
|
242
|
+
pattern(a: Patm._any, Patm.exact => true) do
|
243
|
+
it { should_not match_to(b: 1) }
|
244
|
+
it { should match_to(a: 1) }
|
245
|
+
it { should_not match_to(a: 1, b: 2) }
|
246
|
+
end
|
247
|
+
|
248
|
+
pattern(a: Patm._any[1].opt) do
|
249
|
+
it { should match_to({}).and_capture(nil) }
|
250
|
+
it { should match_to({a: 1}).and_capture(1) }
|
251
|
+
end
|
252
|
+
|
253
|
+
pattern(a: Patm._any[1], b: Patm._any[2].opt) do
|
254
|
+
it { should_not match_to({}) }
|
255
|
+
it { should match_to({a: 1}).and_capture(1, nil) }
|
256
|
+
it { should match_to({a: 1, b: 2}).and_capture(1, 2) }
|
257
|
+
end
|
258
|
+
|
259
|
+
pattern({a: 1} => {b: 2}) do
|
260
|
+
it { should_not match_to({a: 1} => {b: 0}) }
|
261
|
+
it { should_not match_to({a: 0} => {b: 2}) }
|
262
|
+
it { should match_to({a: 1} => {b: 2}) }
|
263
|
+
end
|
264
|
+
|
220
265
|
context 'regression' do
|
221
266
|
pattern [:assign, [:var_field, [:@ident, Patm._1, [Patm._2, Patm._3]]], Patm._4] do
|
222
267
|
it { should match_to([:assign, [:var_field, [:@ident, 10, [20, 30]]], false]).and_capture(10, 20, 30, false) }
|
@@ -225,5 +270,9 @@ describe Patm::Pattern do
|
|
225
270
|
it { should match_to [1] }
|
226
271
|
it { should match_to [2] }
|
227
272
|
end
|
273
|
+
pattern [Patm._1, 2, [Patm._any, 3], Patm._xs[1], 4] do
|
274
|
+
it { should match_to([1, 2, [10, 3], 4]).and_capture([]) }
|
275
|
+
it { should match_to([1, 2, [10, 3], 20, 4]).and_capture([20]) }
|
276
|
+
end
|
228
277
|
end
|
229
278
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: patm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- todesking
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -72,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
72
|
version: '0'
|
73
73
|
requirements: []
|
74
74
|
rubyforge_project:
|
75
|
-
rubygems_version: 2.
|
75
|
+
rubygems_version: 2.2.2
|
76
76
|
signing_key:
|
77
77
|
specification_version: 4
|
78
78
|
summary: PATtern Matching library
|