grammar 0.5 → 0.8

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,1030 @@
1
+ require 'thread'
2
+
3
+ class Grammar
4
+ class Ruby
5
+
6
+ # TODO: better list delimiter handling
7
+
8
+ class Code # :nodoc:
9
+ instance_methods.each { |m|
10
+ next if m.to_s[0]==?_
11
+ next if m.to_s=="object_id"
12
+ send(:alias_method, "_#{m}", m)
13
+ undef_method(m)
14
+ }
15
+ private_instance_methods.each { |m|
16
+ next if m.to_s=="initialize"
17
+ send(:alias_method, "_#{m}", m)
18
+ undef_method(m)
19
+ }
20
+ def self.[](object)
21
+ case object
22
+ when NilClass
23
+ Nil
24
+ when FalseClass
25
+ False
26
+ when TrueClass
27
+ True
28
+ when Fixnum,Symbol,Module # last 3 not really immediates
29
+ Immediate.new(object)
30
+ else
31
+ s = object.inspect
32
+ begin
33
+ object.eql?(eval(s)) && Primary.new(s)
34
+ rescue
35
+ end or
36
+ Immediate.new(Marshal).load(Primary.new(
37
+ Marshal.dump(object).inspect))
38
+ end
39
+ end
40
+ def initialize(code)
41
+ @code = code
42
+ end
43
+ def _codes
44
+ [@code]
45
+ end
46
+ def _data
47
+ nil
48
+ end
49
+ def _equal(other)
50
+ _class.equal?(other._class) && _data==other._data &&
51
+ !_codes.zip(other._codes) { |a,b|
52
+ break(true) unless a._equal(b)
53
+ }
54
+ end
55
+ def _classname
56
+ _class.name.gsub(/.*::/, "")
57
+ end
58
+ def _inspect(s="", newline="\n")
59
+ data = _data
60
+ codes = _codes
61
+ s.concat(_classname) << ?\(
62
+ s.concat(data.inspect) if data
63
+ if !codes.empty?
64
+ newline << ?\s
65
+ if codes.size==1
66
+ s.concat(", ") if data
67
+ codes[0]._inspect(s, newline)
68
+ newline[-1,1] = ""
69
+ else
70
+ codes.each { |code|
71
+ s << ?\, if data
72
+ s.concat(newline)
73
+ code._inspect(s, newline)
74
+ data = true
75
+ }
76
+ newline[-1,1] = ""
77
+ s.concat(newline)
78
+ end
79
+ end
80
+ s << ?\)
81
+ end
82
+ def _lines(text, indent=0, op=nil, maxlen=72)
83
+ @code._lines(text, indent, op, maxlen)
84
+ end
85
+ def _code_self
86
+ self
87
+ end
88
+ def _always
89
+ @code._always
90
+ end
91
+ def _never
92
+ @code._never
93
+ end
94
+ def _immediate
95
+ false
96
+ end
97
+ def _or # :yield:
98
+ _always ? self :
99
+ Or.new(yield._ror(operands = [self]))
100
+ end
101
+ def _ror(before)
102
+ before <<
103
+ (before.last._never ? before.pop._step(self) : self)
104
+ end
105
+ def _and # :yield:
106
+ _never ? self :
107
+ And.new(yield._rand(operands = [self]))
108
+ end
109
+ def _rand(before)
110
+ before <<
111
+ (before.last._always ? before.pop._step(self) : self)
112
+ end
113
+ def _step(after)
114
+ Steps.new(after._rstep(_mid([])))
115
+ end
116
+ def _rstep(before)
117
+ before << self
118
+ end
119
+ def _mid(before)
120
+ before << self
121
+ end
122
+ def _not
123
+ Not.new(self)
124
+ end
125
+ def _question(yes, no)
126
+ Conditional.new(self, yes, no)
127
+ end
128
+ def _unless(cond, yes)
129
+ Conditional.new(cond, yes, self)
130
+ end
131
+ def _rcond(before)
132
+ before << self
133
+ end
134
+ def _assign(rvalue)
135
+ Assign.new([self, rvalue])
136
+ end
137
+ def _splat
138
+ Unary.new("*", self)
139
+ end
140
+ def _to_block
141
+ Unary.new("&", self)
142
+ end
143
+ def _locals(n=0)
144
+ @locals ||= (
145
+ _codes.each { |code|
146
+ n = code._locals(n)
147
+ }
148
+ n
149
+ )
150
+ end
151
+ def _dot(method)
152
+ Dot.new(self, method)
153
+ end
154
+ def _rescue(after, exception=nil, var=nil)
155
+ Begin.new(self)._rescue(after, exception, var)
156
+ end
157
+ def _ensure(after)
158
+ Begin.new(self)._ensure(after)
159
+ end
160
+ def _else(after)
161
+ Begin.new(self)._else(after)
162
+ end
163
+ def _def(name, *args)
164
+ Def.new(name.to_s, args, self)
165
+ end
166
+ def _while(condition)
167
+ While.new(condition, self)
168
+ end
169
+ def _until(condition)
170
+ Until.new(condition, self)
171
+ end
172
+ def method_missing(method, *args, &block)
173
+ if block
174
+ call = args.empty? ? _dot(method.to_s) :
175
+ Method.new(_dot(method.to_s), *args)
176
+ Blocked.new(call, &block)
177
+ else
178
+ case method
179
+ when :**,:*,:/,:%,:+,:-,:<<,:>>,:&,:|,:^,
180
+ :>,:>=,:<,:<=,:<=>,:==,:===,:=~
181
+ Binary.new(" #{method} ", self, args[0])
182
+ when :-@,:+@,:~@
183
+ Unary.new(method.to_s[0..-2], self)
184
+ when :[]
185
+ Brackets.new(self, *args)
186
+ when :[]=
187
+ Brackets.new(self, *args[0..-2])._assign(args[-1])
188
+ else
189
+ if method.to_s[-1] == ?= and args.size==1
190
+ Dot.new(self, method.to_s[0..-2])._assign(args[-1])
191
+ elsif args.empty?
192
+ _dot(method.to_s)
193
+ else
194
+ Method.new(_dot(method.to_s), *args)
195
+ end
196
+ end
197
+ end
198
+ end
199
+ class Primary < Code
200
+ def _lines(text, indent=0, op=nil, maxlen=72)
201
+ text.last.concat(@code)
202
+ end
203
+ def _codes
204
+ []
205
+ end
206
+ def _data
207
+ @code
208
+ end
209
+ def _always
210
+ false
211
+ end
212
+ def _never
213
+ false
214
+ end
215
+ def _mid(before)
216
+ before
217
+ end
218
+ def _step(after)
219
+ after
220
+ end
221
+ def _locals(n=0)
222
+ n
223
+ end
224
+ end
225
+ class Command < Code
226
+ def _lines(text, indent=0, op=nil, maxlen=72)
227
+ text.last.concat(@code)
228
+ end
229
+ def _codes
230
+ []
231
+ end
232
+ def _data
233
+ @code
234
+ end
235
+ def _always
236
+ false
237
+ end
238
+ def _never
239
+ false
240
+ end
241
+ def _locals(n=0)
242
+ n
243
+ end
244
+ end
245
+ class Immediate < Primary
246
+ def _immediate
247
+ true
248
+ end
249
+ def _data
250
+ @code
251
+ end
252
+ def _lines(text, indent=0, op=nil, maxlen=72)
253
+ text.last.concat(@code.inspect)
254
+ end
255
+ end
256
+ class Singleton < Primary
257
+ def initialize
258
+ end
259
+ def _equal(other)
260
+ __id__.equal?(other.__id__)
261
+ end
262
+ def _lines(text, indent=0, op=nil, maxlen=72)
263
+ text
264
+ end
265
+ def _inspect(s="", newline="\n")
266
+ s
267
+ end
268
+ end
269
+ True = Class.new(Singleton) {
270
+ def _immediate; true; end
271
+ def _inspect(s="", newline="\n")
272
+ s.concat("True")
273
+ end
274
+ def _lines(text, indent=0, op=nil, maxlen=72)
275
+ text.last.concat(true.inspect)
276
+ end
277
+ def _always; true; end
278
+ def _ror (before); before << before.pop._step(self); end
279
+ def _and ; yield ; end
280
+ def _rand(before); before; end
281
+ def _not ; False ; end
282
+ }.new
283
+ FalseTerminator = Class.new(Singleton) {
284
+ def _inspect(s="", newline="\n")
285
+ s.concat("FalseTerminator")
286
+ end
287
+ def _lines(text, indent=0, op=nil, maxlen=72)
288
+ text.last.concat(false.inspect)
289
+ end
290
+ def _never; false; end
291
+ def _always; true; end
292
+ def _ror (before); before << Always.new(before.pop); end
293
+ def _and ; raise("#{inspect} &&"); end
294
+ def _or ; raise("#{inspect} ||"); end
295
+ def _not ; raise("!#{inspect}"); end
296
+ }.new
297
+ False = Class.new(Singleton) {
298
+ def _immediate; true; end
299
+ def _inspect(s="", newline="\n")
300
+ s.concat("False")
301
+ end
302
+ def _lines(text, indent=0, op=nil, maxlen=72)
303
+ text.last.concat(false.inspect)
304
+ end
305
+ def _never; true; end
306
+ def _rand(before); before << before.pop._step(self); end
307
+ def _or ; yield ; end
308
+ def _ror (before); before; end
309
+ def _not ; True ; end
310
+ }.new
311
+ Nil = Class.new(Singleton) {
312
+ def _immediate; true; end
313
+ def _inspect(s="", newline="\n")
314
+ s.concat("Nil")
315
+ end
316
+ def _lines(text, indent=0, op=nil, maxlen=72)
317
+ text.last.concat(nil.inspect)
318
+ end
319
+ def _never; true; end
320
+ def _rand(before); before << before.pop._step(self); end
321
+ def _or ; yield ; end
322
+ def _ror (before); before; end
323
+ def _not ; True ; end
324
+ }.new
325
+ Self = Class.new(Singleton) {
326
+ def _inspect(s="", newline="\n")
327
+ s.concat("Self")
328
+ end
329
+ def _lines(text, indent=0, op=nil, maxlen=72)
330
+ text.last.concat("self")
331
+ end
332
+ def _always; true; end
333
+ @@keywords = Hash.new
334
+ %w(
335
+ BEGIN END
336
+ begin if unless while until for case def class module
337
+ then elsif else when in do ensure rescue end
338
+ and or
339
+ not defined?
340
+ return yield super undef alias
341
+ break next retry redo
342
+ nil false true self
343
+ ).each { |keyword|
344
+ @@keywords[keyword] = true
345
+ }
346
+ def _dot(method)
347
+ (@@keywords[method] || /^[A-Za-z]\w*[?!]?$/!~method) ? super :
348
+ Code::Command.new(method)
349
+ end
350
+ }.new
351
+ Implicit = Class.new(Singleton) {
352
+ def _inspect(s="", newline="\n")
353
+ s.concat("Implicit")
354
+ end
355
+ def _dot(method)
356
+ Code::Command.new(method.to_s)
357
+ end
358
+ }.new
359
+ class Always < Code
360
+ def _always; true; end
361
+ end
362
+ class Never < Code
363
+ def _never; true; end
364
+ end
365
+ class Unary < Code
366
+ def initialize(operator, operand)
367
+ @operator = operator
368
+ @operand = operand
369
+ end
370
+ def _codes
371
+ [@operand]
372
+ end
373
+ def _data
374
+ @operator
375
+ end
376
+ def _operator
377
+ @operator
378
+ end
379
+ def _always
380
+ false
381
+ end
382
+ def _never
383
+ false
384
+ end
385
+ def _lines(text, indent=0, op=nil, maxlen=72)
386
+ text.last.concat(_operator)
387
+ @operand._lines(text, indent+1, op, maxlen)
388
+ end
389
+ end
390
+ class Not < Unary
391
+ def initialize(operand)
392
+ @operand = operand
393
+ end
394
+ def _data
395
+ nil
396
+ end
397
+ def _operator
398
+ "!"
399
+ end
400
+ def _always
401
+ @operand._never
402
+ end
403
+ def _never
404
+ @operand._always
405
+ end
406
+ def _not
407
+ @operand
408
+ end
409
+ def _mid(before)
410
+ @operand._mid(before)
411
+ end
412
+ def _step(after)
413
+ @operand._step(after)
414
+ end
415
+ end
416
+ class Dot < Unary
417
+ def initialize(receiver, method)
418
+ @operand = receiver
419
+ @method = method
420
+ end
421
+ def _data
422
+ @method
423
+ end
424
+ def _operator
425
+ @method
426
+ end
427
+ def _lines(text, indent=0, op=nil, maxlen=72)
428
+ @operand._lines(text, indent, op, maxlen)
429
+ ensure
430
+ (text.last << ?\.).concat(@method)
431
+ end
432
+ end
433
+ class List < Code
434
+ def initialize(operands)
435
+ @operands = operands
436
+ end
437
+ def _codes
438
+ @operands
439
+ end
440
+ def _lines(text, indent=0, op=nil, maxlen=72)
441
+ delim = _operator
442
+ delim0 = _operator0
443
+ paren = _paren(op)
444
+ if paren
445
+ text.last << ?\(
446
+ indent += 1
447
+ end
448
+ if @operands.empty?
449
+ last = text.last
450
+ last << ?\) if paren
451
+ return last
452
+ end
453
+ op = (delim==", ") ? nil : delim
454
+ delim ||= ""
455
+ len = text[-2]+text.last.size-delim0.size-delim.size
456
+ n = text.size
457
+ needdelim0 = text.last.empty?
458
+ #text << indent << "" unless needdelim0
459
+ single = true
460
+ @operands.each_with_index { |operand, i|
461
+ text << indent << "" unless text.last.empty?
462
+ if operand._lines(text, indent, op, maxlen)
463
+ len += delim.size+delim0.size+text.last.size
464
+ else
465
+ single = nil
466
+ end
467
+ text.last.concat(delim) unless i==@operands.size-1
468
+ }
469
+ if single && len<=maxlen
470
+ last = text[n-1]
471
+ i = n+1
472
+ while i<text.size
473
+ last.concat(delim0) if needdelim0
474
+ last.concat(text[i])
475
+ needdelim0 = true
476
+ i += 2
477
+ end
478
+ text.slice!(n, i-n)
479
+ last << ?\) if paren
480
+ last
481
+ else
482
+ text << (indent-1) << ")" if paren
483
+ nil
484
+ end
485
+ end
486
+ def _operator
487
+ ", "
488
+ end
489
+ def _operator0
490
+ ""
491
+ end
492
+ def _paren(op)
493
+ op
494
+ end
495
+ def _always
496
+ false
497
+ end
498
+ def _never
499
+ false
500
+ end
501
+ end
502
+ class Binary < List
503
+ def initialize(operator, *operands)
504
+ @operator = operator
505
+ @operands = operands
506
+ end
507
+ def _data
508
+ @operator
509
+ end
510
+ def _operator
511
+ @operator
512
+ end
513
+ def method_missing(method, *args, &block)
514
+ if method.equal?(@operator) && !block
515
+ @operands.concat(args)
516
+ self
517
+ else
518
+ super
519
+ end
520
+ end
521
+ end
522
+ class Assign < List
523
+ def _operator
524
+ " = "
525
+ end
526
+ end
527
+ class And < List
528
+ def self.new(operands)
529
+ (operands.size==1) ? operands[0] : super
530
+ end
531
+ def _operator
532
+ " && "
533
+ end
534
+ def _never
535
+ @operands.last._never
536
+ end
537
+ def _and # :yield:
538
+ _never ? self :
539
+ (yield._rand(@operands); self)
540
+ end
541
+ def _rand(before)
542
+ @operands[0] = before.pop._step(@operands[0]) if
543
+ before.last._always
544
+ before.concat(@operands)
545
+ end
546
+ def _or # :yield:
547
+ after = yield
548
+ last = @operands.last
549
+ (!last._always||after._never) ? Or.new(after._ror(operands = [self])) :
550
+ after._unless(
551
+ (@operands.size==2) ? @operands.first : (@operands.pop;self),
552
+ last)
553
+ end
554
+ def _unless(cond, yes)
555
+ if @operands.last._equal(yes)
556
+ @operands.pop
557
+ cond._or{self}._and{yes}
558
+ else
559
+ super
560
+ end
561
+ end
562
+ def _mid(before)
563
+ @operands.pop._mid(@operands)
564
+ if @operands.size==1
565
+ @operands.first._mid(before)
566
+ else
567
+ before << self
568
+ end
569
+ end
570
+ end
571
+ class Or < List
572
+ def self.new(operands)
573
+ (operands.size==1) ? operands[0] : super
574
+ end
575
+ def _operator
576
+ " || "
577
+ end
578
+ def _always
579
+ @operands.last._always
580
+ end
581
+ def _or # :yield:
582
+ _always ? self :
583
+ (yield._ror(@operands); self)
584
+ end
585
+ def _ror(before)
586
+ @operands[0] = before.pop._step(@operands[0]) if
587
+ before.last._never
588
+ before.concat(@operands)
589
+ end
590
+ def _and # :yield:
591
+ after = yield
592
+ last = @operands.last
593
+ (!last._never||after._always) ? And.new(after._rand(operands = [self])) :
594
+ last._unless(
595
+ (@operands.size==2) ? @operands.first : (@operands.pop;self),
596
+ after)
597
+ end
598
+ def _mid(before)
599
+ @operands.pop._mid(@operands)
600
+ if @operands.size==1
601
+ @operands.first._mid(before)
602
+ else
603
+ before << self
604
+ end
605
+ end
606
+ end
607
+ class Steps < List
608
+ def self.new(operands)
609
+ (operands.size==1) ? operands[0] : super
610
+ end
611
+ def _operator
612
+ nil
613
+ end
614
+ def _operator0
615
+ "; "
616
+ end
617
+ def _always
618
+ @operands.last._always
619
+ end
620
+ def _never
621
+ @operands.last._never
622
+ end
623
+ def _step(after)
624
+ @operands.pop._mid(@operands)
625
+ after._rstep(@operands)
626
+ self
627
+ end
628
+ def _rstep(before)
629
+ before.concat(@operands)
630
+ end
631
+ def _not
632
+ @operands[-1] = @operands[-1]._not
633
+ end
634
+ def _mid(before)
635
+ @operands.pop._mid(@operands)
636
+ if @operands.size==1
637
+ @operands.first._mid(before)
638
+ else
639
+ before << self
640
+ end
641
+ end
642
+ end
643
+ class SharedSteps < Steps
644
+ def _mid(before)
645
+ Steps.new(@operands.clone)._mid(before)
646
+ end
647
+ def _step(after)
648
+ Steps.new(@operands.clone)._step(after)
649
+ end
650
+ def _not
651
+ Steps.new(@operands.clone)._not
652
+ end
653
+ end
654
+ class Conditional < List
655
+ class Question < List
656
+ def _operator
657
+ " ? "
658
+ end
659
+ def _paren(op)
660
+ false
661
+ end
662
+ def _always
663
+ @operands.last._always
664
+ end
665
+ def _never
666
+ @operands.last._never
667
+ end
668
+ def [](i)
669
+ @operands[i]
670
+ end
671
+ def []=(i, code)
672
+ @operands[i] = code
673
+ end
674
+ def _mid(before)
675
+ @operands.pop._mid(@operands)
676
+ if @operands.size==1
677
+ # TODO : translate to Or in this case
678
+ @operands << True
679
+ end
680
+ before << self
681
+ end
682
+ end
683
+ def self.new(cond, yes, no)
684
+ super([Question.new([cond, yes]), no])
685
+ end
686
+ def initialize(operands)
687
+ @operands = operands
688
+ always = true
689
+ never = true
690
+ @operands.each { |operand|
691
+ always &&= operand._always
692
+ never &&= operand._never
693
+ break if !always && !never
694
+ }
695
+ @always = always ? 1 : never ? -1 : 0
696
+ end
697
+ def _operator
698
+ " : "
699
+ end
700
+ def _always
701
+ @always>0
702
+ end
703
+ def _never
704
+ @always<0
705
+ end
706
+ def _unless(cond, yes)
707
+ if @operands.first[1]._equal(yes)
708
+ @operands.first[0] = cond._or{@operands.first[0]}
709
+ else
710
+ @operands.insert(0, operand=Question.new([cond, yes]))
711
+ @always = 0 if @always>0 && !operand._always
712
+ @always = 0 if @always<0 && !operand._never
713
+ end
714
+ self
715
+ end
716
+ def _mid(before)
717
+ operands = []
718
+ last = @operands.pop
719
+ @operands.map { |operand|
720
+ operand._mid(operands)
721
+ }
722
+ @operands = operands
723
+ n = @operands.size
724
+ last._mid(@operands)
725
+ # TODO : remove final else in this case (translate prev to And)
726
+ @operands << last if @operands.size==n
727
+ @always = 0
728
+ before << self
729
+ end
730
+ def _or # :yield:
731
+ last = @operands.pop
732
+ always = true
733
+ @operands.each { |operand|
734
+ always &&= operand._always or break
735
+ }
736
+ unless always
737
+ @operands << last
738
+ return(super)
739
+ end
740
+ last = last._or { yield }
741
+ always &&= last._always
742
+ @always = 1 if always
743
+ last._rcond(@operands)
744
+ self
745
+ end
746
+ def _rcond(before)
747
+ before.concat(@operands)
748
+ end
749
+ end
750
+ class Local < Code
751
+ def initialize(n=nil, &block) # :yield: *vars
752
+ n ||= block.arity
753
+ names = (0...n.abs).map { "_" }
754
+ args = names.map { |name| Code::Primary.new(name) }
755
+ @code = yield(*args)
756
+ @locals = @code._locals(0)
757
+ names.each { |name|
758
+ name.concat(@locals.to_s)
759
+ @locals += 1
760
+ }
761
+ end
762
+ def _data
763
+ @locals
764
+ end
765
+ def _locals(n=0)
766
+ (@locals>n) ? @locals : n
767
+ end
768
+ def _mid(before)
769
+ devalued = @code._mid([])
770
+ if devalued.empty?
771
+ before
772
+ else
773
+ @code = devalued[0]
774
+ before << self
775
+ end
776
+ end
777
+ end
778
+ class Blocked < List
779
+ def initialize(receiver, n=nil, &block) # :yield: *vars
780
+ @receiver = receiver
781
+ n ||= block.arity
782
+ names = (0...n.abs).map { "_" }
783
+ @operands = names.map { |name| Code::Primary.new(name) }
784
+ @block = yield(*@operands)
785
+ @locals = @block._locals(0)
786
+ @operands[-1] = @operands[-1]._splat if n<0
787
+ names.each { |name|
788
+ name.concat(@locals.to_s)
789
+ @locals += 1
790
+ }
791
+ @locals = @receiver._locals(@locals)
792
+ end
793
+ def _codes
794
+ [@receiver].concat(@operands) << @block
795
+ end
796
+ def _lines(text, indent=0, op=nil, maxlen=72)
797
+ single = @receiver._lines(text, indent, true, maxlen)
798
+ text.last << ?\s << ?\{
799
+ unless @operands.empty?
800
+ text << (indent+2) << "|"
801
+ if super(text, indent+3, nil, maxlen) && single &&
802
+ text[-4]+text[-3].size+text.last.size+1<=maxlen
803
+ last = text.last
804
+ text.pop
805
+ text.pop
806
+ (text.last << ?\s).concat(last)
807
+ else
808
+ single = nil
809
+ end
810
+ text.last << ?\|
811
+ end
812
+ text << (indent+2) << ""
813
+ if @block._lines(text, indent+2, nil, maxlen) && single &&
814
+ text[-4]+text[-3].size+text.last.size+1<=maxlen
815
+ last = text.last
816
+ text.pop
817
+ text.pop
818
+ (text.last << ?\s).concat(last).concat(" }")
819
+ else
820
+ text << indent << "}"
821
+ nil
822
+ end
823
+ end
824
+ def _locals(n=0)
825
+ (@locals>n) ? @locals : n
826
+ end
827
+ end
828
+ class Call < List
829
+ def initialize(receiver, *args)
830
+ @receiver = receiver
831
+ @operands = args
832
+ end
833
+ def _codes
834
+ [@receiver].concat(@operands)
835
+ end
836
+ def _lines(text, indent=0, op=nil, maxlen=72)
837
+ single = @receiver._lines(text, indent, op, maxlen)
838
+ text.last << op
839
+ if super(text, indent+2, nil, maxlen)
840
+ single
841
+ else
842
+ text << indent << ""
843
+ nil
844
+ end
845
+ end
846
+ end
847
+ class Brackets < Call
848
+ def _lines(text, indent=0, op=nil, maxlen=72)
849
+ super(text, indent, ?\[, maxlen)
850
+ ensure
851
+ text.last << ?\]
852
+ end
853
+ end
854
+ class Method < Call
855
+ def _lines(text, indent=0, op=nil, maxlen=72)
856
+ super(text, indent, ?\(, maxlen)
857
+ ensure
858
+ text.last << ?\)
859
+ end
860
+ end
861
+ class Rescue < Code
862
+ def initialize(exception=nil, var=nil)
863
+ @exception = exception
864
+ @var = var
865
+ end
866
+ def _codes
867
+ codes = []
868
+ codes << @exception if @exception
869
+ codes << @var if @var
870
+ codes
871
+ end
872
+ def _lines(text, indent=0, op=nil, maxlen=72)
873
+ text[-2] -= 2 if text.last.empty?
874
+ (last = text.last).concat("rescue")
875
+ single = true
876
+ if @exception
877
+ last << ?\s
878
+ single = @exception._lines(text, indent+1, nil, maxlen)
879
+ last = text.last
880
+ else
881
+ single = true
882
+ end
883
+ if @var
884
+ last.concat(" => ")
885
+ @var._lines(text, indent+1, nil, maxlen) && single
886
+ else
887
+ single
888
+ end
889
+ end
890
+ def _always
891
+ false
892
+ end
893
+ def _never
894
+ false
895
+ end
896
+ end
897
+ class Dedented < Command
898
+ def _lines(text, indent=0, op=nil, maxlen=72)
899
+ text[-2] -= 2 if text.last.empty?
900
+ text.last.concat(@code)
901
+ end
902
+ end
903
+ class Begin < List
904
+ def initialize(body)
905
+ @footer = 0
906
+ super([body])
907
+ end
908
+ def _operator
909
+ nil
910
+ end
911
+ def _operator0
912
+ "; "
913
+ end
914
+ def _lines(text, indent=0, op=nil, maxlen=72)
915
+ text.last.concat("begin ")
916
+ if super(text, indent+2, nil, maxlen)
917
+ text.last.concat(" end")
918
+ else
919
+ text << indent << "end"
920
+ nil
921
+ end
922
+ end
923
+ def _rescue(after, exception=nil, var=nil)
924
+ return(super) if @footer>1
925
+ @footer = 1
926
+ @operands << Rescue.new(exception, var) << after
927
+ self
928
+ end
929
+ def _ensure(after)
930
+ return(super) if @footer>=2
931
+ @footer = 2
932
+ @operands << Dedented.new("ensure") << after
933
+ self
934
+ end
935
+ def _else(after)
936
+ return(super) if @footer>=3
937
+ @footer = 3
938
+ @operands << Dedented.new("else") << after
939
+ self
940
+ end
941
+ def _def(name, *args)
942
+ Def.new(name.to_s, args, Steps.new(@operands))
943
+ end
944
+ def _always
945
+ false
946
+ end
947
+ def _never
948
+ false
949
+ end
950
+ end
951
+ class Def < List
952
+ def initialize(name, args, body)
953
+ @name = name
954
+ @operands = args
955
+ @body = body
956
+ end
957
+ def _codes
958
+ @operands+[@body]
959
+ end
960
+ def _data
961
+ @name
962
+ end
963
+ def _lines(text, indent=0, op=nil, maxlen=72)
964
+ text << indent << "" unless text.last.empty?
965
+ (last = text.last).concat("def ").concat(@name.to_s)
966
+ unless @operands.empty?
967
+ last << ?\(
968
+ super(text, indent+3, nil, maxlen) or
969
+ text << indent+2 << ""
970
+ text.last << ?\)
971
+ end
972
+ text << (indent+2) << ""
973
+ @body._lines(text, indent+2, nil, maxlen)
974
+ text << indent << "end"
975
+ nil
976
+ end
977
+ def _always
978
+ false
979
+ end
980
+ def _never
981
+ false
982
+ end
983
+ end
984
+ class While < Code
985
+ def initialize(condition, body=nil)
986
+ @condition = condition
987
+ @body = body && body._mid([])[0]
988
+ end
989
+ def _codes
990
+ codes = [@condition]
991
+ codes << @body if @body
992
+ codes
993
+ end
994
+ def _header
995
+ "while"
996
+ end
997
+ def _lines(text, indent=0, op=nil, maxlen=72)
998
+ (last = text.last).concat(_header) << ?\(
999
+ single = @condition._lines(text, indent+3, nil, maxlen) or
1000
+ text << indent+2 << ""
1001
+ text.last << ?\)
1002
+ if @body
1003
+ text << indent+2 << ""
1004
+ @body._lines(text, indent+2, nil, maxlen)
1005
+ single = nil
1006
+ end
1007
+ if single
1008
+ text.last.concat("; end")
1009
+ else
1010
+ text << indent << "end"
1011
+ nil
1012
+ end
1013
+ end
1014
+ def _always
1015
+ false
1016
+ end
1017
+ def _never
1018
+ false
1019
+ end
1020
+ end
1021
+ class Until < While
1022
+ def _header
1023
+ "until"
1024
+ end
1025
+ end
1026
+ end
1027
+ end
1028
+ end
1029
+
1030
+