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