1#!/usr/bin/ruby
2# encoding: utf-8
3
4require 'antlr3/test/functional'
5
6class TestASTViaRewriteRules < ANTLR3::Test::Functional
7
8  def parse( grammar, rule, input, expect_errors = false )
9    @grammar = inline_grammar( grammar )
10    compile_and_load @grammar
11    grammar_module = self.class.const_get( @grammar.name )
12
13    grammar_module::Lexer.send( :include, ANTLR3::Test::CollectErrors )
14    grammar_module::Lexer.send( :include, ANTLR3::Test::CaptureOutput )
15    grammar_module::Parser.send( :include, ANTLR3::Test::CollectErrors )
16    grammar_module::Parser.send( :include, ANTLR3::Test::CaptureOutput )
17
18    lexer  = grammar_module::Lexer.new( input )
19    parser = grammar_module::Parser.new( lexer )
20
21    r = parser.send( rule )
22    parser.reported_errors.should be_empty unless expect_errors
23    result = ''
24
25    unless r.nil?
26      result += r.result if r.respond_to?( :result )
27      result += r.tree.inspect if r.tree
28    end
29    return( expect_errors ? [ result, parser.reported_errors ] : result )
30  end
31
32  def tree_parse( grammar, tree_grammar, rule, tree_rule, input )
33    @grammar = inline_grammar( grammar )
34    @tree_grammar = inline_grammar( tree_grammar )
35    compile_and_load @grammar
36    compile_and_load @tree_grammar
37
38    grammar_module = self.class.const_get( @grammar.name )
39    tree_grammar_module = self.class.const_get( @tree_grammar.name )
40
41    grammar_module::Lexer.send( :include, ANTLR3::Test::CollectErrors )
42    grammar_module::Lexer.send( :include, ANTLR3::Test::CaptureOutput )
43    grammar_module::Parser.send( :include, ANTLR3::Test::CollectErrors )
44    grammar_module::Parser.send( :include, ANTLR3::Test::CaptureOutput )
45    tree_grammar_module::TreeParser.send( :include, ANTLR3::Test::CollectErrors )
46    tree_grammar_module::TreeParser.send( :include, ANTLR3::Test::CaptureOutput )
47
48    lexer  = grammar_module::Lexer.new( input )
49    parser = grammar.module::Parser.new( lexer )
50    r = parser.send( rule )
51    nodes = ANTLR3::CommonTreeNodeStream( r.tree )
52    nodes.token_stream = parser.input
53    walker = tree_grammar_module::TreeParser.new( nodes )
54    r = walker.send( tree_rule )
55
56    return( r ? r.tree.inspect : '' )
57  end
58
59  example "delete" do
60    result = parse( <<-'END', :a, 'abc 34' )
61      grammar Delete;
62      options {language=Ruby;output=AST;}
63      a : ID INT -> ;
64      ID : 'a'..'z'+ ;
65      INT : '0'..'9'+;
66      WS : (' '|'\n') {$channel=HIDDEN;} ;
67    END
68    result.should == ''
69  end
70
71
72  example "single token" do
73    result = parse( <<-'END', :a, 'abc' )
74      grammar SingleToken;
75      options {language=Ruby;output=AST;}
76      a : ID -> ID;
77      ID : 'a'..'z'+ ;
78      INT : '0'..'9'+;
79      WS : (' '|'\n') {$channel=HIDDEN;} ;
80
81    END
82    result.should == 'abc'
83  end
84
85
86  example "single token to new node" do
87    result = parse( <<-'END', :a, 'abc' )
88      grammar SingleTokenToNewNode;
89      options {language=Ruby;output=AST;}
90      a : ID -> ID["x"];
91      ID : 'a'..'z'+ ;
92      INT : '0'..'9'+;
93      WS : (' '|'\n') {$channel=HIDDEN;} ;
94
95    END
96    result.should == 'x'
97  end
98
99
100  example "single token to new node root" do
101    result = parse( <<-'END', :a, 'abc' )
102      grammar SingleTokenToNewNodeRoot;
103      options {language=Ruby;output=AST;}
104      a : ID -> ^(ID["x"] INT);
105      ID : 'a'..'z'+ ;
106      INT : '0'..'9'+;
107      WS : (' '|'\n') {$channel=HIDDEN;} ;
108
109    END
110    result.should == '(x INT)'
111  end
112
113
114  example "single token to new node2" do
115    result = parse( <<-'END', :a, 'abc' )
116      grammar SingleTokenToNewNode2;
117      options {language=Ruby;output=AST;}
118      a : ID -> ID[ ];
119      ID : 'a'..'z'+ ;
120      INT : '0'..'9'+;
121      WS : (' '|'\n') {$channel=HIDDEN;} ;
122    END
123    result.should == 'ID'
124  end
125
126
127  example "single char literal" do
128    result = parse( <<-'END', :a, 'c' )
129      grammar SingleCharLiteral;
130      options {language=Ruby;output=AST;}
131      a : 'c' -> 'c';
132      ID : 'a'..'z'+ ;
133      INT : '0'..'9'+;
134      WS : (' '|'\n') {$channel=HIDDEN;} ;
135
136    END
137    result.should == 'c'
138  end
139
140
141  example "single string literal" do
142    result = parse( <<-'END', :a, 'ick' )
143      grammar SingleStringLiteral;
144      options {language=Ruby;output=AST;}
145      a : 'ick' -> 'ick';
146      ID : 'a'..'z'+ ;
147      INT : '0'..'9'+;
148      WS : (' '|'\n') {$channel=HIDDEN;} ;
149
150    END
151    result.should == 'ick'
152  end
153
154
155  example "single rule" do
156    result = parse( <<-'END', :a, 'abc' )
157      grammar SingleRule;
158      options {language=Ruby;output=AST;}
159      a : b -> b;
160      b : ID ;
161      ID : 'a'..'z'+ ;
162      INT : '0'..'9'+;
163      WS : (' '|'\n') {$channel=HIDDEN;} ;
164
165    END
166    result.should == 'abc'
167  end
168
169
170  example "reorder tokens" do
171    result = parse( <<-'END', :a, 'abc 34' )
172      grammar ReorderTokens;
173      options {language=Ruby;output=AST;}
174      a : ID INT -> INT ID;
175      ID : 'a'..'z'+ ;
176      INT : '0'..'9'+;
177      WS : (' '|'\n') {$channel=HIDDEN;} ;
178
179    END
180    result.should == '34 abc'
181  end
182
183
184  example "reorder token and rule" do
185    result = parse( <<-'END', :a, 'abc 34' )
186      grammar ReorderTokenAndRule;
187      options {language=Ruby;output=AST;}
188      a : b INT -> INT b;
189      b : ID ;
190      ID : 'a'..'z'+ ;
191      INT : '0'..'9'+;
192      WS : (' '|'\n') {$channel=HIDDEN;} ;
193
194    END
195    result.should == '34 abc'
196  end
197
198
199  example "token tree" do
200    result = parse( <<-'END', :a, 'abc 34' )
201      grammar TokenTree;
202      options {language=Ruby;output=AST;}
203      a : ID INT -> ^(INT ID);
204      ID : 'a'..'z'+ ;
205      INT : '0'..'9'+;
206      WS : (' '|'\n') {$channel=HIDDEN;} ;
207
208    END
209    result.should == '(34 abc)'
210  end
211
212
213  example "token tree after other stuff" do
214    result = parse( <<-'END', :a, 'void abc 34' )
215      grammar TokenTreeAfterOtherStuff;
216      options {language=Ruby;output=AST;}
217      a : 'void' ID INT -> 'void' ^(INT ID);
218      ID : 'a'..'z'+ ;
219      INT : '0'..'9'+;
220      WS : (' '|'\n') {$channel=HIDDEN;} ;
221
222    END
223    result.should == 'void (34 abc)'
224  end
225
226
227  example "nested token tree with outer loop" do
228    result = parse( <<-'END', :a, 'a 1 b 2' )
229      grammar NestedTokenTreeWithOuterLoop;
230      options {language=Ruby;output=AST;}
231      tokens {DUH;}
232      a : ID INT ID INT -> ^( DUH ID ^( DUH INT) )+ ;
233      ID : 'a'..'z'+ ;
234      INT : '0'..'9'+;
235      WS : (' '|'\n') {$channel=HIDDEN;} ;
236
237    END
238    result.should == '(DUH a (DUH 1)) (DUH b (DUH 2))'
239  end
240
241
242  example "optional single token" do
243    result = parse( <<-'END', :a, 'abc' )
244      grammar OptionalSingleToken;
245      options {language=Ruby;output=AST;}
246      a : ID -> ID? ;
247      ID : 'a'..'z'+ ;
248      INT : '0'..'9'+;
249      WS : (' '|'\n') {$channel=HIDDEN;} ;
250
251    END
252    result.should == 'abc'
253  end
254
255
256  example "closure single token" do
257    result = parse( <<-'END', :a, 'a b' )
258      grammar ClosureSingleToken;
259      options {language=Ruby;output=AST;}
260      a : ID ID -> ID* ;
261      ID : 'a'..'z'+ ;
262      INT : '0'..'9'+;
263      WS : (' '|'\n') {$channel=HIDDEN;} ;
264
265    END
266    result.should == 'a b'
267  end
268
269
270  example "positive closure single token" do
271    result = parse( <<-'END', :a, 'a b' )
272      grammar PositiveClosureSingleToken;
273      options {language=Ruby;output=AST;}
274      a : ID ID -> ID+ ;
275      ID : 'a'..'z'+ ;
276      INT : '0'..'9'+;
277      WS : (' '|'\n') {$channel=HIDDEN;} ;
278
279    END
280    result.should == 'a b'
281  end
282
283
284  example "optional single rule" do
285    result = parse( <<-'END', :a, 'abc' )
286      grammar OptionalSingleRule;
287      options {language=Ruby;output=AST;}
288      a : b -> b?;
289      b : ID ;
290      ID : 'a'..'z'+ ;
291      INT : '0'..'9'+;
292      WS : (' '|'\n') {$channel=HIDDEN;} ;
293
294    END
295    result.should == 'abc'
296  end
297
298
299  example "closure single rule" do
300    result = parse( <<-'END', :a, 'a b' )
301      grammar ClosureSingleRule;
302      options {language=Ruby;output=AST;}
303      a : b b -> b*;
304      b : ID ;
305      ID : 'a'..'z'+ ;
306      INT : '0'..'9'+;
307      WS : (' '|'\n') {$channel=HIDDEN;} ;
308
309    END
310    result.should == 'a b'
311  end
312
313
314  example "closure of label" do
315    result = parse( <<-'END', :a, 'a b' )
316      grammar ClosureOfLabel;
317      options {language=Ruby;output=AST;}
318      a : x+=b x+=b -> $x*;
319      b : ID ;
320      ID : 'a'..'z'+ ;
321      INT : '0'..'9'+;
322      WS : (' '|'\n') {$channel=HIDDEN;} ;
323
324    END
325    result.should == 'a b'
326  end
327
328
329  example "optional label no list label" do
330    result = parse( <<-'END', :a, 'a' )
331      grammar OptionalLabelNoListLabel;
332      options {language=Ruby;output=AST;}
333      a : (x=ID)? -> $x?;
334      ID : 'a'..'z'+ ;
335      INT : '0'..'9'+;
336      WS : (' '|'\n') {$channel=HIDDEN;} ;
337
338    END
339    result.should == 'a'
340  end
341
342
343  example "positive closure single rule" do
344    result = parse( <<-'END', :a, 'a b' )
345      grammar PositiveClosureSingleRule;
346      options {language=Ruby;output=AST;}
347      a : b b -> b+;
348      b : ID ;
349      ID : 'a'..'z'+ ;
350      INT : '0'..'9'+;
351      WS : (' '|'\n') {$channel=HIDDEN;} ;
352
353    END
354    result.should == 'a b'
355  end
356
357
358  example "single predicate t" do
359    result = parse( <<-'END', :a, 'abc' )
360      grammar SinglePredicateT;
361      options {language=Ruby;output=AST;}
362      a : ID -> {true}? ID -> ;
363      ID : 'a'..'z'+ ;
364      INT : '0'..'9'+;
365      WS : (' '|'\n') {$channel=HIDDEN;} ;
366
367    END
368    result.should == 'abc'
369  end
370
371
372  example "single predicate f" do
373    result = parse( <<-'END', :a, 'abc' )
374      grammar SinglePredicateF;
375      options {language=Ruby;output=AST;}
376      a : ID -> {false}? ID -> ;
377      ID : 'a'..'z'+ ;
378      INT : '0'..'9'+;
379      WS : (' '|'\n') {$channel=HIDDEN;} ;
380
381    END
382    result.should == ''
383  end
384
385
386  example "multiple predicate" do
387    result = parse( <<-'END', :a, 'a 2' )
388      grammar MultiplePredicate;
389      options {language=Ruby;output=AST;}
390      a : ID INT -> {false}? ID
391                 -> {true}? INT
392                 ->
393        ;
394      ID : 'a'..'z'+ ;
395      INT : '0'..'9'+;
396      WS : (' '|'\n') {$channel=HIDDEN;} ;
397
398    END
399    result.should == '2'
400  end
401
402
403  example "multiple predicate trees" do
404    result = parse( <<-'END', :a, 'a 2' )
405      grammar MultiplePredicateTrees;
406      options {language=Ruby;output=AST;}
407      a : ID INT -> {false}? ^(ID INT)
408                 -> {true}? ^(INT ID)
409                 -> ID
410        ;
411      ID : 'a'..'z'+ ;
412      INT : '0'..'9'+;
413      WS : (' '|'\n') {$channel=HIDDEN;} ;
414
415    END
416    result.should == '(2 a)'
417  end
418
419
420  example "simple tree" do
421    result = parse( <<-'END', :a, '-34' )
422      grammar SimpleTree;
423      options {language=Ruby;output=AST;}
424      a : op INT -> ^(op INT);
425      op : '+'|'-' ;
426      ID : 'a'..'z'+ ;
427      INT : '0'..'9'+;
428      WS : (' '|'\n') {$channel=HIDDEN;} ;
429
430    END
431    result.should == '(- 34)'
432  end
433
434
435  example "simple tree2" do
436    result = parse( <<-'END', :a, '+ 34' )
437      grammar SimpleTree2;
438      options {language=Ruby;output=AST;}
439      a : op INT -> ^(INT op);
440      op : '+'|'-' ;
441      ID : 'a'..'z'+ ;
442      INT : '0'..'9'+;
443      WS : (' '|'\n') {$channel=HIDDEN;} ;
444
445    END
446    result.should == '(34 +)'
447  end
448
449
450  example "nested trees" do
451    result = parse( <<-'END', :a, 'var a:int; b:float;' )
452      grammar NestedTrees;
453      options {language=Ruby;output=AST;}
454      a : 'var' (ID ':' type ';')+ -> ^('var' ^(':' ID type)+) ;
455      type : 'int' | 'float' ;
456      ID : 'a'..'z'+ ;
457      INT : '0'..'9'+;
458      WS : (' '|'\n') {$channel=HIDDEN;} ;
459
460    END
461    result.should == '(var (: a int) (: b float))'
462  end
463
464
465  example "imaginary token copy" do
466    result = parse( <<-'END', :a, 'a,b,c' )
467      grammar ImaginaryTokenCopy;
468      options {language=Ruby;output=AST;}
469      tokens {VAR;}
470      a : ID (',' ID)*-> ^(VAR ID)+ ;
471      type : 'int' | 'float' ;
472      ID : 'a'..'z'+ ;
473      INT : '0'..'9'+;
474      WS : (' '|'\n') {$channel=HIDDEN;} ;
475
476    END
477    result.should == '(VAR a) (VAR b) (VAR c)'
478  end
479
480
481  example "token unreferenced on left but defined" do
482    result = parse( <<-'END', :a, 'a' )
483      grammar TokenUnreferencedOnLeftButDefined;
484      options {language=Ruby;output=AST;}
485      tokens {VAR;}
486      a : b -> ID ;
487      b : ID ;
488      ID : 'a'..'z'+ ;
489      INT : '0'..'9'+;
490      WS : (' '|'\n') {$channel=HIDDEN;} ;
491
492    END
493    result.should == 'ID'
494  end
495
496
497  example "imaginary token copy set text" do
498    result = parse( <<-'END', :a, 'a,b,c' )
499      grammar ImaginaryTokenCopySetText;
500      options {language=Ruby;output=AST;}
501      tokens {VAR;}
502      a : ID (',' ID)*-> ^(VAR["var"] ID)+ ;
503      type : 'int' | 'float' ;
504      ID : 'a'..'z'+ ;
505      INT : '0'..'9'+;
506      WS : (' '|'\n') {$channel=HIDDEN;} ;
507
508    END
509    result.should == '(var a) (var b) (var c)'
510  end
511
512
513  example "imaginary token no copy from token" do
514    result = parse( <<-'END', :a, '{a b c}' )
515      grammar ImaginaryTokenNoCopyFromToken;
516      options {language=Ruby;output=AST;}
517      tokens {BLOCK;}
518      a : lc='{' ID+ '}' -> ^(BLOCK[$lc] ID+) ;
519      type : 'int' | 'float' ;
520      ID : 'a'..'z'+ ;
521      INT : '0'..'9'+;
522      WS : (' '|'\n') {$channel=HIDDEN;} ;
523
524    END
525    result.should == '({ a b c)'
526  end
527
528
529  example "imaginary token no copy from token set text" do
530    result = parse( <<-'END', :a, '{a b c}' )
531      grammar ImaginaryTokenNoCopyFromTokenSetText;
532      options {language=Ruby;output=AST;}
533      tokens {BLOCK;}
534      a : lc='{' ID+ '}' -> ^(BLOCK[$lc,"block"] ID+) ;
535      type : 'int' | 'float' ;
536      ID : 'a'..'z'+ ;
537      INT : '0'..'9'+;
538      WS : (' '|'\n') {$channel=HIDDEN;} ;
539
540    END
541    result.should == '(block a b c)'
542  end
543
544
545  example "mixed rewrite and auto ast" do
546    result = parse( <<-'END', :a, 'a 1 2' )
547      grammar MixedRewriteAndAutoAST;
548      options {language=Ruby;output=AST;}
549      tokens {BLOCK;}
550      a : b b^ ; // 2nd b matches only an INT; can make it root
551      b : ID INT -> INT ID
552        | INT
553        ;
554      ID : 'a'..'z'+ ;
555      INT : '0'..'9'+;
556      WS : (' '|'\n') {$channel=HIDDEN;} ;
557    END
558    result.should == '(2 1 a)'
559  end
560
561
562  example "subrule with rewrite" do
563    result = parse( <<-'END', :a, 'a 1 2 3' )
564      grammar SubruleWithRewrite;
565      options {language=Ruby;output=AST;}
566      tokens {BLOCK;}
567      a : b b ;
568      b : (ID INT -> INT ID | INT INT -> INT+ )
569        ;
570      ID : 'a'..'z'+ ;
571      INT : '0'..'9'+;
572      WS : (' '|'\n') {$channel=HIDDEN;} ;
573
574    END
575    result.should == '1 a 2 3'
576  end
577
578
579  example "subrule with rewrite2" do
580    result = parse( <<-'END', :a, 'int a; int b=3;' )
581      grammar SubruleWithRewrite2;
582      options {language=Ruby;output=AST;}
583      tokens {TYPE;}
584      a : b b ;
585      b : 'int'
586          ( ID -> ^(TYPE 'int' ID)
587          | ID '=' INT -> ^(TYPE 'int' ID INT)
588          )
589          ';'
590        ;
591      ID : 'a'..'z'+ ;
592      INT : '0'..'9'+;
593      WS : (' '|'\n') {$channel=HIDDEN;} ;
594
595    END
596    result.should == '(TYPE int a) (TYPE int b 3)'
597  end
598
599
600  example "nested rewrite shuts off auto ast" do
601    result = parse( <<-'END', :a, 'a b c d; 42' )
602      grammar NestedRewriteShutsOffAutoAST;
603      options {language=Ruby;output=AST;}
604      tokens {BLOCK;}
605      a : b b ;
606      b : ID ( ID (last=ID -> $last)+ ) ';' // get last ID
607        | INT // should still get auto AST construction
608        ;
609      ID : 'a'..'z'+ ;
610      INT : '0'..'9'+;
611      WS : (' '|'\n') {$channel=HIDDEN;} ;
612
613    END
614    result.should == 'd 42'
615  end
616
617
618  example "rewrite actions" do
619    result = parse( <<-'END', :a, '3' )
620      grammar RewriteActions;
621      options {language=Ruby;output=AST;}
622      a : atom -> ^({ @adaptor.create( INT, "9" ) } atom) ;
623      atom : INT ;
624      ID : 'a'..'z'+ ;
625      INT : '0'..'9'+;
626      WS : (' '|'\n') {$channel=HIDDEN;} ;
627
628    END
629    result.should == '(9 3)'
630  end
631
632
633  example "rewrite actions2" do
634    result = parse( <<-'END', :a, '3' )
635      grammar RewriteActions2;
636      options {language=Ruby;output=AST;}
637      a : atom -> { @adaptor.create( INT, "9" ) } atom ;
638      atom : INT ;
639      ID : 'a'..'z'+ ;
640      INT : '0'..'9'+;
641      WS : (' '|'\n') { $channel = HIDDEN } ;
642
643    END
644    result.should == '9 3'
645  end
646
647
648  example "ref to old value" do
649    result = parse( <<-'END', :a, '3+4+5' )
650      grammar RefToOldValue;
651      options {language=Ruby;output=AST;}
652      tokens {BLOCK;}
653      a : (atom -> atom) (op='+' r=atom -> ^($op $a $r) )* ;
654      atom : INT ;
655      ID : 'a'..'z'+ ;
656      INT : '0'..'9'+;
657      WS : (' '|'\n') {$channel=HIDDEN;} ;
658
659    END
660    result.should == '(+ (+ 3 4) 5)'
661  end
662
663
664  example "copy semantics for rules" do
665    result = parse( <<-'END', :a, '3' )
666      grammar CopySemanticsForRules;
667      options {language=Ruby;output=AST;}
668      tokens {BLOCK;}
669      a : atom -> ^(atom atom) ; // NOT CYCLE! (dup atom)
670      atom : INT ;
671      ID : 'a'..'z'+ ;
672      INT : '0'..'9'+;
673      WS : (' '|'\n') {$channel=HIDDEN;} ;
674
675    END
676    result.should == '(3 3)'
677  end
678
679
680  example "copy semantics for rules2" do
681    result = parse( <<-'END', :a, 'int a,b,c;' )
682      grammar CopySemanticsForRules2;
683      options {language=Ruby;output=AST;}
684      a : type ID (',' ID)* ';' -> ^(type ID)+ ;
685      type : 'int' ;
686      ID : 'a'..'z'+ ;
687      WS : (' '|'\n') {$channel=HIDDEN;} ;
688
689    END
690    result.should == '(int a) (int b) (int c)'
691  end
692
693
694  example "copy semantics for rules3" do
695    result = parse( <<-'END', :a, 'public int a,b,c;' )
696      grammar CopySemanticsForRules3;
697      options {language=Ruby;output=AST;}
698      a : modifier? type ID (',' ID)* ';' -> ^(type modifier? ID)+ ;
699      type : 'int' ;
700      modifier : 'public' ;
701      ID : 'a'..'z'+ ;
702      WS : (' '|'\n') {$channel=HIDDEN;} ;
703
704    END
705    result.should == '(int public a) (int public b) (int public c)'
706  end
707
708
709  example "copy semantics for rules3 double" do
710    result = parse( <<-'END', :a, 'public int a,b,c;' )
711      grammar CopySemanticsForRules3Double;
712      options {language=Ruby;output=AST;}
713      a : modifier? type ID (',' ID)* ';' -> ^(type modifier? ID)+ ^(type modifier? ID)+ ;
714      type : 'int' ;
715      modifier : 'public' ;
716      ID : 'a'..'z'+ ;
717      WS : (' '|'\n') {$channel=HIDDEN;} ;
718
719    END
720    result.should == '(int public a) (int public b) (int public c) (int public a) (int public b) (int public c)'
721  end
722
723
724  example "copy semantics for rules4" do
725    result = parse( <<-'END', :a, 'public int a,b,c;' )
726      grammar CopySemanticsForRules4;
727      options {language=Ruby;output=AST;}
728      tokens {MOD;}
729      a : modifier? type ID (',' ID)* ';' -> ^(type ^(MOD modifier)? ID)+ ;
730      type : 'int' ;
731      modifier : 'public' ;
732      ID : 'a'..'z'+ ;
733      WS : (' '|'\n') {$channel=HIDDEN;} ;
734
735    END
736    result.should == '(int (MOD public) a) (int (MOD public) b) (int (MOD public) c)'
737  end
738
739
740  example "copy semantics lists" do
741    result = parse( <<-'END', :a, 'a,b,c;' )
742      grammar CopySemanticsLists;
743      options {language=Ruby;output=AST;}
744      tokens {MOD;}
745      a : ID (',' ID)* ';' -> ID+ ID+ ;
746      ID : 'a'..'z'+ ;
747      WS : (' '|'\n') {$channel=HIDDEN;} ;
748
749    END
750    result.should == 'a b c a b c'
751  end
752
753
754  example "copy rule label" do
755    result = parse( <<-'END', :a, 'a' )
756      grammar CopyRuleLabel;
757      options {language=Ruby;output=AST;}
758      tokens {BLOCK;}
759      a : x=b -> $x $x;
760      b : ID ;
761      ID : 'a'..'z'+ ;
762      WS : (' '|'\n') {$channel=HIDDEN;} ;
763
764    END
765    result.should == 'a a'
766  end
767
768
769  example "copy rule label2" do
770    result = parse( <<-'END', :a, 'a' )
771      grammar CopyRuleLabel2;
772      options {language=Ruby;output=AST;}
773      tokens {BLOCK;}
774      a : x=b -> ^($x $x);
775      b : ID ;
776      ID : 'a'..'z'+ ;
777      WS : (' '|'\n') {$channel=HIDDEN;} ;
778
779    END
780    result.should == '(a a)'
781  end
782
783
784  example "queueing of tokens" do
785    result = parse( <<-'END', :a, 'int a,b,c;' )
786      grammar QueueingOfTokens;
787      options {language=Ruby;output=AST;}
788      a : 'int' ID (',' ID)* ';' -> ^('int' ID+) ;
789      op : '+'|'-' ;
790      ID : 'a'..'z'+ ;
791      INT : '0'..'9'+;
792      WS : (' '|'\n') {$channel=HIDDEN;} ;
793
794    END
795    result.should == '(int a b c)'
796  end
797
798
799  example "copy of tokens" do
800    result = parse( <<-'END', :a, 'int a;' )
801      grammar CopyOfTokens;
802      options {language=Ruby;output=AST;}
803      a : 'int' ID ';' -> 'int' ID 'int' ID ;
804      op : '+'|'-' ;
805      ID : 'a'..'z'+ ;
806      INT : '0'..'9'+;
807      WS : (' '|'\n') {$channel=HIDDEN;} ;
808
809    END
810    result.should == 'int a int a'
811  end
812
813
814  example "token copy in loop" do
815    result = parse( <<-'END', :a, 'int a,b,c;' )
816      grammar TokenCopyInLoop;
817      options {language=Ruby;output=AST;}
818      a : 'int' ID (',' ID)* ';' -> ^('int' ID)+ ;
819      op : '+'|'-' ;
820      ID : 'a'..'z'+ ;
821      INT : '0'..'9'+;
822      WS : (' '|'\n') {$channel=HIDDEN;} ;
823
824    END
825    result.should == '(int a) (int b) (int c)'
826  end
827
828
829  example "token copy in loop against two others" do
830    result = parse( <<-'END', :a, 'int a:1,b:2,c:3;' )
831      grammar TokenCopyInLoopAgainstTwoOthers;
832      options {language=Ruby;output=AST;}
833      a : 'int' ID ':' INT (',' ID ':' INT)* ';' -> ^('int' ID INT)+ ;
834      op : '+'|'-' ;
835      ID : 'a'..'z'+ ;
836      INT : '0'..'9'+;
837      WS : (' '|'\n') {$channel=HIDDEN;} ;
838
839    END
840    result.should == '(int a 1) (int b 2) (int c 3)'
841  end
842
843
844  example "list refd one at a time" do
845    result = parse( <<-'END', :a, 'a b c' )
846      grammar ListRefdOneAtATime;
847      options {language=Ruby;output=AST;}
848      a : ID+ -> ID ID ID ; // works if 3 input IDs
849      op : '+'|'-' ;
850      ID : 'a'..'z'+ ;
851      INT : '0'..'9'+;
852      WS : (' '|'\n') {$channel=HIDDEN;} ;
853
854    END
855    result.should == 'a b c'
856  end
857
858
859  example "split list with labels" do
860    result = parse( <<-'END', :a, 'a b c' )
861      grammar SplitListWithLabels;
862      options {language=Ruby;output=AST;}
863      tokens {VAR;}
864      a : first=ID others+=ID* -> $first VAR $others+ ;
865      op : '+'|'-' ;
866      ID : 'a'..'z'+ ;
867      INT : '0'..'9'+;
868      WS : (' '|'\n') {$channel=HIDDEN;} ;
869
870    END
871    result.should == 'a VAR b c'
872  end
873
874
875  example "complicated melange" do
876    result = parse( <<-'END', :a, 'a a b b b c c c d' )
877      grammar ComplicatedMelange;
878      options {language=Ruby;output=AST;}
879      tokens {BLOCK;}
880      a : A A b=B B b=B c+=C C c+=C D {s=$D.text} -> A+ B+ C+ D ;
881      type : 'int' | 'float' ;
882      A : 'a' ;
883      B : 'b' ;
884      C : 'c' ;
885      D : 'd' ;
886      WS : (' '|'\n') {$channel=HIDDEN;} ;
887
888    END
889    result.should == 'a a b b b c c c d'
890  end
891
892
893  example "rule label" do
894    result = parse( <<-'END', :a, 'a' )
895      grammar RuleLabel;
896      options {language=Ruby;output=AST;}
897      tokens {BLOCK;}
898      a : x=b -> $x;
899      b : ID ;
900      ID : 'a'..'z'+ ;
901      WS : (' '|'\n') {$channel=HIDDEN;} ;
902
903    END
904    result.should == 'a'
905  end
906
907
908  example "ambiguous rule" do
909    result = parse( <<-'END', :a, 'abc 34' )
910      grammar AmbiguousRule;
911      options {language=Ruby;output=AST;}
912      a : ID a -> a | INT ;
913      ID : 'a'..'z'+ ;
914      INT: '0'..'9'+ ;
915      WS : (' '|'\n') {$channel=HIDDEN;} ;
916
917    END
918    result.should == '34'
919  end
920
921
922  example "rule list label" do
923    result = parse( <<-'END', :a, 'a b' )
924      grammar RuleListLabel;
925      options {language=Ruby;output=AST;}
926      tokens {BLOCK;}
927      a : x+=b x+=b -> $x+;
928      b : ID ;
929      ID : 'a'..'z'+ ;
930      WS : (' '|'\n') {$channel=HIDDEN;} ;
931
932    END
933    result.should == 'a b'
934  end
935
936
937  example "rule list label2" do
938    result = parse( <<-'END', :a, 'a b' )
939      grammar RuleListLabel2;
940      options {language=Ruby;output=AST;}
941      tokens {BLOCK;}
942      a : x+=b x+=b -> $x $x*;
943      b : ID ;
944      ID : 'a'..'z'+ ;
945      WS : (' '|'\n') {$channel=HIDDEN;} ;
946
947    END
948    result.should == 'a b'
949  end
950
951
952  example "optional" do
953    result = parse( <<-'END', :a, 'a' )
954      grammar Optional;
955      options {language=Ruby;output=AST;}
956      tokens {BLOCK;}
957      a : x=b (y=b)? -> $x $y?;
958      b : ID ;
959      ID : 'a'..'z'+ ;
960      WS : (' '|'\n') {$channel=HIDDEN;} ;
961
962    END
963    result.should == 'a'
964  end
965
966
967  example "optional2" do
968    result = parse( <<-'END', :a, 'a b' )
969      grammar Optional2;
970      options {language=Ruby;output=AST;}
971      tokens {BLOCK;}
972      a : x=ID (y=b)? -> $x $y?;
973      b : ID ;
974      ID : 'a'..'z'+ ;
975      WS : (' '|'\n') {$channel=HIDDEN;} ;
976
977    END
978    result.should == 'a b'
979  end
980
981
982  example "optional3" do
983    result = parse( <<-'END', :a, 'a b' )
984      grammar Optional3;
985      options {language=Ruby;output=AST;}
986      tokens {BLOCK;}
987      a : x=ID (y=b)? -> ($x $y)?;
988      b : ID ;
989      ID : 'a'..'z'+ ;
990      WS : (' '|'\n') {$channel=HIDDEN;} ;
991
992    END
993    result.should == 'a b'
994  end
995
996
997  example "optional4" do
998    result = parse( <<-'END', :a, 'a b' )
999      grammar Optional4;
1000      options {language=Ruby;output=AST;}
1001      tokens {BLOCK;}
1002      a : x+=ID (y=b)? -> ($x $y)?;
1003      b : ID ;
1004      ID : 'a'..'z'+ ;
1005      WS : (' '|'\n') {$channel=HIDDEN;} ;
1006    END
1007    result.should == 'a b'
1008  end
1009
1010
1011  example "optional5" do
1012    result = parse( <<-'END', :a, 'a' )
1013      grammar Optional5;
1014      options {language=Ruby;output=AST;}
1015      tokens {BLOCK;}
1016      a : ID -> ID? ; // match an ID to optional ID
1017      b : ID ;
1018      ID : 'a'..'z'+ ;
1019      WS : (' '|'\n') {$channel=HIDDEN;} ;
1020
1021    END
1022    result.should == 'a'
1023  end
1024
1025
1026  example "arbitrary expr type" do
1027    result = parse( <<-'END', :a, 'a b' )
1028      grammar ArbitraryExprType;
1029      options {language=Ruby;output=AST;}
1030      tokens {BLOCK;}
1031      a : x+=b x+=b -> {ANTLR3::CommonTree.new(nil)};
1032      b : ID ;
1033      ID : 'a'..'z'+ ;
1034      WS : (' '|'\n') {$channel=HIDDEN;} ;
1035
1036    END
1037    result.should == ''
1038  end
1039
1040
1041  example "set" do
1042    result = parse( <<-'END', :a, '2 a 34 de' )
1043      grammar SetT;
1044      options {language=Ruby;output=AST;}
1045      a: (INT|ID)+ -> INT+ ID+ ;
1046      INT: '0'..'9'+;
1047      ID : 'a'..'z'+;
1048      WS : (' '|'\n') {$channel=HIDDEN;} ;
1049
1050    END
1051    result.should == '2 34 a de'
1052  end
1053
1054
1055  example "set2" do
1056    result = parse( <<-'END', :a, '2' )
1057      grammar Set2;
1058      options {language=Ruby;output=AST;}
1059      a: (INT|ID) -> INT? ID? ;
1060      INT: '0'..'9'+;
1061      ID : 'a'..'z'+;
1062      WS : (' '|'\n') {$channel=HIDDEN;} ;
1063
1064    END
1065    result.should == '2'
1066  end
1067
1068
1069  example "set with label" do
1070    warn( 'test SetWithLabel officially broken' )
1071    #result = parse(<<-'END', :a, '2')
1072    #  grammar SetWithLabel;
1073    #  options {language=Ruby;output=AST;}
1074    #  a : x=(INT|ID) -> $x ;
1075    #  INT: '0'..'9'+;
1076    #  ID : 'a'..'z'+;
1077    #  WS : (' '|'\n') {$channel=HIDDEN;} ;
1078    #
1079    #END
1080    #result.should == '2'
1081  end
1082
1083
1084  example "rewrite action" do
1085    result = parse( <<-'END', :r, '25' )
1086      grammar RewriteAction;
1087      options {language=Ruby;output=AST;}
1088      tokens { FLOAT; }
1089      r
1090          : INT -> { ANTLR3::CommonTree.new( create_token( FLOAT, nil, "#{$INT.text}.0" ) ) }
1091          ;
1092      INT : '0'..'9'+;
1093      WS: (' ' | '\n' | '\t')+ {$channel = HIDDEN;};
1094
1095    END
1096    result.should == '25.0'
1097  end
1098
1099
1100  example "optional subrule without real elements" do
1101    result = parse( <<-'END', :modulo, 'modulo abc (x y #)' )
1102      grammar OptionalSubruleWithoutRealElements;
1103      options {language=Ruby;output=AST;}
1104      tokens {PARMS;}
1105
1106      modulo
1107       : 'modulo' ID ('(' parms+ ')')? -> ^('modulo' ID ^(PARMS parms+)?)
1108       ;
1109      parms : '#'|ID;
1110      ID : ('a'..'z' | 'A'..'Z')+;
1111      WS : (' '|'\n') {$channel=HIDDEN;} ;
1112
1113    END
1114    result.should == '(modulo abc (PARMS x y #))'
1115  end
1116
1117
1118  example "wildcard" do
1119    result = parse( <<-'END', :a, 'abc 34' )
1120      grammar Wildcard;
1121      options {language=Ruby;output=AST;}
1122      a : ID c=. -> $c;
1123      ID : 'a'..'z'+ ;
1124      INT : '0'..'9'+;
1125      WS : (' '|'\n') {$channel=HIDDEN;} ;
1126
1127    END
1128    result.should == '34'
1129  end
1130
1131
1132  example "extra token in simple decl" do
1133    result, errors = parse( <<-'END', :decl, 'int 34 x=1;', true )
1134      grammar ExtraTokenInSimpleDecl;
1135      options {language=Ruby;output=AST;}
1136      tokens {EXPR;}
1137      decl : type ID '=' INT ';' -> ^(EXPR type ID INT) ;
1138      type : 'int' | 'float' ;
1139      ID : 'a'..'z'+ ;
1140      INT : '0'..'9'+;
1141      WS : (' '|'\n') {$channel=HIDDEN;} ;
1142
1143    END
1144    errors.should == [ 'line 1:4 extraneous input "34" expecting ID' ]
1145    result.should == '(EXPR int x 1)'
1146  end
1147
1148
1149  example "missing id in simple decl" do
1150    result, errors = parse( <<-'END', :decl, 'int =1;', true )
1151      grammar MissingIDInSimpleDecl;
1152      options {language=Ruby;output=AST;}
1153      tokens {EXPR;}
1154      decl : type ID '=' INT ';' -> ^(EXPR type ID INT) ;
1155      type : 'int' | 'float' ;
1156      ID : 'a'..'z'+ ;
1157      INT : '0'..'9'+;
1158      WS : (' '|'\n') {$channel=HIDDEN;} ;
1159
1160    END
1161    errors.should == [ 'line 1:4 missing ID at "="' ]
1162    result.should == '(EXPR int <missing ID> 1)'
1163  end
1164
1165
1166  example "missing set in simple decl" do
1167    result, errors = parse( <<-'END', :decl, 'x=1;', true )
1168      grammar MissingSetInSimpleDecl;
1169      options {language=Ruby;output=AST;}
1170      tokens {EXPR;}
1171      decl : type ID '=' INT ';' -> ^(EXPR type ID INT) ;
1172      type : 'int' | 'float' ;
1173      ID : 'a'..'z'+ ;
1174      INT : '0'..'9'+;
1175      WS : (' '|'\n') {$channel=HIDDEN;} ;
1176
1177    END
1178    errors.should == [ 'line 1:0 mismatched input "x" expecting set nil' ]
1179    result.should == '(EXPR <error: x> x 1)'
1180  end
1181
1182
1183  example "missing token gives error node" do
1184    result, errors = parse( <<-'END', :a, 'abc', true )
1185      grammar MissingTokenGivesErrorNode;
1186      options {language=Ruby;output=AST;}
1187      a : ID INT -> ID INT ;
1188      ID : 'a'..'z'+ ;
1189      INT : '0'..'9'+;
1190      WS : (' '|'\n') {$channel=HIDDEN;} ;
1191
1192    END
1193    errors.should == [ "line 0:-1 missing INT at \"<EOF>\"" ]
1194    result.should == 'abc <missing INT>'
1195    #end
1196  end
1197
1198
1199  example "extra token gives error node" do
1200    result, errors = parse( <<-'END', :a, 'abc ick 34', true )
1201      grammar ExtraTokenGivesErrorNode;
1202      options {language=Ruby;output=AST;}
1203      a : b c -> b c;
1204      b : ID -> ID ;
1205      c : INT -> INT ;
1206      ID : 'a'..'z'+ ;
1207      INT : '0'..'9'+;
1208      WS : (' '|'\n') {$channel=HIDDEN;} ;
1209
1210    END
1211    errors.should == [ 'line 1:4 extraneous input "ick" expecting INT' ]
1212    result.should == 'abc 34'
1213  end
1214
1215
1216  example "missing first token gives error node" do
1217    result, errors = parse( <<-'END', :a, '34', true )
1218      grammar MissingFirstTokenGivesErrorNode;
1219      options {language=Ruby;output=AST;}
1220      a : ID INT -> ID INT ;
1221      ID : 'a'..'z'+ ;
1222      INT : '0'..'9'+;
1223      WS : (' '|'\n') {$channel=HIDDEN;} ;
1224
1225    END
1226    errors.should == [ 'line 1:0 missing ID at "34"' ]
1227    result.should == '<missing ID> 34'
1228  end
1229
1230
1231  example "missing first token gives error node2" do
1232    result, errors = parse( <<-'END', :a, '34', true )
1233      grammar MissingFirstTokenGivesErrorNode2;
1234      options {language=Ruby;output=AST;}
1235      a : b c -> b c;
1236      b : ID -> ID ;
1237      c : INT -> INT ;
1238      ID : 'a'..'z'+ ;
1239      INT : '0'..'9'+;
1240      WS : (' '|'\n') {$channel=HIDDEN;} ;
1241
1242    END
1243    errors.should == [ 'line 1:0 missing ID at "34"' ]
1244    result.should == '<missing ID> 34'
1245  end
1246
1247
1248  example "no viable alt gives error node" do
1249    result, errors = parse( <<-'END', :a, '*', true )
1250      grammar NoViableAltGivesErrorNode;
1251      options {language=Ruby;output=AST;}
1252      a : b -> b | c -> c;
1253      b : ID -> ID ;
1254      c : INT -> INT ;
1255      ID : 'a'..'z'+ ;
1256      S : '*' ;
1257      INT : '0'..'9'+;
1258      WS : (' '|'\n') {$channel=HIDDEN;} ;
1259
1260    END
1261    errors.should == [ 'line 1:0 no viable alternative at input "*"' ]
1262    result.should == '<unexpected: 0 S["*"] @ line 1 col 0 (0..0), resync = *>'
1263  end
1264
1265
1266  example "cardinality" do
1267    lambda do
1268      parse( <<-'END', :a, "a b 3 4 5" )
1269        grammar Cardinality;
1270        options {language=Ruby;output=AST;}
1271        tokens {BLOCK;}
1272        a : ID ID INT INT INT -> (ID INT)+;
1273        ID : 'a'..'z'+ ;
1274        INT : '0'..'9'+;
1275        WS : (' '|'\n') {$channel=HIDDEN;} ;
1276      END
1277    end.should raise_error( ANTLR3::Error::RewriteCardinalityError )
1278  end
1279
1280  example "cardinality2" do
1281    lambda do
1282      parse( <<-'END', :a, "a b" )
1283        grammar Cardinality2;
1284        options {language=Ruby;output=AST;}
1285        tokens {BLOCK;}
1286        a : ID+ -> ID ID ID ; // only 2 input IDs
1287        op : '+'|'-' ;
1288        ID : 'a'..'z'+ ;
1289        INT : '0'..'9'+;
1290        WS : (' '|'\n') {$channel=HIDDEN;} ;
1291      END
1292    end.should raise_error( ANTLR3::Error::RewriteCardinalityError )
1293  end
1294
1295  example "cardinality3" do
1296    lambda do
1297      parse( <<-'END', :a, "3" )
1298        grammar Cardinality3;
1299        options {language=Ruby;output=AST;}
1300        tokens {BLOCK;}
1301        a : ID? INT -> ID INT ;
1302        op : '+'|'-' ;
1303        ID : 'a'..'z'+ ;
1304        INT : '0'..'9'+;
1305        WS : (' '|'\n') {$channel=HIDDEN;} ;
1306      END
1307    end.should raise_error( ANTLR3::Error::RewriteEmptyStream )
1308  end
1309
1310  example "loop cardinality" do
1311    lambda do
1312      parse( <<-'END', :a, "3" )
1313        grammar LoopCardinality;
1314        options {language=Ruby;output=AST;}
1315        a : ID? INT -> ID+ INT ;
1316        op : '+'|'-' ;
1317        ID : 'a'..'z'+ ;
1318        INT : '0'..'9'+;
1319        WS : (' '|'\n') {$channel=HIDDEN;} ;
1320      END
1321    end.should raise_error( ANTLR3::Error::RewriteEarlyExit )
1322  end
1323
1324
1325
1326end
1327