reg 0.4.8 → 0.5.0a0
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 -0
- data/COPYING +0 -0
- data/History.txt +14 -0
- data/Makefile +59 -0
- data/README +87 -40
- data/article.txt +838 -0
- data/{assert.rb → lib/assert.rb} +3 -3
- data/{reg.rb → lib/reg.rb} +11 -4
- data/lib/reg/version.rb +21 -0
- data/lib/regarray.rb +455 -0
- data/{regarrayold.rb → lib/regarrayold.rb} +33 -7
- data/lib/regbackref.rb +73 -0
- data/lib/regbind.rb +230 -0
- data/{regcase.rb → lib/regcase.rb} +15 -5
- data/lib/regcompiler.rb +2341 -0
- data/{regcore.rb → lib/regcore.rb} +196 -85
- data/{regdeferred.rb → lib/regdeferred.rb} +35 -4
- data/{regposition.rb → lib/regevent.rb} +36 -38
- data/lib/reggraphpoint.rb +28 -0
- data/lib/reghash.rb +631 -0
- data/lib/reginstrumentation.rb +36 -0
- data/{regitem_that.rb → lib/regitem_that.rb} +32 -11
- data/{regknows.rb → lib/regknows.rb} +4 -2
- data/{reglogic.rb → lib/reglogic.rb} +76 -59
- data/{reglookab.rb → lib/reglookab.rb} +31 -21
- data/lib/regmatchset.rb +323 -0
- data/{regold.rb → lib/regold.rb} +27 -27
- data/{regpath.rb → lib/regpath.rb} +91 -1
- data/lib/regposition.rb +79 -0
- data/lib/regprogress.rb +1522 -0
- data/lib/regrepeat.rb +307 -0
- data/lib/regreplace.rb +254 -0
- data/lib/regslicing.rb +581 -0
- data/lib/regsubseq.rb +72 -0
- data/lib/regsugar.rb +361 -0
- data/lib/regvar.rb +180 -0
- data/lib/regxform.rb +212 -0
- data/{trace.rb → lib/trace_during.rb} +6 -4
- data/lib/warning.rb +37 -0
- data/parser.txt +26 -8
- data/philosophy.txt +18 -0
- data/reg.gemspec +58 -25
- data/regguide.txt +18 -0
- data/test/andtest.rb +46 -0
- data/test/regcompiler_test.rb +346 -0
- data/test/regdemo.rb +20 -0
- data/{item_thattest.rb → test/regitem_thattest.rb} +2 -2
- data/test/regtest.rb +2125 -0
- data/test/test_all.rb +32 -0
- data/test/test_reg.rb +19 -0
- metadata +108 -73
- data/calc.reg +0 -73
- data/forward_to.rb +0 -49
- data/numberset.rb +0 -200
- data/regarray.rb +0 -675
- data/regbackref.rb +0 -126
- data/regbind.rb +0 -74
- data/reggrid.csv +1 -2
- data/reghash.rb +0 -318
- data/regprogress.rb +0 -1054
- data/regreplace.rb +0 -114
- data/regsugar.rb +0 -230
- data/regtest.rb +0 -1078
- data/regvar.rb +0 -76
@@ -1,6 +1,6 @@
|
|
1
1
|
=begin copyright
|
2
2
|
reg - the ruby extended grammar
|
3
|
-
Copyright (C) 2005,
|
3
|
+
Copyright (C) 2005, 2016 Caleb Clausen
|
4
4
|
|
5
5
|
This library is free software; you can redistribute it and/or
|
6
6
|
modify it under the terms of the GNU Lesser General Public
|
@@ -17,31 +17,43 @@
|
|
17
17
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18
18
|
=end
|
19
19
|
|
20
|
-
require '
|
21
|
-
|
22
|
-
module Reg #namespace
|
20
|
+
require 'trace_during.rb'
|
23
21
|
|
24
22
|
|
25
23
|
|
26
24
|
|
27
|
-
|
25
|
+
Infinity= begin
|
28
26
|
result= [ Float::MAX**Float::MAX, Float::MAX**2, Float::MAX*2].max
|
29
|
-
result.infinite? ? result :
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
)
|
27
|
+
result.infinite? ? result : result=1.0/0
|
28
|
+
rescue; Float::MAX #maybe 1.0/0 doesn't work on some systems?
|
29
|
+
end unless defined? Infinity
|
30
|
+
|
34
31
|
#there's also this way: 999999999999999999999999999999999999999999999999e999999999999999999999999999999
|
35
32
|
#but stuff like that sometimes returns zero, so it doesn't seem as reliable.
|
36
33
|
#(plus it generates a warning)
|
37
34
|
|
38
|
-
|
39
|
-
|
35
|
+
#Infinity>1_000_000 or raise 'Infinity is too small'
|
36
|
+
Infinity.to_f.infinite? or raise "Infinity is merely very large, not infinite"
|
37
|
+
|
38
|
+
NaN=[(Infinity*0 rescue nil), (0.0/0.0 rescue nil)].find{|x| x.nan?} or warn "oops, NaN is not set right (probably nil)..."
|
39
|
+
|
40
|
+
#Infinity is the approved capitalization.
|
41
|
+
#INFINITY is the older form, still supported for now
|
42
|
+
INFINITY= Infinity unless defined? INFINITY
|
40
43
|
|
44
|
+
module Reg #namespace
|
45
|
+
class <<self
|
46
|
+
#Reg::Array convenience constructor. see Array#+@ for details.
|
47
|
+
def [](*args)
|
48
|
+
::Reg::Array.new(*args)
|
49
|
+
end
|
50
|
+
end
|
41
51
|
|
42
52
|
#--------------------------
|
43
53
|
#abstact ancestor of all reg classes
|
44
|
-
module Reg
|
54
|
+
module Reg
|
55
|
+
|
56
|
+
|
45
57
|
|
46
58
|
#=== must be defined in the includer for the appropriate types
|
47
59
|
#and some others:
|
@@ -55,13 +67,17 @@ module Reg #namespace
|
|
55
67
|
#--------------------------
|
56
68
|
def =~(other)
|
57
69
|
self===other
|
70
|
+
rescue #this is rediculuous; === should never raise an exception
|
71
|
+
false #I think the fix to Range#=== below elminates the need for this kind of thing
|
58
72
|
end
|
59
73
|
|
74
|
+
=begin
|
60
75
|
#--------------------------
|
61
76
|
#low-precedence method call
|
62
77
|
def <=>(other)
|
63
78
|
send other
|
64
79
|
end
|
80
|
+
=end
|
65
81
|
|
66
82
|
#--------------------------
|
67
83
|
alias pristine_inspect inspect
|
@@ -69,6 +85,11 @@ module Reg #namespace
|
|
69
85
|
pp pristine_inspect
|
70
86
|
end
|
71
87
|
|
88
|
+
#--------------------------
|
89
|
+
def to_s
|
90
|
+
inspect
|
91
|
+
end
|
92
|
+
|
72
93
|
|
73
94
|
#--------------------------
|
74
95
|
#makes a Reg object literal (aliased to +@ by default)
|
@@ -87,13 +108,32 @@ module Reg #namespace
|
|
87
108
|
#separated by other. watch out if other and self might
|
88
109
|
#match the same thing(s).
|
89
110
|
def sep other; -[self,-[other,self]+0]; end
|
111
|
+
#...or -[self.-, other.reg|Reg::Position[-0.0]].*
|
90
112
|
|
91
113
|
#--------------------------
|
92
114
|
#returns a (vector) Reg that will match a list of stuff
|
93
115
|
#separated by self. somewhat analogous to Regexp#split,
|
94
116
|
#but returns the separators as well.
|
95
|
-
def splitter;
|
117
|
+
def splitter; OBS.l.sep self; end
|
96
118
|
|
119
|
+
#split the input into records using self as a separator expression.
|
120
|
+
#block, if given will be invoked with each record. with no block,
|
121
|
+
#an array of records is returned.
|
122
|
+
def split(input,&block)
|
123
|
+
unless block
|
124
|
+
result=[]
|
125
|
+
block=proc{|x| result<<x}
|
126
|
+
end
|
127
|
+
|
128
|
+
huh #convert input to cursor if it isn't already
|
129
|
+
|
130
|
+
while input.skip_until(self)
|
131
|
+
block.call $` #`
|
132
|
+
end
|
133
|
+
return result
|
134
|
+
end
|
135
|
+
|
136
|
+
=begin
|
97
137
|
#--------------------------
|
98
138
|
#set a breakpoint when matches against a Reg
|
99
139
|
#are made. of dubious value to those unfamiliar
|
@@ -104,17 +144,38 @@ module Reg #namespace
|
|
104
144
|
alias_method :unbroken___mmatch,
|
105
145
|
method_defined?(:mmatch) ? :mmatch : :fail #:nodoc:
|
106
146
|
def ===(other) #:nodoc:
|
107
|
-
defined? DEBUGGER__ and Process.kill("INT",0)
|
147
|
+
(defined? DEBUGGER__ or defined? Debugger) and Process.kill("INT",0)
|
108
148
|
unbroken___eee other
|
149
|
+
rescue
|
150
|
+
false
|
109
151
|
end
|
110
152
|
|
111
|
-
def mmatch(
|
112
|
-
defined? DEBUGGER__ and Process.kill("INT",0)
|
113
|
-
unbroken___mmatch
|
153
|
+
def mmatch(*xx) #:nodoc:
|
154
|
+
(defined? DEBUGGER__ or defined? Debugger) and Process.kill("INT",0)
|
155
|
+
unbroken___mmatch(*xx)
|
114
156
|
end
|
115
157
|
end
|
116
158
|
self
|
117
159
|
end
|
160
|
+
=end
|
161
|
+
|
162
|
+
#--------------------------
|
163
|
+
#makes matcher greedy. on by default
|
164
|
+
def g; self end
|
165
|
+
|
166
|
+
#--------------------------
|
167
|
+
#makes matcher lazy.
|
168
|
+
def l; abstract end
|
169
|
+
|
170
|
+
|
171
|
+
#--------------------------
|
172
|
+
#*,+,- are defined in regarray.rb
|
173
|
+
#~,&,|,^ are defined in reglogic.rb
|
174
|
+
#** is in reghash.rb
|
175
|
+
#bind,side_effect,undo in regbind.rb
|
176
|
+
#>> and finally in regreplace.rb
|
177
|
+
#la,lb in reglookab.rb
|
178
|
+
#+[],-[],+{},-{},-:symbol in regsugar.rb
|
118
179
|
|
119
180
|
#--------------------------
|
120
181
|
#return a list of sub Regs of this Reg (if any)
|
@@ -135,22 +196,36 @@ module Reg #namespace
|
|
135
196
|
end
|
136
197
|
|
137
198
|
#--------------------------
|
199
|
+
#is the parameter an interesting matcher?
|
200
|
+
#interesting matchers have an implementation of === that's
|
201
|
+
#different form their ==. unfortunately, that's not easy to
|
202
|
+
#test in ruby.
|
203
|
+
#this algorithm isn't perfect, but it's pretty good.
|
204
|
+
#in other words, very rarely, the method will fail and LIE to you.
|
205
|
+
#it should work >99%, of the time I think.
|
138
206
|
def Reg.interesting_matcher?(mat) #a hack
|
139
207
|
case mat
|
208
|
+
when Integer,Float,Symbol,true,false,nil,Method,UnboundMethod; false
|
140
209
|
when ItemThatLike,BackrefLike,Module,Set,Regexp,Range,::Reg::Reg; true
|
141
|
-
#when Symbol,Pathname
|
210
|
+
#when Symbol,Pathname; false
|
142
211
|
else
|
143
212
|
/^#<UnboundMethod: .*\(Kernel\)#===>$/===mat.method(:===).unbind.inspect and return false
|
213
|
+
assert( /^#<UnboundMethod: .*\(?(#<)?[A-Z:][A-Za-z_:0-9]+\>?\)?#===>$/===mat.method(:===).unbind.inspect )
|
214
|
+
|
215
|
+
#in case there's an object that redefined ===, then defined it back to
|
216
|
+
#== later in the inheiritance chain
|
217
|
+
#or, someone might write: def === other; self==other end
|
218
|
+
#out of ignorance that it's unnecessary
|
144
219
|
|
145
220
|
eee_call=nil
|
146
|
-
result=!
|
221
|
+
result=!trace_during(proc do|event,*stuff|
|
147
222
|
if /call$/===event
|
148
223
|
eee_call=stuff
|
149
224
|
|
150
225
|
#attempt to remain debuggable while restoring the old trace func
|
151
226
|
set_trace_func((defined? DEBUGGER__ and (DEBUGGER__.context.method:trace_func).to_proc))
|
152
227
|
end
|
153
|
-
end){mat===mat}; line=__LINE__
|
228
|
+
end){mat===mat rescue false}; line=__LINE__
|
154
229
|
assert eee_call[0] == __FILE__
|
155
230
|
assert eee_call[1] == line
|
156
231
|
assert eee_call[2] == :===
|
@@ -165,14 +240,6 @@ module Reg #namespace
|
|
165
240
|
Reg.interesting_matcher? mat
|
166
241
|
end
|
167
242
|
|
168
|
-
#--------------------------
|
169
|
-
#*,+,- are defined in regarray.rb
|
170
|
-
#~,&,|,^ are defined in reglogic.rb
|
171
|
-
#** is in reghash.rb
|
172
|
-
#<< and side_effect,undo in regbind.rb
|
173
|
-
#>> and later in regreplace.rb
|
174
|
-
#la,lb in reglookab.rb
|
175
|
-
|
176
243
|
|
177
244
|
|
178
245
|
#--------------------------
|
@@ -185,38 +252,36 @@ module Reg #namespace
|
|
185
252
|
end
|
186
253
|
end
|
187
254
|
=end
|
255
|
+
|
188
256
|
#--------------------------
|
189
257
|
def mmatch(ary,idx)
|
190
258
|
assert idx<=ary.size
|
191
259
|
idx==ary.size and return nil
|
192
|
-
self===ary[idx] and [[[ary[idx]]],1]
|
260
|
+
(self===ary[idx] rescue false) and [[[ary[idx]]],1]
|
193
261
|
end
|
194
262
|
|
195
263
|
protected
|
196
|
-
#--------------------------
|
197
|
-
def maybe_multiples(*regs)
|
198
|
-
regs.each{|reg|
|
199
|
-
reg.respond_to? :maybe_multiple and
|
200
|
-
reg.maybe_multiple(self)
|
201
|
-
}
|
202
|
-
end
|
203
264
|
|
204
265
|
#--------------------------
|
205
266
|
|
267
|
+
=begin
|
206
268
|
#eventually, this will be a list of all tla mappings
|
207
|
-
|
208
|
-
|
269
|
+
#RegMethods=proc do
|
270
|
+
module_function
|
271
|
+
# class<<self
|
272
|
+
@@TLAs={}
|
209
273
|
define_method :assign_TLA do |*args|
|
210
274
|
hash=args.pop #extract hash from args
|
211
275
|
noconst,*bogus=*args #peel noconst off front of args
|
212
276
|
hash.each{|k,v|
|
213
|
-
v
|
277
|
+
v=@@TLAs[k]= noconst ? [v,true] : v #fold noconst into v (longname) and store in @@TLAs
|
214
278
|
TLA_aliases k,v #always alias the TLA into ::Reg namespace
|
215
279
|
}
|
216
280
|
end
|
217
281
|
|
218
282
|
|
219
283
|
alias_method :assign_TLAs, :assign_TLA
|
284
|
+
|
220
285
|
define_method :TLA_aliases do |short,long_args,*rest| myself=rest.first||::Object
|
221
286
|
long=nil
|
222
287
|
if ::Array===long_args
|
@@ -227,19 +292,23 @@ module Reg #namespace
|
|
227
292
|
end
|
228
293
|
myself.const_set(short,::Reg::const_get(long)) unless noconst #alias the constant name
|
229
294
|
|
230
|
-
long=(::Reg.const_get long) #convert long from symbol to a module or class
|
231
|
-
myself.
|
295
|
+
#long=(::Reg.const_get long) #convert long from symbol to a module or class
|
296
|
+
myself.instance_eval %{
|
297
|
+
private
|
298
|
+
def #{short}(*args) #{long}.new( *args) end #forward short name to long
|
299
|
+
}
|
232
300
|
end
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
301
|
+
# end
|
302
|
+
# def self.included(mod)
|
303
|
+
# (class<<mod;self;end).instance_eval( &RegMethods )
|
304
|
+
# end
|
237
305
|
|
238
|
-
TLA_pirate= proc {
|
306
|
+
TLA_pirate= proc { @@TLAs.each{|k,v| Reg.TLA_aliases k,v,self} }
|
307
|
+
=end
|
308
|
+
|
239
309
|
|
240
|
-
|
241
310
|
end
|
242
|
-
TLA_pirate= Reg::TLA_pirate
|
311
|
+
# TLA_pirate= Reg::TLA_pirate
|
243
312
|
#the tlas (and where they're found):
|
244
313
|
|
245
314
|
#Rob,Rah,Rap (reghash.rb)
|
@@ -247,33 +316,50 @@ module Reg #namespace
|
|
247
316
|
#Rac, (regcase.rb)
|
248
317
|
#Rip (right here, regcore.rb)-----v
|
249
318
|
|
319
|
+
#p :TLA_stuff_defined
|
320
|
+
|
321
|
+
#forward decl
|
322
|
+
module Composite; end
|
323
|
+
module CausesBacktracking; end
|
324
|
+
|
325
|
+
|
250
326
|
|
251
327
|
#--------------------------
|
252
|
-
class Wrapper
|
328
|
+
class Wrapper
|
253
329
|
|
254
330
|
include Reg
|
255
|
-
def initialize(o)
|
331
|
+
def initialize(o=nil)
|
256
332
|
@o=o
|
333
|
+
#super
|
257
334
|
end
|
258
335
|
|
259
|
-
def matches_class; @o.class end
|
260
336
|
def lit; @o end
|
261
337
|
alias unwrap lit
|
262
338
|
|
263
|
-
def
|
264
|
-
"(#{@o.inspect}).reg"
|
265
|
-
end
|
266
|
-
|
267
|
-
def ===x; raise NoMethodError.new( "Reg::Wrapper") end
|
339
|
+
def ===x; raise NoMethodError.new( "Reg::Wrapper is abstract") end
|
268
340
|
|
269
341
|
end
|
270
342
|
|
271
343
|
|
272
344
|
#--------------------------
|
273
345
|
class Fixed < Wrapper #matches like a plain object, but responds to Reg#|, etc
|
274
|
-
#but still behaves in a match just like the unadorned obj (uses === to match)
|
346
|
+
#but still behaves in a match just like the unadorned obj (uses wrapee's === to match)
|
347
|
+
def inspect
|
348
|
+
if Reg===@o
|
349
|
+
"Reg::Fixed.new("+@o.inspect+")"
|
350
|
+
else
|
351
|
+
"(#{@o.inspect}).reg"
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
275
355
|
def ===(other)
|
276
356
|
@o===other
|
357
|
+
rescue #shouldn't be needed
|
358
|
+
false
|
359
|
+
end
|
360
|
+
|
361
|
+
def matches_class
|
362
|
+
huh
|
277
363
|
end
|
278
364
|
end
|
279
365
|
|
@@ -283,10 +369,15 @@ module Reg #namespace
|
|
283
369
|
def ===(other)
|
284
370
|
@o==other
|
285
371
|
end
|
372
|
+
|
373
|
+
def inspect; huh end
|
374
|
+
|
375
|
+
def matches_class; @o.class end
|
286
376
|
end
|
287
377
|
|
288
378
|
#--------------------------
|
289
379
|
class Literal < Equals #a literalized Reg
|
380
|
+
#literal is really the same as const... the 2 classes should be merged
|
290
381
|
def reg; @o end
|
291
382
|
def lit; Literal.new self end
|
292
383
|
def unlit; @o end
|
@@ -294,6 +385,8 @@ module Reg #namespace
|
|
294
385
|
def formula_value(*ctx)
|
295
386
|
@o
|
296
387
|
end
|
388
|
+
|
389
|
+
def inspect; huh end
|
297
390
|
end
|
298
391
|
|
299
392
|
#--------------------------
|
@@ -307,10 +400,13 @@ module Reg #namespace
|
|
307
400
|
def reg
|
308
401
|
Fixed.new(self)
|
309
402
|
end
|
403
|
+
def to_reg; reg end
|
310
404
|
|
311
|
-
#
|
405
|
+
# return a literal version of the object... one whose === has been
|
406
|
+
# forced to be the same as ==, regardless of whether it's usually
|
407
|
+
# a matcher or not.
|
312
408
|
def lit
|
313
|
-
self
|
409
|
+
self #implementation needs some more work...
|
314
410
|
end
|
315
411
|
|
316
412
|
#just like ===, but receiver and argument are switched.
|
@@ -318,6 +414,8 @@ module Reg #namespace
|
|
318
414
|
#to match to the left, and the pattern on the right.
|
319
415
|
def matches pattern
|
320
416
|
pattern===self
|
417
|
+
rescue #shouldn't be needed
|
418
|
+
false
|
321
419
|
end
|
322
420
|
end
|
323
421
|
|
@@ -330,6 +428,7 @@ module Reg #namespace
|
|
330
428
|
|
331
429
|
def initialize(rex)
|
332
430
|
@rex=rex
|
431
|
+
# super
|
333
432
|
end
|
334
433
|
|
335
434
|
def matches_class; ::Symbol end
|
@@ -342,37 +441,49 @@ module Reg #namespace
|
|
342
441
|
@rex.inspect+'.sym'
|
343
442
|
end
|
344
443
|
end
|
345
|
-
|
346
|
-
#a dynamically created Reg
|
347
|
-
def (::Reg).regproc klass=::Object,&block
|
348
|
-
class <<block
|
349
|
-
include Interpret
|
350
|
-
end
|
351
|
-
block.klass=klass
|
352
|
-
block
|
353
|
-
end
|
354
|
-
|
355
|
-
|
356
444
|
|
357
445
|
#--------------------------
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
@@klass===other || return
|
363
|
-
r=call
|
364
|
-
#eventually pass params to call
|
365
|
-
Reg::Multiple===r and raise 'this oughtta work, but doesn`t yet'
|
366
|
-
r===other
|
367
|
-
end
|
368
|
-
def matches_class; @@klass end
|
369
|
-
alias starts_with matches_class
|
370
|
-
alias ends_with matches_class
|
446
|
+
#a dynamically created Reg
|
447
|
+
def (::Reg).regproc klass=::Object,&block
|
448
|
+
Interpret.new(&block)
|
449
|
+
end
|
371
450
|
|
451
|
+
class Interpret #a Reg whose makeup isn't determined until matchtime.
|
452
|
+
include Reg
|
453
|
+
|
454
|
+
def initialize(&matchercode)
|
455
|
+
@matchercode=matchercode
|
456
|
+
super
|
457
|
+
end
|
372
458
|
|
373
|
-
|
459
|
+
def ===(other)
|
460
|
+
mtr=@matchercode.call(Progress.new(self,::Sequence::SingleItem.new(other)))
|
461
|
+
mtr===other rescue false
|
462
|
+
#eventually pass more params to call?
|
463
|
+
end
|
464
|
+
|
465
|
+
def mmatch(progress)
|
466
|
+
@matchercode.call(progress).mmatch(progress)
|
467
|
+
end
|
468
|
+
|
469
|
+
#assign_TLA true, :Rip=>:Interpret
|
374
470
|
end
|
375
471
|
|
376
472
|
|
377
473
|
|
378
474
|
end
|
475
|
+
|
476
|
+
|
477
|
+
#workaround potential error in class Range.
|
478
|
+
#ruby 1.9 appearently fixes this
|
479
|
+
begin
|
480
|
+
("a"..."b")===4
|
481
|
+
rescue Exception
|
482
|
+
class Range
|
483
|
+
#dammit, === should never raise an exception
|
484
|
+
unsafe_eee = instance_method :===
|
485
|
+
define_method(:===) {|other|
|
486
|
+
unsafe_eee.bind(self)[other] rescue false
|
487
|
+
}
|
488
|
+
end
|
489
|
+
end
|