rip-parser 0.1.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.
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