rltk3 3.0.2

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 (56) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +1 -0
  3. data/LICENSE +27 -0
  4. data/README.md +852 -0
  5. data/Rakefile +197 -0
  6. data/lib/rltk/ast.rb +573 -0
  7. data/lib/rltk/cfg.rb +683 -0
  8. data/lib/rltk/cg/basic_block.rb +157 -0
  9. data/lib/rltk/cg/bindings.rb +151 -0
  10. data/lib/rltk/cg/builder.rb +1127 -0
  11. data/lib/rltk/cg/context.rb +48 -0
  12. data/lib/rltk/cg/contractor.rb +51 -0
  13. data/lib/rltk/cg/execution_engine.rb +194 -0
  14. data/lib/rltk/cg/function.rb +237 -0
  15. data/lib/rltk/cg/generated_bindings.rb +8118 -0
  16. data/lib/rltk/cg/generic_value.rb +95 -0
  17. data/lib/rltk/cg/instruction.rb +519 -0
  18. data/lib/rltk/cg/llvm.rb +150 -0
  19. data/lib/rltk/cg/memory_buffer.rb +75 -0
  20. data/lib/rltk/cg/module.rb +451 -0
  21. data/lib/rltk/cg/pass_manager.rb +252 -0
  22. data/lib/rltk/cg/support.rb +29 -0
  23. data/lib/rltk/cg/target.rb +230 -0
  24. data/lib/rltk/cg/triple.rb +58 -0
  25. data/lib/rltk/cg/type.rb +554 -0
  26. data/lib/rltk/cg/value.rb +1272 -0
  27. data/lib/rltk/cg.rb +32 -0
  28. data/lib/rltk/lexer.rb +372 -0
  29. data/lib/rltk/lexers/calculator.rb +44 -0
  30. data/lib/rltk/lexers/ebnf.rb +38 -0
  31. data/lib/rltk/parser.rb +1702 -0
  32. data/lib/rltk/parsers/infix_calc.rb +43 -0
  33. data/lib/rltk/parsers/postfix_calc.rb +34 -0
  34. data/lib/rltk/parsers/prefix_calc.rb +34 -0
  35. data/lib/rltk/token.rb +90 -0
  36. data/lib/rltk/version.rb +11 -0
  37. data/lib/rltk.rb +16 -0
  38. data/test/cg/tc_basic_block.rb +83 -0
  39. data/test/cg/tc_control_flow.rb +191 -0
  40. data/test/cg/tc_function.rb +54 -0
  41. data/test/cg/tc_generic_value.rb +33 -0
  42. data/test/cg/tc_instruction.rb +256 -0
  43. data/test/cg/tc_llvm.rb +25 -0
  44. data/test/cg/tc_math.rb +88 -0
  45. data/test/cg/tc_module.rb +89 -0
  46. data/test/cg/tc_transforms.rb +68 -0
  47. data/test/cg/tc_type.rb +69 -0
  48. data/test/cg/tc_value.rb +151 -0
  49. data/test/cg/ts_cg.rb +23 -0
  50. data/test/tc_ast.rb +332 -0
  51. data/test/tc_cfg.rb +164 -0
  52. data/test/tc_lexer.rb +216 -0
  53. data/test/tc_parser.rb +711 -0
  54. data/test/tc_token.rb +34 -0
  55. data/test/ts_rltk.rb +47 -0
  56. metadata +317 -0
