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.
Files changed (64) hide show
  1. checksums.yaml +4 -0
  2. data/COPYING +0 -0
  3. data/History.txt +14 -0
  4. data/Makefile +59 -0
  5. data/README +87 -40
  6. data/article.txt +838 -0
  7. data/{assert.rb → lib/assert.rb} +3 -3
  8. data/{reg.rb → lib/reg.rb} +11 -4
  9. data/lib/reg/version.rb +21 -0
  10. data/lib/regarray.rb +455 -0
  11. data/{regarrayold.rb → lib/regarrayold.rb} +33 -7
  12. data/lib/regbackref.rb +73 -0
  13. data/lib/regbind.rb +230 -0
  14. data/{regcase.rb → lib/regcase.rb} +15 -5
  15. data/lib/regcompiler.rb +2341 -0
  16. data/{regcore.rb → lib/regcore.rb} +196 -85
  17. data/{regdeferred.rb → lib/regdeferred.rb} +35 -4
  18. data/{regposition.rb → lib/regevent.rb} +36 -38
  19. data/lib/reggraphpoint.rb +28 -0
  20. data/lib/reghash.rb +631 -0
  21. data/lib/reginstrumentation.rb +36 -0
  22. data/{regitem_that.rb → lib/regitem_that.rb} +32 -11
  23. data/{regknows.rb → lib/regknows.rb} +4 -2
  24. data/{reglogic.rb → lib/reglogic.rb} +76 -59
  25. data/{reglookab.rb → lib/reglookab.rb} +31 -21
  26. data/lib/regmatchset.rb +323 -0
  27. data/{regold.rb → lib/regold.rb} +27 -27
  28. data/{regpath.rb → lib/regpath.rb} +91 -1
  29. data/lib/regposition.rb +79 -0
  30. data/lib/regprogress.rb +1522 -0
  31. data/lib/regrepeat.rb +307 -0
  32. data/lib/regreplace.rb +254 -0
  33. data/lib/regslicing.rb +581 -0
  34. data/lib/regsubseq.rb +72 -0
  35. data/lib/regsugar.rb +361 -0
  36. data/lib/regvar.rb +180 -0
  37. data/lib/regxform.rb +212 -0
  38. data/{trace.rb → lib/trace_during.rb} +6 -4
  39. data/lib/warning.rb +37 -0
  40. data/parser.txt +26 -8
  41. data/philosophy.txt +18 -0
  42. data/reg.gemspec +58 -25
  43. data/regguide.txt +18 -0
  44. data/test/andtest.rb +46 -0
  45. data/test/regcompiler_test.rb +346 -0
  46. data/test/regdemo.rb +20 -0
  47. data/{item_thattest.rb → test/regitem_thattest.rb} +2 -2
  48. data/test/regtest.rb +2125 -0
  49. data/test/test_all.rb +32 -0
  50. data/test/test_reg.rb +19 -0
  51. metadata +108 -73
  52. data/calc.reg +0 -73
  53. data/forward_to.rb +0 -49
  54. data/numberset.rb +0 -200
  55. data/regarray.rb +0 -675
  56. data/regbackref.rb +0 -126
  57. data/regbind.rb +0 -74
  58. data/reggrid.csv +1 -2
  59. data/reghash.rb +0 -318
  60. data/regprogress.rb +0 -1054
  61. data/regreplace.rb +0 -114
  62. data/regsugar.rb +0 -230
  63. data/regtest.rb +0 -1078
  64. data/regvar.rb +0 -76
@@ -1,6 +1,6 @@
1
1
  =begin copyright
2
2
  reg - the ruby extended grammar
3
- Copyright (C) 2005,2009 Caleb Clausen
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 'trace.rb'
21
-
22
- module Reg #namespace
20
+ require 'trace_during.rb'
23
21
 
24
22
 
25
23
 
26
24
 
27
- INFINITY= (
25
+ Infinity= begin
28
26
  result= [ Float::MAX**Float::MAX, Float::MAX**2, Float::MAX*2].max
29
- result.infinite? ? result :
30
- begin result=1.0/0
31
- rescue; Float::MAX #maybe 1.0/0 doesn't work on some systems?
32
- end
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
- INFINITY>1_000_000 or raise 'INFINITY is too small'
39
- INFINITY.to_f.infinite? or warn "INFINITY is merely very large, not infinite"
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; (~self+0).sep self; end
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(arr,start) #:nodoc:
112
- defined? DEBUGGER__ and Process.kill("INT",0)
113
- unbroken___mmatch arr,start
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: false
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=!trace(proc do|event,*stuff|
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
- ::Reg::TLAs=Hash.new{|h,k| h[k]={} }
208
- RegMethods=proc do
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=TLAs[self][k]= noconst ? [v,true] : v #fold noconst into v (longname) and store in ::Reg::TLAs
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.send:define_method, short do|*args| long.new( *args) end #forward short name to long
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
- end
234
- def self.included(mod)
235
- (class<<mod;self;end).instance_eval( &RegMethods )
236
- end
301
+ # end
302
+ # def self.included(mod)
303
+ # (class<<mod;self;end).instance_eval( &RegMethods )
304
+ # end
237
305
 
238
- TLA_pirate= proc { ::Reg::TLAs[self].each{|k,v| Reg.TLA_aliases k,v,self} }
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 inspect
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
- module Interpret #a Reg whose makeup isn't determined until runtime.
359
- include Reg
360
- def klass=(k) @@klass=k end
361
- def ===(other)
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
- assign_TLA true, :Rip=>:Interpret
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