rltk3 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
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