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
@@ -0,0 +1,323 @@
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
+
21
+ #--------------------------
22
+ class MatchSet
23
+
24
+ def next_match(ary,start)
25
+ abstract
26
+ end
27
+
28
+ def deep_copy
29
+ abstract
30
+ end
31
+
32
+ def ob_state
33
+ instance_variables.sort.map{|i| instance_variable_get i }
34
+ end
35
+
36
+ def ==(other)
37
+ self.class==other.class and ob_state==other.ob_state
38
+ end
39
+
40
+ end
41
+
42
+ #--------------------------
43
+ class SingleRepeatMatchSet < MatchSet
44
+ def initialize(startcnt,stepper,endcnt)
45
+ endcnt==startcnt and raise 'why even make it a set, then?'
46
+ (endcnt-startcnt)*stepper>0 or raise "tried to make null match set"
47
+ assert startcnt>=0
48
+ assert endcnt>=0
49
+ @matchtimes,@stepper,@endcnt=startcnt,stepper,endcnt
50
+ end
51
+
52
+ def next_match(arr,idx)
53
+ assert @stepper.abs == 1
54
+ (@endcnt-@matchtimes)*@stepper>=0 or return nil
55
+ assert @matchtimes >=0
56
+ result=[RR[arr[idx...idx+@matchtimes]], @matchtimes]
57
+ assert ::Array===result.first.first
58
+ @matchtimes+=@stepper
59
+ return result
60
+ end
61
+
62
+ def deep_copy
63
+ dup
64
+ end
65
+ end
66
+
67
+
68
+ #--------------------------
69
+ class OrMatchSet < MatchSet
70
+ def initialize(orreg,idx,set,firstmatchlen)
71
+ @orreg,@idx,@set,@firstmatchlen=orreg,idx,set,firstmatchlen
72
+ assert @firstmatchlen.nil? || Integer===@firstmatchlen
73
+ end
74
+
75
+ def ob_state
76
+ instance_variables.map{|i| instance_variable_get i }
77
+ end
78
+
79
+ def ==(other)
80
+ OrMatchSet===other and ob_state==other.ob_state
81
+ end
82
+
83
+ def next_match(ary,idx)
84
+ if @firstmatchlen
85
+ resultlen,@firstmatchlen=@firstmatchlen,nil
86
+ assert Integer===resultlen
87
+ return [ary[idx,resultlen],resultlen]
88
+ end
89
+ @set and result= @set.next_match(ary,idx)
90
+ while result.nil?
91
+ @idx+=1
92
+ @idx >= @orreg.regs.size and return nil
93
+ x=@orreg.regs[@idx].mmatch(ary,idx)
94
+ @set,result=*if MatchSet===x then [x,x.next_match] else [nil,x] end
95
+ end
96
+ a=RR[nil]*@orreg.regs.size
97
+ a[idx]=result[0]
98
+ result[0]=a
99
+ assert ::Array===result.first.first
100
+ return result
101
+ end
102
+
103
+ def deep_copy
104
+ result=OrMatchSet.new(@orreg,@idx,@set && @set.deep_copy,@firstmatchlen)
105
+ assert self==result
106
+ return result
107
+ end
108
+ end
109
+
110
+ class SingleMatch_MatchSet < MatchSet
111
+ #this is somewhat of a hack, and shouldn't be necessary....
112
+ #it exists because every backtracking stop has to have a
113
+ #matchset in it, even the ones that only match one way.
114
+ #this class encapsulates matchsets that match only one way.
115
+ def initialize; end
116
+ def next_match*; end
117
+ end
118
+
119
+
120
+ #--------------------------
121
+ class RepeatMatchSet < MatchSet
122
+
123
+ attr :progress
124
+ def initialize(progress,consumed)
125
+ @progress=progress
126
+ #@cnt=@startcnt-stepper
127
+ #@ary.push 1
128
+ @consumed=consumed
129
+ @firstmatch=[progress.clean_result,@consumed]
130
+ assert( progress.matcher.times===progress.regsidx)
131
+ assert progress.regsidx
132
+ #assert(@ri==@firstmatch.first.size)
133
+ end
134
+
135
+ def match_iterations;
136
+ #assert(@ri==Backtrace.clean_result(@ary).size)
137
+ progress.regsidx
138
+ end
139
+
140
+ #very nearly identical to SubseqMatchSet#next_match
141
+ def next_match(arr,idx)
142
+ #fewer assertions in twin
143
+ if @firstmatch
144
+ result,@firstmatch=@firstmatch,nil
145
+ assert result.first.empty? || ::Array===result.first.first
146
+ #print "idx=#{idx}, inc=#{result.last}, arr.size=#{arr.size}\n"
147
+ # assert idx+result.last<=arr.size
148
+ # assert(progress.regsidx==result.first.size)
149
+ return result
150
+ end
151
+
152
+ @progress or return #not in twin ... ignore it
153
+
154
+ assert progress.check_result
155
+
156
+ i=@context.position_inc
157
+ =begin extents not used
158
+ extents= if i==0
159
+ []
160
+ else
161
+ progress.position_stack[-i..-1]
162
+ end
163
+ =end
164
+ #this part's not in twin
165
+ #'need to check for fewer matches here before rematching last matchset'
166
+
167
+ #what if the match that gets discarded was returned by a matchset
168
+ #that has more matches in it?
169
+ #in that case, i is 1 and the body of this if should not be executed...
170
+ if @context.regsidx>@context.matcher.times.begin #&& i>1
171
+ progress.backup_stacks(@context) or raise
172
+ huh #need to change progress.cursor.pos here too
173
+ #result of backup_stacks is abandoned, leaked, orphaned
174
+ #we don't want it anymore
175
+ #but what if it's nil?
176
+
177
+ #but now i need to undo all other progress state too, if
178
+ #the state was created with the match result just popped.
179
+ #in general, it's not possible to distinguish state with the
180
+ #last match from state with the matches that might have preceeded it...
181
+ #unless I create a backtracking point for each optional iteration
182
+ #of the repeat matcher.
183
+ #currently, making a backtracking point implies making a matchset
184
+ #as well. I'll need a matchset the contains only 1 match.
185
+ #ok, i think this is working now. no extra code needed here.
186
+
187
+ @consumed-=pos-progress.position_stack.last
188
+ #assert(@ri==Backtrace.clean_result(@ary).size)
189
+ assert idx+@consumed<=arr.size
190
+ assert progress.check_result
191
+ result= [progress.clean_result, @consumed]
192
+ assert progress.check_result
193
+ return result
194
+ end
195
+
196
+
197
+ assert progress.check_result
198
+ assert( (0..@progress.matcher.max_matches)===@progress.regsidx)
199
+ result,di,ri=progress.last_next_match
200
+ if result and @progress.matcher.enough_matches? ri #condition slightly different in twin
201
+ result=[progress.clean_result,di]
202
+ @consumed=di #not in twin...why?
203
+ #@progress.regsidx-=1
204
+ assert ::Array===result.first.first
205
+ assert idx+result.last<=arr.size
206
+ assert progress.check_result
207
+ #assert(@ri==result.first.size)
208
+ return result
209
+ end
210
+
211
+ assert( (0..@progress.matcher.max_matches)===@progress.regsidx)
212
+ #assert(@ri==Backtrace.clean_result(@ary).size)
213
+ assert(progress.check_result)
214
+
215
+
216
+
217
+ @progress.matchset_stack.empty? and return @progress=nil #also checking @ary in twin... ignore it
218
+ assert @progress.regsidx>0
219
+
220
+ @progress.backtrack or return @progress=nil #@progress never set to nil like this in twin... ignore it
221
+
222
+ #this is where the divergence widens. ri is a local in twin
223
+
224
+ #assert(@ri==Backtrace.clean_result(@ary).size)
225
+ assert(progress.check_result)
226
+ mat,di,@ri=@progress.bt_match #mat is @ary in twin
227
+ mat.nil? and return @progress=nil
228
+
229
+ #assert(@ri==Backtrace.clean_result(mat).size)
230
+ assert @progress.regsidx
231
+ assert( (0..@progress.matcher.max_matches)===@progress.regsidx)
232
+
233
+ result=[@progress.clean_result,di]
234
+ @consumed=di #no @consumed in twin
235
+ assert ::Array===result.first.first
236
+ assert idx+result.last<=arr.size
237
+ assert progress.check_result
238
+ #assert(@ri==result.last.size)
239
+ return result
240
+ end
241
+
242
+ end
243
+
244
+ #---------------------------------------------
245
+ class SubseqMatchSet < MatchSet
246
+
247
+ def initialize progress,di;
248
+ @reg,@progress= progress.matcher,progress
249
+
250
+ @orig_pos=progress.cursor.pos-di
251
+ @firstresult= [progress.clean_result,di]
252
+ end
253
+
254
+ #(@reg=>progress.matcher,@matchary=>progress.huh,di=>progress.cursor.pos-@orig_pos)
255
+
256
+ def next_match(ary,start)
257
+ if @firstresult
258
+ @firstresult,result=nil,@firstresult
259
+ assert ::Array===result.first.first
260
+ return result
261
+ end
262
+
263
+
264
+ result,di,ri=@progress.last_next_match
265
+ result or return @progress=nil
266
+ if result and ri==@reg.max_matches
267
+ result=[@progress.clean_result,di]
268
+ assert ::Array===result.first.first
269
+ return result
270
+ end
271
+
272
+
273
+ (@progress and !@progress.matchset_stack.empty?) or return @progress=nil
274
+ assert @progress.regsidx
275
+ @progress.backtrack or return @progress=nil
276
+
277
+ #need to adjust ri?
278
+
279
+ #is this right... dunno...
280
+ result,di,bogus=@progress.bt_match
281
+
282
+
283
+ if result
284
+ result=[@progress.clean_result,di]
285
+ assert ::Array===result.first.first
286
+ return result
287
+ end
288
+ end
289
+
290
+ def match_iterations
291
+ progress.matcher.max_matches
292
+ end
293
+
294
+ end
295
+ #--------------------------
296
+ class AndMatchSet < SubseqMatchSet
297
+ #this isn't really right...
298
+ #on next_match, we need to backtrack the longest alternative(s)
299
+ #if they're then shorter than the next longest alternative,
300
+ #then that (formerly next longest) alternative becomes
301
+ #the dominating alternative, and determines how much is consumed
302
+
303
+ end
304
+ #might need Reg::Or tooo....
305
+
306
+
307
+ #--------------------------
308
+ class ReplaceMatchSet < MatchSet
309
+ def initialize(replacer, progress, origpos, ms)
310
+ @replacer,@progress,@origpos,@ms=replacer,@progress,origpos,ms
311
+ end
312
+
313
+ def next_match(*args)
314
+ result=@ms.next_match(*args)
315
+ @replacer.replace @origpos,result.last,@progress
316
+ return result
317
+ end
318
+
319
+ end
320
+
321
+
322
+
323
+ 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
@@ -20,32 +20,32 @@
20
20
 
