sorcerer 0.2.0 → 0.3.0
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.
- data/README.textile +33 -7
- data/lib/sorcerer/resource.rb +18 -4
- data/lib/sorcerer/version.rb +1 -1
- data/test/sorcerer/resource_test.rb +134 -116
- data/test/sorcerer/subexpression_test.rb +4 -4
- metadata +1 -1
data/README.textile
CHANGED
@@ -46,15 +46,14 @@ Ripper may be used to produce the s-expressions used by Sorcerer. The following
|
|
46
46
|
|
47
47
|
h2. Options
|
48
48
|
|
49
|
-
h3.
|
49
|
+
h3. No Options
|
50
50
|
|
51
|
-
|
52
|
-
the source command.
|
51
|
+
By default, sorcerer will output its source in single line mode.
|
53
52
|
|
54
53
|
For example, given:
|
55
54
|
|
56
55
|
<pre style="background: LightGrey">
|
57
|
-
sexp = Ripper::SexpBuilder.new("def foo; end").parse
|
56
|
+
sexp = Ripper::SexpBuilder.new("def foo; bar; end").parse
|
58
57
|
</pre>
|
59
58
|
|
60
59
|
Then the following
|
@@ -66,10 +65,15 @@ Then the following
|
|
66
65
|
generates single line output (the default):
|
67
66
|
|
68
67
|
<pre style="background: LightBlue">
|
69
|
-
def foo; end
|
68
|
+
def foo; bar; end
|
70
69
|
</pre>
|
71
70
|
|
72
|
-
|
71
|
+
h3. Multi-Line Output
|
72
|
+
|
73
|
+
If you want multi-line output of source, add the multiline option to
|
74
|
+
the source command.
|
75
|
+
|
76
|
+
For example, given the sexp generated above, then this
|
73
77
|
|
74
78
|
<pre style="background: LightGrey">
|
75
79
|
puts Sorcerer.source(sexp, multiline: true)
|
@@ -79,6 +83,28 @@ generates multi-line output
|
|
79
83
|
|
80
84
|
<pre style="background: LightBlue">
|
81
85
|
def foo
|
86
|
+
bar
|
87
|
+
end
|
88
|
+
</pre>
|
89
|
+
|
90
|
+
(Note that all multi-line output will have a final newline.)
|
91
|
+
|
92
|
+
h3. Indentation
|
93
|
+
|
94
|
+
By default, sorcerer does not indent its multiline output. Adding the
|
95
|
+
"indent" option will cause the output to be indented.
|
96
|
+
|
97
|
+
For example, given the sexp generated above, then the following
|
98
|
+
|
99
|
+
<pre style="background: LightGrey">
|
100
|
+
puts Sorcerer.source(sexp, indent: true)
|
101
|
+
</pre>
|
102
|
+
|
103
|
+
generates indented output:
|
104
|
+
|
105
|
+
<pre style="background: LightBlue">
|
106
|
+
def foo
|
107
|
+
bar
|
82
108
|
end
|
83
109
|
</pre>
|
84
110
|
|
@@ -96,6 +122,6 @@ h2. History
|
|
96
122
|
* 0.0.7 - Basic single line version
|
97
123
|
* 0.1.0 - Added support for multi-line output. Improved rendering of a
|
98
124
|
number of constructs
|
99
|
-
|
125
|
+
* 0.2.0 - Added support for indented output.
|
100
126
|
|
101
127
|
|
data/lib/sorcerer/resource.rb
CHANGED
@@ -33,6 +33,9 @@ module Sorcerer
|
|
33
33
|
def source
|
34
34
|
@stack.clear
|
35
35
|
resource(@sexp)
|
36
|
+
if multiline?
|
37
|
+
@source << "\n" unless @source =~ /\n\z/m
|
38
|
+
end
|
36
39
|
@source
|
37
40
|
end
|
38
41
|
|
@@ -203,6 +206,10 @@ module Sorcerer
|
|
203
206
|
sexp == VOID_BODY2
|
204
207
|
end
|
205
208
|
|
209
|
+
def label?(sexp)
|
210
|
+
sexp?(sexp) && sexp.first == :@label
|
211
|
+
end
|
212
|
+
|
206
213
|
def last_handler
|
207
214
|
@stack.last
|
208
215
|
end
|
@@ -350,7 +357,11 @@ module Sorcerer
|
|
350
357
|
:assign_error => NYI,
|
351
358
|
:assoc_new => lambda { |sexp|
|
352
359
|
resource(sexp[1])
|
353
|
-
|
360
|
+
if label?(sexp[1])
|
361
|
+
emit(" ")
|
362
|
+
else
|
363
|
+
emit(" => ")
|
364
|
+
end
|
354
365
|
resource(sexp[2])
|
355
366
|
},
|
356
367
|
:assoclist_from_args => lambda { |sexp|
|
@@ -536,8 +547,11 @@ module Sorcerer
|
|
536
547
|
},
|
537
548
|
:hash => lambda { |sexp|
|
538
549
|
emit("{")
|
539
|
-
|
540
|
-
|
550
|
+
if sexp[1]
|
551
|
+
emit(" ")
|
552
|
+
resource(sexp[1])
|
553
|
+
end
|
554
|
+
emit(" }")
|
541
555
|
},
|
542
556
|
:if => lambda { |sexp|
|
543
557
|
emit("if ")
|
@@ -862,7 +876,7 @@ module Sorcerer
|
|
862
876
|
:@int => EMIT1,
|
863
877
|
:@ivar => EMIT1,
|
864
878
|
:@kw => EMIT1,
|
865
|
-
:@label =>
|
879
|
+
:@label => EMIT1,
|
866
880
|
:@lbrace => NYI,
|
867
881
|
:@lbracket => NYI,
|
868
882
|
:@lparen => NYI,
|
data/lib/sorcerer/version.rb
CHANGED
@@ -32,7 +32,7 @@ class SourcerTest < Test::Unit::TestCase
|
|
32
32
|
# * "#" is expected to be a tabbed indent in indent mode and a null
|
33
33
|
# string in single line and multi-line modes.
|
34
34
|
#
|
35
|
-
def
|
35
|
+
def assert_resource_lines(string)
|
36
36
|
assert_resource_for_mode(string, multiline: false) { |s| for_single_line(s) }
|
37
37
|
assert_resource_for_mode(string, multiline: true) { |s| for_multi_line(s) }
|
38
38
|
assert_resource_for_mode(string, indent: true) { |s| for_indented(s) }
|
@@ -46,15 +46,26 @@ class SourcerTest < Test::Unit::TestCase
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def for_single_line(string)
|
49
|
-
string.
|
49
|
+
string.
|
50
|
+
gsub(/\bTHEN~/, "then ").
|
51
|
+
gsub(/~/, " ").
|
52
|
+
gsub(/#/,'')
|
50
53
|
end
|
51
54
|
|
52
55
|
def for_multi_line(string)
|
53
|
-
string.
|
56
|
+
string.
|
57
|
+
gsub(/\b THEN~/, "; ").
|
58
|
+
gsub(/~/, "\n").
|
59
|
+
gsub(/; /, "\n").
|
60
|
+
gsub(/#/,'') + "\n"
|
54
61
|
end
|
55
62
|
|
56
63
|
def for_indented(string)
|
57
|
-
string.
|
64
|
+
string.
|
65
|
+
gsub(/\b THEN~/, "; ").
|
66
|
+
gsub(/~/, "\n").
|
67
|
+
gsub(/; /, "\n").
|
68
|
+
gsub(/#/,' ') + "\n"
|
58
69
|
end
|
59
70
|
|
60
71
|
def source(string, options={})
|
@@ -63,6 +74,7 @@ class SourcerTest < Test::Unit::TestCase
|
|
63
74
|
puts "***************************** options: #{options.inspect}"
|
64
75
|
end
|
65
76
|
sexp = Ripper::SexpBuilder.new(string).parse
|
77
|
+
fail "Failed to parts '#{string}'" if sexp.nil?
|
66
78
|
Sorcerer.source(sexp, options)
|
67
79
|
end
|
68
80
|
|
@@ -149,42 +161,50 @@ class SourcerTest < Test::Unit::TestCase
|
|
149
161
|
assert_resource "meth(a, :x => 1, :y => 2)"
|
150
162
|
end
|
151
163
|
|
164
|
+
def test_can_source_method_with_new_hash_syntax
|
165
|
+
assert_resource "meth(x: 1)"
|
166
|
+
assert_resource "meth(x: 1, y: 2)"
|
167
|
+
assert_resource "meth(a, x: 1)"
|
168
|
+
assert_resource "meth(a, x: 1, y: 2)"
|
169
|
+
assert_resource "meth(a, :x => 1, y: 2)"
|
170
|
+
end
|
171
|
+
|
152
172
|
def test_can_source_method_with_do_block
|
153
|
-
|
154
|
-
|
155
|
-
|
173
|
+
assert_resource_lines "meth do end"
|
174
|
+
assert_resource_lines "meth do |a| end"
|
175
|
+
assert_resource_lines "meth(x, y, *rest, &code) do |a, b=1, c=x, *args, &block|~#one; #two; #three~end"
|
156
176
|
end
|
157
177
|
|
158
178
|
def test_can_source_method_with_block
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
179
|
+
assert_resource_lines "meth { }"
|
180
|
+
assert_resource_lines "meth { |a| }"
|
181
|
+
assert_resource_lines "meth { |a, b| }"
|
182
|
+
assert_resource_lines "meth { |*args| }"
|
183
|
+
assert_resource_lines "meth { |a, *args| }"
|
184
|
+
assert_resource_lines "meth { |&block| }"
|
185
|
+
assert_resource_lines "meth { |*args, &block| }"
|
186
|
+
assert_resource_lines "meth { |a, b, *args, &block| }"
|
187
|
+
assert_resource_lines "meth { |a, b=1, *args, &block| }"
|
188
|
+
assert_resource_lines "meth { |a, b=1, c=x, *args, &block| }"
|
169
189
|
end
|
170
190
|
|
171
191
|
def test_can_source_method_with_block_contents
|
172
|
-
|
173
|
-
|
192
|
+
assert_resource_lines "meth { |a|~#a.x~}"
|
193
|
+
assert_resource_lines "meth { |a|~#a.x; #b.z~}"
|
174
194
|
end
|
175
195
|
|
176
196
|
def test_can_source_method_with_complex_args_and_block
|
177
|
-
|
197
|
+
assert_resource_lines "meth(x, y, *rest, &code) { |a, b=1, c=x, *args, &block|~#one; #two; #three~}"
|
178
198
|
end
|
179
199
|
|
180
200
|
def test_can_source_stabby_procs
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
201
|
+
assert_resource_lines "-> { }"
|
202
|
+
assert_resource_lines "->() { }"
|
203
|
+
assert_resource_lines "->(a) { }"
|
204
|
+
assert_resource_lines "->(a, b) { }"
|
205
|
+
assert_resource_lines "->(a, *args) { }"
|
206
|
+
assert_resource_lines "->(a, b=12, *args, &block) { }"
|
207
|
+
assert_resource_lines "->(a) {~b~}"
|
188
208
|
end
|
189
209
|
|
190
210
|
def test_can_source_dot_calls
|
@@ -295,9 +315,19 @@ class SourcerTest < Test::Unit::TestCase
|
|
295
315
|
end
|
296
316
|
|
297
317
|
def test_can_source_hash_literals
|
298
|
-
assert_resource "{}"
|
299
|
-
assert_resource "{:a => 1}"
|
300
|
-
assert_resource "{:a => 1, :b => 2}"
|
318
|
+
assert_resource "{ }"
|
319
|
+
assert_resource "{ :a => 1 }"
|
320
|
+
assert_resource "{ :a => 1, :b => 2 }"
|
321
|
+
end
|
322
|
+
|
323
|
+
def test_can_source_new_hash_literals
|
324
|
+
assert_resource "{ }"
|
325
|
+
assert_resource "{ a: 1 }"
|
326
|
+
assert_resource "{ a: 1, b: 2 }"
|
327
|
+
end
|
328
|
+
|
329
|
+
def test_can_source_mixed_hash_literals
|
330
|
+
assert_resource "{ a: 1, :b => 2, c: 3, :d => 4 }"
|
301
331
|
end
|
302
332
|
|
303
333
|
def test_can_source_unary_expression
|
@@ -376,41 +406,41 @@ class SourcerTest < Test::Unit::TestCase
|
|
376
406
|
end
|
377
407
|
|
378
408
|
def test_can_source_statement_sequences
|
379
|
-
|
380
|
-
|
381
|
-
|
409
|
+
assert_resource_lines "a"
|
410
|
+
assert_resource_lines "a; b"
|
411
|
+
assert_resource_lines "a; b; c"
|
382
412
|
end
|
383
413
|
|
384
414
|
def test_can_source_begin_end
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
415
|
+
assert_resource_lines "begin end"
|
416
|
+
assert_resource_lines "begin~#a; end"
|
417
|
+
assert_resource_lines "begin~#a(); end"
|
418
|
+
assert_resource_lines "begin~#a; #b; #c; end"
|
389
419
|
end
|
390
420
|
|
391
421
|
def test_can_source_begin_rescue_end
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
422
|
+
assert_resource_lines "begin~rescue; end"
|
423
|
+
assert_resource_lines "begin~rescue E => ex; #b; end"
|
424
|
+
assert_resource_lines "begin~#a; rescue E => ex; #b; end"
|
425
|
+
assert_resource_lines "begin~#a; rescue E, F => ex; #b; end"
|
426
|
+
assert_resource_lines "begin~#a; rescue E, F => ex; #b; #c; end"
|
427
|
+
assert_resource_lines "begin~rescue E, F => ex; #b; #c; end"
|
398
428
|
end
|
399
429
|
|
400
430
|
def test_can_source_begin_ensure_end
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
431
|
+
assert_resource_lines "begin~ensure~end"
|
432
|
+
assert_resource_lines "begin~ensure~#b; end"
|
433
|
+
assert_resource_lines "begin~#a; ensure~#b; end"
|
434
|
+
assert_resource_lines "begin~#a; ensure~#b; end"
|
405
435
|
end
|
406
436
|
|
407
437
|
def test_can_source_begin_rescue_ensure_end
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
438
|
+
assert_resource_lines "begin~rescue; end"
|
439
|
+
assert_resource_lines "begin~rescue E => ex; #b; ensure~#c; end"
|
440
|
+
assert_resource_lines "begin~#a; rescue E => ex; #b; ensure~#c; end"
|
441
|
+
assert_resource_lines "begin~#a; rescue E, F => ex; #b; ensure~#c; end"
|
442
|
+
assert_resource_lines "begin~#a; rescue E, F => ex; #b; #c; ensure~#d; end"
|
443
|
+
assert_resource_lines "begin~rescue E, F => ex; #b; #c; ensure~#d; end"
|
414
444
|
end
|
415
445
|
|
416
446
|
def test_can_source_rescue_modifier
|
@@ -418,69 +448,57 @@ class SourcerTest < Test::Unit::TestCase
|
|
418
448
|
end
|
419
449
|
|
420
450
|
def test_can_source_if
|
421
|
-
|
422
|
-
assert_resource "if a\nb\nend", multiline: true
|
423
|
-
assert_resource "if a\n b\nend", indent: 2
|
451
|
+
assert_resource_lines "if a THEN~#b~end"
|
424
452
|
end
|
425
453
|
|
426
454
|
def test_can_source_if_else
|
427
|
-
|
428
|
-
assert_resource "if a\nb\nelse\nc\nend", multiline: true
|
429
|
-
assert_resource "if a\n b\nelse\n c\nend", indent: 2
|
455
|
+
assert_resource_lines "if a THEN~#b~else~#c~end"
|
430
456
|
end
|
431
457
|
|
432
458
|
def test_can_source_if_elsif
|
433
|
-
|
434
|
-
assert_resource "if a\nb\nelsif c\nd\nend", multiline: true
|
435
|
-
assert_resource "if a\n b\nelsif c\n d\nend", indent: 2
|
459
|
+
assert_resource_lines "if a THEN~#b~elsif c THEN~#d~end"
|
436
460
|
end
|
437
461
|
|
438
462
|
def test_can_source_if_elsif_else
|
439
|
-
|
440
|
-
assert_resource "if a\nb\nelsif c\nd\nelse\ne\nend", multiline: true
|
441
|
-
assert_resource "if a\n b\nelsif c\n d\nelse\n e\nend", indent: 2
|
463
|
+
assert_resource_lines "if a THEN~#b~elsif c THEN~#d~else~#e~end"
|
442
464
|
end
|
443
465
|
|
444
466
|
def test_can_source_unless
|
445
|
-
|
446
|
-
assert_resource "unless a\nb\nend", multiline: true
|
447
|
-
assert_resource "unless a\n b\nend", indent: 2
|
467
|
+
assert_resource_lines "unless a THEN~#b~end"
|
448
468
|
end
|
449
469
|
|
450
470
|
def test_can_source_unless_else
|
451
|
-
|
452
|
-
assert_resource "unless a\nb\nelse\nc\nend", multiline: true
|
453
|
-
assert_resource "unless a\n b\nelse\n c\nend", indent: 2
|
471
|
+
assert_resource_lines "unless a THEN~#b~else~#c~end"
|
454
472
|
end
|
455
473
|
|
456
474
|
def test_can_source_while
|
457
|
-
|
458
|
-
|
475
|
+
assert_resource_lines "while c; end"
|
476
|
+
assert_resource_lines "while c; #body; end"
|
459
477
|
end
|
460
478
|
|
461
479
|
def test_can_source_until
|
462
|
-
|
480
|
+
assert_resource_lines "until c; #body end"
|
463
481
|
end
|
464
482
|
|
465
483
|
def test_can_source_for
|
466
|
-
|
467
|
-
|
484
|
+
assert_resource_lines "for a in list; end"
|
485
|
+
assert_resource_lines "for a in list; #c~end"
|
468
486
|
end
|
469
487
|
|
470
488
|
def test_can_source_break
|
471
|
-
|
472
|
-
|
489
|
+
assert_resource_lines "while c; #a; #break if b; #c; end"
|
490
|
+
assert_resource_lines "while c; #a; #break value if b; #c; end"
|
473
491
|
end
|
474
492
|
|
475
493
|
def test_can_source_next
|
476
|
-
|
477
|
-
|
494
|
+
assert_resource_lines "while c; #a; #next if b; #c; end"
|
495
|
+
assert_resource_lines "while c; #a; #next if b; #c; end"
|
478
496
|
end
|
479
497
|
|
480
498
|
def test_can_source_case
|
481
|
-
|
482
|
-
|
483
|
-
|
499
|
+
assert_resource_lines "case a~when b; #c; end"
|
500
|
+
assert_resource_lines "case a~when b; #c when d; #e; end"
|
501
|
+
assert_resource_lines "case a~when b; #c when d; #e~else~#f; end"
|
484
502
|
end
|
485
503
|
|
486
504
|
def test_can_source_if_modifier
|
@@ -545,63 +563,63 @@ class SourcerTest < Test::Unit::TestCase
|
|
545
563
|
end
|
546
564
|
|
547
565
|
def test_can_source_def
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
566
|
+
assert_resource_lines "def f; end"
|
567
|
+
assert_resource_lines "def f; #x; end"
|
568
|
+
assert_resource_lines "def f a; end"
|
569
|
+
assert_resource_lines "def f(); end"
|
570
|
+
assert_resource_lines "def f(a); end"
|
571
|
+
assert_resource_lines "def f(a, b); end"
|
572
|
+
assert_resource_lines "def f(a, *args); end"
|
573
|
+
assert_resource_lines "def f(a, *args, &block); end"
|
574
|
+
assert_resource_lines "def f(a); #x; end"
|
575
|
+
assert_resource_lines "def f(a); #x; #y; end"
|
558
576
|
end
|
559
577
|
|
560
578
|
def test_can_source_class_without_parent
|
561
|
-
|
562
|
-
|
563
|
-
|
579
|
+
assert_resource_lines "class X; end"
|
580
|
+
assert_resource_lines "class X; #x; end"
|
581
|
+
assert_resource_lines "class X; #def f(); #end; end"
|
564
582
|
end
|
565
583
|
|
566
584
|
def test_can_source_class_with_parent
|
567
|
-
|
568
|
-
|
585
|
+
assert_resource_lines "class X < Y; end"
|
586
|
+
assert_resource_lines "class X < Y; #x; end"
|
569
587
|
end
|
570
588
|
|
571
589
|
def test_can_source_class_with_self_parent
|
572
|
-
|
590
|
+
assert_resource_lines "class X < self; end"
|
573
591
|
end
|
574
592
|
|
575
593
|
def test_can_source_private_etc_in_class
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
594
|
+
assert_resource_lines "class X; #public; #def f(); #end; end"
|
595
|
+
assert_resource_lines "class X; #protected; #def f(); #end; end"
|
596
|
+
assert_resource_lines "class X; #private; #def f(); #end; end"
|
597
|
+
assert_resource_lines "class X; #def f(); #end; #public :f; end"
|
598
|
+
assert_resource_lines "class X; #def f(); #end; #protected :f; end"
|
599
|
+
assert_resource_lines "class X; #def f(); #end; #private :f; end"
|
582
600
|
end
|
583
601
|
|
584
602
|
def test_can_source_module
|
585
|
-
|
586
|
-
|
587
|
-
|
603
|
+
assert_resource_lines "module X; end"
|
604
|
+
assert_resource_lines "module X; #x; end"
|
605
|
+
assert_resource_lines "module X; #def f(); #end; end"
|
588
606
|
end
|
589
607
|
|
590
608
|
def test_can_source_BEGIN
|
591
|
-
|
592
|
-
|
593
|
-
|
609
|
+
assert_resource_lines "BEGIN { }"
|
610
|
+
assert_resource_lines "BEGIN {~#x~}"
|
611
|
+
assert_resource_lines "BEGIN {~#x; #y~}"
|
594
612
|
end
|
595
613
|
|
596
614
|
def test_can_source_END
|
597
|
-
|
598
|
-
|
599
|
-
|
615
|
+
assert_resource_lines "END { }"
|
616
|
+
assert_resource_lines "END {~#x~}"
|
617
|
+
assert_resource_lines "END {~#x; #y~}"
|
600
618
|
end
|
601
619
|
|
602
620
|
def test_can_source_then
|
603
|
-
|
604
|
-
|
621
|
+
assert_resource_lines "Then {~#a == b~}"
|
622
|
+
assert_resource_lines "Then {~#a == b; #x~}"
|
605
623
|
end
|
606
624
|
|
607
625
|
def test_can_use_ripper_sexp_output
|
@@ -20,7 +20,7 @@ class SubexpressionTest < Test::Unit::TestCase
|
|
20
20
|
|
21
21
|
def test_unary_expressions
|
22
22
|
assert_subexpressions "-(a+b)", [
|
23
|
-
"-(a + b)", "a + b", "a", "b",
|
23
|
+
"-(a + b)", "a + b", "a", "b",
|
24
24
|
]
|
25
25
|
end
|
26
26
|
|
@@ -61,8 +61,8 @@ class SubexpressionTest < Test::Unit::TestCase
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def test_hash_literal
|
64
|
-
assert_subexpressions "{:a => aa, :b => bb}", [
|
65
|
-
"{:a => aa, :b => bb}", "aa", "bb"
|
64
|
+
assert_subexpressions "{ :a => aa, :b => bb }", [
|
65
|
+
"{ :a => aa, :b => bb }", "aa", "bb"
|
66
66
|
]
|
67
67
|
end
|
68
68
|
|
@@ -74,7 +74,7 @@ class SubexpressionTest < Test::Unit::TestCase
|
|
74
74
|
assert_subexpressions "o.f(a+b, c*d, x.y, z(k, 2, 3)) { xx }", [
|
75
75
|
"o.f(a + b, c * d, x.y, z(k, 2, 3)) { xx }",
|
76
76
|
"a + b", "a", "b",
|
77
|
-
"c * d", "c", "d",
|
77
|
+
"c * d", "c", "d",
|
78
78
|
"x.y", "x",
|
79
79
|
"z(k, 2, 3)", "k",
|
80
80
|
"o",
|