reg 0.4.8 → 0.5.0a0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/regsubseq.rb
ADDED
@@ -0,0 +1,72 @@
|
|
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
|
+
require 'regarray'
|
20
|
+
module Reg
|
21
|
+
|
22
|
+
#--------------------------
|
23
|
+
class Subseq < ::Reg::Array
|
24
|
+
include Multiple,Composite
|
25
|
+
|
26
|
+
def max_matches; @regs.size end
|
27
|
+
|
28
|
+
def initialize(*regs)
|
29
|
+
regs.each{|reg|
|
30
|
+
class<<self
|
31
|
+
undef mmatch
|
32
|
+
def mmatch(*xx) mmatch_full(*xx) end
|
33
|
+
end if Multiple===reg
|
34
|
+
|
35
|
+
if reg.equal? self or (Variable===reg and reg.lit.equal? self)
|
36
|
+
raise RegParseError, "subsequence cannot directly contain itself"
|
37
|
+
end
|
38
|
+
}
|
39
|
+
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
def inspect
|
44
|
+
super.sub( /^\+/,'-')
|
45
|
+
end
|
46
|
+
|
47
|
+
def enough_matches? matchcnt,eof
|
48
|
+
matchcnt==@regs.size
|
49
|
+
end
|
50
|
+
|
51
|
+
alias itemrange subitemrange
|
52
|
+
|
53
|
+
def -@ #subsequence inclusion... that's what we are, do nothing
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def +@ #cvt to Reg::Array
|
58
|
+
Array.new(*@regs)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
#p ancestors
|
64
|
+
#tla of +[], regproc{}
|
65
|
+
#::Reg::Array.assign_TLA true, :Reg=>:Array
|
66
|
+
#::Reg::Array.assign_TLA :Res=>:Subseq
|
67
|
+
#no need to alias the constant name 'Reg', too.
|
68
|
+
#ruby does it for us.
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
end
|
data/lib/regsugar.rb
ADDED
@@ -0,0 +1,361 @@
|
|
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
|
+
=begin
|
21
|
+
this file contains the various 'convenience constructors' which might pollute the
|
22
|
+
global namespace. it's optional, but highly recommended.
|
23
|
+
|
24
|
+
(note that reg.rb calls this, so requiring 'reg' gives you global sugar by default).
|
25
|
+
=end
|
26
|
+
|
27
|
+
require 'set'
|
28
|
+
|
29
|
+
#if run within irb, disable irb's definition of _
|
30
|
+
if defined? IRB
|
31
|
+
warn "loading reg within irb; irb's definition of _ disabled"
|
32
|
+
module IRB
|
33
|
+
class Context
|
34
|
+
def set_last_value(value)
|
35
|
+
@last_value = value
|
36
|
+
#@workspace.evaluate self, "_ = IRB.CurrentContext.last_value"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
fail unless defined? WorkSpace
|
40
|
+
class WorkSpace
|
41
|
+
alias initialize_with_underscore_lvar initialize
|
42
|
+
def initialize(*main)
|
43
|
+
initialize_with_underscore_lvar(*main)
|
44
|
+
@binding=eval("def irb_binding; binding; end; irb_binding",TOPLEVEL_BINDING,__FILE__, __LINE__)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
IRB.CurrentContext.workspace.instance_variable_set(:@binding,
|
49
|
+
eval("def irb_binding; binding; end; irb_binding",TOPLEVEL_BINDING,__FILE__, __LINE__)
|
50
|
+
) if IRB.CurrentContext
|
51
|
+
end
|
52
|
+
|
53
|
+
#tla sugar moved into the related files plus central stuff in regcore.rb
|
54
|
+
#(maybe the regcore stuff can move here?,,, but sugar is supposed to be optional...\
|
55
|
+
|
56
|
+
|
57
|
+
#need tlas for Reg::Knows, Reg::Symbol
|
58
|
+
|
59
|
+
class Array
|
60
|
+
def +@
|
61
|
+
::Reg::Array.new(*self)
|
62
|
+
end
|
63
|
+
def -@
|
64
|
+
::Reg::Subseq.new(*self)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class Hash
|
69
|
+
def +@
|
70
|
+
::Reg::Hash.new(self)
|
71
|
+
end
|
72
|
+
def -@
|
73
|
+
::Reg::Object.new(self)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Symbol
|
78
|
+
def [](*args)
|
79
|
+
huh #is the [] method even defined below?
|
80
|
+
::Reg::Knows.new(self)[*args]
|
81
|
+
end
|
82
|
+
|
83
|
+
def **(other)
|
84
|
+
reg ** other
|
85
|
+
end
|
86
|
+
|
87
|
+
def -@
|
88
|
+
#item_that.respond_to?(self).reg
|
89
|
+
::Reg::Knows.new(self)
|
90
|
+
end
|
91
|
+
|
92
|
+
def ~
|
93
|
+
::Reg::BoundRef.new(self)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
class String
|
97
|
+
def -@
|
98
|
+
#item_that.respond_to?(self).reg
|
99
|
+
::Reg::Knows.new(self)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
class Regexp
|
105
|
+
#just like the original version of ::Regexp#~
|
106
|
+
#(except this takes an optional argument to
|
107
|
+
#compare against something else.)
|
108
|
+
def cmp(other=$_);
|
109
|
+
self =~ other
|
110
|
+
end
|
111
|
+
|
112
|
+
include ::Reg::Reg
|
113
|
+
|
114
|
+
def matches_class; ::String end
|
115
|
+
|
116
|
+
#creates a Regexp that works with symbols instead of strings
|
117
|
+
def sym; ::Reg::Symbol.new(self) end
|
118
|
+
|
119
|
+
#take over Regexp#~ to mean 'not' rather than 'compare to $_'
|
120
|
+
#eval needed to avoid "class inside of def" syntax error
|
121
|
+
#negates the sense of receiver regexp. returns something that matches everything
|
122
|
+
#that the original didn't, (including all non-Strings!).
|
123
|
+
undef ~
|
124
|
+
alias ~ not
|
125
|
+
end
|
126
|
+
|
127
|
+
class Module
|
128
|
+
include ::Reg::Reg
|
129
|
+
#if the right side of oper & is also a Module...
|
130
|
+
#could provide custom version of & here (and in Class)
|
131
|
+
#to return not just a matcher, but a Module that combines
|
132
|
+
#the two Modules... several complexities here.
|
133
|
+
end
|
134
|
+
|
135
|
+
class Range
|
136
|
+
include ::Reg::Reg
|
137
|
+
|
138
|
+
#could provide custom versions of &, |, maybe even ^ over Ranges
|
139
|
+
def &(range)
|
140
|
+
::Range===range or return super
|
141
|
+
l,rl=last,range.last
|
142
|
+
l=l.pred if le=exclude_end?
|
143
|
+
rl=rl.pred if re=range.exclude_end?
|
144
|
+
l,le=*case l<=>rl
|
145
|
+
when -1; [l,le]
|
146
|
+
when 0; [l,le&&re]
|
147
|
+
when 1; [rl,re]
|
148
|
+
else return super
|
149
|
+
end
|
150
|
+
return ::Range.new([first,range.first].max, l, le)
|
151
|
+
rescue
|
152
|
+
return super
|
153
|
+
end
|
154
|
+
|
155
|
+
def |(range)
|
156
|
+
::Range===range or return super
|
157
|
+
l,rl=last,range.last
|
158
|
+
l=l.pred if le=exclude_end?
|
159
|
+
rl=rl.pred if re=range.exclude_end?
|
160
|
+
if self===range.last
|
161
|
+
::Range.new([first,range.first].min, self.last, le)
|
162
|
+
elsif range===self.last
|
163
|
+
::Range.new([first,range.first].min, range.last, re)
|
164
|
+
else
|
165
|
+
super
|
166
|
+
end
|
167
|
+
rescue
|
168
|
+
return super
|
169
|
+
end
|
170
|
+
|
171
|
+
def ^(range)
|
172
|
+
::Range===range or return super
|
173
|
+
l,rl=last,range.last
|
174
|
+
l=l.pred if le=exclude_end?
|
175
|
+
rl=rl.pred if re=range.exclude_end?
|
176
|
+
|
177
|
+
if first==range.first
|
178
|
+
if last<range.last
|
179
|
+
return super unless exclude_end?
|
180
|
+
::Range.new(last,range.last,range.exclude_end?)
|
181
|
+
else
|
182
|
+
return super unless range.exclude_end?
|
183
|
+
::Range.new(range.last,last,exclude_end?)
|
184
|
+
end
|
185
|
+
elsif last==range.last and exclude_end?()==range.exclude_end?
|
186
|
+
if first<range.first
|
187
|
+
first...range.first
|
188
|
+
else
|
189
|
+
range.first...first
|
190
|
+
end
|
191
|
+
else
|
192
|
+
super
|
193
|
+
end
|
194
|
+
rescue
|
195
|
+
return super
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
class Set
|
200
|
+
#&|^+- are already defined in Set... resolved by piracy below
|
201
|
+
include ::Reg::Reg
|
202
|
+
include ::Reg::Undoable #just pretending here, to force Reg::Hash et al to use #mmatch_full instead of #===
|
203
|
+
|
204
|
+
def mmatch(progress)
|
205
|
+
other=progress.cursor.readahead1
|
206
|
+
include? other and return [true,1]
|
207
|
+
end
|
208
|
+
#don't re-define ===; could break case statements that use Set in when expressions
|
209
|
+
|
210
|
+
def >>(repl)
|
211
|
+
class<<copy=dup
|
212
|
+
def === other; include? other end
|
213
|
+
end
|
214
|
+
Reg::Transform.new(copy,repl)
|
215
|
+
end
|
216
|
+
|
217
|
+
#need an optimized ~ that returns a Set-like...
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
class Object
|
222
|
+
%w[item_that item_is regproc BR BackRef].each{|name|
|
223
|
+
eval "def #{name}(*a,&b) ::Reg.#{name}(*a,&b) end\n"
|
224
|
+
}
|
225
|
+
end
|
226
|
+
|
227
|
+
=begin
|
228
|
+
def Object.+ list
|
229
|
+
huh
|
230
|
+
end
|
231
|
+
|
232
|
+
def Array.+ list
|
233
|
+
huh
|
234
|
+
end
|
235
|
+
|
236
|
+
def Array./ list
|
237
|
+
huh
|
238
|
+
end
|
239
|
+
|
240
|
+
def String.+ list
|
241
|
+
huh
|
242
|
+
end
|
243
|
+
|
244
|
+
def Hash.+ list
|
245
|
+
huh
|
246
|
+
end
|
247
|
+
=end
|
248
|
+
|
249
|
+
module ::Reg
|
250
|
+
|
251
|
+
module Sugar
|
252
|
+
class << self
|
253
|
+
|
254
|
+
@@oplookup = {
|
255
|
+
:"+" => :"op_plus",
|
256
|
+
:"-" => :"op_minus",
|
257
|
+
:"+@" => :"op_plus_self",
|
258
|
+
:"-@" => :"op_minus_self",
|
259
|
+
:"*" => :"op_mul",
|
260
|
+
:"**" => :"op_pow",
|
261
|
+
:"/" => :"op_div",
|
262
|
+
:"%" => :"op_mod",
|
263
|
+
:"<<" => :"op_lshift",
|
264
|
+
:">>" => :"op_rshift",
|
265
|
+
:"~" => :"op_tilde",
|
266
|
+
:"<=>" => :"op_cmp",
|
267
|
+
:"<" => :"op_lt",
|
268
|
+
:">" => :"op_gt",
|
269
|
+
:"==" => :"op_equal",
|
270
|
+
:"<=" => :"op_lt_eq",
|
271
|
+
:">=" => :"op_gt_eq",
|
272
|
+
:"===" => :"op_case_eq",
|
273
|
+
:"=~" => :"op_apply",
|
274
|
+
:"|" => :"op_or",
|
275
|
+
:"&" => :"op_and",
|
276
|
+
:"^" => :"op_xor",
|
277
|
+
:"[]" => :"op_fetch",
|
278
|
+
:"[]=" => :"op_store"
|
279
|
+
}
|
280
|
+
|
281
|
+
|
282
|
+
def alphabetic_name(meth)
|
283
|
+
@@oplookup[meth] or case meth
|
284
|
+
when /\?$/; :"op_#{meth[0...-1]}_p"
|
285
|
+
when /!$/; :"op_#{meth[0...-1]}_bang"
|
286
|
+
when /=$/; :"op_#{meth[0...-1]}_setter"
|
287
|
+
when /^op_/; :"op_#{meth}"
|
288
|
+
else meth
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
|
293
|
+
#override klass's exisiting version of meth
|
294
|
+
#in cases where the argument to meth has the
|
295
|
+
#class of exception, delegate back to the existing
|
296
|
+
#version of meth. otherwise, the Reg::Reg version
|
297
|
+
#of meth is invoked.
|
298
|
+
def pirate_school(klass,meth,exception)
|
299
|
+
|
300
|
+
klass=klass.to_s; exception=exception.to_s
|
301
|
+
/^::/===klass or klass="::#{klass}"
|
302
|
+
/^::/===exception or exception="::#{exception}"
|
303
|
+
eval %{
|
304
|
+
class #{klass}
|
305
|
+
setmeth=instance_method :#{meth}
|
306
|
+
undef #{meth}
|
307
|
+
regmeth= ::Reg::Reg.instance_method :#{meth}
|
308
|
+
define_method :#{meth} do |other|
|
309
|
+
#{exception}===other and return setmeth.bind(self).call(other)
|
310
|
+
regmeth.bind(self).call(other)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
}
|
314
|
+
end
|
315
|
+
|
316
|
+
|
317
|
+
|
318
|
+
end
|
319
|
+
|
320
|
+
#extend Set's version of certain operators to respect the
|
321
|
+
#reg versions as well. (The type of the rhs determines which
|
322
|
+
#version is used.)
|
323
|
+
[:+, :-, :&, :|, :^ ].each {|opname|
|
324
|
+
pirate_school ::Set, opname, ::Enumerable
|
325
|
+
} if ::Reg::Reg>::Set
|
326
|
+
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
|
331
|
+
BR=::Reg::BR
|
332
|
+
|
333
|
+
Any=::Reg::Any if defined? ::Reg::Any
|
334
|
+
Many=::Reg::Many if defined? ::Reg::Many
|
335
|
+
None=::Reg::None if defined? ::Reg::None
|
336
|
+
|
337
|
+
def _; ::Reg::Any end
|
338
|
+
def __; ::Reg::Many end
|
339
|
+
|
340
|
+
#older names... to be obsoleted someday?
|
341
|
+
OB=::Reg::OB if defined? ::Reg::OB
|
342
|
+
OBS=::Reg::OBS if defined? ::Reg::OBS
|
343
|
+
|
344
|
+
Rah=::Reg::Hash
|
345
|
+
def Rah(hash={}) ::Reg::Hash.new(hash) end
|
346
|
+
alias matches_hash Rah
|
347
|
+
|
348
|
+
Res=::Reg::Subseq
|
349
|
+
def Res(*args) ::Reg::Subseq.new(args) end
|
350
|
+
alias matches_subsequence Res
|
351
|
+
alias matches_subseq matches_subsequence
|
352
|
+
|
353
|
+
Rob=::Reg::Object
|
354
|
+
def Rob(hash={}) ::Reg::Object.new(hash) end
|
355
|
+
alias matches_object Rob
|
356
|
+
alias matches_obj matches_object
|
357
|
+
|
358
|
+
def Reg(*args) ::Reg::Array.new(args) end
|
359
|
+
alias matches_array Reg
|
360
|
+
alias matches_arr matches_array
|
361
|
+
|
data/lib/regvar.rb
ADDED
@@ -0,0 +1,180 @@
|
|
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 'regdeferred' #for BlankSlate
|
21
|
+
require "ron"
|
22
|
+
|
23
|
+
module Reg
|
24
|
+
def self.minlen_formula regx, session={}
|
25
|
+
x=session[regx.__id__] and return x
|
26
|
+
session[regx.__id__]="x#{session.size}_"
|
27
|
+
|
28
|
+
case regx
|
29
|
+
when Repeat; "("+minlen_formula(regx.reg(x), session )+")*"+regx.range.first.to_s
|
30
|
+
when Subseq; regx.regs.map{|r| minlen_formula(r, session) }.join'+'
|
31
|
+
when Variable; minlen_formula(regx.lit,session)
|
32
|
+
when LookAhead,LookBehind; '0'
|
33
|
+
when And; "[#{regx.regs.map{|r| minlen_formula(r, session) }.join', '}].max"
|
34
|
+
when Or,Xor; "[#{regx.regs.map{|r| minlen_formula(r, session) }.join', '}].min"
|
35
|
+
when Not; (regx.reg.itemrange==(1..1)) ? 1 : 0
|
36
|
+
when Many; '0'
|
37
|
+
else '1'
|
38
|
+
end
|
39
|
+
huh
|
40
|
+
ensure
|
41
|
+
session.delete regx.__id__
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.maxlen_formula regx, session={}
|
45
|
+
x=session[regx.__id__] and return x
|
46
|
+
session[regx.__id__]="x#{session.size}_"
|
47
|
+
|
48
|
+
case regx
|
49
|
+
when Repeat; "("+maxlen_formula(regx.reg(x), session )+")*"+regx.range.last.to_s
|
50
|
+
when Subseq; regx.regs.map{|r| maxlen_formula(r, session) }.join'+'
|
51
|
+
when Variable; maxlen_formula(regx.lit,session)
|
52
|
+
when LookAhead,LookBehind; '0'
|
53
|
+
when And; "[#{regx.regs.map{|r| maxlen_formula(r, session) }.join', '}].max"
|
54
|
+
when Or,Xor; "[#{regx.regs.map{|r| maxlen_formula(r, session) }.join', '}].max"
|
55
|
+
when Not; (regx.reg.itemrange==(1..1)) ? 1 : 0
|
56
|
+
when Many; 'Infinity'
|
57
|
+
else '1'
|
58
|
+
end
|
59
|
+
huh
|
60
|
+
ensure
|
61
|
+
session.delete regx.__id__
|
62
|
+
end
|
63
|
+
|
64
|
+
class Variable < Fixed
|
65
|
+
include Reg,Multiple,Undoable
|
66
|
+
#include BlankSlate
|
67
|
+
#restore :hash
|
68
|
+
|
69
|
+
#fer gawds sake, why BlankSlate??!!!
|
70
|
+
|
71
|
+
#we should only be Multiple and Undoable if @to is as well.
|
72
|
+
#unfortunately, we don't know what @to is when we construct the Variable,
|
73
|
+
#(and its value may change subsequently), so we'll make the conservative
|
74
|
+
#assumption that @to is Multiple and Undoable and so we must be also.
|
75
|
+
|
76
|
+
def initialize(*a);
|
77
|
+
super(*a)
|
78
|
+
@to=@o #get rid of @to eventually
|
79
|
+
@inspect=nil
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
def set!(areg)
|
87
|
+
|
88
|
+
@to=@o=areg
|
89
|
+
@inspect=nil
|
90
|
+
class<<self
|
91
|
+
def method_missing msg, *args, &block
|
92
|
+
@to.send msg, *args, &block
|
93
|
+
end
|
94
|
+
eval [ :itemrange,:subitemrange,].map {|name|
|
95
|
+
"
|
96
|
+
def #{name}(*a,&b)
|
97
|
+
name='$RegVarItemRangeRecursing#{object_id}'
|
98
|
+
if Thread.current[name]
|
99
|
+
warning 'hacking itemrange of Reg::var'
|
100
|
+
#this is an approximation
|
101
|
+
#if I can get an equation solver, this won't hack won't be needed
|
102
|
+
(0..Infinity)
|
103
|
+
else
|
104
|
+
Thread.current[name]=true
|
105
|
+
result=@o.#{name}(*a,&b)
|
106
|
+
Thread.current[name]=nil
|
107
|
+
result
|
108
|
+
end
|
109
|
+
end
|
110
|
+
"
|
111
|
+
}.join+
|
112
|
+
[ :subregs,:to_h].map {|name|
|
113
|
+
"
|
114
|
+
def #{name}(*a,&b)
|
115
|
+
@o.#{name}(*a,&b)
|
116
|
+
end
|
117
|
+
"
|
118
|
+
}.join
|
119
|
+
|
120
|
+
alias_method :cmatch, :cmatch_jit_compiler if instance_methods.include? "cmatch"
|
121
|
+
alias_method :bmatch, :bmatch_jit_compiler if instance_methods.include? "bmatch"
|
122
|
+
end
|
123
|
+
self
|
124
|
+
end
|
125
|
+
|
126
|
+
@@inspectcount=0
|
127
|
+
def _inspect
|
128
|
+
tvname="$RegVarInspectRecursing#{object_id}"
|
129
|
+
Thread.current[tvname] or begin
|
130
|
+
Thread.current[tvname]=name="var#{@@inspectcount+=1}"
|
131
|
+
result="Recursive(#{name}={}, #{@to.inspect})"
|
132
|
+
Thread.current[tvname]=nil
|
133
|
+
result
|
134
|
+
end
|
135
|
+
end
|
136
|
+
def inspect
|
137
|
+
@inspect and return @inspect
|
138
|
+
@inspect=_inspect
|
139
|
+
end
|
140
|
+
|
141
|
+
def formula_value(*ctx) #not sure about this...
|
142
|
+
@to
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
#a Constant is like a Variable, except it can only be #set! once.
|
147
|
+
#Constant should really be the superclass of Variable, not the other way around...
|
148
|
+
class Constant < Variable
|
149
|
+
def set!(areg)
|
150
|
+
super
|
151
|
+
def self.set!
|
152
|
+
raise TypeError,'Reg::Constant can only be set once'
|
153
|
+
end
|
154
|
+
result=Ron::Recursive( self, areg )
|
155
|
+
freeze
|
156
|
+
result
|
157
|
+
end
|
158
|
+
|
159
|
+
def inspect
|
160
|
+
_inspect.sub 'var;', 'const;'
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
class <<self
|
166
|
+
#Reg::Variable convenience constructor.
|
167
|
+
def variable
|
168
|
+
::Reg::Variable.new
|
169
|
+
end
|
170
|
+
alias var variable
|
171
|
+
|
172
|
+
#Reg::Constant convenience constructor.
|
173
|
+
def constant
|
174
|
+
::Reg::Constant.new
|
175
|
+
end
|
176
|
+
alias const constant
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
end
|