reg 0.4.8 → 0.5.0a0

Sign up to get free protection for your applications and to get access to all the features.
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