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
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
|