21
21
  #the names defined here are considered obsolete, and will not be supported
22
22
  #anymore at some point in the future.
23
-
24
- for name in ["And", "Array","Equals", "Fixed", "Hash", "Literal",
25
- "Multiple", "Not", "Object", "Or", "Repeat",
26
- "String", "Subseq", "Symbol", "Xor"] do
27
-
28
- if Class===::Reg.const_get(name)
29
- eval <<-endeval
30
- class ::Reg#{name} < Reg::#{name}
31
-
32
- def initialize(*args,&block)
33
- @@warned_already ||= !warn("Reg#{name} is obsolete; use Reg::#{name} instead")
34
- super
35
- end
36
- end
37
- endeval
38
- else
39
- eval <<-endeval
40
- module ::Reg#{name}; include Reg::#{name}
41
- def self.included(*args,&block)
42
- @@warned_already ||= !warn("Reg#{name} is obsolete; use Reg::#{name} instead")
43
- super
44
- end
45
- end
46
- endeval
47
-
48
- end
23
+ OBSOLETE_NAMES=["And", "Array","Equals", "Fixed", "Hash", "Literal",
24
+ "Multiple", "Not", "Object", "Or", "Repeat",
25
+ "String", "Subseq", "Symbol", "Xor"]
26
+ for name in OBSOLETE_NAMES do
27
+
28
+ if Class===::Reg.const_get(name)
29
+ eval <<-endeval
30
+ class ::Reg#{name} < Reg::#{name}
31
+
32
+ def initialize(*args,&block)
33
+ @@warned_already ||= !warn("Reg#{name} is obsolete; use Reg::#{name} instead")
34
+ super
35
+ end
36
+ end
37
+ endeval
38
+ else
39
+ eval <<-endeval
40
+ module ::Reg#{name}; include Reg::#{name}
41
+ def self.included(*args,&block)
42
+ @@warned_already ||= !warn("Reg#{name} is obsolete; use Reg::#{name} instead")
43
+ super
44
+ end
45
+ end
46
+ endeval
47
+
48
+ end
49
49
 
