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,5 +1,5 @@
1
1
  =begin copyright
2
- Copyright (C) 2004,2005 Caleb Clausen
2
+ Copyright (C) 2004,2005, 2016 Caleb Clausen
3
3
 
4
4
  This library is free software; you can redistribute it and/or
5
5
  modify it under the terms of the GNU Lesser General Public
@@ -18,14 +18,14 @@
18
18
 
19
19
  module Kernel
20
20
  def assert(expr,msg="assertion failed")
21
- $Debug and (expr or raise msg)
21
+ defined? $Debug and $Debug and (expr or raise msg)
22
22
  end
23
23
 
24
24
  @@printed={}
25
25
  def fixme(s)
26
26
  unless @@printed[s]
27
27
  @@printed[s]=1
28
- $Debug and $stderr.print "FIXME: #{s}\n"
28
+ defined? $Debug and $Debug and $stderr.print "FIXME: #{s}\n"
29
29
  end
30
30
  end
31
31
  end
@@ -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
@@ -16,19 +16,26 @@
16
16
  License along with this library; if not, write to the Free Software
17
17
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
18
  =end
19
-
20
19
  require 'regcore'
21
20
  require 'reglogic'
22
21
  require 'reghash'
23
22
  require 'regarray'
23
+ require 'regrepeat'
24
+ require 'regsubseq'
24
25
  #require 'regarrayold' #old bt engine
25
26
  require 'regprogress' #new bt engine
26
27
  #enable one engine or the other, but not both
27
28
 
29
+ require 'regevent'
30
+ require 'regbind'
31
+ require 'regreplace'
28
32
  require 'regbackref'
29
33
  require 'regitem_that'
30
34
  require 'regknows'
31
35
  require 'regsugar'
36
+ require 'regvar'
37
+ require 'regposition'
32
38
  require 'regold' #will go away
