rip-parser 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +15 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE.md +9 -0
  8. data/README.md +13 -0
  9. data/Rakefile +1 -0
  10. data/bin/console +8 -0
  11. data/bin/setup +8 -0
  12. data/legacy/normalizer.rb +279 -0
  13. data/legacy/parser_spec.rb +999 -0
  14. data/legacy/rules.rb +250 -0
  15. data/legacy/rules_spec.rb +1700 -0
  16. data/rip-parser.gemspec +20 -0
  17. data/source/rip/parser/about.rb +9 -0
  18. data/source/rip/parser/error.rb +36 -0
  19. data/source/rip/parser/grammar.rb +23 -0
  20. data/source/rip/parser/keywords.rb +84 -0
  21. data/source/rip/parser/location.rb +47 -0
  22. data/source/rip/parser/node.rb +115 -0
  23. data/source/rip/parser/rules/assignment.rb +23 -0
  24. data/source/rip/parser/rules/binary_condition.rb +24 -0
  25. data/source/rip/parser/rules/character.rb +40 -0
  26. data/source/rip/parser/rules/class.rb +60 -0
  27. data/source/rip/parser/rules/common.rb +47 -0
  28. data/source/rip/parser/rules/date_time.rb +31 -0
  29. data/source/rip/parser/rules/expression.rb +122 -0
  30. data/source/rip/parser/rules/import.rb +23 -0
  31. data/source/rip/parser/rules/invocation.rb +15 -0
  32. data/source/rip/parser/rules/invocation_index.rb +15 -0
  33. data/source/rip/parser/rules/keyword.rb +12 -0
  34. data/source/rip/parser/rules/lambda.rb +45 -0
  35. data/source/rip/parser/rules/list.rb +18 -0
  36. data/source/rip/parser/rules/map.rb +15 -0
  37. data/source/rip/parser/rules/module.rb +29 -0
  38. data/source/rip/parser/rules/number.rb +21 -0
  39. data/source/rip/parser/rules/pair.rb +13 -0
  40. data/source/rip/parser/rules/property.rb +33 -0
  41. data/source/rip/parser/rules/range.rb +15 -0
  42. data/source/rip/parser/rules/reference.rb +16 -0
  43. data/source/rip/parser/rules/string.rb +41 -0
  44. data/source/rip/parser/rules/unit.rb +17 -0
  45. data/source/rip/parser/rules.rb +7 -0
  46. data/source/rip/parser/utilities/normalizer.rb +638 -0
  47. data/source/rip/parser.rb +24 -0
  48. data/source/rip-parser.rb +1 -0
  49. data/spec/fixtures/syntax_sample.rip +96 -0
  50. data/spec/spec_helper.rb +20 -0
  51. data/spec/support/helpers.rb +57 -0
  52. data/spec/support/parslet.rb +1 -0
  53. data/spec/support/shared_examples.rb +9 -0
  54. data/spec/unit/rip/parser/grammar_spec.rb +8 -0
  55. data/spec/unit/rip/parser/location_spec.rb +89 -0
  56. data/spec/unit/rip/parser/node_spec.rb +157 -0
  57. data/spec/unit/rip/parser/rules/assignment_spec.rb +59 -0
  58. data/spec/unit/rip/parser/rules/binary_condition_spec.rb +41 -0
  59. data/spec/unit/rip/parser/rules/character_spec.rb +29 -0
  60. data/spec/unit/rip/parser/rules/class_spec.rb +181 -0
  61. data/spec/unit/rip/parser/rules/common_spec.rb +88 -0
  62. data/spec/unit/rip/parser/rules/date_time_spec.rb +61 -0
  63. data/spec/unit/rip/parser/rules/expression_spec.rb +95 -0
  64. data/spec/unit/rip/parser/rules/import_spec.rb +64 -0
  65. data/spec/unit/rip/parser/rules/invocation_index_spec.rb +46 -0
  66. data/spec/unit/rip/parser/rules/invocation_spec.rb +46 -0
  67. data/spec/unit/rip/parser/rules/keyword_spec.rb +17 -0
  68. data/spec/unit/rip/parser/rules/lambda_spec.rb +174 -0
  69. data/spec/unit/rip/parser/rules/list_spec.rb +45 -0
  70. data/spec/unit/rip/parser/rules/map_spec.rb +36 -0
  71. data/spec/unit/rip/parser/rules/module_spec.rb +63 -0
  72. data/spec/unit/rip/parser/rules/number_spec.rb +40 -0
  73. data/spec/unit/rip/parser/rules/pair_spec.rb +25 -0
  74. data/spec/unit/rip/parser/rules/property_spec.rb +27 -0
  75. data/spec/unit/rip/parser/rules/range_spec.rb +37 -0
  76. data/spec/unit/rip/parser/rules/reference_spec.rb +43 -0
  77. data/spec/unit/rip/parser/rules/string_spec.rb +166 -0
  78. data/spec/unit/rip/parser/rules/unit_spec.rb +17 -0
  79. data/spec/unit/rip/parser_spec.rb +106 -0
  80. metadata +192 -0
