1import unittest
2import textwrap
3import antlr3
4import antlr3.tree
5import testbase
6import sys
7
8class TestRewriteAST(testbase.ANTLRTest):
9    def parserClass(self, base):
10        class TParser(base):
11            def __init__(self, *args, **kwargs):
12                base.__init__(self, *args, **kwargs)
13
14                self._errors = []
15                self._output = ""
16
17
18            def capture(self, t):
19                self._output += t
20
21
22            def traceIn(self, ruleName, ruleIndex):
23                self.traces.append('>'+ruleName)
24
25
26            def traceOut(self, ruleName, ruleIndex):
27                self.traces.append('<'+ruleName)
28
29
30            def emitErrorMessage(self, msg):
31                self._errors.append(msg)
32
33
34        return TParser
35
36
37    def lexerClass(self, base):
38        class TLexer(base):
39            def __init__(self, *args, **kwargs):
40                base.__init__(self, *args, **kwargs)
41
42                self._output = ""
43
44
45            def capture(self, t):
46                self._output += t
47
48
49            def traceIn(self, ruleName, ruleIndex):
50                self.traces.append('>'+ruleName)
51
52
53            def traceOut(self, ruleName, ruleIndex):
54                self.traces.append('<'+ruleName)
55
56
57            def recover(self, input, re):
58                # no error recovery yet, just crash!
59                raise
60
61        return TLexer
62
63
64    def execParser(self, grammar, grammarEntry, input, expectErrors=False):
65        lexerCls, parserCls = self.compileInlineGrammar(grammar)
66
67        cStream = antlr3.StringStream(input)
68        lexer = lexerCls(cStream)
69        tStream = antlr3.CommonTokenStream(lexer)
70        parser = parserCls(tStream)
71        r = getattr(parser, grammarEntry)()
72
73        if not expectErrors:
74            self.assertEquals(len(parser._errors), 0, parser._errors)
75
76        result = ""
77
78        if r is not None:
79            if hasattr(r, 'result'):
80                result += r.result
81
82            if r.tree is not None:
83                result += r.tree.toStringTree()
84
85        if not expectErrors:
86            return result
87
88        else:
89            return result, parser._errors
90
91
92    def execTreeParser(self, grammar, grammarEntry, treeGrammar, treeEntry, input):
93        lexerCls, parserCls = self.compileInlineGrammar(grammar)
94        walkerCls = self.compileInlineGrammar(treeGrammar)
95
96        cStream = antlr3.StringStream(input)
97        lexer = lexerCls(cStream)
98        tStream = antlr3.CommonTokenStream(lexer)
99        parser = parserCls(tStream)
100        r = getattr(parser, grammarEntry)()
101        nodes = antlr3.tree.CommonTreeNodeStream(r.tree)
102        nodes.setTokenStream(tStream)
103        walker = walkerCls(nodes)
104        r = getattr(walker, treeEntry)()
105
106        if r is not None:
107            return r.tree.toStringTree()
108
109        return ""
110
111
112    def testDelete(self):
113        grammar = textwrap.dedent(
114            r'''
115            grammar T;
116            options {language=Python;output=AST;}
117            a : ID INT -> ;
118            ID : 'a'..'z'+ ;
119            INT : '0'..'9'+;
120            WS : (' '|'\n') {$channel=HIDDEN;} ;
121            ''')
122
123        found = self.execParser(grammar, "a", "abc 34")
124        self.assertEquals("", found)
125
126
127    def testSingleToken(self):
128        grammar = textwrap.dedent(
129            r'''
130            grammar T;
131            options {language=Python;output=AST;}
132            a : ID -> ID;
133            ID : 'a'..'z'+ ;
134            INT : '0'..'9'+;
135            WS : (' '|'\n') {$channel=HIDDEN;} ;
136            ''')
137
138        found = self.execParser(grammar, "a", "abc")
139        self.assertEquals("abc", found)
140
141
142    def testSingleTokenToNewNode(self):
143        grammar = textwrap.dedent(
144            r'''
145            grammar T;
146            options {language=Python;output=AST;}
147            a : ID -> ID["x"];
148            ID : 'a'..'z'+ ;
149            INT : '0'..'9'+;
150            WS : (' '|'\n') {$channel=HIDDEN;} ;
151            ''')
152
153        found = self.execParser(grammar, "a", "abc")
154        self.assertEquals("x", found)
155
156
157    def testSingleTokenToNewNodeRoot(self):
158        grammar = textwrap.dedent(
159            r'''
160            grammar T;
161            options {language=Python;output=AST;}
162            a : ID -> ^(ID["x"] INT);
163            ID : 'a'..'z'+ ;
164            INT : '0'..'9'+;
165            WS : (' '|'\n') {$channel=HIDDEN;} ;
166            ''')
167
168        found = self.execParser(grammar, "a", "abc")
169        self.assertEquals("(x INT)", found)
170
171
172    def testSingleTokenToNewNode2(self):
173        # Allow creation of new nodes w/o args.
174        grammar = textwrap.dedent(
175            r'''
176            grammar TT;
177            options {language=Python;output=AST;}
178            a : ID -> ID[ ];
179            ID : 'a'..'z'+ ;
180            INT : '0'..'9'+;
181            WS : (' '|'\n') {$channel=HIDDEN;} ;
182            ''')
183
184        found = self.execParser(grammar, "a", "abc")
185        self.assertEquals("ID", found)
186
187
188    def testSingleCharLiteral(self):
189        grammar = textwrap.dedent(
190            r'''
191            grammar T;
192            options {language=Python;output=AST;}
193            a : 'c' -> 'c';
194            ID : 'a'..'z'+ ;
195            INT : '0'..'9'+;
196            WS : (' '|'\n') {$channel=HIDDEN;} ;
197            ''')
198
199        found = self.execParser(grammar, "a", "c")
200        self.assertEquals("c", found)
201
202
203    def testSingleStringLiteral(self):
204        grammar = textwrap.dedent(
205            r'''
206            grammar T;
207            options {language=Python;output=AST;}
208            a : 'ick' -> 'ick';
209            ID : 'a'..'z'+ ;
210            INT : '0'..'9'+;
211            WS : (' '|'\n') {$channel=HIDDEN;} ;
212            ''')
213
214        found = self.execParser(grammar, "a", "ick")
215        self.assertEquals("ick", found)
216
217
218    def testSingleRule(self):
219        grammar = textwrap.dedent(
220            r'''
221            grammar T;
222            options {language=Python;output=AST;}
223            a : b -> b;
224            b : ID ;
225            ID : 'a'..'z'+ ;
226            INT : '0'..'9'+;
227            WS : (' '|'\n') {$channel=HIDDEN;} ;
228            ''')
229
230        found = self.execParser(grammar, "a", "abc")
231        self.assertEquals("abc", found)
232
233
234    def testReorderTokens(self):
235        grammar = textwrap.dedent(
236            r'''
237            grammar T;
238            options {language=Python;output=AST;}
239            a : ID INT -> INT ID;
240            ID : 'a'..'z'+ ;
241            INT : '0'..'9'+;
242            WS : (' '|'\n') {$channel=HIDDEN;} ;
243            ''')
244
245        found = self.execParser(grammar, "a", "abc 34")
246        self.assertEquals("34 abc", found)
247
248
249    def testReorderTokenAndRule(self):
250        grammar = textwrap.dedent(
251            r'''
252            grammar T;
253            options {language=Python;output=AST;}
254            a : b INT -> INT b;
255            b : ID ;
256            ID : 'a'..'z'+ ;
257            INT : '0'..'9'+;
258            WS : (' '|'\n') {$channel=HIDDEN;} ;
259            ''')
260
261        found = self.execParser(grammar, "a", "abc 34")
262        self.assertEquals("34 abc", found)
263
264
265    def testTokenTree(self):
266        grammar = textwrap.dedent(
267            r'''
268            grammar T;
269            options {language=Python;output=AST;}
270            a : ID INT -> ^(INT ID);
271            ID : 'a'..'z'+ ;
272            INT : '0'..'9'+;
273            WS : (' '|'\n') {$channel=HIDDEN;} ;
274            ''')
275
276        found = self.execParser(grammar, "a", "abc 34")
277        self.assertEquals("(34 abc)", found)
278
279
280    def testTokenTreeAfterOtherStuff(self):
281        grammar = textwrap.dedent(
282            r'''
283            grammar T;
284            options {language=Python;output=AST;}
285            a : 'void' ID INT -> 'void' ^(INT ID);
286            ID : 'a'..'z'+ ;
287            INT : '0'..'9'+;
288            WS : (' '|'\n') {$channel=HIDDEN;} ;
289            ''')
290
291        found = self.execParser(grammar, "a", "void abc 34")
292        self.assertEquals("void (34 abc)", found)
293
294
295    def testNestedTokenTreeWithOuterLoop(self):
296        # verify that ID and INT both iterate over outer index variable
297        grammar = textwrap.dedent(
298            r'''
299            grammar T;
300            options {language=Python;output=AST;}
301            tokens {DUH;}
302            a : ID INT ID INT -> ^( DUH ID ^( DUH INT) )+ ;
303            ID : 'a'..'z'+ ;
304            INT : '0'..'9'+;
305            WS : (' '|'\n') {$channel=HIDDEN;} ;
306            ''')
307
308        found = self.execParser(grammar, "a", "a 1 b 2")
309        self.assertEquals("(DUH a (DUH 1)) (DUH b (DUH 2))", found)
310
311
312    def testOptionalSingleToken(self):
313        grammar = textwrap.dedent(
314            r'''
315            grammar T;
316            options {language=Python;output=AST;}
317            a : ID -> ID? ;
318            ID : 'a'..'z'+ ;
319            INT : '0'..'9'+;
320            WS : (' '|'\n') {$channel=HIDDEN;} ;
321            ''')
322
323        found = self.execParser(grammar, "a", "abc")
324        self.assertEquals("abc", found)
325
326
327    def testClosureSingleToken(self):
328        grammar = textwrap.dedent(
329            r'''
330            grammar T;
331            options {language=Python;output=AST;}
332            a : ID ID -> ID* ;
333            ID : 'a'..'z'+ ;
334            INT : '0'..'9'+;
335            WS : (' '|'\n') {$channel=HIDDEN;} ;
336            ''')
337
338        found = self.execParser(grammar, "a", "a b")
339        self.assertEquals("a b", found)
340
341
342    def testPositiveClosureSingleToken(self):
343        grammar = textwrap.dedent(
344            r'''
345            grammar T;
346            options {language=Python;output=AST;}
347            a : ID ID -> ID+ ;
348            ID : 'a'..'z'+ ;
349            INT : '0'..'9'+;
350            WS : (' '|'\n') {$channel=HIDDEN;} ;
351            ''')
352
353        found = self.execParser(grammar, "a", "a b")
354        self.assertEquals("a b", found)
355
356
357    def testOptionalSingleRule(self):
358        grammar = textwrap.dedent(
359            r'''
360            grammar T;
361            options {language=Python;output=AST;}
362            a : b -> b?;
363            b : ID ;
364            ID : 'a'..'z'+ ;
365            INT : '0'..'9'+;
366            WS : (' '|'\n') {$channel=HIDDEN;} ;
367            ''')
368
369        found = self.execParser(grammar, "a", "abc")
370        self.assertEquals("abc", found)
371
372
373    def testClosureSingleRule(self):
374        grammar = textwrap.dedent(
375            r'''
376            grammar T;
377            options {language=Python;output=AST;}
378            a : b b -> b*;
379            b : ID ;
380            ID : 'a'..'z'+ ;
381            INT : '0'..'9'+;
382            WS : (' '|'\n') {$channel=HIDDEN;} ;
383            ''')
384
385        found = self.execParser(grammar, "a", "a b")
386        self.assertEquals("a b", found)
387
388
389    def testClosureOfLabel(self):
390        grammar = textwrap.dedent(
391            r'''
392            grammar T;
393            options {language=Python;output=AST;}
394            a : x+=b x+=b -> $x*;
395            b : ID ;
396            ID : 'a'..'z'+ ;
397            INT : '0'..'9'+;
398            WS : (' '|'\n') {$channel=HIDDEN;} ;
399            ''')
400
401        found = self.execParser(grammar, "a", "a b")
402        self.assertEquals("a b", found)
403
404
405    def testOptionalLabelNoListLabel(self):
406        grammar = textwrap.dedent(
407            r'''
408            grammar T;
409            options {language=Python;output=AST;}
410            a : (x=ID)? -> $x?;
411            ID : 'a'..'z'+ ;
412            INT : '0'..'9'+;
413            WS : (' '|'\n') {$channel=HIDDEN;} ;
414            ''')
415
416        found = self.execParser(grammar, "a", "a")
417        self.assertEquals("a", found)
418
419
420    def testPositiveClosureSingleRule(self):
421        grammar = textwrap.dedent(
422            r'''
423            grammar T;
424            options {language=Python;output=AST;}
425            a : b b -> b+;
426            b : ID ;
427            ID : 'a'..'z'+ ;
428            INT : '0'..'9'+;
429            WS : (' '|'\n') {$channel=HIDDEN;} ;
430            ''')
431
432        found = self.execParser(grammar, "a", "a b")
433        self.assertEquals("a b", found)
434
435
436    def testSinglePredicateT(self):
437        grammar = textwrap.dedent(
438            r'''
439            grammar T;
440            options {language=Python;output=AST;}
441            a : ID -> {True}? ID -> ;
442            ID : 'a'..'z'+ ;
443            INT : '0'..'9'+;
444            WS : (' '|'\n') {$channel=HIDDEN;} ;
445            ''')
446
447        found = self.execParser(grammar, "a", "abc")
448        self.assertEquals("abc", found)
449
450
451    def testSinglePredicateF(self):
452        grammar = textwrap.dedent(
453            r'''
454            grammar T;
455            options {language=Python;output=AST;}
456            a : ID -> {False}? ID -> ;
457            ID : 'a'..'z'+ ;
458            INT : '0'..'9'+;
459            WS : (' '|'\n') {$channel=HIDDEN;} ;
460            ''')
461
462        found = self.execParser(grammar, "a", "abc")
463        self.assertEquals("", found)
464
465
466    def testMultiplePredicate(self):
467        grammar = textwrap.dedent(
468            r'''
469            grammar T;
470            options {language=Python;output=AST;}
471            a : ID INT -> {False}? ID
472                       -> {True}? INT
473                       ->
474              ;
475            ID : 'a'..'z'+ ;
476            INT : '0'..'9'+;
477            WS : (' '|'\n') {$channel=HIDDEN;} ;
478            ''')
479
480        found = self.execParser(grammar, "a", "a 2")
481        self.assertEquals("2", found)
482
483
484    def testMultiplePredicateTrees(self):
485        grammar = textwrap.dedent(
486            r'''
487            grammar T;
488            options {language=Python;output=AST;}
489            a : ID INT -> {False}? ^(ID INT)
490                       -> {True}? ^(INT ID)
491                       -> ID
492              ;
493            ID : 'a'..'z'+ ;
494            INT : '0'..'9'+;
495            WS : (' '|'\n') {$channel=HIDDEN;} ;
496            ''')
497
498        found = self.execParser(grammar, "a", "a 2")
499        self.assertEquals("(2 a)", found)
500
501
502    def testSimpleTree(self):
503        grammar = textwrap.dedent(
504            r'''
505            grammar T;
506            options {language=Python;output=AST;}
507            a : op INT -> ^(op INT);
508            op : '+'|'-' ;
509            ID : 'a'..'z'+ ;
510            INT : '0'..'9'+;
511            WS : (' '|'\n') {$channel=HIDDEN;} ;
512            ''')
513
514        found = self.execParser(grammar, "a", "-34")
515        self.assertEquals("(- 34)", found)
516
517
518    def testSimpleTree2(self):
519        grammar = textwrap.dedent(
520            r'''
521            grammar T;
522            options {language=Python;output=AST;}
523            a : op INT -> ^(INT op);
524            op : '+'|'-' ;
525            ID : 'a'..'z'+ ;
526            INT : '0'..'9'+;
527            WS : (' '|'\n') {$channel=HIDDEN;} ;
528            ''')
529
530        found = self.execParser(grammar, "a", "+ 34")
531        self.assertEquals("(34 +)", found)
532
533
534
535    def testNestedTrees(self):
536        grammar = textwrap.dedent(
537            r'''
538            grammar T;
539            options {language=Python;output=AST;}
540            a : 'var' (ID ':' type ';')+ -> ^('var' ^(':' ID type)+) ;
541            type : 'int' | 'float' ;
542            ID : 'a'..'z'+ ;
543            INT : '0'..'9'+;
544            WS : (' '|'\n') {$channel=HIDDEN;} ;
545            ''')
546
547        found = self.execParser(grammar, "a", "var a:int; b:float;")
548        self.assertEquals("(var (: a int) (: b float))", found)
549
550
551    def testImaginaryTokenCopy(self):
552        grammar = textwrap.dedent(
553            r'''
554            grammar T;
555            options {language=Python;output=AST;}
556            tokens {VAR;}
557            a : ID (',' ID)*-> ^(VAR ID)+ ;
558            type : 'int' | 'float' ;
559            ID : 'a'..'z'+ ;
560            INT : '0'..'9'+;
561            WS : (' '|'\n') {$channel=HIDDEN;} ;
562            ''')
563
564        found = self.execParser(grammar, "a", "a,b,c")
565        self.assertEquals("(VAR a) (VAR b) (VAR c)", found)
566
567
568    def testTokenUnreferencedOnLeftButDefined(self):
569        grammar = textwrap.dedent(
570            r'''
571            grammar T;
572            options {language=Python;output=AST;}
573            tokens {VAR;}
574            a : b -> ID ;
575            b : ID ;
576            ID : 'a'..'z'+ ;
577            INT : '0'..'9'+;
578            WS : (' '|'\n') {$channel=HIDDEN;} ;
579            ''')
580
581        found = self.execParser(grammar, "a", "a")
582        self.assertEquals("ID", found)
583
584
585    def testImaginaryTokenCopySetText(self):
586        grammar = textwrap.dedent(
587            r'''
588            grammar T;
589            options {language=Python;output=AST;}
590            tokens {VAR;}
591            a : ID (',' ID)*-> ^(VAR["var"] ID)+ ;
592            type : 'int' | 'float' ;
593            ID : 'a'..'z'+ ;
594            INT : '0'..'9'+;
595            WS : (' '|'\n') {$channel=HIDDEN;} ;
596            ''')
597
598        found = self.execParser(grammar, "a", "a,b,c")
599        self.assertEquals("(var a) (var b) (var c)", found)
600
601
602    def testImaginaryTokenNoCopyFromToken(self):
603        grammar = textwrap.dedent(
604            r'''
605            grammar T;
606            options {language=Python;output=AST;}
607            tokens {BLOCK;}
608            a : lc='{' ID+ '}' -> ^(BLOCK[$lc] ID+) ;
609            type : 'int' | 'float' ;
610            ID : 'a'..'z'+ ;
611            INT : '0'..'9'+;
612            WS : (' '|'\n') {$channel=HIDDEN;} ;
613            ''')
614
615        found = self.execParser(grammar, "a", "{a b c}")
616        self.assertEquals("({ a b c)", found)
617
618
619    def testImaginaryTokenNoCopyFromTokenSetText(self):
620        grammar = textwrap.dedent(
621            r'''
622            grammar T;
623            options {language=Python;output=AST;}
624            tokens {BLOCK;}
625            a : lc='{' ID+ '}' -> ^(BLOCK[$lc,"block"] ID+) ;
626            type : 'int' | 'float' ;
627            ID : 'a'..'z'+ ;
628            INT : '0'..'9'+;
629            WS : (' '|'\n') {$channel=HIDDEN;} ;
630            ''')
631
632        found = self.execParser(grammar, "a", "{a b c}")
633        self.assertEquals("(block a b c)", found)
634
635
636    def testMixedRewriteAndAutoAST(self):
637        grammar = textwrap.dedent(
638            r'''
639            grammar T;
640            options {language=Python;output=AST;}
641            tokens {BLOCK;}
642            a : b b^ ; // 2nd b matches only an INT; can make it root
643            b : ID INT -> INT ID
644              | INT
645              ;
646            ID : 'a'..'z'+ ;
647            INT : '0'..'9'+;
648            WS : (' '|'\n') {$channel=HIDDEN;} ;
649            ''')
650
651        found = self.execParser(grammar, "a", "a 1 2")
652        self.assertEquals("(2 1 a)", found)
653
654
655    def testSubruleWithRewrite(self):
656        grammar = textwrap.dedent(
657            r'''
658            grammar T;
659            options {language=Python;output=AST;}
660            tokens {BLOCK;}
661            a : b b ;
662            b : (ID INT -> INT ID | INT INT -> INT+ )
663              ;
664            ID : 'a'..'z'+ ;
665            INT : '0'..'9'+;
666            WS : (' '|'\n') {$channel=HIDDEN;} ;
667            ''')
668
669        found = self.execParser(grammar, "a", "a 1 2 3")
670        self.assertEquals("1 a 2 3", found)
671
672
673    def testSubruleWithRewrite2(self):
674        grammar = textwrap.dedent(
675            r'''
676            grammar T;
677            options {language=Python;output=AST;}
678            tokens {TYPE;}
679            a : b b ;
680            b : 'int'
681                ( ID -> ^(TYPE 'int' ID)
682                | ID '=' INT -> ^(TYPE 'int' ID INT)
683                )
684                ';'
685              ;
686            ID : 'a'..'z'+ ;
687            INT : '0'..'9'+;
688            WS : (' '|'\n') {$channel=HIDDEN;} ;
689            ''')
690
691        found = self.execParser(grammar, "a", "int a; int b=3;")
692        self.assertEquals("(TYPE int a) (TYPE int b 3)", found)
693
694
695    def testNestedRewriteShutsOffAutoAST(self):
696        grammar = textwrap.dedent(
697            r'''
698            grammar T;
699            options {language=Python;output=AST;}
700            tokens {BLOCK;}
701            a : b b ;
702            b : ID ( ID (last=ID -> $last)+ ) ';' // get last ID
703              | INT // should still get auto AST construction
704              ;
705            ID : 'a'..'z'+ ;
706            INT : '0'..'9'+;
707            WS : (' '|'\n') {$channel=HIDDEN;} ;
708            ''')
709
710        found = self.execParser(grammar, "a", "a b c d; 42")
711        self.assertEquals("d 42", found)
712
713
714    def testRewriteActions(self):
715        grammar = textwrap.dedent(
716            r'''
717            grammar T;
718            options {language=Python;output=AST;}
719            a : atom -> ^({self.adaptor.create(INT,"9")} atom) ;
720            atom : INT ;
721            ID : 'a'..'z'+ ;
722            INT : '0'..'9'+;
723            WS : (' '|'\n') {$channel=HIDDEN;} ;
724            ''')
725
726        found = self.execParser(grammar, "a", "3")
727        self.assertEquals("(9 3)", found)
728
729
730    def testRewriteActions2(self):
731        grammar = textwrap.dedent(
732            r'''
733            grammar T;
734            options {language=Python;output=AST;}
735            a : atom -> {self.adaptor.create(INT,"9")} atom ;
736            atom : INT ;
737            ID : 'a'..'z'+ ;
738            INT : '0'..'9'+;
739            WS : (' '|'\n') {$channel=HIDDEN;} ;
740            ''')
741
742        found = self.execParser(grammar, "a", "3")
743        self.assertEquals("9 3", found)
744
745
746    def testRefToOldValue(self):
747        grammar = textwrap.dedent(
748            r'''
749            grammar T;
750            options {language=Python;output=AST;}
751            tokens {BLOCK;}
752            a : (atom -> atom) (op='+' r=atom -> ^($op $a $r) )* ;
753            atom : INT ;
754            ID : 'a'..'z'+ ;
755            INT : '0'..'9'+;
756            WS : (' '|'\n') {$channel=HIDDEN;} ;
757            ''')
758
759        found = self.execParser(grammar, "a", "3+4+5")
760        self.assertEquals("(+ (+ 3 4) 5)", found)
761
762
763    def testCopySemanticsForRules(self):
764        grammar = textwrap.dedent(
765            r'''
766            grammar T;
767            options {language=Python;output=AST;}
768            tokens {BLOCK;}
769            a : atom -> ^(atom atom) ; // NOT CYCLE! (dup atom)
770            atom : INT ;
771            ID : 'a'..'z'+ ;
772            INT : '0'..'9'+;
773            WS : (' '|'\n') {$channel=HIDDEN;} ;
774            ''')
775
776        found = self.execParser(grammar, "a", "3")
777        self.assertEquals("(3 3)", found)
778
779
780    def testCopySemanticsForRules2(self):
781        # copy type as a root for each invocation of (...)+ in rewrite
782        grammar = textwrap.dedent(
783            r'''
784            grammar T;
785            options {language=Python;output=AST;}
786            a : type ID (',' ID)* ';' -> ^(type ID)+ ;
787            type : 'int' ;
788            ID : 'a'..'z'+ ;
789            WS : (' '|'\n') {$channel=HIDDEN;} ;
790            ''')
791
792        found = self.execParser(grammar, "a", "int a,b,c;")
793        self.assertEquals("(int a) (int b) (int c)", found)
794
795
796    def testCopySemanticsForRules3(self):
797        # copy type *and* modifier even though it's optional
798        # for each invocation of (...)+ in rewrite
799        grammar = textwrap.dedent(
800            r'''
801            grammar T;
802            options {language=Python;output=AST;}
803            a : modifier? type ID (',' ID)* ';' -> ^(type modifier? ID)+ ;
804            type : 'int' ;
805            modifier : 'public' ;
806            ID : 'a'..'z'+ ;
807            WS : (' '|'\n') {$channel=HIDDEN;} ;
808            ''')
809
810        found = self.execParser(grammar, "a", "public int a,b,c;")
811        self.assertEquals("(int public a) (int public b) (int public c)", found)
812
813
814    def testCopySemanticsForRules3Double(self):
815        # copy type *and* modifier even though it's optional
816        # for each invocation of (...)+ in rewrite
817        grammar = textwrap.dedent(
818            r'''
819            grammar T;
820            options {language=Python;output=AST;}
821            a : modifier? type ID (',' ID)* ';' -> ^(type modifier? ID)+ ^(type modifier? ID)+ ;
822            type : 'int' ;
823            modifier : 'public' ;
824            ID : 'a'..'z'+ ;
825            WS : (' '|'\n') {$channel=HIDDEN;} ;
826            ''')
827
828        found = self.execParser(grammar, "a", "public int a,b,c;")
829        self.assertEquals("(int public a) (int public b) (int public c) (int public a) (int public b) (int public c)", found)
830
831
832    def testCopySemanticsForRules4(self):
833        # copy type *and* modifier even though it's optional
834        # for each invocation of (...)+ in rewrite
835        grammar = textwrap.dedent(
836            r'''
837            grammar T;
838            options {language=Python;output=AST;}
839            tokens {MOD;}
840            a : modifier? type ID (',' ID)* ';' -> ^(type ^(MOD modifier)? ID)+ ;
841            type : 'int' ;
842            modifier : 'public' ;
843            ID : 'a'..'z'+ ;
844            WS : (' '|'\n') {$channel=HIDDEN;} ;
845            ''')
846
847        found = self.execParser(grammar, "a", "public int a,b,c;")
848        self.assertEquals("(int (MOD public) a) (int (MOD public) b) (int (MOD public) c)", found)
849
850
851    def testCopySemanticsLists(self):
852        grammar = textwrap.dedent(
853            r'''
854            grammar T;
855            options {language=Python;output=AST;}
856            tokens {MOD;}
857            a : ID (',' ID)* ';' -> ID+ ID+ ;
858            ID : 'a'..'z'+ ;
859            WS : (' '|'\n') {$channel=HIDDEN;} ;
860            ''')
861
862        found = self.execParser(grammar, "a", "a,b,c;")
863        self.assertEquals("a b c a b c", found)
864
865
866    def testCopyRuleLabel(self):
867        grammar = textwrap.dedent(
868            r'''
869            grammar T;
870            options {language=Python;output=AST;}
871            tokens {BLOCK;}
872            a : x=b -> $x $x;
873            b : ID ;
874            ID : 'a'..'z'+ ;
875            WS : (' '|'\n') {$channel=HIDDEN;} ;
876            ''')
877
878        found = self.execParser(grammar, "a", "a")
879        self.assertEquals("a a", found)
880
881
882    def testCopyRuleLabel2(self):
883        grammar = textwrap.dedent(
884            r'''
885            grammar T;
886            options {language=Python;output=AST;}
887            tokens {BLOCK;}
888            a : x=b -> ^($x $x);
889            b : ID ;
890            ID : 'a'..'z'+ ;
891            WS : (' '|'\n') {$channel=HIDDEN;} ;
892            ''')
893
894        found = self.execParser(grammar, "a", "a")
895        self.assertEquals("(a a)", found)
896
897
898    def testQueueingOfTokens(self):
899        grammar = textwrap.dedent(
900            r'''
901            grammar T;
902            options {language=Python;output=AST;}
903            a : 'int' ID (',' ID)* ';' -> ^('int' ID+) ;
904            op : '+'|'-' ;
905            ID : 'a'..'z'+ ;
906            INT : '0'..'9'+;
907            WS : (' '|'\n') {$channel=HIDDEN;} ;
908            ''')
909
910        found = self.execParser(grammar, "a", "int a,b,c;")
911        self.assertEquals("(int a b c)", found)
912
913
914    def testCopyOfTokens(self):
915        grammar = textwrap.dedent(
916            r'''
917            grammar T;
918            options {language=Python;output=AST;}
919            a : 'int' ID ';' -> 'int' ID 'int' ID ;
920            op : '+'|'-' ;
921            ID : 'a'..'z'+ ;
922            INT : '0'..'9'+;
923            WS : (' '|'\n') {$channel=HIDDEN;} ;
924            ''')
925
926        found = self.execParser(grammar, "a", "int a;")
927        self.assertEquals("int a int a", found)
928
929
930    def testTokenCopyInLoop(self):
931        grammar = textwrap.dedent(
932            r'''
933            grammar T;
934            options {language=Python;output=AST;}
935            a : 'int' ID (',' ID)* ';' -> ^('int' ID)+ ;
936            op : '+'|'-' ;
937            ID : 'a'..'z'+ ;
938            INT : '0'..'9'+;
939            WS : (' '|'\n') {$channel=HIDDEN;} ;
940            ''')
941
942        found = self.execParser(grammar, "a", "int a,b,c;")
943        self.assertEquals("(int a) (int b) (int c)", found)
944
945
946    def testTokenCopyInLoopAgainstTwoOthers(self):
947        # must smear 'int' copies across as root of multiple trees
948        grammar = textwrap.dedent(
949            r'''
950            grammar T;
951            options {language=Python;output=AST;}
952            a : 'int' ID ':' INT (',' ID ':' INT)* ';' -> ^('int' ID INT)+ ;
953            op : '+'|'-' ;
954            ID : 'a'..'z'+ ;
955            INT : '0'..'9'+;
956            WS : (' '|'\n') {$channel=HIDDEN;} ;
957            ''')
958
959        found = self.execParser(grammar, "a", "int a:1,b:2,c:3;")
960        self.assertEquals("(int a 1) (int b 2) (int c 3)", found)
961
962
963    def testListRefdOneAtATime(self):
964        grammar = textwrap.dedent(
965            r'''
966            grammar T;
967            options {language=Python;output=AST;}
968            a : ID+ -> ID ID ID ; // works if 3 input IDs
969            op : '+'|'-' ;
970            ID : 'a'..'z'+ ;
971            INT : '0'..'9'+;
972            WS : (' '|'\n') {$channel=HIDDEN;} ;
973            ''')
974
975        found = self.execParser(grammar, "a", "a b c")
976        self.assertEquals("a b c", found)
977
978
979    def testSplitListWithLabels(self):
980        grammar = textwrap.dedent(
981            r'''
982            grammar T;
983            options {language=Python;output=AST;}
984            tokens {VAR;}
985            a : first=ID others+=ID* -> $first VAR $others+ ;
986            op : '+'|'-' ;
987            ID : 'a'..'z'+ ;
988            INT : '0'..'9'+;
989            WS : (' '|'\n') {$channel=HIDDEN;} ;
990            ''')
991
992        found = self.execParser(grammar, "a", "a b c")
993        self.assertEquals("a VAR b c", found)
994
995
996    def testComplicatedMelange(self):
997        grammar = textwrap.dedent(
998            r'''
999            grammar T;
1000            options {language=Python;output=AST;}
1001            tokens {BLOCK;}
1002            a : A A b=B B b=B c+=C C c+=C D {s=$D.text} -> A+ B+ C+ D ;
1003            type : 'int' | 'float' ;
1004            A : 'a' ;
1005            B : 'b' ;
1006            C : 'c' ;
1007            D : 'd' ;
1008            WS : (' '|'\n') {$channel=HIDDEN;} ;
1009            ''')
1010
1011        found = self.execParser(grammar, "a", "a a b b b c c c d")
1012        self.assertEquals("a a b b b c c c d", found)
1013
1014
1015    def testRuleLabel(self):
1016        grammar = textwrap.dedent(
1017            r'''
1018            grammar T;
1019            options {language=Python;output=AST;}
1020            tokens {BLOCK;}
1021            a : x=b -> $x;
1022            b : ID ;
1023            ID : 'a'..'z'+ ;
1024            WS : (' '|'\n') {$channel=HIDDEN;} ;
1025            ''')
1026
1027        found = self.execParser(grammar, "a", "a")
1028        self.assertEquals("a", found)
1029
1030
1031    def testAmbiguousRule(self):
1032        grammar = textwrap.dedent(
1033            r'''
1034            grammar T;
1035            options {language=Python;output=AST;}
1036            a : ID a -> a | INT ;
1037            ID : 'a'..'z'+ ;
1038            INT: '0'..'9'+ ;
1039            WS : (' '|'\n') {$channel=HIDDEN;} ;
1040            ''')
1041
1042        found = self.execParser(grammar,
1043				    "a", "abc 34")
1044        self.assertEquals("34", found)
1045
1046
1047    def testRuleListLabel(self):
1048        grammar = textwrap.dedent(
1049            r'''
1050            grammar T;
1051            options {language=Python;output=AST;}
1052            tokens {BLOCK;}
1053            a : x+=b x+=b -> $x+;
1054            b : ID ;
1055            ID : 'a'..'z'+ ;
1056            WS : (' '|'\n') {$channel=HIDDEN;} ;
1057            ''')
1058
1059        found = self.execParser(grammar, "a", "a b")
1060        self.assertEquals("a b", found)
1061
1062
1063    def testRuleListLabel2(self):
1064        grammar = textwrap.dedent(
1065            r'''
1066            grammar T;
1067            options {language=Python;output=AST;}
1068            tokens {BLOCK;}
1069            a : x+=b x+=b -> $x $x*;
1070            b : ID ;
1071            ID : 'a'..'z'+ ;
1072            WS : (' '|'\n') {$channel=HIDDEN;} ;
1073            ''')
1074
1075        found = self.execParser(grammar, "a", "a b")
1076        self.assertEquals("a b", found)
1077
1078
1079    def testOptional(self):
1080        grammar = textwrap.dedent(
1081            r'''
1082            grammar T;
1083            options {language=Python;output=AST;}
1084            tokens {BLOCK;}
1085            a : x=b (y=b)? -> $x $y?;
1086            b : ID ;
1087            ID : 'a'..'z'+ ;
1088            WS : (' '|'\n') {$channel=HIDDEN;} ;
1089            ''')
1090
1091        found = self.execParser(grammar, "a", "a")
1092        self.assertEquals("a", found)
1093
1094
1095    def testOptional2(self):
1096        grammar = textwrap.dedent(
1097            r'''
1098            grammar T;
1099            options {language=Python;output=AST;}
1100            tokens {BLOCK;}
1101            a : x=ID (y=b)? -> $x $y?;
1102            b : ID ;
1103            ID : 'a'..'z'+ ;
1104            WS : (' '|'\n') {$channel=HIDDEN;} ;
1105            ''')
1106
1107        found = self.execParser(grammar, "a", "a b")
1108        self.assertEquals("a b", found)
1109
1110
1111    def testOptional3(self):
1112        grammar = textwrap.dedent(
1113            r'''
1114            grammar T;
1115            options {language=Python;output=AST;}
1116            tokens {BLOCK;}
1117            a : x=ID (y=b)? -> ($x $y)?;
1118            b : ID ;
1119            ID : 'a'..'z'+ ;
1120            WS : (' '|'\n') {$channel=HIDDEN;} ;
1121            ''')
1122
1123        found = self.execParser(grammar, "a", "a b")
1124        self.assertEquals("a b", found)
1125
1126
1127    def testOptional4(self):
1128        grammar = textwrap.dedent(
1129            r'''
1130            grammar T;
1131            options {language=Python;output=AST;}
1132            tokens {BLOCK;}
1133            a : x+=ID (y=b)? -> ($x $y)?;
1134            b : ID ;
1135            ID : 'a'..'z'+ ;
1136            WS : (' '|'\n') {$channel=HIDDEN;} ;
1137            ''')
1138
1139        found = self.execParser(grammar, "a", "a b")
1140        self.assertEquals("a b", found)
1141
1142
1143    def testOptional5(self):
1144        grammar = textwrap.dedent(
1145            r'''
1146            grammar T;
1147            options {language=Python;output=AST;}
1148            tokens {BLOCK;}
1149            a : ID -> ID? ; // match an ID to optional ID
1150            b : ID ;
1151            ID : 'a'..'z'+ ;
1152            WS : (' '|'\n') {$channel=HIDDEN;} ;
1153            ''')
1154
1155        found = self.execParser(grammar, "a", "a")
1156        self.assertEquals("a", found)
1157
1158
1159    def testArbitraryExprType(self):
1160        grammar = textwrap.dedent(
1161            r'''
1162            grammar T;
1163            options {language=Python;output=AST;}
1164            tokens {BLOCK;}
1165            a : x+=b x+=b -> {CommonTree(None)};
1166            b : ID ;
1167            ID : 'a'..'z'+ ;
1168            WS : (' '|'\n') {$channel=HIDDEN;} ;
1169            ''')
1170
1171        found = self.execParser(grammar, "a", "a b")
1172        self.assertEquals("", found)
1173
1174
1175    def testSet(self):
1176        grammar = textwrap.dedent(
1177            r'''
1178            grammar T;
1179            options {language=Python;output=AST;}
1180            a: (INT|ID)+ -> INT+ ID+ ;
1181            INT: '0'..'9'+;
1182            ID : 'a'..'z'+;
1183            WS : (' '|'\n') {$channel=HIDDEN;} ;
1184            ''')
1185
1186        found = self.execParser(grammar, "a", "2 a 34 de")
1187        self.assertEquals("2 34 a de", found)
1188
1189
1190    def testSet2(self):
1191        grammar = textwrap.dedent(
1192            r'''
1193            grammar T;
1194            options {language=Python;output=AST;}
1195            a: (INT|ID) -> INT? ID? ;
1196            INT: '0'..'9'+;
1197            ID : 'a'..'z'+;
1198            WS : (' '|'\n') {$channel=HIDDEN;} ;
1199            ''')
1200
1201        found = self.execParser(grammar, "a", "2")
1202        self.assertEquals("2", found)
1203
1204
1205    @testbase.broken("http://www.antlr.org:8888/browse/ANTLR-162",
1206                     antlr3.tree.RewriteEmptyStreamException)
1207    def testSetWithLabel(self):
1208        grammar = textwrap.dedent(
1209            r'''
1210            grammar T;
1211            options {language=Python;output=AST;}
1212            a : x=(INT|ID) -> $x ;
1213            INT: '0'..'9'+;
1214            ID : 'a'..'z'+;
1215            WS : (' '|'\n') {$channel=HIDDEN;} ;
1216            ''')
1217
1218        found = self.execParser(grammar, "a", "2")
1219        self.assertEquals("2", found)
1220
1221
1222    def testRewriteAction(self):
1223        grammar = textwrap.dedent(
1224            r'''
1225            grammar T;
1226            options {language=Python;output=AST;}
1227            tokens { FLOAT; }
1228            r
1229                : INT -> {CommonTree(CommonToken(type=FLOAT, text=$INT.text+".0"))}
1230                ;
1231            INT : '0'..'9'+;
1232            WS: (' ' | '\n' | '\t')+ {$channel = HIDDEN;};
1233            ''')
1234
1235        found = self.execParser(grammar, "r", "25")
1236        self.assertEquals("25.0", found)
1237
1238
1239    def testOptionalSubruleWithoutRealElements(self):
1240        # copy type *and* modifier even though it's optional
1241        # for each invocation of (...)+ in rewrite
1242        grammar = textwrap.dedent(
1243            r"""
1244            grammar T;
1245            options {language=Python;output=AST;}
1246            tokens {PARMS;}
1247
1248            modulo
1249             : 'modulo' ID ('(' parms+ ')')? -> ^('modulo' ID ^(PARMS parms+)?)
1250             ;
1251            parms : '#'|ID;
1252            ID : ('a'..'z' | 'A'..'Z')+;
1253            WS : (' '|'\n') {$channel=HIDDEN;} ;
1254            """)
1255
1256        found = self.execParser(grammar, "modulo", "modulo abc (x y #)")
1257        self.assertEquals("(modulo abc (PARMS x y #))", found)
1258
1259
1260    ## C A R D I N A L I T Y  I S S U E S
1261
1262    def testCardinality(self):
1263        grammar = textwrap.dedent(
1264            r'''
1265            grammar T;
1266            options {language=Python;output=AST;}
1267            tokens {BLOCK;}
1268            a : ID ID INT INT INT -> (ID INT)+;
1269            ID : 'a'..'z'+ ;
1270            INT : '0'..'9'+;
1271            WS : (' '|'\n') {$channel=HIDDEN;} ;
1272            ''')
1273
1274        try:
1275            self.execParser(grammar, "a", "a b 3 4 5")
1276            self.fail()
1277        except antlr3.tree.RewriteCardinalityException:
1278            pass
1279
1280
1281    def testCardinality2(self):
1282        grammar = textwrap.dedent(
1283            r'''
1284            grammar T;
1285            options {language=Python;output=AST;}
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            ''')
1292
1293        try:
1294            self.execParser(grammar, "a", "a b")
1295            self.fail()
1296        except antlr3.tree.RewriteCardinalityException:
1297            pass
1298
1299
1300    def testCardinality3(self):
1301        grammar = textwrap.dedent(
1302            r'''
1303            grammar T;
1304            options {language=Python;output=AST;}
1305            a : ID? INT -> ID INT ;
1306            op : '+'|'-' ;
1307            ID : 'a'..'z'+ ;
1308            INT : '0'..'9'+;
1309            WS : (' '|'\n') {$channel=HIDDEN;} ;
1310            ''')
1311
1312        try:
1313            self.execParser(grammar, "a", "3")
1314            self.fail()
1315        except antlr3.tree.RewriteEmptyStreamException:
1316            pass
1317
1318
1319    def testLoopCardinality(self):
1320        grammar = textwrap.dedent(
1321            r'''
1322            grammar T;
1323            options {language=Python;output=AST;}
1324            a : ID? INT -> ID+ INT ;
1325            op : '+'|'-' ;
1326            ID : 'a'..'z'+ ;
1327            INT : '0'..'9'+;
1328            WS : (' '|'\n') {$channel=HIDDEN;} ;
1329            ''')
1330
1331        try:
1332            self.execParser(grammar, "a", "3")
1333            self.fail()
1334        except antlr3.tree.RewriteEarlyExitException:
1335            pass
1336
1337
1338    def testWildcard(self):
1339        grammar = textwrap.dedent(
1340            r'''
1341            grammar T;
1342            options {language=Python;output=AST;}
1343            a : ID c=. -> $c;
1344            ID : 'a'..'z'+ ;
1345            INT : '0'..'9'+;
1346            WS : (' '|'\n') {$channel=HIDDEN;} ;
1347            ''')
1348
1349        found = self.execParser(grammar, "a", "abc 34")
1350        self.assertEquals("34", found)
1351
1352
1353    # E R R O R S
1354
1355    def testExtraTokenInSimpleDecl(self):
1356        grammar = textwrap.dedent(
1357            r'''
1358            grammar foo;
1359            options {language=Python;output=AST;}
1360            tokens {EXPR;}
1361            decl : type ID '=' INT ';' -> ^(EXPR type ID INT) ;
1362            type : 'int' | 'float' ;
1363            ID : 'a'..'z'+ ;
1364            INT : '0'..'9'+;
1365            WS : (' '|'\n') {$channel=HIDDEN;} ;
1366            ''')
1367
1368        found, errors = self.execParser(grammar, "decl", "int 34 x=1;",
1369                                        expectErrors=True)
1370        self.assertEquals(["line 1:4 extraneous input u'34' expecting ID"],
1371                          errors)
1372        self.assertEquals("(EXPR int x 1)", found) # tree gets correct x and 1 tokens
1373
1374
1375    #@testbase.broken("FIXME", AssertionError)
1376    def testMissingIDInSimpleDecl(self):
1377        grammar = textwrap.dedent(
1378            r'''
1379            grammar foo;
1380            options {language=Python;output=AST;}
1381            tokens {EXPR;}
1382            decl : type ID '=' INT ';' -> ^(EXPR type ID INT) ;
1383            type : 'int' | 'float' ;
1384            ID : 'a'..'z'+ ;
1385            INT : '0'..'9'+;
1386            WS : (' '|'\n') {$channel=HIDDEN;} ;
1387            ''')
1388
1389        found, errors = self.execParser(grammar, "decl", "int =1;",
1390                                        expectErrors=True)
1391        self.assertEquals(["line 1:4 missing ID at u'='"], errors)
1392        self.assertEquals("(EXPR int <missing ID> 1)", found) # tree gets invented ID token
1393
1394
1395    def testMissingSetInSimpleDecl(self):
1396        grammar = textwrap.dedent(
1397            r'''
1398            grammar foo;
1399            options {language=Python;output=AST;}
1400            tokens {EXPR;}
1401            decl : type ID '=' INT ';' -> ^(EXPR type ID INT) ;
1402            type : 'int' | 'float' ;
1403            ID : 'a'..'z'+ ;
1404            INT : '0'..'9'+;
1405            WS : (' '|'\n') {$channel=HIDDEN;} ;
1406            ''')
1407
1408        found, errors = self.execParser(grammar, "decl", "x=1;",
1409                                        expectErrors=True)
1410        self.assertEquals(["line 1:0 mismatched input u'x' expecting set None"],
1411                          errors);
1412        self.assertEquals("(EXPR <error: x> x 1)", found) # tree gets invented ID token
1413
1414
1415    def testMissingTokenGivesErrorNode(self):
1416        grammar = textwrap.dedent(
1417            r'''
1418            grammar foo;
1419            options {language=Python;output=AST;}
1420            a : ID INT -> ID INT ;
1421            ID : 'a'..'z'+ ;
1422            INT : '0'..'9'+;
1423            WS : (' '|'\n') {$channel=HIDDEN;} ;
1424            ''')
1425
1426        found, errors = self.execParser(grammar, "a", "abc",
1427                                        expectErrors=True)
1428        self.assertEquals(["line 1:3 missing INT at '<EOF>'"], errors)
1429        # doesn't do in-line recovery for sets (yet?)
1430        self.assertEquals("abc <missing INT>", found)
1431
1432
1433    def testExtraTokenGivesErrorNode(self):
1434        grammar = textwrap.dedent(
1435            r'''
1436            grammar foo;
1437            options {language=Python;output=AST;}
1438            a : b c -> b c;
1439            b : ID -> ID ;
1440            c : INT -> INT ;
1441            ID : 'a'..'z'+ ;
1442            INT : '0'..'9'+;
1443            WS : (' '|'\n') {$channel=HIDDEN;} ;
1444            ''')
1445
1446        found, errors = self.execParser(grammar, "a", "abc ick 34",
1447                                        expectErrors=True)
1448        self.assertEquals(["line 1:4 extraneous input u'ick' expecting INT"],
1449                          errors)
1450        self.assertEquals("abc 34", found)
1451
1452
1453    #@testbase.broken("FIXME", AssertionError)
1454    def testMissingFirstTokenGivesErrorNode(self):
1455        grammar = textwrap.dedent(
1456            r'''
1457            grammar foo;
1458            options {language=Python;output=AST;}
1459            a : ID INT -> ID INT ;
1460            ID : 'a'..'z'+ ;
1461            INT : '0'..'9'+;
1462            WS : (' '|'\n') {$channel=HIDDEN;} ;
1463            ''')
1464
1465        found, errors = self.execParser(grammar, "a", "34", expectErrors=True)
1466        self.assertEquals(["line 1:0 missing ID at u'34'"], errors)
1467        self.assertEquals("<missing ID> 34", found)
1468
1469
1470    #@testbase.broken("FIXME", AssertionError)
1471    def testMissingFirstTokenGivesErrorNode2(self):
1472        grammar = textwrap.dedent(
1473            r'''
1474            grammar foo;
1475            options {language=Python;output=AST;}
1476            a : b c -> b c;
1477            b : ID -> ID ;
1478            c : INT -> INT ;
1479            ID : 'a'..'z'+ ;
1480            INT : '0'..'9'+;
1481            WS : (' '|'\n') {$channel=HIDDEN;} ;
1482            ''')
1483
1484        found, errors = self.execParser(grammar, "a", "34", expectErrors=True)
1485        # finds an error at the first token, 34, and re-syncs.
1486        # re-synchronizing does not consume a token because 34 follows
1487        # ref to rule b (start of c). It then matches 34 in c.
1488        self.assertEquals(["line 1:0 missing ID at u'34'"], errors)
1489        self.assertEquals("<missing ID> 34", found)
1490
1491
1492    def testNoViableAltGivesErrorNode(self):
1493        grammar = textwrap.dedent(
1494            r'''
1495            grammar foo;
1496            options {language=Python;output=AST;}
1497            a : b -> b | c -> c;
1498            b : ID -> ID ;
1499            c : INT -> INT ;
1500            ID : 'a'..'z'+ ;
1501            S : '*' ;
1502            INT : '0'..'9'+;
1503            WS : (' '|'\n') {$channel=HIDDEN;} ;
1504            ''')
1505
1506        found, errors = self.execParser(grammar, "a", "*", expectErrors=True)
1507        # finds an error at the first token, 34, and re-syncs.
1508        # re-synchronizing does not consume a token because 34 follows
1509        # ref to rule b (start of c). It then matches 34 in c.
1510        self.assertEquals(["line 1:0 no viable alternative at input u'*'"],
1511                          errors);
1512        self.assertEquals("<unexpected: [@0,0:0=u'*',<6>,1:0], resync=*>",
1513                          found)
1514
1515
1516if __name__ == '__main__':
1517    unittest.main()
1518