33
- Kernel.instance_eval( &Reg::TLA_pirate)
34
- Reg::Sugar.include!
39
+
40
+ require 'regcompiler' #engine, bah
41
+ #Kernel.instance_eval( &Reg::TLA_pirate)
@@ -0,0 +1,21 @@
1
+ =begin copyright
2
+ reg - the ruby extended grammar
3
+ Copyright (C) 2016 Caleb Clausen
4
+
5
+ This library is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU Lesser General Public
7
+ License as published by the Free Software Foundation; either
8
+ version 2.1 of the License, or (at your option) any later version.
9
+
10
+ This library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public
16
+ License along with this library; if not, write to the Free Software
17
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ =end
19
+ module Reg
20
+ VERSION="0.5.0a0"
21
+ end
@@ -0,0 +1,455 @@
1
+ =begin copyright
2
+ reg - the ruby extended grammar
3
+ Copyright (C) 2005, 2016 Caleb Clausen
4
+
5
+ This library is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU Lesser General Public
7
+ License as published by the Free Software Foundation; either
8
+ version 2.1 of the License, or (at your option) any later version.
9
+
10
+ This library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public
16
+ License along with this library; if not, write to the Free Software
17
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ =end
19
+
20
+ require "assert"
21
+ require "pp"
22
+ require "forwardable"
23
+ require "regdeferred"
24
+
25
+ module Reg
26
+ module Reg
27
+ def itemrange; 1..1 end #default match 1 item
28
+
29
+
30
+ #create a (vector) Reg that will match this pattern repeatedly.
31
+ #(creates a Reg::Repeat.)
32
+ #the argument determines the number of times to match.
33
+ #times may be a positive integer, zero, Infinity, or a
34
+ #range over any of the above. if a range, the lower
35
+ #end may not be Infinity! Reg#- and Reg#+ are shortcuts
36
+ #for the most common cases of multiplting by a range.
37
+ #(at least 0 and at most Infinity.) watch out when
38
+ #multiplying with zero and Infinity (including in a
39
+ #range), as you can easily create a situation where
40
+ #the number of matches to enumerate explodes exponentionaly,
41
+ #or even is infinite. i won't say too much here except
42
+ #that these are generally the same sorts of problems you
43
+ #can run into with Regexps as well.
44
+ def *(times=0..Infinity)
45
+ Repeat.new(self,times)
46
+ end
47
+
48
+ #repeat this pattern up to atmost times. could match
49
+ #0 times as the minimum number of matches here is zero.
50
+ def -(atmost=1)
51
+ self*(0..atmost)
52
+ end
53
+
54
+ #repeat this pattern atleast times or more
55
+ def +(atleast=1)
56
+ self*(atleast..Infinity)
57
+ end
58
+
59
+ end
60
+
61
+ #--------------------------
62
+ module Undoable
63
+
64
+ end
65
+
66
+ #--------------------------
67
+ module Composite
68
+ include Reg
69
+ def initialize(*args,&block)
70
+ at_construct_time(*args,&block)
71
+ # super
72
+ end
73
+
74
+ def at_construct_time(*a,&b); end #default does nothing
75
+
76
+ def visit_subregs()
77
+ todo=[self]
78
+ visited=Set[]
79
+ while node=todo.shift
80
+ next if visited[node.__id__]
81
+ yield node #visit this node
82
+ visited<<node.__id__
83
+ todo.push(*node.subregs) #schedule children to be visited
84
+ end
85
+ end
86
+ alias breadth_visit_subregs visit_subregs
87
+
88
+ def depth_visit_subregs(set=Set[],&visit)
89
+ set[self.__id__] and return
90
+ set<<self.__id__
91
+ subregs.each{|r| r.depth_visit_subregs(set,&visit) }
92
+ visit[self]
93
+ end
94
+
95
+ def undoable_infection
96
+ unless subregs.grep(Undoable).empty?
97
+ extend Undoable
98
+ class <<self
99
+ undef mmatch
100
+ alias mmatch mmatch_full
101
+ end
102
+ end
103
+ end
104
+
105
+
106
+ def subregs
107
+ [@reg]
108
+ end
109
+ #includers should define #subregs if they don't have just a single @reg
110
+
111
+ protected
112
+ def multiple_infection(*regs)
113
+ regs.empty? and regs=subregs
114
+ regs.each{|reg|
115
+ reg.respond_to? :maybe_multiple and
116
+ reg.maybe_multiple(self)
117
+ }
118
+ end
119
+ end
120
+
121
+ #--------------------------
122
+ module Multiple
123
+ include Reg
124
+ def ===(other)
125
+ method_missing(:===, other)
126
+ end
127
+ =begin
128
+ def maybe_multiple(needsmult) #better name needed
129
+ assert( needsmult.respond_to?( :mmatch))
130
+ class <<needsmult
131
+ undef_method :mmatch
132
+ include Multiple
133
+ #alias mmatch mmatch_full #this doesn't work... why?
134
+ def mmatch(*xx) mmatch_full(*xx); end #have to do this instead
135
+ end
136
+ assert( needsmult.respond_to?( :mmatch))
137
+ end
138
+
139
+ def multiple_infection(*args) end #not needed?
140
+ #we're already multiple; no need to try to become multiple again
141
+ =end
142
+ def mmatch(*xx) #multiple match
143
+ abstract
144
+ end
145
+
146
+ #negated Reg::Multiple's are automatically lookaheads
147
+ def ~
148
+ ~(Lookahead.new self)
149
+ end
150
+
151
+
152
+ def starts_with
153
+ abstract
154
+ end
155
+
156
+ def ends_with
157
+ abstract
158
+ end
159
+
160
+ def matches_class
161
+ raise 'multiple regs match no single class'
162
+ end
163
+ end
164
+
165
+ #--------------------------
166
+ module Backtrace
167
+ # protected
168
+
169
+ def regs(ri) @regs[ri] end
170
+
171
+ def update_di(di,len); di+len; end
172
+ #--------------------------
173
+ $RegTraceEnable=$RegTraceDisable=nil
174
+ def trace_enabled?
175
+ @trace||=nil
176
+ $RegTraceEnable or (!$RegTraceDisable && @trace)
177
+ end
178
+
179
+ #--------------------------
180
+ def trace!
181
+ @trace=true
182
+ self
183
+ end
184
+
185
+ #--------------------------
186
+ def notrace!
187
+ @trace=false
188
+ self
189
+ end
190
+ end
191
+
192
+ #--------------------------
193
+ if false
194
+ class RR < ::Array
195
+ def inspect
196
+ [self,super].to_s
197
+ end
198
+
199
+ def rrflatten
200
+ result=[]
201
+ each{|i|
202
+ case i
203
+ when RR then result +=i.rrflatten
204
+ when Literal then result << i.unlit
205
+ else result << i
206
+ end
207
+ }
208
+ end
209
+
210
+ def +(other)
211
+ RR[*super]
212
+ end
213
+ end
214
+ Result=RR
215
+ else
216
+ RR=::Array
217
+ end
218
+
219
+
220
+
221
+
222
+ #--------------------------
223
+ class Or
224
+ def mmatch(arr,start)
225
+ assert start <= arr.size
226
+ @regs.each_with_index {|reg,i|
227
+ reg===arr[start] and
228
+ return OrMatchSet.new(self,i,nil,1)
229
+ } unless start == arr.size
230
+ return nil
231
+ end
232
+
233
+ def itemrange
234
+ if true
235
+ min,max=Infinity,0
236
+ @regs.each {|r|
237
+ min=r.itemrange.first if Reg===r and min>r.itemrange.first
238
+ max=r.itemrange.last if Reg===r and max<r.itemrange.last
239
+ }
240
+ return min..max
241
+ else
242
+ limits=@regs.map{|r|
243
+
244
+ i=(r.respond_to? :itemrange)? r.itemrange : 1..1
245
+ [i.first,i.last]
246
+ }.transpose
247
+ limits.first.sort.first .. limits.last.sort.last
248
+ end
249
+ end
250
+
251
+ private
252
+ def mmatch_full(arr,start)
253
+ mat=nil
254
+ @regs.each_with_index{|r,i|
255
+ if r.respond_to? :mmatch
256
+ mat=r.mmatch(arr,start) or next
257
+ if mat.respond_to? :next_match
258
+ return OrMatchSet.new(self,i,mat,mat.next_match(arr,start).last)
259
+ else
260
+ return OrMatchSet.new(self,i,nil,mat.last)
261
+ end
262
+ else
263
+ r===arr[start] and
264
+ return OrMatchSet.new(self,i,nil,1)
265
+ end
266
+ }
267
+
268
+ assert mat.nil?
269
+ return nil
270
+ end
271
+ end
272
+
273
+ #--------------------------
274
+ class Xor
275
+ def clean_result
276
+ huh
277
+ end
278
+
279
+ def itemrange
280
+ #min,max=Infinity,0
281
+ #@regs.each {|r|
282
+ # min=[min,r.itemrange.first].sort.first
283
+ # max=[r.itemrange.last,max].sort.last
284
+ #}
285
+ #return min..max
286
+ limits=@regs.map{|r| i=r.itemrange; [i.first,i.last]}.transpose
287
+ limits.first.sort.first .. limits.last.sort.last
288
+ end
289
+
290
+ private
291
+ if false
292
+ def mmatch_full(arr,start)
293
+ mat=i=nil
294
+ count=0
295
+ @regs.each_with_index{|reg,idx|
296
+ if reg.respond_to? :mmatch
297
+ mat=reg.mmatch(arr,start) or next
298
+ else
299
+ reg===arr[start] or next
300
+ mat=[[arr[start]],1]
301
+ end
302
+ count==0 or return nil
303
+ count=1
304
+ assert mat
305
+ }
306
+
307
+ return nil unless mat
308
+ assert count==1
309
+ mat.respond_to? :next_match and return XorMatchSet.new(reg,idx,mat,huh)
310
+
311
+ a=RR[nil]*regs.size
312
+ a[idx]=mat[0]
313
+ mat[0]=a
314
+ assert huh
315
+ assert ::Array===mat.first.first
316
+ return mat
317
+ end
318
+ end
319
+
320
+ def mmatch_full arr, start
321
+ found=nil
322
+ @regs.each{|reg|
323
+ if m=reg.mmatch(arr, start)
324
+ return if found
325
+ found=m
326
+ end
327
+ }
328
+ return found
329
+ end
330
+
331
+ end
332
+
333
+ #--------------------------
334
+ class And
335
+ include Backtrace #shouldn't this be included only when needed?
336
+
337
+ def update_di(di,len) di; end
338
+
339
+
340
+ def clean_result
341
+ huh
342
+ end
343
+
344
+
345
+ def enough_matches? matchcnt,*bogus
346
+ matchcnt==@regs.size
347
+ end
348
+
349
+ def itemrange
350
+ limits=@regs.map{|r| i=r.itemrange; [i.first,i.last]}.transpose
351
+ limits.first.sort.last .. limits.last.sort.last
352
+ end
353
+
354
+ private
355
+ def mmatch_full(arr,start)
356
+ #in this version, at least one of @regs is a multiple reg
357
+ assert( (0..arr.size).include?( start))
358
+ result,*bogus=huh.bt_match(arr,start,0,0,[RR[]])
359
+ result and AndMatchSet.new(self,result)
360
+ end
361
+ end
362
+
363
+ #--------------------------
364
+ class Array
365
+ include Reg,Backtrace,Composite
366
+
367
+ def max_matches; @regs.size end
368
+
369
+ def initialize(*regs)
370
+
371
+ #inline subsequences and short fixed repetitions
372
+ iterate=proc{|list|
373
+ result=[]
374
+ list.each{|reg|
375
+ case reg
376
+ when Subseq
377
+ result.push(*iterate[reg.subregs])
378
+ when Repeat
379
+ rr=reg.times
380
+ if rr.first==rr.last and rr.first<=3
381
+ result.push(*iterate[[reg.regs(nil)]*rr.first])
382
+ else
383
+ result<<reg
384
+ end
385
+ else result<< Deferred.defang!(reg)
386
+ end
387
+ }
388
+ result
389
+ }
390
+ @regs=iterate[regs]
391
+ # p [:+, :[]]
392
+ super
393
+ end
394
+
395
+ class <<self
396
+ alias new__nobooleans new
397
+ def new(*args)
398
+ # args.detect{|o| /^(AND|X?OR)$/.sym===o } or return new__nobooleans(*args)
399
+ # +[/^(AND|X?OR)$/.sym.splitter].match(args)
400
+ Pair===args.first and return ::Reg::OrderedHash.new(*args)
401
+ new__nobooleans(*args)
402
+ end
403
+ alias [] new
404
+ end
405
+
406
+ def matches_class; ::Array end
407
+
408
+ def subitemrange
409
+ #add the ranges of the individual items
410
+ @subitemrange ||= #some caching...
411
+ begin
412
+ list=Thread.current[:$Reg__Subseq__subitemranges_in_progress]||={}
413
+ id=__id__
414
+ list[id] and throw(id.to_s.to_sym,0..Infinity)
415
+ list[id]=1
416
+ catch(id.to_s.to_sym){
417
+ @regs.inject(0){|sum,ob| sum+(Reg===ob ? ob.itemrange.begin : 1) } ..
418
+ @regs.inject(0){|sum,ob| sum+(Reg===ob ? ob.itemrange.end : 1) }
419
+ }
420
+ ensure
421
+ list.delete id
422
+ end
423
+
424
+ end
425
+
426
+ def multiple_infection(*args) end #never do anything for Reg::Array
427
+
428
+ def enough_matches? matchcnt,eof
429
+ matchcnt==@regs.size and eof
430
+ end
431
+
432
+ def +(reg)
433
+ if self.class==reg.class
434
+ self.class.new( *@regs+reg.regs )
435
+ else
436
+ super
437
+ end
438
+ end
439
+
440
+ def inspect
441
+ name="$RegInspectRecursing#{object_id}"
442
+ Thread.current[name] and return '+[...]'
443
+ Thread.current[name]=true
444
+ result="+["+ @regs.collect{|r| r.inspect}.join(', ') +"]"
445
+ Thread.current[name]=nil
446
+ result
447
+ end
448
+
449
+ def subregs; @regs.dup end
450
+ end
451
+
452
+
453
+
454
+
455
+ end