reg 0.4.6

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.
@@ -0,0 +1,126 @@
1
+ =begin copyright
2
+ reg - the ruby extended grammar
3
+ Copyright (C) 2005 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 'pp'
20
+ require 'regdeferred'
21
+
22
+ module Reg
23
+
24
+ =begin
25
+ #----------------------------------
26
+ module Block
27
+ # include Formula
28
+
29
+ attr_writer :klass #for internal use only
30
+
31
+ def eeee(val)
32
+ @klass and @klass===val || return
33
+ begin call(val)
34
+ rescue: false
35
+ end
36
+ end
37
+ alias === eeee #does nothing in includers.... why?
38
+ alias formula_value eeee
39
+
40
+
41
+ def mixmod; ItemThatLike end
42
+ def reg; extend Reg end
43
+ end
44
+ #----------------------------------
45
+ module ItemThatLike
46
+ def eee(item)
47
+ begin formula_value item
48
+ rescue: false
49
+ end
50
+ end
51
+ alias === eee #this doesn't work!!! WHY????
52
+ #there's no way to define the method === in this
53
+ #module and have it be defined in class ItemThat.
54
+ #mixmod and reg don't have this problem. this must
55
+ #be a bug. for now, I work around it with clever
56
+ #alias/undefing in places that include/extend ItemThatLike
57
+ #(seemingly, this is only a problem when including, not extending... dunno why)
58
+ #this bug may be gone now; need to try to get rid of weird eee stuff.
59
+
60
+ def mixmod; ItemThatLike end
61
+ def reg; extend Reg end
62
+ end
63
+ #----------------------------------
64
+ class ItemThat
65
+ include BlankSlate
66
+ restore :inspect,:extend
67
+ include Formula
68
+ include ItemThatLike
69
+ alias === eee
70
+ undef eee
71
+ def initialize(klass=nil)
72
+ @klass=klass
73
+ end
74
+
75
+ def formula_value(val,*rest)
76
+ #the exception raised here should be (eventually) caught by
77
+ #the handler in ItemThatLike#eee. calling ItemThat#formula_value isn't
78
+ #really legitimate otherwise.
79
+ @klass and @klass===val || fail("item_that constraint mismatch")
80
+
81
+ val
82
+ end
83
+
84
+ end
85
+ =end
86
+ #----------------------------------
87
+ module BackrefLike
88
+ def mmatch(ary,idx)
89
+ huh #need info thats not_in ary or idx
90
+ end
91
+
92
+ def mixmod; BackrefLike end
93
+ end
94
+ #----------------------------------
95
+ class Backref
96
+ include BlankSlate
97
+ restore :inspect,:extend
98
+ include Formula
99
+ include BackrefLike
100
+ def initialize(name,*path)
101
+ #complex paths not handled yet
102
+ raise ParameterError.new unless path.empty? and Reg|Symbol===name
103
+ @name=name
104
+ end
105
+
106
+ def formula_value(*ctx)
107
+ progress=ctx[1]
108
+ progress.variables[@name]
109
+ end
110
+
111
+ class<<self
112
+ alias [] new
113
+ end
114
+ end
115
+
116
+
117
+ #----------------------------------
118
+ module BRLike
119
+ include BackrefLike
120
+ include Reg
121
+ def mixmod; BRLike end
122
+ end
123
+ class BR < Backref
124
+ include BRLike
125
+ end
126
+ end
@@ -0,0 +1,74 @@
1
+ =begin copyright
2
+ reg - the ruby extended grammar
3
+ Copyright (C) 2005 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
+ module Reg
21
+ def bind(name=self)
22
+ Bound.new(name,self)
23
+ end
24
+ alias << bind
25
+
26
+ def side_effect(&block); SideEffect.new(self,&block) end
27
+ def undo(&block); Undo.new(self,&block) end
28
+ end
29
+
30
+ #-------------------------------------
31
+ class Bound
32
+ include Reg
33
+ def initialize(name,reg)
34
+ @name,@reg=name,reg
35
+ end
36
+
37
+
38
+ def mmatch(progress)
39
+ result=@reg.mmatch(progress) and
40
+ progress.register_var(@name,@reg)
41
+ return result
42
+ end
43
+ end
44
+
45
+ #-------------------------------------
46
+ class SideEffect
47
+ include Reg
48
+
49
+ def initialize(reg,&block)
50
+ @reg,@block=reg,block
51
+ end
52
+
53
+ def mmatch(progress)
54
+ result=@reg.mmatch(progress) and
55
+ @block.call(progress)
56
+ return result
57
+ end
58
+ end
59
+
60
+ #------------------------------------
61
+ class Undo
62
+ include Reg
63
+
64
+ def initialize(reg,&block)
65
+ @reg,@block=reg,block
66
+ end
67
+
68
+ def mmatch(progress)
69
+ result=@reg.mmatch(progress) and
70
+ progress.register_undo(@block)
71
+ return result
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,78 @@
1
+ =begin copyright
2
+ reg - the ruby extended grammar
3
+ Copyright (C) 2005 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
+ class Case
21
+ def initialize(*args)
22
+ if args.size==1 and Hash===args.first
23
+ scalars=[]; sets=[]
24
+ matchers=[];
25
+
26
+ args.first.each{|k,v|
27
+ if Reg.interesting_matcher? k
28
+ matchers<<k.reg**v
29
+ elsif Set===k
30
+ sets<<k.reg**v
31
+ else
32
+ scalars<<k.reg**v
33
+ end
34
+ }
35
+ args=scalars+sets+matchers
36
+ end
37
+
38
+ @others=others_given=nil
39
+ @pairlist=args.delete_if{|a|
40
+ if !(Pair===a)
41
+ warn "ignoring non-Reg::Pair in Reg::Case: #{a}"
42
+ true
43
+ elsif OB==a.left
44
+ others_given and warn 'more than one default specified'
45
+ others_given=true
46
+ @others=v
47
+ end
48
+ }
49
+ end
50
+
51
+ def ===(other)
52
+ @pairlist.each{|pair|
53
+ pair.left===other and pair.right===other || return
54
+ }
55
+ @others===other
56
+ end
57
+
58
+ #hash-based optimization of scalars and sets is possible here
59
+
60
+ def previous_matchers(val,*)
61
+ val #by default, do nothing
62
+ end
63
+
64
+ def previous_matchers_ordered(val,index,other)
65
+ val,index=*args
66
+ (0..index).each{|i|
67
+ pair=@pairlist[i]
68
+
69
+ pair.left===other and pair.right===other || return
70
+ }
71
+
72
+ end
73
+
74
+ end
75
+
76
+ Rac=Case #tla of case
77
+ assign_TLA :Rac=>:Case
78
+ end
@@ -0,0 +1,379 @@
1
+ =begin copyright
2
+ reg - the ruby extended grammar
3
+ Copyright (C) 2005 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 'trace.rb'
21
+
22
+ module Reg #namespace
23
+
24
+
25
+
26
+
27
+ INFINITY= (
28
+ result= [ Float::MAX**Float::MAX, Float::MAX**2, Float::MAX*2].max
29
+ result.infinite? ? result :
30
+ begin result=1.0/0
31
+ rescue: Float::MAX #maybe 1.0/0 doesn't work on some systems?
32
+ end
33
+ )
34
+ #there's also this way: 999999999999999999999999999999999999999999999999e999999999999999999999999999999
35
+ #but stuff like that sometimes returns zero, so it doesn't seem as reliable.
36
+ #(plus it generates a warning)
37
+
38
+ INFINITY>1_000_000 or raise 'INFINITY is too small'
39
+ INFINITY.to_f.infinite? or warn "INFINITY is merely very large, not infinite"
40
+
41
+
42
+ #--------------------------
43
+ #abstact ancestor of all reg classes
44
+ module Reg
45
+
46
+ #=== must be defined in the includer for the appropriate types
47
+ #and some others:
48
+ #itemrange
49
+ #scalar?, vector?, multiple?, variable?, multilength?, fixed?
50
+ #starts_with
51
+ #ends_with
52
+ #breakdown
53
+ #what else?
54
+
55
+ #--------------------------
56
+ def =~(other)
57
+ self===other
58
+ end
59
+
60
+ #--------------------------
61
+ #low-precedence method call
62
+ def <=>(other)
63
+ send other
64
+ end
65
+
66
+ #--------------------------
67
+ alias pristine_inspect inspect
68
+ def pp_inspect
69
+ pp pristine_inspect
70
+ end
71
+
72
+
73
+ #--------------------------
74
+ #makes a Reg object literal (aliased to +@ by default)
75
+ def lit
76
+ Literal.new(self)
77
+ end
78
+ def +@; lit end
79
+
80
+ #--------------------------
81
+ #makes a version of self suitable for use in Reg matching
82
+ #expressions. in subclasses of Reg this just returns self.
83
+ def reg; self end
84
+
85
+ #--------------------------
86
+ #returns a (vector) Reg that will match a list of self
87
+ #separated by other. watch out if other and self might
88
+ #match the same thing(s).
89
+ def sep other; -[self,-[other,self]+0]; end
90
+
91
+ #--------------------------
92
+ #returns a (vector) Reg that will match a list of stuff
93
+ #separated by self. somewhat analogous to Regexp#split,
94
+ #but returns the separators as well.
95
+ def splitter; (~self+0).sep self; end
96
+
97
+ #--------------------------
98
+ #set a breakpoint when matches against a Reg
99
+ #are made. of dubious value to those unfamiliar
100
+ #with Reg::Array source code.
101
+ def bp #:nodoc: all
102
+ class <<self #:nodoc:
103
+ alias_method :unbroken___eee, :=== #:nodoc:
104
+ alias_method :unbroken___mmatch,
105
+ method_defined?(:mmatch) ? :mmatch : :fail #:nodoc:
106
+ def ===(other) #:nodoc:
107
+ defined? DEBUGGER__ and Process.kill("INT",0)
108
+ unbroken___eee other
109
+ end
110
+
111
+ def mmatch(arr,start) #:nodoc:
112
+ defined? DEBUGGER__ and Process.kill("INT",0)
113
+ unbroken___mmatch arr,start
114
+ end
115
+ end
116
+ self
117
+ end
118
+
119
+ #--------------------------
120
+ #return a list of sub Regs of this Reg (if any)
121
+ def subregs
122
+ []
123
+ end
124
+
125
+ #--------------------------
126
+ #a simple reg that always starts this reg
127
+ def starts_with
128
+ self
129
+ end
130
+
131
+ #--------------------------
132
+ #a simple reg that always ends this reg
133
+ def ends_with
134
+ self
135
+ end
136
+
137
+ #--------------------------
138
+ def Reg.interesting_matcher?(mat) #a hack
139
+ case mat
140
+ when ItemThatLike,BackrefLike,Module,Set,Regexp,Range,::Reg::Reg: true
141
+ #when Symbol,Pathname: false
142
+ else
143
+ /^#<UnboundMethod: .*\(Kernel\)#===>$/===mat.method(:===).unbind.inspect and return false
144
+
145
+ eee_call=nil
146
+ result=!trace(proc do|event,*stuff|
147
+ if /call$/===event
148
+ eee_call=stuff
149
+
150
+ #attempt to remain debuggable while restoring the old trace func
151
+ set_trace_func((defined? DEBUGGER__ and (DEBUGGER__.context.method:trace_func).to_proc))
152
+ end
153
+ end){mat===mat}; line=__LINE__
154
+ assert eee_call[0] == __FILE__
155
+ assert eee_call[1] == line
156
+ assert eee_call[2] == :===
157
+ assert eee_call[3].class == Binding
158
+ assert Module===eee_call[4].class
159
+ return eee_call[4]!=Kernel && result
160
+ end
161
+ end
162
+
163
+ #--------------------------
164
+ def interesting_matcher?(mat=self)
165
+ Reg.interesting_matcher? mat
166
+ end
167
+
168
+ #--------------------------
169
+ #*,+,- are defined in regarray.rb
170
+ #~,&,|,^ are defined in reglogic.rb
171
+ #** is in reghash.rb
172
+ #<< and side_effect,undo in regbind.rb
173
+ #>> and later in regreplace.rb
174
+ #la,lb in reglookab.rb
175
+
176
+
177
+
178
+ #--------------------------
179
+ =begin seems risky... disabled til I know why i want it
180
+ def coerce(other)
181
+ if Reg===other
182
+ [other,self]
183
+ else
184
+ [other.reg,self]
185
+ end
186
+ end
187
+ =end
188
+ #--------------------------
189
+ def mmatch(ary,idx)
190
+ assert idx<=ary.size
191
+ idx==ary.size and return nil
192
+ self===ary[idx] and [[[ary[idx]]],1]
193
+ end
194
+
195
+ protected
196
+ #--------------------------
197
+ def maybe_multiples(*regs)
198
+ regs.each{|reg|
199
+ reg.respond_to? :maybe_multiple and
200
+ reg.maybe_multiple(self)
201
+ }
202
+ end
203
+
204
+ #--------------------------
205
+
206
+ #eventually, this will be a list of all tla mappings
207
+ RegMethods=proc do
208
+ @@TLAs={}
209
+ define_method :assign_TLA do |*args|
210
+ hash=args.pop #extract hash from args
211
+ noconst,*bogus=*args #peel noconst off front of args
212
+ hash.each{|k,v|
213
+ v=@@TLAs[k]= noconst ? [v,true] : v #fold noconst into v (longname) and store in @@TLAs
214
+ TLA_aliases k,v #always alias the TLA into ::Reg namespace
215
+ }
216
+ end
217
+
218
+
219
+ alias_method :assign_TLAs, :assign_TLA
220
+
221
+ define_method :TLA_aliases do |short,long_args,*rest| myself=rest.first||::Object
222
+ long=nil
223
+ if ::Array===long_args
224
+ long=long_args.shift
225
+ noconst=long_args.shift #unfold noconst from long if folded
226
+ else
227
+ long=long_args
228
+ end
229
+ myself.const_set(short,::Reg::const_get(long)) unless noconst #alias the constant name
230
+
231
+ long=(::Reg.const_get long) #convert long from symbol to a module or class
232
+ myself.send:define_method, short do|*args| long.new( *args) end #forward short name to long
233
+ end
234
+ end
235
+ def self.included(mod)
236
+ (class<<mod;self;end).instance_eval( &RegMethods )
237
+ end
238
+
239
+ TLA_pirate= proc { @@TLAs.each{|k,v| Reg.TLA_aliases k,v,self} }
240
+
241
+
242
+ end
243
+ TLA_pirate= Reg::TLA_pirate
244
+ #the tlas (and where they're found):
245
+
246
+ #Rob,Rah,Rap (reghash.rb)
247
+ #Reg,Res, (regarray.rb)
248
+ #Rac, (regcase.rb)
249
+ #Rip (right here, regcore.rb)-----v
250
+
251
+
252
+ #--------------------------
253
+ class Wrapper
254
+
255
+ include Reg
256
+ def initialize(o)
257
+ @o=o
258
+ end
259
+
260
+ def matches_class; @o.class end
261
+ def lit; @o end
262
+ alias unwrap lit
263
+
264
+ def inspect
265
+ "(#{@o.inspect}).reg"
266
+ end
267
+
268
+ def ===x; raise NoMethodError.new( "Reg::Wrapper") end
269
+
270
+ end
271
+
272
+
273
+ #--------------------------
274
+ class Fixed < Wrapper #matches like a plain object, but responds to Reg#|, etc
275
+ #but still behaves in a match just like the unadorned obj (uses === to match)
276
+ def ===(other)
277
+ @o===other
278
+ end
279
+ end
280
+
281
+
282
+ #--------------------------
283
+ class Equals < Wrapper #like Reg::Fixed, but == instead of ===
284
+ def ===(other)
285
+ @o==other
286
+ end
287
+ end
288
+
289
+ #--------------------------
290
+ class Literal < Equals #a literalized Reg
291
+ def reg; @o end
292
+ def lit; Literal.new self end
293
+ def unlit; @o end
294
+
295
+ def formula_value(*ctx)
296
+ @o
297
+ end
298
+ end
299
+
300
+ #--------------------------
301
+ class ::Object
302
+ #turns any object into a matcher which matches the same
303
+ #thing that the object matches, except it's also a Reg::Reg,
304
+ #and thus respects reg's meanings of: +,*,>>,&,~, etc
305
+ #the generic case creates a wrapper Reg around any object whose ===
306
+ #forwards to the wrapped object's ===. the original object is
307
+ #unchanged.
308
+ def reg
309
+ Fixed.new(self)
310
+ end
311
+
312
+ #
313
+ def lit
314
+ self
315
+ end
316
+
317
+ #just like ===, but receiver and argument are switched.
318
+ #for those situations where you just have to put the item
319
+ #to match to the left, and the pattern on the right.
320
+ def matches pattern
321
+ pattern===self
322
+ end
323
+ end
324
+
325
+ #--------------------------
326
+ String=::Regexp
327
+
328
+ #--------------------------
329
+ class Symbol
330
+ include Reg
331
+
332
+ def initialize(rex)
333
+ @rex=rex
334
+ end
335
+
336
+ def matches_class; ::Symbol end
337
+
338
+ def ===(other)
339
+ ::Symbol===other and m=@rex.match(other.to_s) and m[0]
340
+ end
341
+
342
+ def inspect
343
+ @rex.inspect+'.sym'
344
+ end
345
+ end
346
+
347
+ #a dynamically created Reg
348
+ def (::Reg).regproc klass=::Object,&block
349
+ class <<block
350
+ include Interpret
351
+ end
352
+ block.klass=klass
353
+ block
354
+ end
355
+
356
+
357
+
358
+ #--------------------------
359
+ module Interpret #a Reg whose makeup isn't determined until runtime.
360
+ include Reg
361
+ def klass=(k) @@klass=k end
362
+ def ===(other)
363
+ @@klass===other || return
364
+ r=call
365
+ #eventually pass params to call
366
+ Reg::Multiple===r and raise 'this oughtta work, but doesn`t yet'
367
+ r===other
368
+ end
369
+ def matches_class; @@klass end
370
+ alias starts_with matches_class
371
+ alias ends_with matches_class
372
+
373
+
374
+ assign_TLA true, :Rip=>:Interpret
375
+ end
376
+
377
+
378
+
379
+ end