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,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
@@ -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
+
@@ -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