1#!/usr/bin/ruby
2# encoding: utf-8
3
4require 'antlr3/test/functional'
5
6
7class TestHeterogeneousNodeTypes < ANTLR3::Test::Functional
8
9  inline_grammar( <<-'END' )
10    grammar VToken;
11    options {
12        language=Ruby;
13        output=AST;
14    }
15    @members {
16      class V < ANTLR3::CommonTree
17        def to_s
18          return @token.text + "<V>"
19        end
20      end
21    }
22    a : ID<V> ;
23    ID : 'a'..'z'+ ;
24    WS : (' '|'\n') {$channel=HIDDEN;} ;
25  END
26
27
28  inline_grammar( <<-'END' )
29    grammar TokenWithQualifiedType;
30    options {
31        language=Ruby;
32        output=AST;
33    }
34    @members {
35      class V < ANTLR3::CommonTree
36        def to_s
37          return @token.text + "<V>"
38        end
39      end
40    }
41    a : ID<TokenWithQualifiedType.Parser.V> ;
42    ID : 'a'..'z'+ ;
43    WS : (' '|'\n') {$channel=HIDDEN;} ;
44  END
45
46
47  inline_grammar( <<-'END' )
48    grammar TokenWithLabel;
49    options {
50        language=Ruby;
51        output=AST;
52    }
53    @members {
54    class V < ANTLR3::CommonTree
55      def to_s
56        return @token.text + "<V>"
57      end
58    end
59    }
60    a : x=ID<V> ;
61    ID : 'a'..'z'+ ;
62    WS : (' '|'\n') {$channel=HIDDEN;} ;
63  END
64
65
66  inline_grammar( <<-'END' )
67    grammar TokenWithListLabel;
68    options {
69        language=Ruby;
70        output=AST;
71    }
72    @members {
73      class V < ANTLR3::CommonTree
74        def to_s
75          return @token.text + "<V>"
76        end
77      end
78    }
79    a : x+=ID<V> ;
80    ID : 'a'..'z'+ ;
81    WS : (' '|'\n') {$channel=HIDDEN;} ;
82  END
83
84
85  inline_grammar( <<-'END' )
86    grammar TokenRoot;
87    options {
88        language=Ruby;
89        output=AST;
90    }
91    @members {
92      class V < ANTLR3::CommonTree
93        def to_s
94          return @token.text + "<V>"
95        end
96      end
97    
98    }
99    a : ID<V>^ ;
100    ID : 'a'..'z'+ ;
101    WS : (' '|'\n') {$channel=HIDDEN;} ;
102  END
103
104
105  inline_grammar( <<-'END' )
106    grammar TokenRootWithListLabel;
107    options {
108        language=Ruby;
109        output=AST;
110    }
111    @members {
112      class V < ANTLR3::CommonTree
113        def to_s
114          return @token.text + "<V>"
115        end
116      end
117    
118    }
119    a : x+=ID<V>^ ;
120    ID : 'a'..'z'+ ;
121    WS : (' '|'\n') {$channel=HIDDEN;} ;
122  END
123
124
125  inline_grammar( <<-'END' )
126    grammar FromString;
127    options {
128        language=Ruby;
129        output=AST;
130    }
131    @members {
132      class V < ANTLR3::CommonTree
133        def to_s
134          return @token.text + "<V>"
135        end
136      end
137    
138    }
139    a : 'begin'<V> ;
140    ID : 'a'..'z'+ ;
141    WS : (' '|'\n') {$channel=HIDDEN;} ;
142  END
143
144
145  inline_grammar( <<-'END' )
146    grammar StringRoot;
147    options {
148        language=Ruby;
149        output=AST;
150    }
151    @members {
152      class V < ANTLR3::CommonTree
153        def to_s
154          return @token.text + "<V>"
155        end
156      end
157    
158    }
159    a : 'begin'<V>^ ;
160    ID : 'a'..'z'+ ;
161    WS : (' '|'\n') {$channel=HIDDEN;} ;
162  END
163
164
165  inline_grammar( <<-'END' )
166    grammar RewriteToken;
167    options {
168        language=Ruby;
169        output=AST;
170    }
171    @members {
172      class V < ANTLR3::CommonTree
173        def to_s
174          return @token.text + "<V>"
175        end
176      end
177    
178    }
179    a : ID -> ID<V> ;
180    ID : 'a'..'z'+ ;
181    WS : (' '|'\n') {$channel=HIDDEN;} ;
182  END
183
184
185  inline_grammar( <<-'END' )
186    grammar RewriteTokenWithArgs;
187    options {
188        language=Ruby;
189        output=AST;
190    }
191    @members {
192      class V < ANTLR3::CommonTree
193        def initialize(*args)
194          case args.length
195          when 4
196            ttype, @x, @y, @z = args
197            token = ANTLR3::CommonToken.new(ttype, nil, '')
198          when 3
199            ttype, token, @x = args
200            @y = @z = 0
201          else raise ArgumentError, "invalid number of arguments: #{args.length} for 3-4"
202          end
203          super(token)
204        end
205        
206        def to_s
207          (@token.text.to_s rescue '') << "<V>;\%d\%d\%d" \% [@x, @y, @z]
208        end
209      end
210    
211    }
212    a : ID -> ID<V>[42,19,30] ID<V>[$ID,99];
213    ID : 'a'..'z'+ ;
214    WS : (' '|'\n') {$channel=HIDDEN;} ;
215  END
216
217
218  inline_grammar( <<-'END' )
219    grammar RewriteTokenRoot;
220    options {
221        language=Ruby;
222        output=AST;
223    }
224    @members {
225      class V < ANTLR3::CommonTree
226        def to_s
227          return @token.text + "<V>"
228        end
229      end
230    
231    }
232    a : ID INT -> ^(ID<V> INT) ;
233    ID : 'a'..'z'+ ;
234    INT : '0'..'9'+ ;
235    WS : (' '|'\n') {$channel=HIDDEN;} ;
236  END
237
238
239  inline_grammar( <<-'END' )
240    grammar RewriteString;
241    options {
242        language=Ruby;
243        output=AST;
244    }
245    @members {
246      class V < ANTLR3::CommonTree
247        def to_s
248          return @token.text + "<V>"
249        end
250      end
251    
252    }
253    a : 'begin' -> 'begin'<V> ;
254    ID : 'a'..'z'+ ;
255    WS : (' '|'\n') {$channel=HIDDEN;} ;
256  END
257
258
259  inline_grammar( <<-'END' )
260    grammar RewriteStringRoot;
261    options {
262        language=Ruby;
263        output=AST;
264    }
265    @members {
266      class V < ANTLR3::CommonTree
267        def to_s
268          return @token.text + "<V>"
269        end
270      end
271    
272    }
273    a : 'begin' INT -> ^('begin'<V> INT) ;
274    ID : 'a'..'z'+ ;
275    INT : '0'..'9'+ ;
276    WS : (' '|'\n') {$channel=HIDDEN;} ;
277  END
278
279
280  inline_grammar( <<-'END' )
281    grammar RewriteRuleResults;
282    options {
283        language=Ruby;
284        output=AST;
285    }
286    tokens {LIST;}
287    @members {
288      class V < ANTLR3::CommonTree
289        def to_s
290          return @token.text + "<V>"
291        end
292      end
293      class W < ANTLR3::CommonTree
294        def initialize(tok, text)
295          tok.text = text
296          super(tok)
297        end
298        def to_s
299          return @token.text + "<W>"
300        end
301      end
302    
303    }
304    a : id (',' id)* -> ^(LIST<W>["LIST"] id+);
305    id : ID -> ID<V>;
306    ID : 'a'..'z'+ ;
307    WS : (' '|'\n') {$channel=HIDDEN;} ;
308  END
309
310
311  inline_grammar( <<-'END' )
312    grammar CopySemanticsWithHetero;
313    options {
314        language=Ruby;
315        output=AST;
316    }
317    @members {
318      class V < ANTLR3::CommonTree
319        def dup_node
320          return V.new(self)
321        end
322        def to_s
323          return @token.text + "<V>"
324        end
325      end
326    }
327    a : type ID (',' ID)* ';' -> ^(type ID)+;
328    type : 'int'<V> ;
329    ID : 'a'..'z'+ ;
330    INT : '0'..'9'+;
331    WS : (' '|'\\n') {$channel=HIDDEN;} ;
332  END
333
334
335  inline_grammar( <<-'END' )
336    grammar TreeParserRewriteFlatList;
337    options {
338        language=Ruby;
339        output=AST;
340    }
341    a : ID INT;
342    ID : 'a'..'z'+ ;
343    INT : '0'..'9'+;
344    WS : (' '|'\n') {$channel=HIDDEN;} ;
345  END
346
347
348  inline_grammar( <<-'END' )
349    tree grammar TreeParserRewriteFlatListWalker;
350    options {
351        language=Ruby;
352        output=AST;
353        ASTLabelType=CommonTree;
354        tokenVocab=TreeParserRewriteFlatList;
355    }
356    @members {
357      class V < ANTLR3::CommonTree
358        def to_s
359          return @token.text + "<V>"
360        end
361      end
362      class W < ANTLR3::CommonTree
363        def to_s
364          return @token.text + "<W>"
365        end
366      end
367    }
368    a : ID INT -> INT<V> ID<W>
369      ;
370  END
371
372
373  inline_grammar( <<-'END' )
374    grammar TreeParserRewriteTree;
375    options {
376        language=Ruby;
377        output=AST;
378    }
379    a : ID INT;
380    ID : 'a'..'z'+ ;
381    INT : '0'..'9'+;
382    WS : (' '|'\n') {$channel=HIDDEN;} ;
383  END
384
385
386  inline_grammar( <<-'END' )
387    tree grammar TreeParserRewriteTreeWalker;
388    options {
389        language=Ruby;
390        output=AST;
391        ASTLabelType=CommonTree;
392        tokenVocab=TreeParserRewriteTree;
393    }
394    @members {
395      class V < ANTLR3::CommonTree
396        def to_s
397          return @token.text + "<V>"
398        end
399      end
400    
401      class W < ANTLR3::CommonTree
402        def to_s
403          return @token.text + "<W>"
404        end
405      end      
406    }
407    a : ID INT -> ^(INT<V> ID<W>)
408      ;
409  END
410
411
412  inline_grammar( <<-'END' )
413    grammar TreeParserRewriteImaginary;
414    options {
415        language=Ruby;
416        output=AST;
417    }
418    a : ID ;
419    ID : 'a'..'z'+ ;
420    INT : '0'..'9'+;
421    WS : (' '|'\n') {$channel=HIDDEN;} ;
422  END
423
424
425  inline_grammar( <<-'END' )
426    tree grammar TreeParserRewriteImaginaryWalker;
427    options {
428        language=Ruby;
429        output=AST;
430        ASTLabelType=CommonTree;
431        tokenVocab=TreeParserRewriteImaginary;
432    }
433    tokens { ROOT; }
434    @members {
435      class V < ANTLR3::CommonTree
436        def to_s
437          return @token.name + "<V>"
438        end
439      end
440    }
441    a : ID -> ROOT<V> ID
442      ;
443  END
444
445
446  inline_grammar( <<-'END' )
447    grammar TreeParserRewriteImaginaryWithArgs;
448    options {
449        language=Ruby;
450        output=AST;
451    }
452    a : ID ;
453    ID : 'a'..'z'+ ;
454    INT : '0'..'9'+;
455    WS : (' '|'\n') {$channel=HIDDEN;} ;
456  END
457
458
459  inline_grammar( <<-'END' )
460    tree grammar TreeParserRewriteImaginaryWithArgsWalker;
461    options {
462        language=Ruby;
463        output=AST;
464        ASTLabelType=CommonTree;
465        tokenVocab=TreeParserRewriteImaginaryWithArgs;
466    }
467    tokens { ROOT; }
468    @members {
469      class V < ANTLR3::CommonTree
470        def initialize(token_type, x)
471          super(token_type)
472          @x = x
473        end
474        def to_s
475          return @token.name + "<V>;#@x"
476        end
477      end
478    }
479    a : ID -> ROOT<V>[42] ID
480      ;
481  END
482
483
484  inline_grammar( <<-'END' )
485    grammar TreeParserRewriteImaginaryRoot;
486    options {
487        language=Ruby;
488        output=AST;
489    }
490    a : ID ;
491    ID : 'a'..'z'+ ;
492    INT : '0'..'9'+;
493    WS : (' '|'\n') {$channel=HIDDEN;} ;
494  END
495
496
497  inline_grammar( <<-'END' )
498    tree grammar TreeParserRewriteImaginaryRootWalker;
499    options {
500        language=Ruby;
501        output=AST;
502        ASTLabelType=CommonTree;
503        tokenVocab=TreeParserRewriteImaginaryRoot;
504    }
505    tokens { ROOT; }
506    @members {
507      class V < ANTLR3::CommonTree
508        def to_s
509          return @token.name + "<V>"
510        end
511      end
512    }
513    a : ID -> ^(ROOT<V> ID)
514      ;
515  END
516
517
518  inline_grammar( <<-'END' )
519    grammar TreeParserRewriteImaginaryFromReal;
520    options {
521        language=Ruby;
522        output=AST;
523    }
524    a : ID ;
525    ID : 'a'..'z'+ ;
526    INT : '0'..'9'+;
527    WS : (' '|'\n') {$channel=HIDDEN;} ;
528  END
529
530
531  inline_grammar( <<-'END' )
532    tree grammar TreeParserRewriteImaginaryFromRealWalker;
533    options {
534        language=Ruby;
535        output=AST;
536        ASTLabelType=CommonTree;
537        tokenVocab=TreeParserRewriteImaginaryFromReal;
538    }
539    tokens { ROOT; }
540    @members {
541      class V < ANTLR3::CommonTree
542        def initialize(token, tree = nil)
543          if tree.nil? then super(token)
544          else
545            super(tree)
546            @token = TokenData::Token.from_token(@token)
547            @token.type = token.type
548          end
549        end
550        def to_s
551          return @token.name + "<V>@" + @token.line.to_s
552        end
553      end
554    }
555    a : ID -> ROOT<V>[$ID]
556      ;
557  END
558
559
560  inline_grammar( <<-'END' )
561    grammar TreeParserAutoHeteroAST;
562    options {
563        language=Ruby;
564        output=AST;
565    }
566    a : ID ';' ;
567    ID : 'a'..'z'+ ;
568    INT : '0'..'9'+;
569    WS : (' '|'\n') {$channel=HIDDEN;} ;
570  END
571
572
573  inline_grammar( <<-'END' )
574    tree grammar TreeParserAutoHeteroASTWalker;
575    options {
576        language=Ruby;
577        output=AST;
578        ASTLabelType=CommonTree;
579        tokenVocab=TreeParserAutoHeteroAST;
580    }
581    tokens { ROOT; }
582    @members {
583      class V < ANTLR3::CommonTree
584        def to_s
585          return @token.text + "<V>"
586        end
587      end
588    }
589    
590    a : ID<V> ';'<V>;
591  END
592
593  def parse( grammar_name, grammar_rule, input )
594    grammar_module = self.class.const_get( grammar_name.to_s )
595    lexer  = grammar_module::Lexer.new( input )
596    tokens = ANTLR3::CommonTokenStream.new( lexer )
597    parser = grammar_module::Parser.new( tokens )
598    r = parser.send( grammar_rule )
599    
600    return( r.tree.inspect rescue '' )
601  end
602  
603  def tree_parse( grammar_name, grammar_rule, tree_grammar_rule, input )
604    grammar_module = self.class.const_get( grammar_name.to_s )
605    tree_grammar_module = self.class.const_get( grammar_name.to_s + 'Walker' )
606    
607    lexer  = grammar_module::Lexer.new( input )
608    tokens = ANTLR3::CommonTokenStream.new( lexer )
609    parser = grammar_module::Parser.new( tokens )
610    r = parser.send( grammar_rule )
611    
612    nodes = ANTLR3::CommonTreeNodeStream.new( r.tree )
613    nodes.token_stream = tokens
614    tree_parser = tree_grammar_module::TreeParser.new( nodes )
615    r = tree_parser.send( tree_grammar_rule )
616    
617    return( r.tree.inspect rescue '' )
618  end
619
620  example "v token" do
621    result = parse( :VToken, :a, 'a' )
622    result.should == 'a<V>'
623  end
624
625
626  example "token with qualified type" do
627    result = parse( :TokenWithQualifiedType, :a, 'a' )
628    result.should == 'a<V>'
629  end
630
631
632  example "token with label" do
633    result = parse( :TokenWithLabel, :a, 'a' )
634    result.should == 'a<V>'
635  end
636
637
638  example "token with list label" do
639    result = parse( :TokenWithListLabel, :a, 'a' )
640    result.should == 'a<V>'
641  end
642
643
644  example "token root" do
645    result = parse( :TokenRoot, :a, 'a' )
646    result.should == 'a<V>'
647  end
648
649
650  example "token root with list label" do
651    result = parse( :TokenRootWithListLabel, :a, 'a' )
652    result.should == 'a<V>'
653  end
654
655
656  example "string" do
657    result = parse( :FromString, :a, 'begin' )
658    result.should == 'begin<V>'
659  end
660
661
662  example "string root" do
663    result = parse( :StringRoot, :a, 'begin' )
664    result.should == 'begin<V>'
665  end
666
667
668  example "rewrite token" do
669    result = parse( :RewriteToken, :a, 'a' )
670    result.should == 'a<V>'
671  end
672
673
674  example "rewrite token with args" do
675    result = parse( :RewriteTokenWithArgs, :a, 'a' )
676    result.should == '<V>;421930 a<V>;9900'
677  end
678
679
680  example "rewrite token root" do
681    result = parse( :RewriteTokenRoot, :a, 'a 2' )
682    result.should == '(a<V> 2)'
683  end
684
685
686  example "rewrite string" do
687    result = parse( :RewriteString, :a, 'begin' )
688    result.should == 'begin<V>'
689  end
690
691
692  example "rewrite string root" do
693    result = parse( :RewriteStringRoot, :a, 'begin 2' )
694    result.should == '(begin<V> 2)'
695  end
696
697
698  example "rewrite rule results" do
699    result = parse( :RewriteRuleResults, :a, 'a,b,c' )
700    result.should == '(LIST<W> a<V> b<V> c<V>)'
701  end
702
703
704  example "copy semantics with hetero" do
705    result = parse( :CopySemanticsWithHetero, :a, 'int a, b, c;' )
706    result.should == '(int<V> a) (int<V> b) (int<V> c)'
707  end
708
709
710  example "tree parser rewrite flat list" do
711    result = tree_parse( :TreeParserRewriteFlatList, :a, :a, 'abc 34' )
712    result.should == '34<V> abc<W>'
713  end
714
715
716  example "tree parser rewrite tree" do
717    result = tree_parse( :TreeParserRewriteTree, :a, :a, 'abc 34' )
718    result.should == '(34<V> abc<W>)'
719  end
720
721
722  example "tree parser rewrite imaginary" do
723    result = tree_parse( :TreeParserRewriteImaginary, :a, :a, 'abc' )
724    result.should == 'ROOT<V> abc'
725  end
726
727
728  example "tree parser rewrite imaginary with args" do
729    result = tree_parse( :TreeParserRewriteImaginaryWithArgs, :a, :a, 'abc' )
730    result.should == 'ROOT<V>;42 abc'
731  end
732
733
734  example "tree parser rewrite imaginary root" do
735    result = tree_parse( :TreeParserRewriteImaginaryRoot, :a, :a, 'abc' )
736    result.should == '(ROOT<V> abc)'
737  end
738
739
740  example "tree parser rewrite imaginary from real" do
741    result = tree_parse( :TreeParserRewriteImaginaryFromReal, :a, :a, 'abc' )
742    result.should == 'ROOT<V>@1'
743  end
744
745
746  example "tree parser auto hetero ast" do
747    result = tree_parse( :TreeParserAutoHeteroAST, :a, :a, 'abc;' )
748    result.should == 'abc<V> ;<V>'
749  end
750
751end
752