xref: /aosp_15_r20/external/antlr/runtime/Python3/tests/t057autoAST.py (revision 16467b971bd3e2009fad32dd79016f2c7e421deb)
1*16467b97STreehugger Robotimport unittest
2*16467b97STreehugger Robotimport textwrap
3*16467b97STreehugger Robotimport antlr3
4*16467b97STreehugger Robotimport antlr3.tree
5*16467b97STreehugger Robotimport testbase
6*16467b97STreehugger Robotimport sys
7*16467b97STreehugger Robot
8*16467b97STreehugger Robotclass TestAutoAST(testbase.ANTLRTest):
9*16467b97STreehugger Robot    def parserClass(self, base):
10*16467b97STreehugger Robot        class TParser(base):
11*16467b97STreehugger Robot            def __init__(self, *args, **kwargs):
12*16467b97STreehugger Robot                super().__init__(*args, **kwargs)
13*16467b97STreehugger Robot
14*16467b97STreehugger Robot                self._errors = []
15*16467b97STreehugger Robot                self._output = ""
16*16467b97STreehugger Robot
17*16467b97STreehugger Robot
18*16467b97STreehugger Robot            def capture(self, t):
19*16467b97STreehugger Robot                self._output += t
20*16467b97STreehugger Robot
21*16467b97STreehugger Robot
22*16467b97STreehugger Robot            def traceIn(self, ruleName, ruleIndex):
23*16467b97STreehugger Robot                self.traces.append('>'+ruleName)
24*16467b97STreehugger Robot
25*16467b97STreehugger Robot
26*16467b97STreehugger Robot            def traceOut(self, ruleName, ruleIndex):
27*16467b97STreehugger Robot                self.traces.append('<'+ruleName)
28*16467b97STreehugger Robot
29*16467b97STreehugger Robot
30*16467b97STreehugger Robot            def emitErrorMessage(self, msg):
31*16467b97STreehugger Robot                self._errors.append(msg)
32*16467b97STreehugger Robot
33*16467b97STreehugger Robot
34*16467b97STreehugger Robot        return TParser
35*16467b97STreehugger Robot
36*16467b97STreehugger Robot
37*16467b97STreehugger Robot    def lexerClass(self, base):
38*16467b97STreehugger Robot        class TLexer(base):
39*16467b97STreehugger Robot            def __init__(self, *args, **kwargs):
40*16467b97STreehugger Robot                super().__init__(*args, **kwargs)
41*16467b97STreehugger Robot
42*16467b97STreehugger Robot                self._output = ""
43*16467b97STreehugger Robot
44*16467b97STreehugger Robot
45*16467b97STreehugger Robot            def capture(self, t):
46*16467b97STreehugger Robot                self._output += t
47*16467b97STreehugger Robot
48*16467b97STreehugger Robot
49*16467b97STreehugger Robot            def traceIn(self, ruleName, ruleIndex):
50*16467b97STreehugger Robot                self.traces.append('>'+ruleName)
51*16467b97STreehugger Robot
52*16467b97STreehugger Robot
53*16467b97STreehugger Robot            def traceOut(self, ruleName, ruleIndex):
54*16467b97STreehugger Robot                self.traces.append('<'+ruleName)
55*16467b97STreehugger Robot
56*16467b97STreehugger Robot
57*16467b97STreehugger Robot            def recover(self, input, re):
58*16467b97STreehugger Robot                # no error recovery yet, just crash!
59*16467b97STreehugger Robot                raise
60*16467b97STreehugger Robot
61*16467b97STreehugger Robot        return TLexer
62*16467b97STreehugger Robot
63*16467b97STreehugger Robot
64*16467b97STreehugger Robot    def execParser(self, grammar, grammarEntry, input, expectErrors=False):
65*16467b97STreehugger Robot        lexerCls, parserCls = self.compileInlineGrammar(grammar)
66*16467b97STreehugger Robot
67*16467b97STreehugger Robot        cStream = antlr3.StringStream(input)
68*16467b97STreehugger Robot        lexer = lexerCls(cStream)
69*16467b97STreehugger Robot        tStream = antlr3.CommonTokenStream(lexer)
70*16467b97STreehugger Robot        parser = parserCls(tStream)
71*16467b97STreehugger Robot        r = getattr(parser, grammarEntry)()
72*16467b97STreehugger Robot
73*16467b97STreehugger Robot        if not expectErrors:
74*16467b97STreehugger Robot            self.assertEqual(len(parser._errors), 0, parser._errors)
75*16467b97STreehugger Robot
76*16467b97STreehugger Robot        result = ""
77*16467b97STreehugger Robot
78*16467b97STreehugger Robot        if r:
79*16467b97STreehugger Robot            if hasattr(r, 'result'):
80*16467b97STreehugger Robot                result += r.result
81*16467b97STreehugger Robot
82*16467b97STreehugger Robot            if r.tree:
83*16467b97STreehugger Robot                result += r.tree.toStringTree()
84*16467b97STreehugger Robot
85*16467b97STreehugger Robot        if not expectErrors:
86*16467b97STreehugger Robot            return result
87*16467b97STreehugger Robot
88*16467b97STreehugger Robot        else:
89*16467b97STreehugger Robot            return result, parser._errors
90*16467b97STreehugger Robot
91*16467b97STreehugger Robot
92*16467b97STreehugger Robot    def execTreeParser(self, grammar, grammarEntry, treeGrammar, treeEntry, input):
93*16467b97STreehugger Robot        lexerCls, parserCls = self.compileInlineGrammar(grammar)
94*16467b97STreehugger Robot        walkerCls = self.compileInlineGrammar(treeGrammar)
95*16467b97STreehugger Robot
96*16467b97STreehugger Robot        cStream = antlr3.StringStream(input)
97*16467b97STreehugger Robot        lexer = lexerCls(cStream)
98*16467b97STreehugger Robot        tStream = antlr3.CommonTokenStream(lexer)
99*16467b97STreehugger Robot        parser = parserCls(tStream)
100*16467b97STreehugger Robot        r = getattr(parser, grammarEntry)()
101*16467b97STreehugger Robot        nodes = antlr3.tree.CommonTreeNodeStream(r.tree)
102*16467b97STreehugger Robot        nodes.setTokenStream(tStream)
103*16467b97STreehugger Robot        walker = walkerCls(nodes)
104*16467b97STreehugger Robot        r = getattr(walker, treeEntry)()
105*16467b97STreehugger Robot
106*16467b97STreehugger Robot        if r:
107*16467b97STreehugger Robot            return r.tree.toStringTree()
108*16467b97STreehugger Robot
109*16467b97STreehugger Robot        return ""
110*16467b97STreehugger Robot
111*16467b97STreehugger Robot
112*16467b97STreehugger Robot    def testTokenList(self):
113*16467b97STreehugger Robot        grammar = textwrap.dedent(
114*16467b97STreehugger Robot            r'''
115*16467b97STreehugger Robot            grammar foo;
116*16467b97STreehugger Robot            options {language=Python3;output=AST;}
117*16467b97STreehugger Robot            a : ID INT ;
118*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
119*16467b97STreehugger Robot            INT : '0'..'9'+;
120*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN};
121*16467b97STreehugger Robot            ''')
122*16467b97STreehugger Robot
123*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "abc 34")
124*16467b97STreehugger Robot        self.assertEqual("abc 34", found);
125*16467b97STreehugger Robot
126*16467b97STreehugger Robot
127*16467b97STreehugger Robot    def testTokenListInSingleAltBlock(self):
128*16467b97STreehugger Robot        grammar = textwrap.dedent(
129*16467b97STreehugger Robot            r'''
130*16467b97STreehugger Robot            grammar foo;
131*16467b97STreehugger Robot            options {language=Python3;output=AST;}
132*16467b97STreehugger Robot            a : (ID INT) ;
133*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
134*16467b97STreehugger Robot            INT : '0'..'9'+;
135*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
136*16467b97STreehugger Robot            ''')
137*16467b97STreehugger Robot
138*16467b97STreehugger Robot        found = self.execParser(grammar,"a", "abc 34")
139*16467b97STreehugger Robot        self.assertEqual("abc 34", found)
140*16467b97STreehugger Robot
141*16467b97STreehugger Robot
142*16467b97STreehugger Robot    def testSimpleRootAtOuterLevel(self):
143*16467b97STreehugger Robot        grammar = textwrap.dedent(
144*16467b97STreehugger Robot            r'''
145*16467b97STreehugger Robot            grammar foo;
146*16467b97STreehugger Robot            options {language=Python3;output=AST;}
147*16467b97STreehugger Robot            a : ID^ INT ;
148*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
149*16467b97STreehugger Robot            INT : '0'..'9'+;
150*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
151*16467b97STreehugger Robot            ''')
152*16467b97STreehugger Robot
153*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "abc 34")
154*16467b97STreehugger Robot        self.assertEqual("(abc 34)", found)
155*16467b97STreehugger Robot
156*16467b97STreehugger Robot
157*16467b97STreehugger Robot    def testSimpleRootAtOuterLevelReverse(self):
158*16467b97STreehugger Robot        grammar = textwrap.dedent(
159*16467b97STreehugger Robot            r'''
160*16467b97STreehugger Robot            grammar T;
161*16467b97STreehugger Robot            options {language=Python3;output=AST;}
162*16467b97STreehugger Robot            a : INT ID^ ;
163*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
164*16467b97STreehugger Robot            INT : '0'..'9'+;
165*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
166*16467b97STreehugger Robot            ''')
167*16467b97STreehugger Robot
168*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "34 abc")
169*16467b97STreehugger Robot        self.assertEqual("(abc 34)", found)
170*16467b97STreehugger Robot
171*16467b97STreehugger Robot
172*16467b97STreehugger Robot    def testBang(self):
173*16467b97STreehugger Robot        grammar = textwrap.dedent(
174*16467b97STreehugger Robot            r'''
175*16467b97STreehugger Robot            grammar T;
176*16467b97STreehugger Robot            options {language=Python3;output=AST;}
177*16467b97STreehugger Robot            a : ID INT! ID! INT ;
178*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
179*16467b97STreehugger Robot            INT : '0'..'9'+;
180*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
181*16467b97STreehugger Robot            ''')
182*16467b97STreehugger Robot
183*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "abc 34 dag 4532")
184*16467b97STreehugger Robot        self.assertEqual("abc 4532", found)
185*16467b97STreehugger Robot
186*16467b97STreehugger Robot
187*16467b97STreehugger Robot    def testOptionalThenRoot(self):
188*16467b97STreehugger Robot        grammar = textwrap.dedent(
189*16467b97STreehugger Robot            r'''
190*16467b97STreehugger Robot            grammar T;
191*16467b97STreehugger Robot            options {language=Python3;output=AST;}
192*16467b97STreehugger Robot            a : ( ID INT )? ID^ ;
193*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
194*16467b97STreehugger Robot            INT : '0'..'9'+;
195*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
196*16467b97STreehugger Robot            ''')
197*16467b97STreehugger Robot
198*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a 1 b")
199*16467b97STreehugger Robot        self.assertEqual("(b a 1)", found)
200*16467b97STreehugger Robot
201*16467b97STreehugger Robot
202*16467b97STreehugger Robot    def testLabeledStringRoot(self):
203*16467b97STreehugger Robot        grammar = textwrap.dedent(
204*16467b97STreehugger Robot            r'''
205*16467b97STreehugger Robot            grammar T;
206*16467b97STreehugger Robot            options {language=Python3;output=AST;}
207*16467b97STreehugger Robot            a : v='void'^ ID ';' ;
208*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
209*16467b97STreehugger Robot            INT : '0'..'9'+;
210*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
211*16467b97STreehugger Robot            ''')
212*16467b97STreehugger Robot
213*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "void foo;")
214*16467b97STreehugger Robot        self.assertEqual("(void foo ;)", found)
215*16467b97STreehugger Robot
216*16467b97STreehugger Robot
217*16467b97STreehugger Robot    def testWildcard(self):
218*16467b97STreehugger Robot        grammar = textwrap.dedent(
219*16467b97STreehugger Robot            r'''
220*16467b97STreehugger Robot            grammar T;
221*16467b97STreehugger Robot            options {language=Python3;output=AST;}
222*16467b97STreehugger Robot            a : v='void'^ . ';' ;
223*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
224*16467b97STreehugger Robot            INT : '0'..'9'+;
225*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
226*16467b97STreehugger Robot            ''')
227*16467b97STreehugger Robot
228*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "void foo;")
229*16467b97STreehugger Robot        self.assertEqual("(void foo ;)", found)
230*16467b97STreehugger Robot
231*16467b97STreehugger Robot
232*16467b97STreehugger Robot    def testWildcardRoot(self):
233*16467b97STreehugger Robot        grammar = textwrap.dedent(
234*16467b97STreehugger Robot            r'''
235*16467b97STreehugger Robot            grammar T;
236*16467b97STreehugger Robot            options {language=Python3;output=AST;}
237*16467b97STreehugger Robot            a : v='void' .^ ';' ;
238*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
239*16467b97STreehugger Robot            INT : '0'..'9'+;
240*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
241*16467b97STreehugger Robot            ''')
242*16467b97STreehugger Robot
243*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "void foo;")
244*16467b97STreehugger Robot        self.assertEqual("(foo void ;)", found)
245*16467b97STreehugger Robot
246*16467b97STreehugger Robot
247*16467b97STreehugger Robot    def testWildcardRootWithLabel(self):
248*16467b97STreehugger Robot        grammar = textwrap.dedent(
249*16467b97STreehugger Robot            r'''
250*16467b97STreehugger Robot            grammar T;
251*16467b97STreehugger Robot            options {language=Python3;output=AST;}
252*16467b97STreehugger Robot            a : v='void' x=.^ ';' ;
253*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
254*16467b97STreehugger Robot            INT : '0'..'9'+;
255*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
256*16467b97STreehugger Robot            ''')
257*16467b97STreehugger Robot
258*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "void foo;")
259*16467b97STreehugger Robot        self.assertEqual("(foo void ;)", found)
260*16467b97STreehugger Robot
261*16467b97STreehugger Robot
262*16467b97STreehugger Robot    def testWildcardRootWithListLabel(self):
263*16467b97STreehugger Robot        grammar = textwrap.dedent(
264*16467b97STreehugger Robot            r'''
265*16467b97STreehugger Robot            grammar T;
266*16467b97STreehugger Robot            options {language=Python3;output=AST;}
267*16467b97STreehugger Robot            a : v='void' x=.^ ';' ;
268*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
269*16467b97STreehugger Robot            INT : '0'..'9'+;
270*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
271*16467b97STreehugger Robot            ''')
272*16467b97STreehugger Robot
273*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "void foo;")
274*16467b97STreehugger Robot        self.assertEqual("(foo void ;)", found)
275*16467b97STreehugger Robot
276*16467b97STreehugger Robot
277*16467b97STreehugger Robot    def testWildcardBangWithListLabel(self):
278*16467b97STreehugger Robot        grammar = textwrap.dedent(
279*16467b97STreehugger Robot            r'''
280*16467b97STreehugger Robot            grammar T;
281*16467b97STreehugger Robot            options {language=Python3;output=AST;}
282*16467b97STreehugger Robot            a : v='void' x=.! ';' ;
283*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
284*16467b97STreehugger Robot            INT : '0'..'9'+;
285*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
286*16467b97STreehugger Robot            ''')
287*16467b97STreehugger Robot
288*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "void foo;")
289*16467b97STreehugger Robot        self.assertEqual("void ;", found)
290*16467b97STreehugger Robot
291*16467b97STreehugger Robot
292*16467b97STreehugger Robot    def testRootRoot(self):
293*16467b97STreehugger Robot        grammar = textwrap.dedent(
294*16467b97STreehugger Robot            r'''
295*16467b97STreehugger Robot            grammar T;
296*16467b97STreehugger Robot            options {language=Python3;output=AST;}
297*16467b97STreehugger Robot            a : ID^ INT^ ID ;
298*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
299*16467b97STreehugger Robot            INT : '0'..'9'+;
300*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
301*16467b97STreehugger Robot            ''')
302*16467b97STreehugger Robot
303*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a 34 c")
304*16467b97STreehugger Robot        self.assertEqual("(34 a c)", found)
305*16467b97STreehugger Robot
306*16467b97STreehugger Robot
307*16467b97STreehugger Robot    def testRootRoot2(self):
308*16467b97STreehugger Robot        grammar = textwrap.dedent(
309*16467b97STreehugger Robot            r'''
310*16467b97STreehugger Robot            grammar T;
311*16467b97STreehugger Robot            options {language=Python3;output=AST;}
312*16467b97STreehugger Robot            a : ID INT^ ID^ ;
313*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
314*16467b97STreehugger Robot            INT : '0'..'9'+;
315*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
316*16467b97STreehugger Robot            ''')
317*16467b97STreehugger Robot
318*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a 34 c")
319*16467b97STreehugger Robot        self.assertEqual("(c (34 a))", found)
320*16467b97STreehugger Robot
321*16467b97STreehugger Robot
322*16467b97STreehugger Robot    def testRootThenRootInLoop(self):
323*16467b97STreehugger Robot        grammar = textwrap.dedent(
324*16467b97STreehugger Robot            r'''
325*16467b97STreehugger Robot            grammar T;
326*16467b97STreehugger Robot            options {language=Python3;output=AST;}
327*16467b97STreehugger Robot            a : ID^ (INT '*'^ ID)+ ;
328*16467b97STreehugger Robot            ID  : 'a'..'z'+ ;
329*16467b97STreehugger Robot            INT : '0'..'9'+;
330*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
331*16467b97STreehugger Robot            ''')
332*16467b97STreehugger Robot
333*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a 34 * b 9 * c")
334*16467b97STreehugger Robot        self.assertEqual("(* (* (a 34) b 9) c)", found)
335*16467b97STreehugger Robot
336*16467b97STreehugger Robot
337*16467b97STreehugger Robot    def testNestedSubrule(self):
338*16467b97STreehugger Robot        grammar = textwrap.dedent(
339*16467b97STreehugger Robot            r'''
340*16467b97STreehugger Robot            grammar T;
341*16467b97STreehugger Robot            options {language=Python3;output=AST;}
342*16467b97STreehugger Robot            a : 'void' (({pass}ID|INT) ID | 'null' ) ';' ;
343*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
344*16467b97STreehugger Robot            INT : '0'..'9'+;
345*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
346*16467b97STreehugger Robot            ''')
347*16467b97STreehugger Robot
348*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "void a b;")
349*16467b97STreehugger Robot        self.assertEqual("void a b ;", found)
350*16467b97STreehugger Robot
351*16467b97STreehugger Robot
352*16467b97STreehugger Robot    def testInvokeRule(self):
353*16467b97STreehugger Robot        grammar = textwrap.dedent(
354*16467b97STreehugger Robot            r'''
355*16467b97STreehugger Robot            grammar T;
356*16467b97STreehugger Robot            options {language=Python3;output=AST;}
357*16467b97STreehugger Robot            a  : type ID ;
358*16467b97STreehugger Robot            type : {pass}'int' | 'float' ;
359*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
360*16467b97STreehugger Robot            INT : '0'..'9'+;
361*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
362*16467b97STreehugger Robot            ''')
363*16467b97STreehugger Robot
364*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "int a")
365*16467b97STreehugger Robot        self.assertEqual("int a", found)
366*16467b97STreehugger Robot
367*16467b97STreehugger Robot
368*16467b97STreehugger Robot    def testInvokeRuleAsRoot(self):
369*16467b97STreehugger Robot        grammar = textwrap.dedent(
370*16467b97STreehugger Robot            r'''
371*16467b97STreehugger Robot            grammar T;
372*16467b97STreehugger Robot            options {language=Python3;output=AST;}
373*16467b97STreehugger Robot            a  : type^ ID ;
374*16467b97STreehugger Robot            type : {pass}'int' | 'float' ;
375*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
376*16467b97STreehugger Robot            INT : '0'..'9'+;
377*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
378*16467b97STreehugger Robot            ''')
379*16467b97STreehugger Robot
380*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "int a")
381*16467b97STreehugger Robot        self.assertEqual("(int a)", found)
382*16467b97STreehugger Robot
383*16467b97STreehugger Robot
384*16467b97STreehugger Robot    def testInvokeRuleAsRootWithLabel(self):
385*16467b97STreehugger Robot        grammar = textwrap.dedent(
386*16467b97STreehugger Robot            r'''
387*16467b97STreehugger Robot            grammar T;
388*16467b97STreehugger Robot            options {language=Python3;output=AST;}
389*16467b97STreehugger Robot            a  : x=type^ ID ;
390*16467b97STreehugger Robot            type : {pass}'int' | 'float' ;
391*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
392*16467b97STreehugger Robot            INT : '0'..'9'+;
393*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
394*16467b97STreehugger Robot            ''')
395*16467b97STreehugger Robot
396*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "int a")
397*16467b97STreehugger Robot        self.assertEqual("(int a)", found)
398*16467b97STreehugger Robot
399*16467b97STreehugger Robot
400*16467b97STreehugger Robot    def testInvokeRuleAsRootWithListLabel(self):
401*16467b97STreehugger Robot        grammar = textwrap.dedent(
402*16467b97STreehugger Robot            r'''
403*16467b97STreehugger Robot            grammar T;
404*16467b97STreehugger Robot            options {language=Python3;output=AST;}
405*16467b97STreehugger Robot            a  : x+=type^ ID ;
406*16467b97STreehugger Robot            type : {pass}'int' | 'float' ;
407*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
408*16467b97STreehugger Robot            INT : '0'..'9'+;
409*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
410*16467b97STreehugger Robot            ''')
411*16467b97STreehugger Robot
412*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "int a")
413*16467b97STreehugger Robot        self.assertEqual("(int a)", found)
414*16467b97STreehugger Robot
415*16467b97STreehugger Robot
416*16467b97STreehugger Robot    def testRuleRootInLoop(self):
417*16467b97STreehugger Robot        grammar = textwrap.dedent(
418*16467b97STreehugger Robot            r'''
419*16467b97STreehugger Robot            grammar T;
420*16467b97STreehugger Robot            options {language=Python3;output=AST;}
421*16467b97STreehugger Robot            a : ID ('+'^ ID)* ;
422*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
423*16467b97STreehugger Robot            INT : '0'..'9'+;
424*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
425*16467b97STreehugger Robot            ''')
426*16467b97STreehugger Robot
427*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a+b+c+d")
428*16467b97STreehugger Robot        self.assertEqual("(+ (+ (+ a b) c) d)", found)
429*16467b97STreehugger Robot
430*16467b97STreehugger Robot
431*16467b97STreehugger Robot    def testRuleInvocationRuleRootInLoop(self):
432*16467b97STreehugger Robot        grammar = textwrap.dedent(
433*16467b97STreehugger Robot            r'''
434*16467b97STreehugger Robot            grammar T;
435*16467b97STreehugger Robot            options {language=Python3;output=AST;}
436*16467b97STreehugger Robot            a : ID (op^ ID)* ;
437*16467b97STreehugger Robot            op : {pass}'+' | '-' ;
438*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
439*16467b97STreehugger Robot            INT : '0'..'9'+;
440*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
441*16467b97STreehugger Robot            ''')
442*16467b97STreehugger Robot
443*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a+b+c-d")
444*16467b97STreehugger Robot        self.assertEqual("(- (+ (+ a b) c) d)", found)
445*16467b97STreehugger Robot
446*16467b97STreehugger Robot
447*16467b97STreehugger Robot    def testTailRecursion(self):
448*16467b97STreehugger Robot        grammar = textwrap.dedent(
449*16467b97STreehugger Robot            r'''
450*16467b97STreehugger Robot            grammar T;
451*16467b97STreehugger Robot            options {language=Python3;output=AST;}
452*16467b97STreehugger Robot            s : a ;
453*16467b97STreehugger Robot            a : atom ('exp'^ a)? ;
454*16467b97STreehugger Robot            atom : INT ;
455*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
456*16467b97STreehugger Robot            INT : '0'..'9'+;
457*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
458*16467b97STreehugger Robot            ''')
459*16467b97STreehugger Robot
460*16467b97STreehugger Robot        found = self.execParser(grammar, "s", "3 exp 4 exp 5")
461*16467b97STreehugger Robot        self.assertEqual("(exp 3 (exp 4 5))", found)
462*16467b97STreehugger Robot
463*16467b97STreehugger Robot
464*16467b97STreehugger Robot    def testSet(self):
465*16467b97STreehugger Robot        grammar = textwrap.dedent(
466*16467b97STreehugger Robot            r'''
467*16467b97STreehugger Robot            grammar T;
468*16467b97STreehugger Robot            options {language=Python3;output=AST;}
469*16467b97STreehugger Robot            a : ID|INT ;
470*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
471*16467b97STreehugger Robot            INT : '0'..'9'+;
472*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
473*16467b97STreehugger Robot            ''')
474*16467b97STreehugger Robot
475*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "abc")
476*16467b97STreehugger Robot        self.assertEqual("abc", found)
477*16467b97STreehugger Robot
478*16467b97STreehugger Robot
479*16467b97STreehugger Robot    def testSetRoot(self):
480*16467b97STreehugger Robot        grammar = textwrap.dedent(
481*16467b97STreehugger Robot        r'''
482*16467b97STreehugger Robot            grammar T;
483*16467b97STreehugger Robot            options {language=Python3;output=AST;}
484*16467b97STreehugger Robot            a : ('+' | '-')^ ID ;
485*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
486*16467b97STreehugger Robot            INT : '0'..'9'+;
487*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
488*16467b97STreehugger Robot            ''')
489*16467b97STreehugger Robot
490*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "+abc")
491*16467b97STreehugger Robot        self.assertEqual("(+ abc)", found)
492*16467b97STreehugger Robot
493*16467b97STreehugger Robot
494*16467b97STreehugger Robot    @testbase.broken(
495*16467b97STreehugger Robot        "FAILS until antlr.g rebuilt in v3", testbase.GrammarCompileError)
496*16467b97STreehugger Robot    def testSetRootWithLabel(self):
497*16467b97STreehugger Robot        grammar = textwrap.dedent(
498*16467b97STreehugger Robot            r'''
499*16467b97STreehugger Robot            grammar T;
500*16467b97STreehugger Robot            options {language=Python3;output=AST;}
501*16467b97STreehugger Robot            a : x=('+' | '-')^ ID ;
502*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
503*16467b97STreehugger Robot            INT : '0'..'9'+;
504*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
505*16467b97STreehugger Robot            ''')
506*16467b97STreehugger Robot
507*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "+abc")
508*16467b97STreehugger Robot        self.assertEqual("(+ abc)", found)
509*16467b97STreehugger Robot
510*16467b97STreehugger Robot
511*16467b97STreehugger Robot    def testSetAsRuleRootInLoop(self):
512*16467b97STreehugger Robot        grammar = textwrap.dedent(
513*16467b97STreehugger Robot            r'''
514*16467b97STreehugger Robot            grammar T;
515*16467b97STreehugger Robot            options {language=Python3;output=AST;}
516*16467b97STreehugger Robot            a : ID (('+'|'-')^ ID)* ;
517*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
518*16467b97STreehugger Robot            INT : '0'..'9'+;
519*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
520*16467b97STreehugger Robot            ''')
521*16467b97STreehugger Robot
522*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a+b-c")
523*16467b97STreehugger Robot        self.assertEqual("(- (+ a b) c)", found)
524*16467b97STreehugger Robot
525*16467b97STreehugger Robot
526*16467b97STreehugger Robot    def testNotSet(self):
527*16467b97STreehugger Robot        grammar = textwrap.dedent(
528*16467b97STreehugger Robot            r'''
529*16467b97STreehugger Robot            grammar T;
530*16467b97STreehugger Robot            options {language=Python3;output=AST;}
531*16467b97STreehugger Robot            a : ~ID '+' INT ;
532*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
533*16467b97STreehugger Robot            INT : '0'..'9'+;
534*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
535*16467b97STreehugger Robot            ''')
536*16467b97STreehugger Robot
537*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "34+2")
538*16467b97STreehugger Robot        self.assertEqual("34 + 2", found)
539*16467b97STreehugger Robot
540*16467b97STreehugger Robot
541*16467b97STreehugger Robot    def testNotSetWithLabel(self):
542*16467b97STreehugger Robot        grammar = textwrap.dedent(
543*16467b97STreehugger Robot            r'''
544*16467b97STreehugger Robot            grammar T;
545*16467b97STreehugger Robot            options {language=Python3;output=AST;}
546*16467b97STreehugger Robot            a : x=~ID '+' INT ;
547*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
548*16467b97STreehugger Robot            INT : '0'..'9'+;
549*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
550*16467b97STreehugger Robot            ''')
551*16467b97STreehugger Robot
552*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "34+2")
553*16467b97STreehugger Robot        self.assertEqual("34 + 2", found)
554*16467b97STreehugger Robot
555*16467b97STreehugger Robot
556*16467b97STreehugger Robot    def testNotSetWithListLabel(self):
557*16467b97STreehugger Robot        grammar = textwrap.dedent(
558*16467b97STreehugger Robot            r'''
559*16467b97STreehugger Robot            grammar T;
560*16467b97STreehugger Robot            options {language=Python3;output=AST;}
561*16467b97STreehugger Robot            a : x=~ID '+' INT ;
562*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
563*16467b97STreehugger Robot            INT : '0'..'9'+;
564*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
565*16467b97STreehugger Robot            ''')
566*16467b97STreehugger Robot
567*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "34+2")
568*16467b97STreehugger Robot        self.assertEqual("34 + 2", found)
569*16467b97STreehugger Robot
570*16467b97STreehugger Robot
571*16467b97STreehugger Robot    def testNotSetRoot(self):
572*16467b97STreehugger Robot        grammar = textwrap.dedent(
573*16467b97STreehugger Robot            r'''
574*16467b97STreehugger Robot            grammar T;
575*16467b97STreehugger Robot            options {language=Python3;output=AST;}
576*16467b97STreehugger Robot            a : ~'+'^ INT ;
577*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
578*16467b97STreehugger Robot            INT : '0'..'9'+;
579*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
580*16467b97STreehugger Robot            ''')
581*16467b97STreehugger Robot
582*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "34 55")
583*16467b97STreehugger Robot        self.assertEqual("(34 55)", found)
584*16467b97STreehugger Robot
585*16467b97STreehugger Robot
586*16467b97STreehugger Robot    def testNotSetRootWithLabel(self):
587*16467b97STreehugger Robot        grammar = textwrap.dedent(
588*16467b97STreehugger Robot            r'''
589*16467b97STreehugger Robot            grammar T;
590*16467b97STreehugger Robot            options {language=Python3;output=AST;}
591*16467b97STreehugger Robot            a : ~'+'^ INT ;
592*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
593*16467b97STreehugger Robot            INT : '0'..'9'+;
594*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
595*16467b97STreehugger Robot            ''')
596*16467b97STreehugger Robot
597*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "34 55")
598*16467b97STreehugger Robot        self.assertEqual("(34 55)", found)
599*16467b97STreehugger Robot
600*16467b97STreehugger Robot
601*16467b97STreehugger Robot    def testNotSetRootWithListLabel(self):
602*16467b97STreehugger Robot        grammar = textwrap.dedent(
603*16467b97STreehugger Robot            r'''
604*16467b97STreehugger Robot            grammar T;
605*16467b97STreehugger Robot            options {language=Python3;output=AST;}
606*16467b97STreehugger Robot            a : ~'+'^ INT ;
607*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
608*16467b97STreehugger Robot            INT : '0'..'9'+;
609*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
610*16467b97STreehugger Robot            ''')
611*16467b97STreehugger Robot
612*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "34 55")
613*16467b97STreehugger Robot        self.assertEqual("(34 55)", found)
614*16467b97STreehugger Robot
615*16467b97STreehugger Robot
616*16467b97STreehugger Robot    def testNotSetRuleRootInLoop(self):
617*16467b97STreehugger Robot        grammar = textwrap.dedent(
618*16467b97STreehugger Robot            r'''
619*16467b97STreehugger Robot            grammar T;
620*16467b97STreehugger Robot            options {language=Python3;output=AST;}
621*16467b97STreehugger Robot            a : INT (~INT^ INT)* ;
622*16467b97STreehugger Robot            blort : '+' ;
623*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
624*16467b97STreehugger Robot            INT : '0'..'9'+;
625*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
626*16467b97STreehugger Robot            ''')
627*16467b97STreehugger Robot
628*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "3+4+5")
629*16467b97STreehugger Robot        self.assertEqual("(+ (+ 3 4) 5)", found)
630*16467b97STreehugger Robot
631*16467b97STreehugger Robot
632*16467b97STreehugger Robot    @testbase.broken("FIXME: What happened to the semicolon?", AssertionError)
633*16467b97STreehugger Robot    def testTokenLabelReuse(self):
634*16467b97STreehugger Robot        # check for compilation problem due to multiple defines
635*16467b97STreehugger Robot        grammar = textwrap.dedent(
636*16467b97STreehugger Robot            r'''
637*16467b97STreehugger Robot            grammar T;
638*16467b97STreehugger Robot            options {language=Python3;output=AST;}
639*16467b97STreehugger Robot            a returns [result] : id=ID id=ID {$result = "2nd id="+$id.text+";"} ;
640*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
641*16467b97STreehugger Robot            INT : '0'..'9'+;
642*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
643*16467b97STreehugger Robot            ''')
644*16467b97STreehugger Robot
645*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a b")
646*16467b97STreehugger Robot        self.assertEqual("2nd id=b;a b", found)
647*16467b97STreehugger Robot
648*16467b97STreehugger Robot
649*16467b97STreehugger Robot    def testTokenLabelReuse2(self):
650*16467b97STreehugger Robot        # check for compilation problem due to multiple defines
651*16467b97STreehugger Robot        grammar = textwrap.dedent(
652*16467b97STreehugger Robot            r'''
653*16467b97STreehugger Robot            grammar T;
654*16467b97STreehugger Robot            options {language=Python3;output=AST;}
655*16467b97STreehugger Robot            a returns [result]: id=ID id=ID^ {$result = "2nd id="+$id.text+','} ;
656*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
657*16467b97STreehugger Robot            INT : '0'..'9'+;
658*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
659*16467b97STreehugger Robot            ''')
660*16467b97STreehugger Robot
661*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a b")
662*16467b97STreehugger Robot        self.assertEqual("2nd id=b,(b a)", found)
663*16467b97STreehugger Robot
664*16467b97STreehugger Robot
665*16467b97STreehugger Robot    def testTokenListLabelReuse(self):
666*16467b97STreehugger Robot        # check for compilation problem due to multiple defines
667*16467b97STreehugger Robot        # make sure ids has both ID tokens
668*16467b97STreehugger Robot        grammar = textwrap.dedent(
669*16467b97STreehugger Robot            r'''
670*16467b97STreehugger Robot            grammar T;
671*16467b97STreehugger Robot            options {language=Python3;output=AST;}
672*16467b97STreehugger Robot            a returns [result] : ids+=ID ids+=ID {$result = "id list=[{}],".format(",".join([t.text for t in $ids]))} ;
673*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
674*16467b97STreehugger Robot            INT : '0'..'9'+;
675*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
676*16467b97STreehugger Robot            ''')
677*16467b97STreehugger Robot
678*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a b")
679*16467b97STreehugger Robot        expecting = "id list=[a,b],a b"
680*16467b97STreehugger Robot        self.assertEqual(expecting, found)
681*16467b97STreehugger Robot
682*16467b97STreehugger Robot
683*16467b97STreehugger Robot    def testTokenListLabelReuse2(self):
684*16467b97STreehugger Robot        # check for compilation problem due to multiple defines
685*16467b97STreehugger Robot        # make sure ids has both ID tokens
686*16467b97STreehugger Robot        grammar = textwrap.dedent(
687*16467b97STreehugger Robot            r'''
688*16467b97STreehugger Robot            grammar T;
689*16467b97STreehugger Robot            options {language=Python3;output=AST;}
690*16467b97STreehugger Robot            a returns [result] : ids+=ID^ ids+=ID {$result = "id list=[{}],".format(",".join([t.text for t in $ids]))} ;
691*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
692*16467b97STreehugger Robot            INT : '0'..'9'+;
693*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
694*16467b97STreehugger Robot            ''')
695*16467b97STreehugger Robot
696*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a b")
697*16467b97STreehugger Robot        expecting = "id list=[a,b],(a b)"
698*16467b97STreehugger Robot        self.assertEqual(expecting, found)
699*16467b97STreehugger Robot
700*16467b97STreehugger Robot
701*16467b97STreehugger Robot    def testTokenListLabelRuleRoot(self):
702*16467b97STreehugger Robot        grammar = textwrap.dedent(
703*16467b97STreehugger Robot            r'''
704*16467b97STreehugger Robot            grammar T;
705*16467b97STreehugger Robot            options {language=Python3;output=AST;}
706*16467b97STreehugger Robot            a : id+=ID^ ;
707*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
708*16467b97STreehugger Robot            INT : '0'..'9'+;
709*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
710*16467b97STreehugger Robot            ''')
711*16467b97STreehugger Robot
712*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a")
713*16467b97STreehugger Robot        self.assertEqual("a", found)
714*16467b97STreehugger Robot
715*16467b97STreehugger Robot
716*16467b97STreehugger Robot    def testTokenListLabelBang(self):
717*16467b97STreehugger Robot        grammar = textwrap.dedent(
718*16467b97STreehugger Robot            r'''
719*16467b97STreehugger Robot            grammar T;
720*16467b97STreehugger Robot            options {language=Python3;output=AST;}
721*16467b97STreehugger Robot            a : id+=ID! ;
722*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
723*16467b97STreehugger Robot            INT : '0'..'9'+;
724*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
725*16467b97STreehugger Robot            ''')
726*16467b97STreehugger Robot
727*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a")
728*16467b97STreehugger Robot        self.assertEqual("", found)
729*16467b97STreehugger Robot
730*16467b97STreehugger Robot
731*16467b97STreehugger Robot    def testRuleListLabel(self):
732*16467b97STreehugger Robot        grammar = textwrap.dedent(
733*16467b97STreehugger Robot            r'''
734*16467b97STreehugger Robot            grammar T;
735*16467b97STreehugger Robot            options {language=Python3;output=AST;}
736*16467b97STreehugger Robot            a returns [result]: x+=b x+=b {
737*16467b97STreehugger Robot            t=$x[1]
738*16467b97STreehugger Robot            $result = "2nd x="+t.toStringTree()+',';
739*16467b97STreehugger Robot            };
740*16467b97STreehugger Robot            b : ID;
741*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
742*16467b97STreehugger Robot            INT : '0'..'9'+;
743*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
744*16467b97STreehugger Robot            ''')
745*16467b97STreehugger Robot
746*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a b")
747*16467b97STreehugger Robot        self.assertEqual("2nd x=b,a b", found)
748*16467b97STreehugger Robot
749*16467b97STreehugger Robot
750*16467b97STreehugger Robot    def testRuleListLabelRuleRoot(self):
751*16467b97STreehugger Robot        grammar = textwrap.dedent(
752*16467b97STreehugger Robot            r'''
753*16467b97STreehugger Robot            grammar T;
754*16467b97STreehugger Robot            options {language=Python3;output=AST;}
755*16467b97STreehugger Robot            a returns [result] : ( x+=b^ )+ {
756*16467b97STreehugger Robot            $result = "x="+$x[1].toStringTree()+',';
757*16467b97STreehugger Robot            } ;
758*16467b97STreehugger Robot            b : ID;
759*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
760*16467b97STreehugger Robot            INT : '0'..'9'+;
761*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
762*16467b97STreehugger Robot            ''')
763*16467b97STreehugger Robot
764*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a b")
765*16467b97STreehugger Robot        self.assertEqual("x=(b a),(b a)", found)
766*16467b97STreehugger Robot
767*16467b97STreehugger Robot
768*16467b97STreehugger Robot    def testRuleListLabelBang(self):
769*16467b97STreehugger Robot        grammar = textwrap.dedent(
770*16467b97STreehugger Robot            r'''
771*16467b97STreehugger Robot            grammar T;
772*16467b97STreehugger Robot            options {language=Python3;output=AST;}
773*16467b97STreehugger Robot            a returns [result] : x+=b! x+=b {
774*16467b97STreehugger Robot            $result = "1st x="+$x[0].toStringTree()+',';
775*16467b97STreehugger Robot            } ;
776*16467b97STreehugger Robot            b : ID;
777*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
778*16467b97STreehugger Robot            INT : '0'..'9'+;
779*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
780*16467b97STreehugger Robot            ''')
781*16467b97STreehugger Robot
782*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a b")
783*16467b97STreehugger Robot        self.assertEqual("1st x=a,b", found)
784*16467b97STreehugger Robot
785*16467b97STreehugger Robot
786*16467b97STreehugger Robot    def testComplicatedMelange(self):
787*16467b97STreehugger Robot        # check for compilation problem
788*16467b97STreehugger Robot        grammar = textwrap.dedent(
789*16467b97STreehugger Robot            r'''
790*16467b97STreehugger Robot            grammar T;
791*16467b97STreehugger Robot            options {language=Python3;output=AST;}
792*16467b97STreehugger Robot            a : A b=B b=B c+=C c+=C D {s = $D.text} ;
793*16467b97STreehugger Robot            A : 'a' ;
794*16467b97STreehugger Robot            B : 'b' ;
795*16467b97STreehugger Robot            C : 'c' ;
796*16467b97STreehugger Robot            D : 'd' ;
797*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
798*16467b97STreehugger Robot            ''')
799*16467b97STreehugger Robot
800*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "a b b c c d")
801*16467b97STreehugger Robot        self.assertEqual("a b b c c d", found)
802*16467b97STreehugger Robot
803*16467b97STreehugger Robot
804*16467b97STreehugger Robot    def testReturnValueWithAST(self):
805*16467b97STreehugger Robot        grammar = textwrap.dedent(
806*16467b97STreehugger Robot            r'''
807*16467b97STreehugger Robot            grammar foo;
808*16467b97STreehugger Robot            options {language=Python3;output=AST;}
809*16467b97STreehugger Robot            a returns [result] : ID b { $result = str($b.i) + '\n';} ;
810*16467b97STreehugger Robot            b returns [i] : INT {$i=int($INT.text);} ;
811*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
812*16467b97STreehugger Robot            INT : '0'..'9'+;
813*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
814*16467b97STreehugger Robot            ''')
815*16467b97STreehugger Robot
816*16467b97STreehugger Robot        found = self.execParser(grammar, "a", "abc 34")
817*16467b97STreehugger Robot        self.assertEqual("34\nabc 34", found)
818*16467b97STreehugger Robot
819*16467b97STreehugger Robot
820*16467b97STreehugger Robot    def testSetLoop(self):
821*16467b97STreehugger Robot        grammar = textwrap.dedent(
822*16467b97STreehugger Robot            r'''
823*16467b97STreehugger Robot            grammar T;
824*16467b97STreehugger Robot            options { language=Python3;output=AST; }
825*16467b97STreehugger Robot            r : (INT|ID)+ ;
826*16467b97STreehugger Robot            ID : 'a'..'z' + ;
827*16467b97STreehugger Robot            INT : '0'..'9' +;
828*16467b97STreehugger Robot            WS: (' ' | '\n' | '\\t')+ {$channel = HIDDEN};
829*16467b97STreehugger Robot            ''')
830*16467b97STreehugger Robot
831*16467b97STreehugger Robot        found = self.execParser(grammar, "r", "abc 34 d")
832*16467b97STreehugger Robot        self.assertEqual("abc 34 d", found)
833*16467b97STreehugger Robot
834*16467b97STreehugger Robot
835*16467b97STreehugger Robot    def testExtraTokenInSimpleDecl(self):
836*16467b97STreehugger Robot        grammar = textwrap.dedent(
837*16467b97STreehugger Robot            r'''
838*16467b97STreehugger Robot            grammar foo;
839*16467b97STreehugger Robot            options {language=Python3;output=AST;}
840*16467b97STreehugger Robot            decl : type^ ID '='! INT ';'! ;
841*16467b97STreehugger Robot            type : 'int' | 'float' ;
842*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
843*16467b97STreehugger Robot            INT : '0'..'9'+;
844*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
845*16467b97STreehugger Robot            ''')
846*16467b97STreehugger Robot
847*16467b97STreehugger Robot        found, errors = self.execParser(grammar, "decl", "int 34 x=1;",
848*16467b97STreehugger Robot                                        expectErrors=True)
849*16467b97STreehugger Robot        self.assertEqual(["line 1:4 extraneous input '34' expecting ID"],
850*16467b97STreehugger Robot                         errors)
851*16467b97STreehugger Robot        self.assertEqual("(int x 1)", found) # tree gets correct x and 1 tokens
852*16467b97STreehugger Robot
853*16467b97STreehugger Robot
854*16467b97STreehugger Robot    def testMissingIDInSimpleDecl(self):
855*16467b97STreehugger Robot        grammar = textwrap.dedent(
856*16467b97STreehugger Robot            r'''
857*16467b97STreehugger Robot            grammar foo;
858*16467b97STreehugger Robot            options {language=Python3;output=AST;}
859*16467b97STreehugger Robot            tokens {EXPR;}
860*16467b97STreehugger Robot            decl : type^ ID '='! INT ';'! ;
861*16467b97STreehugger Robot            type : 'int' | 'float' ;
862*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
863*16467b97STreehugger Robot            INT : '0'..'9'+;
864*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
865*16467b97STreehugger Robot            ''')
866*16467b97STreehugger Robot
867*16467b97STreehugger Robot        found, errors = self.execParser(grammar, "decl", "int =1;",
868*16467b97STreehugger Robot                                        expectErrors=True)
869*16467b97STreehugger Robot        self.assertEqual(["line 1:4 missing ID at '='"], errors)
870*16467b97STreehugger Robot        self.assertEqual("(int <missing ID> 1)", found) # tree gets invented ID token
871*16467b97STreehugger Robot
872*16467b97STreehugger Robot
873*16467b97STreehugger Robot    def testMissingSetInSimpleDecl(self):
874*16467b97STreehugger Robot        grammar = textwrap.dedent(
875*16467b97STreehugger Robot            r'''
876*16467b97STreehugger Robot            grammar foo;
877*16467b97STreehugger Robot            options {language=Python3;output=AST;}
878*16467b97STreehugger Robot            tokens {EXPR;}
879*16467b97STreehugger Robot            decl : type^ ID '='! INT ';'! ;
880*16467b97STreehugger Robot            type : 'int' | 'float' ;
881*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
882*16467b97STreehugger Robot            INT : '0'..'9'+;
883*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
884*16467b97STreehugger Robot            ''')
885*16467b97STreehugger Robot
886*16467b97STreehugger Robot        found, errors = self.execParser(grammar, "decl", "x=1;",
887*16467b97STreehugger Robot                                        expectErrors=True)
888*16467b97STreehugger Robot        self.assertEqual(["line 1:0 mismatched input 'x' expecting set None"], errors)
889*16467b97STreehugger Robot        self.assertEqual("(<error: x> x 1)", found) # tree gets invented ID token
890*16467b97STreehugger Robot
891*16467b97STreehugger Robot
892*16467b97STreehugger Robot    def testMissingTokenGivesErrorNode(self):
893*16467b97STreehugger Robot        grammar = textwrap.dedent(
894*16467b97STreehugger Robot            r'''
895*16467b97STreehugger Robot            grammar foo;
896*16467b97STreehugger Robot            options {language=Python3;output=AST;}
897*16467b97STreehugger Robot            a : ID INT ; // follow is EOF
898*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
899*16467b97STreehugger Robot            INT : '0'..'9'+;
900*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
901*16467b97STreehugger Robot            ''')
902*16467b97STreehugger Robot
903*16467b97STreehugger Robot        found, errors = self.execParser(grammar, "a", "abc", expectErrors=True)
904*16467b97STreehugger Robot        self.assertEqual(["line 1:3 missing INT at '<EOF>'"], errors)
905*16467b97STreehugger Robot        self.assertEqual("abc <missing INT>", found)
906*16467b97STreehugger Robot
907*16467b97STreehugger Robot
908*16467b97STreehugger Robot    def testMissingTokenGivesErrorNodeInInvokedRule(self):
909*16467b97STreehugger Robot        grammar = textwrap.dedent(
910*16467b97STreehugger Robot            r'''
911*16467b97STreehugger Robot            grammar foo;
912*16467b97STreehugger Robot            options {language=Python3;output=AST;}
913*16467b97STreehugger Robot            a : b ;
914*16467b97STreehugger Robot            b : ID INT ; // follow should see EOF
915*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
916*16467b97STreehugger Robot            INT : '0'..'9'+;
917*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
918*16467b97STreehugger Robot            ''')
919*16467b97STreehugger Robot
920*16467b97STreehugger Robot        found, errors = self.execParser(grammar, "a", "abc", expectErrors=True)
921*16467b97STreehugger Robot        self.assertEqual(["line 1:3 mismatched input '<EOF>' expecting INT"], errors)
922*16467b97STreehugger Robot        self.assertEqual("<mismatched token: <EOF>, resync=abc>", found)
923*16467b97STreehugger Robot
924*16467b97STreehugger Robot
925*16467b97STreehugger Robot    def testExtraTokenGivesErrorNode(self):
926*16467b97STreehugger Robot        grammar = textwrap.dedent(
927*16467b97STreehugger Robot            r'''
928*16467b97STreehugger Robot            grammar foo;
929*16467b97STreehugger Robot            options {language=Python3;output=AST;}
930*16467b97STreehugger Robot            a : b c ;
931*16467b97STreehugger Robot            b : ID ;
932*16467b97STreehugger Robot            c : INT ;
933*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
934*16467b97STreehugger Robot            INT : '0'..'9'+;
935*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
936*16467b97STreehugger Robot            ''')
937*16467b97STreehugger Robot
938*16467b97STreehugger Robot        found, errors = self.execParser(grammar, "a", "abc ick 34",
939*16467b97STreehugger Robot                                        expectErrors=True)
940*16467b97STreehugger Robot        self.assertEqual(["line 1:4 extraneous input 'ick' expecting INT"],
941*16467b97STreehugger Robot                          errors)
942*16467b97STreehugger Robot        self.assertEqual("abc 34", found)
943*16467b97STreehugger Robot
944*16467b97STreehugger Robot
945*16467b97STreehugger Robot    def testMissingFirstTokenGivesErrorNode(self):
946*16467b97STreehugger Robot        grammar = textwrap.dedent(
947*16467b97STreehugger Robot            r'''
948*16467b97STreehugger Robot            grammar foo;
949*16467b97STreehugger Robot            options {language=Python3;output=AST;}
950*16467b97STreehugger Robot            a : ID INT ;
951*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
952*16467b97STreehugger Robot            INT : '0'..'9'+;
953*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
954*16467b97STreehugger Robot            ''')
955*16467b97STreehugger Robot
956*16467b97STreehugger Robot        found, errors = self.execParser(grammar, "a", "34", expectErrors=True)
957*16467b97STreehugger Robot        self.assertEqual(["line 1:0 missing ID at '34'"], errors)
958*16467b97STreehugger Robot        self.assertEqual("<missing ID> 34", found)
959*16467b97STreehugger Robot
960*16467b97STreehugger Robot
961*16467b97STreehugger Robot    def testMissingFirstTokenGivesErrorNode2(self):
962*16467b97STreehugger Robot        grammar = textwrap.dedent(
963*16467b97STreehugger Robot            r'''
964*16467b97STreehugger Robot            grammar foo;
965*16467b97STreehugger Robot            options {language=Python3;output=AST;}
966*16467b97STreehugger Robot            a : b c ;
967*16467b97STreehugger Robot            b : ID ;
968*16467b97STreehugger Robot            c : INT ;
969*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
970*16467b97STreehugger Robot            INT : '0'..'9'+;
971*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
972*16467b97STreehugger Robot            ''')
973*16467b97STreehugger Robot
974*16467b97STreehugger Robot        found, errors = self.execParser(grammar, "a", "34", expectErrors=True)
975*16467b97STreehugger Robot
976*16467b97STreehugger Robot        # finds an error at the first token, 34, and re-syncs.
977*16467b97STreehugger Robot        # re-synchronizing does not consume a token because 34 follows
978*16467b97STreehugger Robot        # ref to rule b (start of c). It then matches 34 in c.
979*16467b97STreehugger Robot        self.assertEqual(["line 1:0 missing ID at '34'"], errors)
980*16467b97STreehugger Robot        self.assertEqual("<missing ID> 34", found)
981*16467b97STreehugger Robot
982*16467b97STreehugger Robot
983*16467b97STreehugger Robot    def testNoViableAltGivesErrorNode(self):
984*16467b97STreehugger Robot        grammar = textwrap.dedent(
985*16467b97STreehugger Robot            r'''
986*16467b97STreehugger Robot            grammar foo;
987*16467b97STreehugger Robot            options {language=Python3;output=AST;}
988*16467b97STreehugger Robot            a : b | c ;
989*16467b97STreehugger Robot            b : ID ;
990*16467b97STreehugger Robot            c : INT ;
991*16467b97STreehugger Robot            ID : 'a'..'z'+ ;
992*16467b97STreehugger Robot            S : '*' ;
993*16467b97STreehugger Robot            INT : '0'..'9'+;
994*16467b97STreehugger Robot            WS : (' '|'\n') {$channel=HIDDEN} ;
995*16467b97STreehugger Robot            ''')
996*16467b97STreehugger Robot
997*16467b97STreehugger Robot        found, errors = self.execParser(grammar, "a", "*", expectErrors=True)
998*16467b97STreehugger Robot        self.assertEqual(["line 1:0 no viable alternative at input '*'"],
999*16467b97STreehugger Robot                         errors)
1000*16467b97STreehugger Robot        self.assertEqual("<unexpected: [@0,0:0='*',<S>,1:0], resync=*>",
1001*16467b97STreehugger Robot                         found)
1002*16467b97STreehugger Robot
1003*16467b97STreehugger Robot
1004*16467b97STreehugger Robotif __name__ == '__main__':
1005*16467b97STreehugger Robot    unittest.main()
1006