@@ -0,0 +1,1700 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rip::Parser::Rules, :blur do
4
+ let(:rules) { Rip::Parser::Rules.new }
5
+
6
+ context 'some basics' do
7
+ it 'parses an empty module' do
8
+ expect('').to parse_raw_as(:module => [])
9
+ end
10
+
11
+ it 'parses an empty string module' do
12
+ expect(' ').to parse_raw_as(:module => ' ')
13
+ end
14
+
15
+ it 'ignores comments as whitespace' do
16
+ expect('# this is a comment').to parse_raw_as(:module => '# this is a comment')
17
+ end
18
+
19
+ it 'recognizes various whitespace sequences' do
20
+ {
21
+ [' ', "\t", "\r", "\n", "\r\n"] => :whitespace,
22
+ [' ', "\t\t"] => :whitespaces,
23
+ ['', "\n", "\t\r"] => :whitespaces?,
24
+ [' ', "\t"] => :space,
25
+ [' ', "\t\t", " \t \t "] => :spaces,
26
+ ['', ' ', " \t \t "] => :spaces?,
27
+ ["\n", "\r", "\r\n"] => :line_break,
28
+ ["\r\n\r\n", "\n\n"] => :line_breaks,
29
+ ['', "\r\n\r\n", "\n\n"] => :line_breaks?
30
+ }.each do |whitespaces, method|
31
+ space_parser = Rip::Parser::Rules.new.send(method)
32
+ whitespaces.each do |space|
33
+ expect(space_parser).to parse(space).as(space)
34
+ end
35
+ end
36
+ end
37
+
38
+ context 'comma-separation' do
39
+ let(:csv_parser) do
40
+ parser = Rip::Parser::Rules.new
41
+ parser.send(:csv, parser.send(:str, 'x').as(:x)).as(:csv)
42
+ end
43
+ let(:expected_x) { { :x => 'x' } }
44
+
45
+ it 'recognizes comma-separated atoms' do
46
+ expect(csv_parser).to parse('').as(:csv => [])
47
+ expect(csv_parser).to parse('x').as(:csv => [expected_x])
48
+ expect(csv_parser).to parse('x,x,x').as(:csv => [expected_x, expected_x, expected_x])
49
+ expect(csv_parser).to_not parse('xx')
50
+ expect(csv_parser).to_not parse('x,xx')
51
+ end
52
+ end
53
+ end
54
+
55
+ recognizes_as_expected 'several statements together' do
56
+ let(:rip) do
57
+ strip_heredoc(<<-RIP)
58
+ if (true) {
59
+ lambda = -> {
60
+ # comment
61
+ }
62
+ lambda()
63
+ } else {
64
+ 1 + 2
65
+ }
66
+ RIP
67
+ end
68
+ let(:expected_raw) do
69
+ {
70
+ :module => [
71
+ {
72
+ :if_block => {
73
+ :if => 'if',
74
+ :argument => { :reference => 'true' },
75
+ :location_body => '{',
76
+ :body => [
77
+ {
78
+ :atom => [
79
+ { :reference => 'lambda' },
80
+ {
81
+ :assignment => {
82
+ :location => '=',
83
+ :rhs => {
84
+ :dash_rocket => '->',
85
+ :location_body => '{',
86
+ :body => []
87
+ }
88
+ }
89
+ }
90
+ ]
91
+ },
92
+ {
93
+ :atom => [
94
+ { :reference => 'lambda' },
95
+ { :regular_invocation => { :location => '(', :arguments => [] } }
96
+ ]
97
+ }
98
+ ]
99
+ },
100
+ :else_block => {
101
+ :else => 'else',
102
+ :location_body => '{',
103
+ :body => [
104
+ {
105
+ :atom => [
106
+ { :integer => '1' },
107
+ {
108
+ :operator_invocation => {
109
+ :operator => '+',
110
+ :argument => { :integer => '2' }
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ ]
116
+ }
117
+ }
118
+ ]
119
+ }
120
+ end
121
+ end
122
+
123
+ describe '#expression' do
124
+ context 'block' do
125
+ recognizes_as_expected 'empty block' do
126
+ let(:rip) { 'try {}' }
127
+ let(:expected_raw) do
128
+ {
129
+ :module => [
130
+ {
131
+ :try_block => {
132
+ :try => 'try',
133
+ :location_body => '{',
134
+ :body => []
135
+ },
136
+ :catch_blocks => []
137
+ }
138
+ ]
139
+ }
140
+ end
141
+ end
142
+
143
+ recognizes_as_expected 'block with argument' do
144
+ let(:rip) { 'if (:name) {} else {}' }
145
+ let(:expected_raw) do
146
+ {
147
+ :module => [
148
+ {
149
+ :if_block => {
150
+ :if => 'if',
151
+ :argument => {
152
+ :location => ':',
153
+ :string => rip_string_raw('name')
154
+ },
155
+ :location_body => '{',
156
+ :body => []
157
+ },
158
+ :else_block => {
159
+ :else => 'else',
160
+ :location_body => '{',
161
+ :body => []
162
+ }
163
+ }
164
+ ]
165
+ }
166
+ end
167
+ end
168
+
169
+ recognizes_as_expected 'block with multiple arguments' do
170
+ let(:rip) { 'type (one, two) {}' }
171
+ let(:expected_raw) do
172
+ {
173
+ :module => [
174
+ {
175
+ :type => 'type',
176
+ :arguments => [
177
+ { :reference => 'one' },
178
+ { :reference => 'two' }
179
+ ],
180
+ :location_body => '{',
181
+ :body => []
182
+ }
183
+ ]
184
+ }
185
+ end
186
+ end
187
+
188
+ recognizes_as_expected 'type with no super_types' do
189
+ let(:rip) do
190
+ <<-RIP
191
+ type {
192
+ # comment
193
+ }
194
+ RIP
195
+ end
196
+ let(:expected_raw) do
197
+ {
198
+ :module => [
199
+ {
200
+ :type => 'type',
201
+ :location_body => '{',
202
+ :body => []
203
+ }
204
+ ]
205
+ }
206
+ end
207
+ end
208
+
209
+ recognizes_as_expected 'overload with no parameters' do
210
+ let(:rip) { '-> {}' }
211
+ let(:expected_raw) do
212
+ {
213
+ :module => [
214
+ {
215
+ :dash_rocket => '->',
216
+ :location_body => '{',
217
+ :body => []
218
+ }
219
+ ]
220
+ }
221
+ end
222
+ end
223
+
224
+ recognizes_as_expected 'lambda with no parameters' do
225
+ let(:rip) { '=> { -> {} }' }
226
+ let(:expected_raw) do
227
+ {
228
+ :module => [
229
+ {
230
+ :fat_rocket => '=>',
231
+ :location_body => '{',
232
+ :overload_blocks => [
233
+ {
234
+ :dash_rocket => '->',
235
+ :location_body => '{',
236
+ :body => []
237
+ }
238
+ ]
239
+ }
240
+ ]
241
+ }
242
+ end
243
+ end
244
+
245
+ recognizes_as_expected 'overload with multiple required parameters' do
246
+ let(:rip) { '-> (one, two) {}' }
247
+ let(:expected_raw) do
248
+ {
249
+ :module => [
250
+ {
251
+ :dash_rocket => '->',
252
+ :parameters => [
253
+ { :parameter => 'one' },
254
+ { :parameter => 'two' }
255
+ ],
256
+ :location_body => '{',
257
+ :body => []
258
+ }
259
+ ]
260
+ }
261
+ end
262
+ end
263
+
264
+ recognizes_as_expected 'overload with multiple required parameters with type restrictions' do
265
+ let(:rip) { '-> (one, two<CustomType>) {}' }
266
+ let(:expected_raw) do
267
+ {
268
+ :module => [
269
+ {
270
+ :dash_rocket => '->',
271
+ :parameters => [
272
+ { :parameter => 'one' },
273
+ {
274
+ :parameter => 'two',
275
+ :type_argument => {
276
+ :reference => 'CustomType'
277
+ }
278
+ }
279
+ ],
280
+ :location_body => '{',
281
+ :body => []
282
+ }
283
+ ]
284
+ }
285
+ end
286
+ end
287
+
288
+ recognizes_as_expected 'overload with multiple optional parameters' do
289
+ let(:rip) { '-> (one = 1, two = 2) {}' }
290
+ let(:expected_raw) do
291
+ {
292
+ :module => [
293
+ {
294
+ :dash_rocket => '->',
295
+ :parameters => [
296
+ {
297
+ :parameter => 'one',
298
+ :default_expression => { :integer => '1' }
299
+ },
300
+ {
301
+ :parameter => 'two',
302
+ :default_expression => { :integer => '2' }
303
+ }
304
+ ],
305
+ :location_body => '{',
306
+ :body => []
307
+ }
308
+ ]
309
+ }
310
+ end
311
+ end
312
+
313
+ recognizes_as_expected 'overload with multiple optional parameters with type restrictions' do
314
+ let(:rip) { '-> (one<System.Integer> = 1, two = 2) {}' }
315
+ end
316
+
317
+ recognizes_as_expected 'overload with required parameter and optional parameter' do
318
+ let(:rip) { '-> (platform, name = :rip) {}' }
319
+ let(:expected_raw) do
320
+ {
321
+ :module => [
322
+ {
323
+ :dash_rocket => '->',
324
+ :parameters => [
325
+ { :parameter => 'platform' },
326
+ {
327
+ :parameter => 'name',
328
+ :default_expression => {
329
+ :location => ':',
330
+ :string => rip_string_raw('rip')
331
+ }
332
+ }
333
+ ],
334
+ :location_body => '{',
335
+ :body => []
336
+ }
337
+ ]
338
+ }
339
+ end
340
+ end
341
+
342
+ recognizes_as_expected 'overload with multiple required parameter and multiple optional parameter' do
343
+ let(:rip) { '-> (abc, xyz, one = 1, two = 2) {}' }
344
+ let(:expected_raw) do
345
+ {
346
+ :module => [
347
+ {
348
+ :dash_rocket => '->',
349
+ :parameters => [
350
+ { :parameter => 'abc' },
351
+ { :parameter => 'xyz' },
352
+ {
353
+ :parameter => 'one',
354
+ :default_expression => { :integer => '1' }
355
+ },
356
+ {
357
+ :parameter => 'two',
358
+ :default_expression => { :integer => '2' }
359
+ }
360
+ ],
361
+ :location_body => '{',
362
+ :body => []
363
+ }
364
+ ]
365
+ }
366
+ end
367
+ end
368
+
369
+ recognizes_as_expected 'blocks with block arguments' do
370
+ let(:rip) { 'type (type () {}) {}' }
371
+ let(:expected_raw) do
372
+ {
373
+ :module => [
374
+ {
375
+ :type => 'type',
376
+ :arguments => [
377
+ {
378
+ :type => 'type',
379
+ :arguments => [],
380
+ :location_body => '{',
381
+ :body => []
382
+ }
383
+ ],
384
+ :location_body => '{',
385
+ :body => []
386
+ }
387
+ ]
388
+ }
389
+ end
390
+ end
391
+
392
+ recognizes_as_expected 'switch' do
393
+ let(:rip) { 'switch (foo) { case (true) { 42 } else { 0 } }' }
394
+ let(:expected_raw) do
395
+ {
396
+ :module => [
397
+ {
398
+ :switch => 'switch',
399
+ :argument => { :reference => 'foo' },
400
+ :case_blocks => [
401
+ {
402
+ :case => 'case',
403
+ :arguments => [
404
+ { :reference => 'true' }
405
+ ],
406
+ :location_body => '{',
407
+ :body => [
408
+ { :integer => '42' }
409
+ ]
410
+ }
411
+ ],
412
+ :else_block => {
413
+ :else => 'else',
414
+ :location_body => '{',
415
+ :body => [
416
+ { :integer => '0' }
417
+ ]
418
+ }
419
+ }
420
+ ]
421
+ }
422
+ end
423
+ end
424
+
425
+ recognizes_as_expected 'switch without argument' do
426
+ let(:rip) { 'switch { case (true) { 42 } else { 0 } }' }
427
+ let(:expected_raw) do
428
+ {
429
+ :module => [
430
+ {
431
+ :switch => 'switch',
432
+ :case_blocks => [
433
+ {
434
+ :case => 'case',
435
+ :arguments => [
436
+ { :reference => 'true' }
437
+ ],
438
+ :location_body => '{',
439
+ :body => [
440
+ { :integer => '42' }
441
+ ]
442
+ }
443
+ ],
444
+ :else_block => {
445
+ :else => 'else',
446
+ :location_body => '{',
447
+ :body => [
448
+ { :integer => '0' }
449
+ ]
450
+ }
451
+ }
452
+ ]
453
+ }
454
+ end
455
+ end
456
+
457
+ recognizes_as_expected 'try-catch' do
458
+ let(:rip) { 'try {} catch (Exception: e) {}' }
459
+ let(:expected_raw) do
460
+ {
461
+ :module => [
462
+ {
463
+ :try_block => {
464
+ :try => 'try',
465
+ :location_body => '{',
466
+ :body => []
467
+ },
468
+ :catch_blocks => [
469
+ {
470
+ :catch => 'catch',
471
+ :argument => {
472
+ :atom => [
473
+ { :reference => 'Exception' },
474
+ {
475
+ :key_value_pair => {
476
+ :location => ':',
477
+ :value => { :reference => 'e' }
478
+ }
479
+ }
480
+ ]
481
+ },
482
+ :location_body => '{',
483
+ :body => []
484
+ }
485
+ ]
486
+ }
487
+ ]
488
+ }
489
+ end
490
+ end
491
+
492
+ recognizes_as_expected 'try-finally' do
493
+ let(:rip) { 'try {} finally {}' }
494
+ end
495
+
496
+ recognizes_as_expected 'try-catch-finally' do
497
+ let(:rip) { 'try {} catch (Exception: e) {} finally {}' }
498
+ end
499
+ end
500
+
501
+ context 'block body' do
502
+ recognizes_as_expected 'comments inside block body' do
503
+ let(:rip) do
504
+ <<-RIP
505
+ -> (x) {
506
+ # comment
507
+ }
508
+ RIP
509
+ end
510
+ let(:expected_raw) do
511
+ {
512
+ :module => [
513
+ {
514
+ :dash_rocket => '->',
515
+ :parameters => [
516
+ { :parameter => 'x' }
517
+ ],
518
+ :location_body => '{',
519
+ :body => []
520
+ }
521
+ ]
522
+ }
523
+ end
524
+ end
525
+
526
+ recognizes_as_expected 'references inside block body' do
527
+ let(:rip) { '-> (x) { name }' }
528
+ let(:expected_raw) do
529
+ {
530
+ :module => [
531
+ {
532
+ :dash_rocket => '->',
533
+ :parameters => [
534
+ { :parameter => 'x' }
535
+ ],
536
+ :location_body => '{',
537
+ :body => [
538
+ { :reference => 'name' }
539
+ ]
540
+ }
541
+ ]
542
+ }
543
+ end
544
+ end
545
+
546
+ recognizes_as_expected 'assignments inside block body' do
547
+ let(:rip) { '-> (foo) { x = :y }' }
548
+ let(:expected_raw) do
549
+ {
550
+ :module => [
551
+ {
552
+ :dash_rocket => '->',
553
+ :parameters => [
554
+ { :parameter => 'foo' }
555
+ ],
556
+ :location_body => '{',
557
+ :body => [
558
+ {
559
+ :atom => [
560
+ { :reference => 'x' },
561
+ {
562
+ :assignment => {
563
+ :location => '=',
564
+ :rhs => {
565
+ :location => ':',
566
+ :string => rip_string_raw('y')
567
+ }
568
+ }
569
+ }
570
+ ]
571
+ }
572
+ ]
573
+ }
574
+ ]
575
+ }
576
+ end
577
+ end
578
+
579
+ recognizes_as_expected 'invocations inside block body' do
580
+ let(:rip) { '-> (run!) { run!() }' }
581
+ let(:expected_raw) do
582
+ {
583
+ :module => [
584
+ {
585
+ :dash_rocket => '->',
586
+ :parameters => [
587
+ { :parameter => 'run!' }
588
+ ],
589
+ :location_body => '{',
590
+ :body => [
591
+ {
592
+ :atom => [
593
+ { :reference => 'run!' },
594
+ { :regular_invocation => { :location => '(', :arguments => [] } }
595
+ ]
596
+ }
597
+ ]
598
+ }
599
+ ]
600
+ }
601
+ end
602
+ end
603
+
604
+ recognizes_as_expected 'operator invocations inside block body' do
605
+ let(:rip) { '-> (steam) { steam will :rise }' }
606
+ let(:expected_raw) do
607
+ {
608
+ :module => [
609
+ {
610
+ :dash_rocket => '->',
611
+ :parameters => [
612
+ { :parameter => 'steam' }
613
+ ],
614
+ :location_body => '{',
615
+ :body => [
616
+ {
617
+ :atom => [
618
+ { :reference => 'steam' },
619
+ {
620
+ :operator_invocation => {
621
+ :operator => 'will',
622
+ :argument => {
623
+ :location => ':',
624
+ :string => rip_string_raw('rise')
625
+ }
626
+ }
627
+ }
628
+ ]
629
+ }
630
+ ]
631
+ }
632
+ ]
633
+ }
634
+ end
635
+ end
636
+
637
+ recognizes_as_expected 'literals inside block body' do
638
+ let(:rip) { '-> (n) { `3 }' }
639
+ let(:expected_raw) do
640
+ {
641
+ :module => [
642
+ {
643
+ :dash_rocket => '->',
644
+ :parameters => [
645
+ { :parameter => 'n' }
646
+ ],
647
+ :location_body => '{',
648
+ :body => [
649
+ {
650
+ :location => '`',
651
+ :character => '3'
652
+ }
653
+ ]
654
+ }
655
+ ]
656
+ }
657
+ end
658
+ end
659
+
660
+ recognizes_as_expected 'blocks inside block body' do
661
+ let(:rip) { '-> (foo) { if (false) { 42 } else { -42 } }' }
662
+ let(:expected_raw) do
663
+ {
664
+ :module => [
665
+ {
666
+ :dash_rocket => '->',
667
+ :parameters => [
668
+ { :parameter => 'foo' }
669
+ ],
670
+ :location_body => '{',
671
+ :body => [
672
+ {
673
+ :if_block => {
674
+ :if => 'if',
675
+ :argument => { :reference => 'false' },
676
+ :location_body => '{',
677
+ :body => [
678
+ { :integer => '42' }
679
+ ]
680
+ },
681
+ :else_block => {
682
+ :else => 'else',
683
+ :location_body => '{',
684
+ :body => [
685
+ { :sign => '-', :integer => '42' }
686
+ ]
687
+ }
688
+ }
689
+ ]
690
+ }
691
+ ]
692
+ }
693
+ end
694
+ end
695
+ end
696
+
697
+ recognizes_as_expected 'keyword' do
698
+ let(:rip) { 'return;' }
699
+ let(:expected_raw) do
700
+ {
701
+ :module => [
702
+ { :return => 'return' }
703
+ ]
704
+ }
705
+ end
706
+ end
707
+
708
+ recognizes_as_expected 'keyword followed by phrase' do
709
+ let(:rip) { 'exit 0' }
710
+ let(:expected_raw) do
711
+ {
712
+ :module => [
713
+ {
714
+ :exit => 'exit',
715
+ :payload => { :integer => '0' }
716
+ }
717
+ ]
718
+ }
719
+ end
720
+ end
721
+
722
+ recognizes_as_expected 'keyword followed by parenthesis around phrase' do
723
+ let(:rip) { 'throw (e)' }
724
+ let(:expected_raw) do
725
+ {
726
+ :module => [
727
+ {
728
+ :throw => 'throw',
729
+ :payload => { :reference => 'e' }
730
+ }
731
+ ]
732
+ }
733
+ end
734
+ end
735
+
736
+ context 'multiple expressions' do
737
+ recognizes_as_expected 'terminates expressions properly' do
738
+ let(:rip) do
739
+ <<-RIP
740
+ one
741
+ two
742
+ three
743
+ RIP
744
+ end
745
+ let(:expected_raw) do
746
+ {
747
+ :module => [
748
+ { :reference => 'one' },
749
+ { :reference => 'two' },
750
+ { :reference => 'three' }
751
+ ]
752
+ }
753
+ end
754
+ end
755
+
756
+ recognizes_as_expected 'allows expressions to take more than one line' do
757
+ let(:rip) do
758
+ <<-RIP
759
+ 1 +
760
+ 2 -
761
+ 3
762
+ RIP
763
+ end
764
+ let(:expected_raw) do
765
+ {
766
+ :module => [
767
+ {
768
+ :atom => [
769
+ { :integer => '1' },
770
+ {
771
+ :operator_invocation => {
772
+ :operator => '+',
773
+ :argument => { :integer => '2' }
774
+ }
775
+ },
776
+ {
777
+ :operator_invocation => {
778
+ :operator => '-',
779
+ :argument => { :integer => '3' }
780
+ }
781
+ }
782
+ ]
783
+ }
784
+ ]
785
+ }
786
+ end
787
+ end
788
+ end
789
+
790
+ context 'invoking lambdas' do
791
+ recognizes_as_expected 'overload literal invocation' do
792
+ let(:rip) { '-> () {}()' }
793
+ let(:expected_raw) do
794
+ {
795
+ :module => [
796
+ {
797
+ :atom => [
798
+ {
799
+ :dash_rocket => '->',
800
+ :parameters => [],
801
+ :location_body => '{',
802
+ :body => []
803
+ },
804
+ :regular_invocation => { :location => '(', :arguments => [] }
805
+ ]
806
+ }
807
+ ]
808
+ }
809
+ end
810
+ end
811
+
812
+ recognizes_as_expected 'lambda reference invocation' do
813
+ let(:rip) { 'full_name()' }
814
+ let(:expected_raw) do
815
+ {
816
+ :module => [
817
+ {
818
+ :atom => [
819
+ { :reference => 'full_name' },
820
+ { :regular_invocation => { :location => '(', :arguments => [] } }
821
+ ]
822
+ }
823
+ ]
824
+ }
825
+ end
826
+ end
827
+
828
+ recognizes_as_expected 'lambda reference invocation arguments' do
829
+ let(:rip) { 'full_name(:Thomas, :Ingram)' }
830
+ let(:expected_raw) do
831
+ {
832
+ :module => [
833
+ {
834
+ :atom => [
835
+ { :reference => 'full_name' },
836
+ {
837
+ :regular_invocation => {
838
+ :location => '(',
839
+ :arguments => [
840
+ { :location => ':', :string => rip_string_raw('Thomas') },
841
+ { :location => ':', :string => rip_string_raw('Ingram') }
842
+ ]
843
+ }
844
+ }
845
+ ]
846
+ }
847
+ ]
848
+ }
849
+ end
850
+ end
851
+
852
+ recognizes_as_expected 'index invocation' do
853
+ let(:rip) { 'list[0]' }
854
+ let(:expected_raw) do
855
+ {
856
+ :module => [
857
+ {
858
+ :atom => [
859
+ { :reference => 'list' },
860
+ {
861
+ :index_invocation => {
862
+ :open => '[',
863
+ :arguments => [
864
+ { :integer => '0' }
865
+ ],
866
+ :close => ']'
867
+ }
868
+ }
869
+ ]
870
+ }
871
+ ]
872
+ }
873
+ end
874
+ end
875
+
876
+ recognizes_as_expected 'operator invocation' do
877
+ let(:rip) { '2 + 2' }
878
+ let(:expected_raw) do
879
+ {
880
+ :module => [
881
+ {
882
+ :atom => [
883
+ { :integer => '2' },
884
+ {
885
+ :operator_invocation => {
886
+ :operator => '+',
887
+ :argument => { :integer => '2' }
888
+ }
889
+ }
890
+ ]
891
+ }
892
+ ]
893
+ }
894
+ end
895
+ end
896
+
897
+ recognizes_as_expected 'reference assignment' do
898
+ let(:rip) { 'favorite_language = :rip' }
899
+ let(:expected_raw) do
900
+ {
901
+ :module => [
902
+ {
903
+ :atom => [
904
+ { :reference => 'favorite_language' },
905
+ {
906
+ :assignment => {
907
+ :location => '=',
908
+ :rhs => { :location => ':', :string => rip_string_raw('rip') }
909
+ }
910
+ }
911
+ ]
912
+ }
913
+ ]
914
+ }
915
+ end
916
+ end
917
+
918
+ recognizes_as_expected 'property assignment' do
919
+ let(:rip) { 'favorite.language = :rip.lang' }
920
+ let(:expected_raw) do
921
+ {
922
+ :module => [
923
+ {
924
+ :atom => [
925
+ {
926
+ :atom => [
927
+ { :reference => 'favorite' },
928
+ {
929
+ :location => '.',
930
+ :property_name => 'language'
931
+ }
932
+ ]
933
+ },
934
+ {
935
+ :assignment => {
936
+ :location => '=',
937
+ :rhs => {
938
+ :atom => [
939
+ { :location => ':', :string => rip_string_raw('rip') },
940
+ {
941
+ :location => '.',
942
+ :property_name => 'lang'
943
+ }
944
+ ]
945
+ }
946
+ }
947
+ }
948
+ ]
949
+ }
950
+ ]
951
+ }
952
+ end
953
+ end
954
+ end
955
+
956
+ context 'nested parenthesis' do
957
+ recognizes_as_expected 'anything surrounded by parenthesis' do
958
+ let(:rip) { '(0)' }
959
+ let(:expected_raw) do
960
+ {
961
+ :module => [
962
+ { :integer => '0' }
963
+ ]
964
+ }
965
+ end
966
+ end
967
+
968
+ recognizes_as_expected 'anything surrounded by parenthesis with crazy nesting' do
969
+ let(:rip) { '((((((l((1 + (((2 - 3)))))))))))' }
970
+ let(:expected_raw) do
971
+ {
972
+ :module => [
973
+ {
974
+ :atom => [
975
+ { :reference => 'l' },
976
+ {
977
+ :regular_invocation => {
978
+ :location => '(',
979
+ :arguments => [
980
+ {
981
+ :atom => [
982
+ { :integer => '1' },
983
+ {
984
+ :operator_invocation => {
985
+ :operator => '+',
986
+ :argument => {
987
+ :atom => [
988
+ { :integer => '2' },
989
+ {
990
+ :operator_invocation => {
991
+ :operator => '-',
992
+ :argument => { :integer => '3' }
993
+ }
994
+ }
995
+ ]
996
+ }
997
+ }
998
+ }
999
+ ]
1000
+ }
1001
+ ]
1002
+ }
1003
+ }
1004
+ ]
1005
+ }
1006
+ ]
1007
+ }
1008
+ end
1009
+ end
1010
+ end
1011
+
1012
+ context 'property chaining' do
1013
+ recognizes_as_expected 'chaining with properies and invocations' do
1014
+ let(:rip) { '0.one().two.three()' }
1015
+ let(:expected_raw) do
1016
+ {
1017
+ :module => [
1018
+ {
1019
+ :atom => [
1020
+ { :integer => '0' },
1021
+ {
1022
+ :location => '.',
1023
+ :property_name => 'one'
1024
+ },
1025
+ { :regular_invocation => { :location => '(', :arguments => [] } },
1026
+ {
1027
+ :location => '.',
1028
+ :property_name => 'two'
1029
+ },
1030
+ {
1031
+ :location => '.',
1032
+ :property_name => 'three'
1033
+ },
1034
+ { :regular_invocation => { :location => '(', :arguments=> [] } }
1035
+ ]
1036
+ }
1037
+ ]
1038
+ }
1039
+ end
1040
+ end
1041
+
1042
+ recognizes_as_expected 'chaining off opererators' do
1043
+ let(:rip) { '(1 - 2).zero?()' }
1044
+ let(:expected_raw) do
1045
+ {
1046
+ :module => [
1047
+ {
1048
+ :atom => [
1049
+ {
1050
+ :atom => [
1051
+ { :integer => '1' },
1052
+ {
1053
+ :operator_invocation => {
1054
+ :operator => '-',
1055
+ :argument => { :integer => '2' }
1056
+ }
1057
+ }
1058
+ ]
1059
+ },
1060
+ {
1061
+ :location => '.',
1062
+ :property_name => 'zero?'
1063
+ },
1064
+ { :regular_invocation => { :location => '(', :arguments => [] } }
1065
+ ]
1066
+ }
1067
+ ]
1068
+ }
1069
+ end
1070
+ end
1071
+
1072
+ recognizes_as_expected 'chaining several opererators' do
1073
+ let(:rip) { '1 + 2 + 3 + 4' }
1074
+ let(:expected_raw) do
1075
+ {
1076
+ :module => [
1077
+ {
1078
+ :atom => [
1079
+ { :integer => '1' },
1080
+ {
1081
+ :operator_invocation => {
1082
+ :operator => '+',
1083
+ :argument => { :integer => '2' }
1084
+ }
1085
+ },
1086
+ {
1087
+ :operator_invocation => {
1088
+ :operator => '+',
1089
+ :argument => { :integer => '3' }
1090
+ }
1091
+ },
1092
+ {
1093
+ :operator_invocation => {
1094
+ :operator => '+',
1095
+ :argument => { :integer => '4' }
1096
+ }
1097
+ }
1098
+ ]
1099
+ }
1100
+ ]
1101
+ }
1102
+ end
1103
+ end
1104
+ end
1105
+
1106
+ context 'atomic literals' do
1107
+ describe 'numbers' do
1108
+ recognizes_as_expected 'integer' do
1109
+ let(:rip) { '42' }
1110
+ let(:expected_raw) do
1111
+ {
1112
+ :module => [
1113
+ { :integer => '42' }
1114
+ ]
1115
+ }
1116
+ end
1117
+ end
1118
+
1119
+ recognizes_as_expected 'decimal' do
1120
+ let(:rip) { '4.2' }
1121
+ let(:expected_raw) do
1122
+ {
1123
+ :module => [
1124
+ { :decimal => '4.2' }
1125
+ ]
1126
+ }
1127
+ end
1128
+ end
1129
+
1130
+ recognizes_as_expected 'negative number' do
1131
+ let(:rip) { '-3' }
1132
+ let(:expected_raw) do
1133
+ {
1134
+ :module => [
1135
+ { :sign => '-', :integer => '3' }
1136
+ ]
1137
+ }
1138
+ end
1139
+ end
1140
+
1141
+ recognizes_as_expected 'large number' do
1142
+ let(:rip) { '123_456_789' }
1143
+ let(:expected_raw) do
1144
+ {
1145
+ :module => [
1146
+ { :integer => '123_456_789' }
1147
+ ]
1148
+ }
1149
+ end
1150
+ end
1151
+ end
1152
+
1153
+ recognizes_as_expected 'regular character' do
1154
+ let(:rip) { '`9' }
1155
+ let(:expected_raw) do
1156
+ {
1157
+ :module => [
1158
+ {
1159
+ :location => '`',
1160
+ :character => '9'
1161
+ }
1162
+ ]
1163
+ }
1164
+ end
1165
+ end
1166
+
1167
+ recognizes_as_expected 'escaped character' do
1168
+ let(:rip) { '`\n' }
1169
+ let(:expected_raw) do
1170
+ {
1171
+ :module => [
1172
+ {
1173
+ :location => '`',
1174
+ :character => { :location => '\\', :escaped_token => 'n' }
1175
+ }
1176
+ ]
1177
+ }
1178
+ end
1179
+ end
1180
+
1181
+ recognizes_as_expected 'symbol string' do
1182
+ let(:rip) { ':0' }
1183
+ let(:expected_raw) do
1184
+ {
1185
+ :module => [
1186
+ {
1187
+ :location => ':',
1188
+ :string => [
1189
+ { :character => '0' }
1190
+ ]
1191
+ }
1192
+ ]
1193
+ }
1194
+ end
1195
+ end
1196
+
1197
+ recognizes_as_expected 'symbol string with escape' do
1198
+ let(:rip) { ':on\e' }
1199
+ let(:expected_raw) do
1200
+ {
1201
+ :module => [
1202
+ {
1203
+ :location => ':',
1204
+ :string => [
1205
+ { :character => 'o' },
1206
+ { :character => 'n' },
1207
+ { :character => '\\' },
1208
+ { :character => 'e' }
1209
+ ]
1210
+ }
1211
+ ]
1212
+ }
1213
+ end
1214
+ end
1215
+
1216
+ recognizes_as_expected 'single-quoted string (empty)' do
1217
+ let(:rip) { "''" }
1218
+ let(:expected_raw) do
1219
+ {
1220
+ :module => [
1221
+ {
1222
+ :location => '\'',
1223
+ :string => []
1224
+ }
1225
+ ]
1226
+ }
1227
+ end
1228
+ end
1229
+
1230
+ recognizes_as_expected 'single-quoted string' do
1231
+ let(:rip) { '\'two\'' }
1232
+ let(:expected_raw) do
1233
+ {
1234
+ :module => [
1235
+ {
1236
+ :location => '\'',
1237
+ :string => [
1238
+ { :character => 't' },
1239
+ { :character => 'w' },
1240
+ { :character => 'o' }
1241
+ ]
1242
+ }
1243
+ ]
1244
+ }
1245
+ end
1246
+ end
1247
+
1248
+ recognizes_as_expected 'double-quoted string (empty)' do
1249
+ let(:rip) { '""' }
1250
+ let(:expected_raw) do
1251
+ {
1252
+ :module => [
1253
+ {
1254
+ :location => '"',
1255
+ :string => []
1256
+ }
1257
+ ]
1258
+ }
1259
+ end
1260
+ end
1261
+
1262
+ recognizes_as_expected 'double-quoted string' do
1263
+ let(:rip) { '"a\nb"' }
1264
+ let(:expected_raw) do
1265
+ {
1266
+ :module => [
1267
+ {
1268
+ :location => '"',
1269
+ :string => [
1270
+ { :character => 'a' },
1271
+ { :character => { :location => '\\', :escaped_token => 'n' } },
1272
+ { :character => 'b' }
1273
+ ]
1274
+ }
1275
+ ]
1276
+ }
1277
+ end
1278
+ end
1279
+
1280
+ recognizes_as_expected 'double-quoted string with interpolation' do
1281
+ let(:rip) { '"ab#{cd}ef"' }
1282
+ let(:expected_raw) do
1283
+ {
1284
+ :module => [
1285
+ {
1286
+ :location => '"',
1287
+ :string => rip_string_raw('ab') + [{ :start => '#{', :interpolation => [
1288
+ { :reference => 'cd' }
1289
+ ], :end => '}' }] + rip_string_raw('ef')
1290
+ }
1291
+ ]
1292
+ }
1293
+ end
1294
+ end
1295
+
1296
+ recognizes_as_expected 'empty heredoc' do
1297
+ let(:rip) { "<<HERE_DOC\nHERE_DOC" }
1298
+ let(:expected_raw) do
1299
+ {
1300
+ :module => [
1301
+ {
1302
+ :location => '<<',
1303
+ :string => rip_string_raw('')
1304
+ }
1305
+ ]
1306
+ }
1307
+ end
1308
+ end
1309
+
1310
+ recognizes_as_expected 'heredoc with just blank lines' do
1311
+ let(:rip) { "<<HERE_DOC\r\n\r\n\r\nHERE_DOC\r\n" }
1312
+ let(:expected_raw) do
1313
+ {
1314
+ :module => [
1315
+ {
1316
+ :location => '<<',
1317
+ :string => [
1318
+ { :line_break => "\r\n" },
1319
+ { :line_break => "\r\n" }
1320
+ ]
1321
+ }
1322
+ ]
1323
+ }
1324
+ end
1325
+ end
1326
+
1327
+ recognizes_as_expected 'heredoc with just indented lines' do
1328
+ let(:rip) { "\t<<HERE_DOC\n\t\n\t\n\tHERE_DOC\n" }
1329
+ let(:expected_raw) do
1330
+ {
1331
+ :module => [
1332
+ {
1333
+ :location => '<<',
1334
+ :string => rip_string_raw("\t") + [ { :line_break => "\n" } ] + rip_string_raw("\t") + [ { :line_break => "\n" } ]
1335
+ }
1336
+ ]
1337
+ }
1338
+ end
1339
+ end
1340
+
1341
+ recognizes_as_expected 'heredoc containing label' do
1342
+ let(:rip) do
1343
+ strip_heredoc(<<-RIP)
1344
+ <<HERE_DOC
1345
+ i'm a HERE_DOC
1346
+ HERE_DOC are multi-line strings
1347
+ HERE_DOC
1348
+ RIP
1349
+ end
1350
+ end
1351
+
1352
+ recognizes_as_expected 'heredoc with interpolation' do
1353
+ let(:rip) do
1354
+ strip_heredoc(<<-RIP)
1355
+ <<HERE_DOC
1356
+ here docs are good for
1357
+ strings that \#{need} multiple lines
1358
+ advantageous, eh?
1359
+ HERE_DOC
1360
+ RIP
1361
+ end
1362
+ let(:expected_raw) do
1363
+ {
1364
+ :module => [
1365
+ {
1366
+ :location => '<<',
1367
+ :string => rip_string_raw('here docs are good for') + [ { :line_break => "\n" } ] +
1368
+ rip_string_raw('strings that ') + [{ :start => '#{', :interpolation => [
1369
+ { :reference => 'need' }
1370
+ ], :end => '}' }] +
1371
+ rip_string_raw(' multiple lines') + [ { :line_break => "\n" } ] +
1372
+ rip_string_raw('advantageous, eh?') + [ { :line_break => "\n" } ]
1373
+ }
1374
+ ]
1375
+ }
1376
+ end
1377
+ end
1378
+
1379
+ recognizes_as_expected 'regular expression (empty)' do
1380
+ let(:rip) { '//' }
1381
+ let(:expected_raw) do
1382
+ {
1383
+ :module => [
1384
+ {
1385
+ :location => '/',
1386
+ :regex => []
1387
+ }
1388
+ ]
1389
+ }
1390
+ end
1391
+ end
1392
+
1393
+ recognizes_as_expected 'regular expression' do
1394
+ let(:rip) { '/hello/' }
1395
+ let(:expected_raw) do
1396
+ {
1397
+ :module => [
1398
+ {
1399
+ :location => '/',
1400
+ :regex => [
1401
+ { :character => 'h' },
1402
+ { :character => 'e' },
1403
+ { :character => 'l' },
1404
+ { :character => 'l' },
1405
+ { :character => 'o' }
1406
+ ]
1407
+ }
1408
+ ]
1409
+ }
1410
+ end
1411
+ end
1412
+
1413
+ recognizes_as_expected 'regular expression with interpolation' do
1414
+ let(:rip) { '/he#{ll}o/' }
1415
+ let(:expected_raw) do
1416
+ {
1417
+ :module => [
1418
+ {
1419
+ :location => '/',
1420
+ :regex => [
1421
+ { :character => 'h' },
1422
+ { :character => 'e' },
1423
+ {
1424
+ :start => '#{',
1425
+ :interpolation_regex => [
1426
+ { :reference => 'll' }
1427
+ ],
1428
+ :end => '}'
1429
+ },
1430
+ { :character => 'o' }
1431
+ ]
1432
+ }
1433
+ ]
1434
+ }
1435
+ end
1436
+ end
1437
+ end
1438
+
1439
+ context 'date and time literals' do
1440
+ recognizes_as_expected 'date' do
1441
+ let(:rip) { '2012-02-12' }
1442
+ let(:expected_raw) do
1443
+ {
1444
+ :module => [
1445
+ {
1446
+ :year => '2012',
1447
+ :month => '02',
1448
+ :day => '12'
1449
+ }
1450
+ ]
1451
+ }
1452
+ end
1453
+ end
1454
+
1455
+ recognizes_as_expected 'time' do
1456
+ let(:rip) { '05:24:00' }
1457
+ let(:expected_raw) do
1458
+ {
1459
+ :module => [
1460
+ {
1461
+ :hour => '05',
1462
+ :minute => '24',
1463
+ :second => '00'
1464
+ }
1465
+ ]
1466
+ }
1467
+ end
1468
+ end
1469
+
1470
+ recognizes_as_expected 'time with optional fractional second' do
1471
+ let(:rip) { '05:24:00.14159' }
1472
+ end
1473
+
1474
+ recognizes_as_expected 'time with optional offset' do
1475
+ let(:rip) { '00:24:00-0500' }
1476
+ end
1477
+
1478
+ recognizes_as_expected 'time with optional fractional second and optional offset' do
1479
+ let(:rip) { '00:24:00.14159-0500' }
1480
+ let(:expected_raw) do
1481
+ {
1482
+ :module => [
1483
+ {
1484
+ :hour => '00',
1485
+ :minute => '24',
1486
+ :second => '00',
1487
+ :sub_second => '14159',
1488
+ :offset => {
1489
+ :sign => '-',
1490
+ :hour => '05',
1491
+ :minute => '00'
1492
+ }
1493
+ }
1494
+ ]
1495
+ }
1496
+ end
1497
+ end
1498
+
1499
+ recognizes_as_expected 'datetime' do
1500
+ let(:rip) { '2012-02-12T05:24:00' }
1501
+ let(:expected_raw) do
1502
+ {
1503
+ :module => [
1504
+ {
1505
+ :date => {
1506
+ :year => '2012',
1507
+ :month => '02',
1508
+ :day => '12'
1509
+ },
1510
+ :time => {
1511
+ :hour => '05',
1512
+ :minute => '24',
1513
+ :second => '00'
1514
+ }
1515
+ }
1516
+ ]
1517
+ }
1518
+ end
1519
+ end
1520
+ end
1521
+
1522
+ context 'molecular literals' do
1523
+ recognizes_as_expected 'key-value pairs' do
1524
+ let(:rip) { '5: \'five\'' }
1525
+ let(:expected_raw) do
1526
+ {
1527
+ :module => [
1528
+ {
1529
+ :atom => [
1530
+ { :integer => '5' },
1531
+ {
1532
+ :key_value_pair => {
1533
+ :location => ':',
1534
+ :value => {
1535
+ :location => '\'',
1536
+ :string => rip_string_raw('five')
1537
+ }
1538
+ }
1539
+ }
1540
+ ]
1541
+ }
1542
+ ]
1543
+ }
1544
+ end
1545
+ end
1546
+
1547
+ recognizes_as_expected 'ranges' do
1548
+ let(:rip) { '1..3' }
1549
+ let(:expected_raw) do
1550
+ {
1551
+ :module => [
1552
+ {
1553
+ :atom => [
1554
+ { :integer => '1' },
1555
+ {
1556
+ :range => {
1557
+ :end => { :integer => '3' },
1558
+ :location => '..',
1559
+ :exclusivity => nil
1560
+ }
1561
+ }
1562
+ ]
1563
+ }
1564
+ ]
1565
+ }
1566
+ end
1567
+ end
1568
+
1569
+ recognizes_as_expected 'exclusive ranges' do
1570
+ let(:rip) { '1...age' }
1571
+ let(:expected_raw) do
1572
+ {
1573
+ :module => [
1574
+ {
1575
+ :atom => [
1576
+ { :integer => '1' },
1577
+ {
1578
+ :range => {
1579
+ :end => { :reference => 'age' },
1580
+ :location => '..',
1581
+ :exclusivity => '.'
1582
+ }
1583
+ }
1584
+ ]
1585
+ }
1586
+ ]
1587
+ }
1588
+ end
1589
+ end
1590
+
1591
+ recognizes_as_expected 'empty map' do
1592
+ let(:rip) { '{}' }
1593
+ let(:expected_raw) do
1594
+ {
1595
+ :module => [
1596
+ {
1597
+ :location => '{',
1598
+ :map => []
1599
+ }
1600
+ ]
1601
+ }
1602
+ end
1603
+ end
1604
+
1605
+ recognizes_as_expected 'map with content' do
1606
+ let(:rip) do
1607
+ <<-RIP
1608
+ {
1609
+ :age: 31,
1610
+ :name: :Thomas
1611
+ }
1612
+ RIP
1613
+ end
1614
+ let(:expected_raw) do
1615
+ {
1616
+ :module => [
1617
+ {
1618
+ :location => '{',
1619
+ :map => [
1620
+ {
1621
+ :atom => [
1622
+ {
1623
+ :location => ':',
1624
+ :string => rip_string_raw('age')
1625
+ },
1626
+ {
1627
+ :key_value_pair => {
1628
+ :location => ':',
1629
+ :value => { :integer => '31' }
1630
+ }
1631
+ }
1632
+ ]
1633
+ },
1634
+ {
1635
+ :atom => [
1636
+ {
1637
+ :location => ':',
1638
+ :string => rip_string_raw('name')
1639
+ },
1640
+ {
1641
+ :key_value_pair => {
1642
+ :location => ':',
1643
+ :value => {
1644
+ :location => ':',
1645
+ :string => rip_string_raw('Thomas')
1646
+ }
1647
+ }
1648
+ }
1649
+ ]
1650
+ }
1651
+ ]
1652
+ }
1653
+ ]
1654
+ }
1655
+ end
1656
+ end
1657
+
1658
+ recognizes_as_expected 'empty list' do
1659
+ let(:rip) { '[]' }
1660
+ let(:expected_raw) do
1661
+ {
1662
+ :module => [
1663
+ {
1664
+ :location => '[',
1665
+ :list => []
1666
+ }
1667
+ ]
1668
+ }
1669
+ end
1670
+ end
1671
+
1672
+ recognizes_as_expected 'list with content' do
1673
+ let(:rip) do
1674
+ <<-RIP
1675
+ [
1676
+ 31,
1677
+ :Thomas
1678
+ ]
1679
+ RIP
1680
+ end
1681
+ let(:expected_raw) do
1682
+ {
1683
+ :module => [
1684
+ {
1685
+ :location => '[',
1686
+ :list => [
1687
+ { :integer => '31' },
1688
+ {
1689
+ :location => ':',
1690
+ :string => rip_string_raw('Thomas')
1691
+ }
1692
+ ]
1693
+ }
1694
+ ]
1695
+ }
1696
+ end
1697
+ end
1698
+ end
1699
+ end
1700
+ end