data/test/tc_parser.rb ADDED
@@ -0,0 +1,711 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2011/04/06
4
+ # Description: This file contains unit tests for the RLTK::Parser class.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Standard Library
11
+ require 'tmpdir'
12
+
13
+ # Gems
14
+ require 'minitest/autorun'
15
+
16
+ # Ruby Language Toolkit
17
+ require 'rltk/lexer'
18
+ require 'rltk/parser'
19
+ require 'rltk/lexers/calculator'
20
+ require 'rltk/parsers/prefix_calc'
21
+ require 'rltk/parsers/infix_calc'
22
+ require 'rltk/parsers/postfix_calc'
23
+
24
+ #######################
25
+ # Classes and Modules #
26
+ #######################
27
+
28
+ class ParserTester < Minitest::Test
29
+ class ABLexer < RLTK::Lexer
30
+ rule(/a/) { [:A, 1] }
31
+ rule(/b/) { [:B, 2] }
32
+
33
+ rule(/\s/)
34
+ end
35
+
36
+ class AlphaLexer < RLTK::Lexer
37
+ rule(/[A-Za-z]/) { |t| [t.upcase.to_sym, t] }
38
+
39
+ rule(/,/) { :COMMA }
40
+
41
+ rule(/\s/)
42
+ end
43
+
44
+ class UnderscoreLexer < RLTK::Lexer
45
+ rule(/\w/) { |t| [:A_TOKEN, t] }
46
+ end
47
+
48
+ class APlusBParser < RLTK::Parser
49
+ production(:a, 'A+ B') { |a, _| a.length }
50
+
51
+ finalize
52
+ end
53
+
54
+ class AQuestionBParser < RLTK::Parser
55
+ production(:a, 'A? B') { |a, _| a }
56
+
57
+ finalize
58
+ end
59
+
60
+ class AStarBParser < RLTK::Parser
61
+ production(:a, 'A* B') { |a, _| a.length }
62
+
63
+ finalize
64
+ end
65
+
66
+ class AmbiguousParser < RLTK::Parser
67
+ production(:e) do
68
+ clause('NUM') {|n| n}
69
+
70
+ clause('e PLS e') { |e0, _, e1| e0 + e1 }
71
+ clause('e SUB e') { |e0, _, e1| e0 - e1 }
72
+ clause('e MUL e') { |e0, _, e1| e0 * e1 }
73
+ clause('e DIV e') { |e0, _, e1| e0 / e1 }
74
+ end
75
+
76
+ finalize
77
+ end
78
+
79
+ class ArrayCalc < RLTK::Parser
80
+ dat :array
81
+
82
+ production(:e) do
83
+ clause('NUM') { |v| v[0] }
84
+
85
+ clause('PLS e e') { |v| v[1] + v[2] }
86
+ clause('SUB e e') { |v| v[1] - v[2] }
87
+ clause('MUL e e') { |v| v[1] * v[2] }
88
+ clause('DIV e e') { |v| v[1] / v[2] }
89
+ end
90
+
91
+ finalize
92
+ end
93
+
94
+ # This grammar is purposefully ambiguous. This should not be equivalent
95
+ # to the grammar produced with `e -> A B? B?`, due to greedy Kleene
96
+ # operators.
97
+ class AmbiguousParseStackParser < RLTK::Parser
98
+ production(:s, 'e*') { |e| e }
99
+
100
+ production(:e, 'A b_question b_question') { |a, b0, b1| [a, b0, b1] }
101
+
102
+ production(:b_question) do
103
+ clause('') { | | nil }
104
+ clause('B') { |b| b }
105
+ end
106
+
107
+ finalize
108
+ end
109
+
110
+ class EBNFSelectorParser < RLTK::Parser
111
+ dat :array
112
+
113
+ production(:s) do
114
+ clause('.A .B* .A') { |a| a }
115
+ clause('.B C* .B') { |a| a }
116
+ end
117
+
118
+ finalize
119
+ end
120
+
121
+ class EmptyListParser0 < RLTK::Parser
122
+ list('list', :A, :COMMA)
123
+
124
+ finalize
125
+ end
126
+
127
+ class EmptyListParser1 < RLTK::Parser
128
+ dat :array
129
+
130
+ list('list', ['A', 'B', 'C D'], :COMMA)
131
+
132
+ finalize
133
+ end
134
+
135
+ class GreedTestParser0 < RLTK::Parser
136
+ production(:e, 'A? A') { |a0, a1| [a0, a1] }
137
+
138
+ finalize
139
+ end
140
+
141
+ class GreedTestParser1 < RLTK::Parser
142
+ production(:e, 'A? A?') { |a0, a1| [a0, a1] }
143
+
144
+ finalize
145
+ end
146
+
147
+ class GreedTestParser2 < RLTK::Parser
148
+ production(:e, 'A* A') { |a0, a1| [a0, a1] }
149
+
150
+ finalize
151
+ end
152
+
153
+ class GreedTestParser3 < RLTK::Parser
154
+ production(:e, 'A+ A') { |a0, a1| [a0, a1] }
155
+
156
+ finalize
157
+ end
158
+
159
+ class NonEmptyListParser0 < RLTK::Parser
160
+ nonempty_list('list', :A, :COMMA)
161
+
162
+ finalize
163
+ end
164
+
165
+ class NonEmptyListParser1 < RLTK::Parser
166
+ nonempty_list('list', [:A, :B], :COMMA)
167
+
168
+ finalize explain: 'nelp1.tbl'
169
+ end
170
+
171
+ class NonEmptyListParser2 < RLTK::Parser
172
+ nonempty_list('list', ['A', 'B', 'C D'], :COMMA)
173
+
174
+ finalize
175
+ end
176
+
177
+ class NonEmptyListParser3 < RLTK::Parser
178
+ nonempty_list('list', 'A+', :COMMA)
179
+
180
+ finalize
181
+ end
182
+
183
+ class NonEmptyListParser4 < RLTK::Parser
184
+ nonempty_list('list', :A)
185
+
186
+ finalize
187
+ end
188
+
189
+ class NonEmptyListParser5 < RLTK::Parser
190
+ nonempty_list('list', :A, 'B C?')
191
+
192
+ finalize
193
+ end
194
+
195
+ class DummyError1 < StandardError; end
196
+ class DummyError2 < StandardError; end
197
+
198
+ class ErrorCalc < RLTK::Parser
199
+ left :ERROR
200
+ right :PLS, :SUB, :MUL, :DIV, :NUM
201
+
202
+ production(:e) do
203
+ clause('NUM') {|n| n}
204
+
205
+ clause('e PLS e') { |e0, _, e1| e0 + e1 }
206
+ clause('e SUB e') { |e0, _, e1| e0 - e1 }
207
+ clause('e MUL e') { |e0, _, e1| e0 * e1 }
208
+ clause('e DIV e') { |e0, _, e1| e0 / e1 }
209
+
210
+ clause('e PLS ERROR e') { |e0, _, ts, e1| error(ts); e0 + e1 }
211
+ end
212
+
213
+ finalize
214
+ end
215
+
216
+ class ELLexer < RLTK::Lexer
217
+ rule(/\n/) { :NEWLINE }
218
+ rule(/;/) { :SEMI }
219
+
220
+ rule(/\s/)
221
+
222
+ rule(/[A-Za-z]+/) { |t| [:WORD, t] }
223
+ end
224
+
225
+ class ErrorLine < RLTK::Parser
226
+
227
+ production(:s, 'line*') { |l| l }
228
+
229
+ production(:line) do
230
+ clause('NEWLINE') { |_| nil }
231
+
232
+ clause('WORD+ SEMI NEWLINE') { |w, _, _| w }
233
+ clause('WORD+ ERROR') { |w, e| error(pos(1).line_number); w }
234
+ end
235
+
236
+ finalize
237
+ end
238
+
239
+ class UnderscoreParser < RLTK::Parser
240
+ production(:s, 'A_TOKEN+') { |o| o }
241
+
242
+ finalize
243
+ end
244
+
245
+ class RotatingCalc < RLTK::Parser
246
+ production(:e) do
247
+ clause('NUM') {|n| n}
248
+
249
+ clause('PLS e e') { |_, e0, e1| e0.send(get_op(:+), e1) }
250
+ clause('SUB e e') { |_, e0, e1| e0.send(get_op(:-), e1) }
251
+ clause('MUL e e') { |_, e0, e1| e0.send(get_op(:*), e1) }
252
+ clause('DIV e e') { |_, e0, e1| e0.send(get_op(:/), e1) }
253
+ end
254
+
255
+ class Environment < Environment
256
+ def initialize
257
+ @map = { :+ => 0, :- => 1, :* => 2, :/ => 3 }
258
+ @ops = [ :+, :-, :*, :/ ]
259
+ end
260
+
261
+ def get_op(orig_op)
262
+ new_op = @ops[@map[orig_op]]
263
+
264
+ @ops = @ops[1..-1] << @ops[0]
265
+
266
+ new_op
267
+ end
268
+ end
269
+
270
+ finalize
271
+ end
272
+
273
+ class SelectionParser < RLTK::Parser
274
+ production(:s, 'A+ .B+') { |bs| bs.inject(&:+) }
275
+
276
+ finalize
277
+ end
278
+
279
+ class UselessParser < RLTK::Parser
280
+ production(:s, 'A+') { |a| a }
281
+ end
282
+
283
+ class TokenHookParser < RLTK::Parser
284
+ dat :array
285
+
286
+ production(:s) do
287
+ clause('A A A A') { |_| nil }
288
+ clause('B B B B') { |_| nil }
289
+ end
290
+
291
+ token_hook(:A) { @counter += 1 }
292
+ token_hook(:B) { @counter += 2 }
293
+
294
+ class Environment < Environment
295
+ attr_reader :counter
296
+
297
+ def initialize
298
+ @counter = 0
299
+ end
300
+ end
301
+
302
+ finalize
303
+ end
304
+
305
+ def test_ambiguous_grammar
306
+ actual = AmbiguousParser.parse(RLTK::Lexers::Calculator.lex('1 + 2 * 3'), {:accept => :all})
307
+ assert_equal([7, 9], actual.sort)
308
+ end
309
+
310
+ # This test is to ensure that objects placed on the output stack are
311
+ # cloned when we split the parse stack. This was posted as Issue #17 on
312
+ # Github.
313
+ def test_ambiguous_parse_stack
314
+ assert_equal(1, AmbiguousParseStackParser.parse(ABLexer.lex('ab')).length)
315
+ end
316
+
317
+ def test_array_args
318
+ actual = ArrayCalc.parse(RLTK::Lexers::Calculator.lex('+ 1 2'))
319
+ assert_equal(3, actual)
320
+
321
+ actual = ArrayCalc.parse(RLTK::Lexers::Calculator.lex('+ 1 * 2 3'))
322
+ assert_equal(7, actual)
323
+
324
+ actual = ArrayCalc.parse(RLTK::Lexers::Calculator.lex('* + 1 2 3'))
325
+ assert_equal(9, actual)
326
+ end
327
+
328
+ def test_construction_error
329
+ assert_raises(RLTK::ParserConstructionException) do
330
+ Class.new(RLTK::Parser) do
331
+ finalize
332
+ end
333
+ end
334
+ end
335
+
336
+ def test_ebnf_parsing
337
+ ################
338
+ # APlusBParser #
339
+ ################
340
+
341
+ assert_raises(RLTK::NotInLanguage) { APlusBParser.parse(ABLexer.lex('b')) }
342
+
343
+ assert_equal(1, APlusBParser.parse(ABLexer.lex('ab')))
344
+ assert_equal(2, APlusBParser.parse(ABLexer.lex('aab')))
345
+ assert_equal(3, APlusBParser.parse(ABLexer.lex('aaab')))
346
+ assert_equal(4, APlusBParser.parse(ABLexer.lex('aaaab')))
347
+
348
+ ####################
349
+ # AQuestionBParser #
350
+ ####################
351
+
352
+ assert_raises(RLTK::NotInLanguage) { AQuestionBParser.parse(ABLexer.lex('aab')) }
353
+ assert_nil(AQuestionBParser.parse(ABLexer.lex('b')))
354
+ refute_nil(AQuestionBParser.parse(ABLexer.lex('ab')))
355
+
356
+ ################
357
+ # AStarBParser #
358
+ ################
359
+
360
+ assert_equal(0, AStarBParser.parse(ABLexer.lex('b')))
361
+ assert_equal(1, AStarBParser.parse(ABLexer.lex('ab')))
362
+ assert_equal(2, AStarBParser.parse(ABLexer.lex('aab')))
363
+ assert_equal(3, AStarBParser.parse(ABLexer.lex('aaab')))
364
+ assert_equal(4, AStarBParser.parse(ABLexer.lex('aaaab')))
365
+ end
366
+
367
+ def test_empty_list
368
+ ####################
369
+ # EmptyListParser0 #
370
+ ####################
371
+
372
+ expected = []
373
+ actual = EmptyListParser0.parse(AlphaLexer.lex(''))
374
+ assert_equal(expected, actual)
375
+
376
+ ####################
377
+ # EmptyListParser1 #
378
+ ####################
379
+
380
+ expected = ['a', 'b', ['c', 'd']]
381
+ actual = EmptyListParser1.parse(AlphaLexer.lex('a, b, c d'))
382
+ assert_equal(expected, actual)
383
+ end
384
+
385
+ def test_greed
386
+
387
+ ####################
388
+ # GreedTestParser0 #
389
+ ####################
390
+
391
+ expected = [nil, 'a']
392
+ actual = GreedTestParser0.parse(AlphaLexer.lex('a'))
393
+ assert_equal(expected, actual)
394
+
395
+ expected = ['a', 'a']
396
+ actual = GreedTestParser0.parse(AlphaLexer.lex('a a'))
397
+ assert_equal(expected, actual)
398
+
399
+ ####################
400
+ # GreedTestParser1 #
401
+ ####################
402
+
403
+ expected = [nil, nil]
404
+ actual = GreedTestParser1.parse(AlphaLexer.lex(''))
405
+ assert_equal(expected, actual)
406
+
407
+ # expected = ['a', nil]
408
+ # actual = GreedTestParser1.parse(AlphaLexer.lex('a'))
409
+ # assert_equal(expected, actual)
410
+
411
+ expected = ['a', 'a']
412
+ actual = GreedTestParser1.parse(AlphaLexer.lex('a a'))
413
+ assert_equal(expected, actual)
414
+
415
+ ####################
416
+ # GreedTestParser2 #
417
+ ####################
418
+
419
+ expected = [[], 'a']
420
+ actual = GreedTestParser2.parse(AlphaLexer.lex('a'))
421
+ assert_equal(expected, actual)
422
+
423
+ expected = [['a'], 'a']
424
+ actual = GreedTestParser2.parse(AlphaLexer.lex('a a'))
425
+ assert_equal(expected, actual)
426
+
427
+ expected = [['a', 'a'], 'a']
428
+ actual = GreedTestParser2.parse(AlphaLexer.lex('a a a'))
429
+ assert_equal(expected, actual)
430
+
431
+ ####################
432
+ # GreedTestParser3 #
433
+ ####################
434
+
435
+ expected = [['a'], 'a']
436
+ actual = GreedTestParser3.parse(AlphaLexer.lex('a a'))
437
+ assert_equal(expected, actual)
438
+
439
+ expected = [['a', 'a'], 'a']
440
+ actual = GreedTestParser3.parse(AlphaLexer.lex('a a a'))
441
+ assert_equal(expected, actual)
442
+ end
443
+
444
+ def test_ebnf_selector_interplay
445
+ expected = ['a', ['b', 'b', 'b'], 'a']
446
+ actual = EBNFSelectorParser.parse(AlphaLexer.lex('abbba'))
447
+ assert_equal(expected, actual)
448
+
449
+ expected = ['a', [], 'a']
450
+ actual = EBNFSelectorParser.parse(AlphaLexer.lex('aa'))
451
+ assert_equal(expected, actual)
452
+
453
+ expected = ['b', 'b']
454
+ actual = EBNFSelectorParser.parse(AlphaLexer.lex('bb'))
455
+ assert_equal(expected, actual)
456
+
457
+ expected = ['b', 'b']
458
+ actual = EBNFSelectorParser.parse(AlphaLexer.lex('bcccccb'))
459
+ assert_equal(expected, actual)
460
+ end
461
+
462
+ def test_environment
463
+ actual = RotatingCalc.parse(RLTK::Lexers::Calculator.lex('+ 1 2'))
464
+ assert_equal(3, actual)
465
+
466
+ actual = RotatingCalc.parse(RLTK::Lexers::Calculator.lex('/ 1 * 2 3'))
467
+ assert_equal(7, actual)
468
+
469
+ actual = RotatingCalc.parse(RLTK::Lexers::Calculator.lex('- + 1 2 3'))
470
+ assert_equal(9, actual)
471
+
472
+ parser = RotatingCalc.new
473
+
474
+ actual = parser.parse(RLTK::Lexers::Calculator.lex('+ 1 2'))
475
+ assert_equal(3, actual)
476
+
477
+ actual = parser.parse(RLTK::Lexers::Calculator.lex('/ 1 2'))
478
+ assert_equal(3, actual)
479
+ end
480
+
481
+ def test_error_productions
482
+
483
+ # Test to see if error reporting is working correctly.
484
+
485
+ test_string = "first line;\n"
486
+ test_string += "second line\n"
487
+ test_string += "third line;\n"
488
+ test_string += "fourth line\n"
489
+
490
+ assert_raises(RLTK::HandledError) { ErrorLine.parse(ELLexer.lex(test_string)) }
491
+
492
+ begin
493
+ ErrorLine.parse(ELLexer.lex(test_string))
494
+
495
+ rescue RLTK::HandledError => e
496
+ assert_equal([2,4], e.errors)
497
+ end
498
+
499
+ # Test to see if we can continue parsing after errors are encounterd.
500
+
501
+ begin
502
+ ErrorCalc.parse(RLTK::Lexers::Calculator.lex('1 + + 1'))
503
+
504
+ rescue RLTK::HandledError => e
505
+ assert_equal(1, e.errors.first.length)
506
+ assert_equal(2, e.result)
507
+ end
508
+
509
+ # Test to see if we pop tokens correctly after an error is
510
+ # encountered.
511
+
512
+ begin
513
+ ErrorCalc.parse(RLTK::Lexers::Calculator.lex('1 + + + + + + 1'))
514
+
515
+ rescue RLTK::HandledError => e
516
+ assert_equal(5, e.errors.first.length)
517
+ assert_equal(2, e.result)
518
+ end
519
+ end
520
+
521
+ def test_infix_calc
522
+ actual = RLTK::Parsers::InfixCalc.parse(RLTK::Lexers::Calculator.lex('1 + 2'))
523
+ assert_equal(3, actual)
524
+
525
+ actual = RLTK::Parsers::InfixCalc.parse(RLTK::Lexers::Calculator.lex('1 + 2 * 3'))
526
+ assert_equal(7, actual)
527
+
528
+ actual = RLTK::Parsers::InfixCalc.parse(RLTK::Lexers::Calculator.lex('(1 + 2) * 3'))
529
+ assert_equal(9, actual)
530
+
531
+ assert_raises(RLTK::NotInLanguage) { RLTK::Parsers::InfixCalc.parse(RLTK::Lexers::Calculator.lex('1 2 + 3 *')) }
532
+ end
533
+
534
+ def test_input
535
+ assert_raises(RLTK::BadToken) { RLTK::Parsers::InfixCalc.parse(RLTK::Lexers::EBNF.lex('A B C')) }
536
+ end
537
+
538
+ def test_nonempty_list
539
+ #######################
540
+ # NonEmptyListParser0 #
541
+ #######################
542
+
543
+ expected = ['a']
544
+ actual = NonEmptyListParser0.parse(AlphaLexer.lex('a'))
545
+ assert_equal(expected, actual)
546
+
547
+ expected = ['a', 'a']
548
+ actual = NonEmptyListParser0.parse(AlphaLexer.lex('a, a'))
549
+ assert_equal(expected, actual)
550
+
551
+ assert_raises(RLTK::NotInLanguage) { NonEmptyListParser0.parse(AlphaLexer.lex('')) }
552
+ assert_raises(RLTK::NotInLanguage) { NonEmptyListParser0.parse(AlphaLexer.lex(',')) }
553
+ assert_raises(RLTK::NotInLanguage) { NonEmptyListParser0.parse(AlphaLexer.lex('aa')) }
554
+ assert_raises(RLTK::NotInLanguage) { NonEmptyListParser0.parse(AlphaLexer.lex('a,')) }
555
+ assert_raises(RLTK::NotInLanguage) { NonEmptyListParser0.parse(AlphaLexer.lex(',a')) }
556
+
557
+ #######################
558
+ # NonEmptyListParser1 #
559
+ #######################
560
+
561
+ expected = ['a']
562
+ actual = NonEmptyListParser1.parse(AlphaLexer.lex('a'))
563
+ assert_equal(expected, actual)
564
+
565
+ expected = ['b']
566
+ actual = NonEmptyListParser1.parse(AlphaLexer.lex('b'))
567
+ assert_equal(expected, actual)
568
+
569
+ expected = ['a', 'b', 'a', 'b']
570
+ actual = NonEmptyListParser1.parse(AlphaLexer.lex('a, b, a, b'))
571
+ assert_equal(expected, actual)
572
+
573
+ assert_raises(RLTK::NotInLanguage) { NonEmptyListParser1.parse(AlphaLexer.lex('a b')) }
574
+ assert_raises(RLTK::NotInLanguage) { NonEmptyListParser1.parse(AlphaLexer.lex('a, ')) }
575
+
576
+ #######################
577
+ # NonEmptyListParser2 #
578
+ #######################
579
+
580
+ expected = ['a']
581
+ actual = NonEmptyListParser2.parse(AlphaLexer.lex('a'))
582
+ assert_equal(expected, actual)
583
+
584
+ expected = ['b']
585
+ actual = NonEmptyListParser2.parse(AlphaLexer.lex('b'))
586
+ assert_equal(expected, actual)
587
+
588
+ expected = [['c', 'd']]
589
+ actual = NonEmptyListParser2.parse(AlphaLexer.lex('c d'))
590
+ assert_equal(expected, actual)
591
+
592
+ expected = [['c', 'd'], ['c', 'd']]
593
+ actual = NonEmptyListParser2.parse(AlphaLexer.lex('c d, c d'))
594
+ assert_equal(expected, actual)
595
+
596
+ expected = ['a', 'b', ['c', 'd']]
597
+ actual = NonEmptyListParser2.parse(AlphaLexer.lex('a, b, c d'))
598
+ assert_equal(expected, actual)
599
+
600
+ assert_raises(RLTK::NotInLanguage) { NonEmptyListParser2.parse(AlphaLexer.lex('c')) }
601
+ assert_raises(RLTK::NotInLanguage) { NonEmptyListParser2.parse(AlphaLexer.lex('d')) }
602
+
603
+ #######################
604
+ # NonEmptyListParser3 #
605
+ #######################
606
+
607
+ expected = [['a'], ['a', 'a'], ['a', 'a', 'a']]
608
+ actual = NonEmptyListParser3.parse(AlphaLexer.lex('a, aa, aaa'))
609
+ assert_equal(expected, actual)
610
+
611
+ #######################
612
+ # NonEmptyListParser4 #
613
+ #######################
614
+
615
+ expected = ['a', 'a', 'a']
616
+ actual = NonEmptyListParser4.parse(AlphaLexer.lex('a a a'))
617
+ assert_equal(expected, actual)
618
+
619
+ #######################
620
+ # NonEmptyListParser5 #
621
+ #######################
622
+
623
+ expected = ['a', 'a', 'a']
624
+ actual = NonEmptyListParser5.parse(AlphaLexer.lex('a b a b c a'))
625
+ assert_equal(expected, actual)
626
+
627
+ assert_raises(RLTK::NotInLanguage) { NonEmptyListParser5.parse(AlphaLexer.lex('a b b a')) }
628
+ end
629
+
630
+ def test_postfix_calc
631
+ actual = RLTK::Parsers::PostfixCalc.parse(RLTK::Lexers::Calculator.lex('1 2 +'))
632
+ assert_equal(3, actual)
633
+
634
+ actual = RLTK::Parsers::PostfixCalc.parse(RLTK::Lexers::Calculator.lex('1 2 3 * +'))
635
+ assert_equal(7, actual)
636
+
637
+ actual = RLTK::Parsers::PostfixCalc.parse(RLTK::Lexers::Calculator.lex('1 2 + 3 *'))
638
+ assert_equal(9, actual)
639
+
640
+ assert_raises(RLTK::NotInLanguage) { RLTK::Parsers::InfixCalc.parse(RLTK::Lexers::Calculator.lex('* + 1 2 3')) }
641
+ end
642
+
643
+ def test_prefix_calc
644
+ actual = RLTK::Parsers::PrefixCalc.parse(RLTK::Lexers::Calculator.lex('+ 1 2'))
645
+ assert_equal(3, actual)
646
+
647
+ actual = RLTK::Parsers::PrefixCalc.parse(RLTK::Lexers::Calculator.lex('+ 1 * 2 3'))
648
+ assert_equal(7, actual)
649
+
650
+ actual = RLTK::Parsers::PrefixCalc.parse(RLTK::Lexers::Calculator.lex('* + 1 2 3'))
651
+ assert_equal(9, actual)
652
+
653
+ assert_raises(RLTK::NotInLanguage) { RLTK::Parsers::PrefixCalc.parse(RLTK::Lexers::Calculator.lex('1 + 2 * 3')) }
654
+ end
655
+
656
+ def test_selection_parser
657
+ actual = SelectionParser.parse(ABLexer.lex('aaabbb'))
658
+ expected = 6
659
+
660
+ assert_equal(expected, actual)
661
+ end
662
+
663
+ def test_token_hooks
664
+ parser = TokenHookParser.new
665
+
666
+ parser.parse(AlphaLexer.lex('a a a a'))
667
+ assert_equal(4, parser.env.counter)
668
+
669
+ parser.parse(AlphaLexer.lex('b b b b'))
670
+ assert_equal(12, parser.env.counter)
671
+ end
672
+
673
+ def test_underscore_tokens
674
+ actual = UnderscoreParser.parse(UnderscoreLexer.lex('abc')).join
675
+ expected = 'abc'
676
+
677
+ assert_equal(expected, actual)
678
+ end
679
+
680
+ def test_use
681
+ tmpfile = File.join(Dir.tmpdir, 'usetest')
682
+
683
+ FileUtils.rm(tmpfile) if File.exist?(tmpfile)
684
+
685
+ parser0 = Class.new(RLTK::Parser) do
686
+ production(:a, 'A+') { |a| a.length }
687
+
688
+ finalize use: tmpfile
689
+ end
690
+
691
+ result0 = parser0.parse(ABLexer.lex('a'))
692
+
693
+ assert(File.exist?(tmpfile), 'Serialized parser file not found.')
694
+
695
+ parser1 = Class.new(RLTK::Parser) do
696
+ production(:a, 'A+') { |a| a.length }
697
+
698
+ finalize use: tmpfile
699
+ end
700
+
701
+ result1 = parser1.parse(ABLexer.lex('a'))
702
+
703
+ assert_equal(result0, result1)
704
+
705
+ File.unlink(tmpfile)
706
+ end
707
+
708
+ def test_uesless_parser_exception
709
+ assert_raises(RLTK::UselessParserException) { UselessParser.new }
710
+ end
711
+ end