50
50
  # Object.const_set "Reg"+name, (Reg.const_get name)
51
51
  end
@@ -1,6 +1,6 @@
1
1
  =begin copyright
2
2
  reg - the ruby extended grammar
3
- Copyright (C) 2005 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
@@ -72,3 +72,93 @@ others n/a single
72
72
 
73
73
 
74
74
  =end
75
+
76
+ =begin
77
+ a Reg::Path is a list of (mostly) pairs of contained in a Reg::Path constructor.
78
+ The preferred Reg::Path constructor is the --[...] syntax.
79
+
80
+ the key (left side) of each pair represents a connector matcher, and the value represents
81
+ a value matcher. here's a list of allowed connector matchers:
82
+
83
+ type allowed connector matchers
84
+ Object Array (+[String|Symbol, __]) , Array (+[Regexp, __]) , Reg::RespondsTo (made like -:foo or -"foo" or -:@foo)
85
+ Hash Any Object, Array of 1 Array|Integer, Reg::Literal, any scalar matcher
86
+ Array Integer,Range of Integer
87
+
88
+ any reg matcher may be used as a value matcher.
89
+
90
+ If the value matcher is OB and the connector matcher is of the below, the value matcher (and ** connecting to it)
91
+ may be left off, so just the connector matcher is given:
92
+
93
+ type allowed standalone connector matchers
94
+ Object Array (+[String|Symbol, __]) , Array (+[Regexp, __]) , Reg::RespondsTo (made like -:foo or -"foo" or -:@foo)
95
+ Hash Array of 1 Array|Integer, Reg::Literal, String, Symbol, Regexp
96
+ Array Integer,Range of Integer
97
+
98
+ Reg::Paths may also contain Reg::Repeat or Reg::Subseq, provided the leaves within
99
+ these are ultimately pairs or standalone connector matchers.
100
+
101
+ =end
102
+
103
+
104
+ module Reg
105
+ class Subseq
106
+ def -@; Path.new @regs; end
107
+ end
108
+
109
+ class Path
110
+ def initialize regs
111
+ @regs=regs
112
+ expand_pairs!
113
+ end
114
+
115
+ def === other
116
+ @regs.each{|r|
117
+ case r
118
+ when Integer
119
+ when Range
120
+ when Reg::Literal
121
+ when Array
122
+ case r[0]
123
+ when String,Symbol
124
+ when Regexp
125
+ when Array
126
+ when Integer
127
+ end
128
+ when Reg::RespondsTo
129
+ when Reg::Reg
130
+ else
131
+ end
132
+ }
133
+ end
134
+ end
135
+
136
+ module Reg
137
+ def expand_pairs!
138
+ 0.upto(@regs.size-1) do |i|
139
+ item=@regs[i]
140
+ @regs[i]=
141
+ case item
142
+ when Reg::Pair; item #ignore
143
+ when Reg::Repeat,Reg::Subseq; item.dup.expand_pairs!
144
+ else Reg::Pair.new(item,OB)
145
+ end
146
+ end
147
+ return self
148
+ end
149
+ end
150
+ class Repeat
151
+ def expand_pairs!
152
+ item=@reg
153
+ @reg=
154
+ case item
155
+ when Reg::Pair; item #ignore
156
+ when Reg::Repeat,Reg::Subseq; item.dup.expand_pairs!
157
+ else Reg::Pair.new(item,OB)
158
+ end
159
+ return self
160
+ end
161
+ end
162
+
163
+ end
164
+