reg 0.4.6

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