xref: /aosp_15_r20/external/antlr/runtime/Python3/tests/t059debug.py (revision 16467b971bd3e2009fad32dd79016f2c7e421deb)
1*16467b97STreehugger Robotimport unittest
2*16467b97STreehugger Robotimport textwrap
3*16467b97STreehugger Robotimport antlr3
4*16467b97STreehugger Robotimport antlr3.tree
5*16467b97STreehugger Robotimport antlr3.debug
6*16467b97STreehugger Robotimport testbase
7*16467b97STreehugger Robotimport sys
8*16467b97STreehugger Robotimport threading
9*16467b97STreehugger Robotimport socket
10*16467b97STreehugger Robotimport errno
11*16467b97STreehugger Robotimport time
12*16467b97STreehugger Robot
13*16467b97STreehugger Robotclass Debugger(threading.Thread):
14*16467b97STreehugger Robot    def __init__(self, port):
15*16467b97STreehugger Robot        super().__init__()
16*16467b97STreehugger Robot        self.events = []
17*16467b97STreehugger Robot        self.success = False
18*16467b97STreehugger Robot        self.port = port
19*16467b97STreehugger Robot
20*16467b97STreehugger Robot    def run(self):
21*16467b97STreehugger Robot        # create listening socket
22*16467b97STreehugger Robot        s = None
23*16467b97STreehugger Robot        tstart = time.time()
24*16467b97STreehugger Robot        while time.time() - tstart < 10:
25*16467b97STreehugger Robot            try:
26*16467b97STreehugger Robot                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
27*16467b97STreehugger Robot                s.connect(('127.0.0.1', self.port))
28*16467b97STreehugger Robot                break
29*16467b97STreehugger Robot            except socket.error as exc:
30*16467b97STreehugger Robot                if s:
31*16467b97STreehugger Robot                    s.close()
32*16467b97STreehugger Robot                if exc.args[0] != errno.ECONNREFUSED:
33*16467b97STreehugger Robot                    raise
34*16467b97STreehugger Robot                time.sleep(0.1)
35*16467b97STreehugger Robot
36*16467b97STreehugger Robot        if s is None:
37*16467b97STreehugger Robot            self.events.append(['nosocket'])
38*16467b97STreehugger Robot            return
39*16467b97STreehugger Robot
40*16467b97STreehugger Robot        s.setblocking(1)
41*16467b97STreehugger Robot        s.settimeout(10.0)
42*16467b97STreehugger Robot
43*16467b97STreehugger Robot        output = s.makefile('w', 1)
44*16467b97STreehugger Robot        input = s.makefile('r', 1)
45*16467b97STreehugger Robot
46*16467b97STreehugger Robot        try:
47*16467b97STreehugger Robot            # handshake
48*16467b97STreehugger Robot            l = input.readline().strip()
49*16467b97STreehugger Robot            assert l == 'ANTLR 2'
50*16467b97STreehugger Robot            l = input.readline().strip()
51*16467b97STreehugger Robot            assert l.startswith('grammar "'), l
52*16467b97STreehugger Robot
53*16467b97STreehugger Robot            output.write('ACK\n')
54*16467b97STreehugger Robot            output.flush()
55*16467b97STreehugger Robot
56*16467b97STreehugger Robot            while True:
57*16467b97STreehugger Robot                event = input.readline().strip()
58*16467b97STreehugger Robot                self.events.append(event.split('\t'))
59*16467b97STreehugger Robot
60*16467b97STreehugger Robot                output.write('ACK\n')
61*16467b97STreehugger Robot                output.flush()
62*16467b97STreehugger Robot
63*16467b97STreehugger Robot                if event == 'terminate':
64*16467b97STreehugger Robot                    self.success = True
65*16467b97STreehugger Robot                    break
66*16467b97STreehugger Robot
67*16467b97STreehugger Robot        except socket.timeout:
68*16467b97STreehugger Robot            self.events.append(['timeout'])
69*16467b97STreehugger Robot        except socket.error as exc:
70*16467b97STreehugger Robot            self.events.append(['socketerror', exc.args])
71*16467b97STreehugger Robot        finally:
72*16467b97STreehugger Robot            output.close()
73*16467b97STreehugger Robot            input.close()
74*16467b97STreehugger Robot            s.close()
75*16467b97STreehugger Robot
76*16467b97STreehugger Robot
77*16467b97STreehugger Robotclass T(testbase.ANTLRTest):
78*16467b97STreehugger Robot    def execParser(self, grammar, grammarEntry, input, listener,
79*16467b97STreehugger Robot                   parser_args={}):
80*16467b97STreehugger Robot        if listener is None:
81*16467b97STreehugger Robot            port = 49100
82*16467b97STreehugger Robot            debugger = Debugger(port)
83*16467b97STreehugger Robot            debugger.start()
84*16467b97STreehugger Robot            # TODO(pink): install alarm, so it doesn't hang forever in case of a bug
85*16467b97STreehugger Robot
86*16467b97STreehugger Robot        else:
87*16467b97STreehugger Robot            port = None
88*16467b97STreehugger Robot
89*16467b97STreehugger Robot        try:
90*16467b97STreehugger Robot            lexerCls, parserCls = self.compileInlineGrammar(
91*16467b97STreehugger Robot                grammar, options='-debug')
92*16467b97STreehugger Robot
93*16467b97STreehugger Robot            cStream = antlr3.StringStream(input)
94*16467b97STreehugger Robot            lexer = lexerCls(cStream)
95*16467b97STreehugger Robot            tStream = antlr3.CommonTokenStream(lexer)
96*16467b97STreehugger Robot            parser = parserCls(tStream, dbg=listener, port=port, **parser_args)
97*16467b97STreehugger Robot            getattr(parser, grammarEntry)()
98*16467b97STreehugger Robot
99*16467b97STreehugger Robot        finally:
100*16467b97STreehugger Robot            if listener is None:
101*16467b97STreehugger Robot                debugger.join()
102*16467b97STreehugger Robot                return debugger
103*16467b97STreehugger Robot
104*16467b97STreehugger Robot    def testBasicParser(self):
105*16467b97STreehugger Robot        grammar = textwrap.dedent(
106*16467b97STreehugger Robot        r'''
107*16467b97STreehugger Robot        grammar T;
108*16467b97STreehugger Robot        options {
109*16467b97STreehugger Robot            language=Python3;
110*16467b97STreehugger Robot        }
111*16467b97STreehugger Robot        a : ID EOF;
112*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
113*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
114*16467b97STreehugger Robot        ''')
115*16467b97STreehugger Robot
116*16467b97STreehugger Robot        listener = antlr3.debug.RecordDebugEventListener()
117*16467b97STreehugger Robot
118*16467b97STreehugger Robot        self.execParser(
119*16467b97STreehugger Robot            grammar, 'a',
120*16467b97STreehugger Robot            input="a",
121*16467b97STreehugger Robot            listener=listener)
122*16467b97STreehugger Robot
123*16467b97STreehugger Robot        # We only check that some LT events are present. How many is subject
124*16467b97STreehugger Robot        # to change (at the time of writing there are two, which is one too
125*16467b97STreehugger Robot        # many).
126*16467b97STreehugger Robot        lt_events = [event for event in listener.events
127*16467b97STreehugger Robot                     if event.startswith("LT ")]
128*16467b97STreehugger Robot        self.assertNotEqual(lt_events, [])
129*16467b97STreehugger Robot
130*16467b97STreehugger Robot        # For the rest, filter out LT events to get a reliable test.
131*16467b97STreehugger Robot        expected = ["enterRule a",
132*16467b97STreehugger Robot                    "location 6:1",
133*16467b97STreehugger Robot                    "location 6:5",
134*16467b97STreehugger Robot                    "location 6:8",
135*16467b97STreehugger Robot                    "location 6:11",
136*16467b97STreehugger Robot                    "exitRule a"]
137*16467b97STreehugger Robot        found = [event for event in listener.events
138*16467b97STreehugger Robot                 if not event.startswith("LT ")]
139*16467b97STreehugger Robot        self.assertListEqual(found, expected)
140*16467b97STreehugger Robot
141*16467b97STreehugger Robot    def testSocketProxy(self):
142*16467b97STreehugger Robot        grammar = textwrap.dedent(
143*16467b97STreehugger Robot        r'''
144*16467b97STreehugger Robot        grammar T;
145*16467b97STreehugger Robot        options {
146*16467b97STreehugger Robot            language=Python3;
147*16467b97STreehugger Robot        }
148*16467b97STreehugger Robot        a : ID EOF;
149*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
150*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
151*16467b97STreehugger Robot        ''')
152*16467b97STreehugger Robot
153*16467b97STreehugger Robot        debugger = self.execParser(
154*16467b97STreehugger Robot            grammar, 'a',
155*16467b97STreehugger Robot            input="a",
156*16467b97STreehugger Robot            listener=None)
157*16467b97STreehugger Robot
158*16467b97STreehugger Robot        self.assertTrue(debugger.success)
159*16467b97STreehugger Robot        expected = [['enterRule', 'T.g', 'a'],
160*16467b97STreehugger Robot                    ['location', '6', '1'],
161*16467b97STreehugger Robot                    ['enterAlt', '1'],
162*16467b97STreehugger Robot                    ['location', '6', '5'],
163*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
164*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
165*16467b97STreehugger Robot                    ['consumeToken', '0', '4', '0', '1', '0', '"a'],
166*16467b97STreehugger Robot                    ['location', '6', '8'],
167*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '1', '"<EOF>'],
168*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '1', '"<EOF>'],
169*16467b97STreehugger Robot                    ['consumeToken', '-1', '-1', '0', '1', '1', '"<EOF>'],
170*16467b97STreehugger Robot                    ['location', '6', '11'],
171*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'a'],
172*16467b97STreehugger Robot                    ['terminate']]
173*16467b97STreehugger Robot
174*16467b97STreehugger Robot        self.assertListEqual(debugger.events, expected)
175*16467b97STreehugger Robot
176*16467b97STreehugger Robot    def testRecognitionException(self):
177*16467b97STreehugger Robot        grammar = textwrap.dedent(
178*16467b97STreehugger Robot        r'''
179*16467b97STreehugger Robot        grammar T;
180*16467b97STreehugger Robot        options {
181*16467b97STreehugger Robot            language=Python3;
182*16467b97STreehugger Robot        }
183*16467b97STreehugger Robot        a : ID EOF;
184*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
185*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
186*16467b97STreehugger Robot        ''')
187*16467b97STreehugger Robot
188*16467b97STreehugger Robot        debugger = self.execParser(
189*16467b97STreehugger Robot            grammar, 'a',
190*16467b97STreehugger Robot            input="a b",
191*16467b97STreehugger Robot            listener=None)
192*16467b97STreehugger Robot
193*16467b97STreehugger Robot        self.assertTrue(debugger.success)
194*16467b97STreehugger Robot        expected = [['enterRule', 'T.g', 'a'],
195*16467b97STreehugger Robot                    ['location', '6', '1'],
196*16467b97STreehugger Robot                    ['enterAlt', '1'],
197*16467b97STreehugger Robot                    ['location', '6', '5'],
198*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
199*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
200*16467b97STreehugger Robot                    ['consumeToken', '0', '4', '0', '1', '0', '"a'],
201*16467b97STreehugger Robot                    ['consumeHiddenToken', '1', '5', '99', '1', '1', '"'],
202*16467b97STreehugger Robot                    ['location', '6', '8'],
203*16467b97STreehugger Robot                    ['LT', '1', '2', '4', '0', '1', '2', '"b'],
204*16467b97STreehugger Robot                    ['LT', '1', '2', '4', '0', '1', '2', '"b'],
205*16467b97STreehugger Robot                    ['LT', '2', '-1', '-1', '0', '1', '3', '"<EOF>'],
206*16467b97STreehugger Robot                    ['LT', '1', '2', '4', '0', '1', '2', '"b'],
207*16467b97STreehugger Robot                    ['LT', '1', '2', '4', '0', '1', '2', '"b'],
208*16467b97STreehugger Robot                    ['beginResync'],
209*16467b97STreehugger Robot                    ['consumeToken', '2', '4', '0', '1', '2', '"b'],
210*16467b97STreehugger Robot                    ['endResync'],
211*16467b97STreehugger Robot                    ['exception', 'UnwantedTokenException', '2', '1', '2'],
212*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '3', '"<EOF>'],
213*16467b97STreehugger Robot                    ['consumeToken', '-1', '-1', '0', '1', '3', '"<EOF>'],
214*16467b97STreehugger Robot                    ['location', '6', '11'],
215*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'a'],
216*16467b97STreehugger Robot                    ['terminate']]
217*16467b97STreehugger Robot
218*16467b97STreehugger Robot        self.assertListEqual(debugger.events, expected)
219*16467b97STreehugger Robot
220*16467b97STreehugger Robot
221*16467b97STreehugger Robot    def testSemPred(self):
222*16467b97STreehugger Robot        grammar = textwrap.dedent(
223*16467b97STreehugger Robot        r'''
224*16467b97STreehugger Robot        grammar T;
225*16467b97STreehugger Robot        options {
226*16467b97STreehugger Robot            language=Python3;
227*16467b97STreehugger Robot        }
228*16467b97STreehugger Robot        a : {True}? ID EOF;
229*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
230*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
231*16467b97STreehugger Robot        ''')
232*16467b97STreehugger Robot
233*16467b97STreehugger Robot        debugger = self.execParser(
234*16467b97STreehugger Robot            grammar, 'a',
235*16467b97STreehugger Robot            input="a",
236*16467b97STreehugger Robot            listener=None)
237*16467b97STreehugger Robot
238*16467b97STreehugger Robot        self.assertTrue(debugger.success)
239*16467b97STreehugger Robot        expected = [['enterRule', 'T.g', 'a'],
240*16467b97STreehugger Robot                    ['location', '6', '1'],
241*16467b97STreehugger Robot                    ['enterAlt', '1'],
242*16467b97STreehugger Robot                    ['location', '6', '5'],
243*16467b97STreehugger Robot                    ['semanticPredicate', '1', 'True'],
244*16467b97STreehugger Robot                    ['location', '6', '13'],
245*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
246*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
247*16467b97STreehugger Robot                    ['consumeToken', '0', '4', '0', '1', '0', '"a'],
248*16467b97STreehugger Robot                    ['location', '6', '16'],
249*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '1', '"<EOF>'],
250*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '1', '"<EOF>'],
251*16467b97STreehugger Robot                    ['consumeToken', '-1', '-1', '0', '1', '1', '"<EOF>'],
252*16467b97STreehugger Robot                    ['location', '6', '19'],
253*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'a'],
254*16467b97STreehugger Robot                    ['terminate']]
255*16467b97STreehugger Robot
256*16467b97STreehugger Robot        self.assertListEqual(debugger.events, expected)
257*16467b97STreehugger Robot
258*16467b97STreehugger Robot
259*16467b97STreehugger Robot    def testPositiveClosureBlock(self):
260*16467b97STreehugger Robot        grammar = textwrap.dedent(
261*16467b97STreehugger Robot        r'''
262*16467b97STreehugger Robot        grammar T;
263*16467b97STreehugger Robot        options {
264*16467b97STreehugger Robot            language=Python3;
265*16467b97STreehugger Robot        }
266*16467b97STreehugger Robot        a : ID ( ID | INT )+ EOF;
267*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
268*16467b97STreehugger Robot        INT : '0'..'9'+ ;
269*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
270*16467b97STreehugger Robot        ''')
271*16467b97STreehugger Robot
272*16467b97STreehugger Robot        debugger = self.execParser(
273*16467b97STreehugger Robot            grammar, 'a',
274*16467b97STreehugger Robot            input="a 1 b c 3",
275*16467b97STreehugger Robot            listener=None)
276*16467b97STreehugger Robot
277*16467b97STreehugger Robot        self.assertTrue(debugger.success)
278*16467b97STreehugger Robot        expected = [['enterRule', 'T.g', 'a'],
279*16467b97STreehugger Robot                    ['location', '6', '1'],
280*16467b97STreehugger Robot                    ['enterAlt', '1'],
281*16467b97STreehugger Robot                    ['location', '6', '5'],
282*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
283*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
284*16467b97STreehugger Robot                    ['consumeToken', '0', '4', '0', '1', '0', '"a'],
285*16467b97STreehugger Robot                    ['consumeHiddenToken', '1', '6', '99', '1', '1', '"'],
286*16467b97STreehugger Robot                    ['location', '6', '8'],
287*16467b97STreehugger Robot                    ['enterSubRule', '1'],
288*16467b97STreehugger Robot                    ['enterDecision', '1', '0'],
289*16467b97STreehugger Robot                    ['LT', '1', '2', '5', '0', '1', '2', '"1'],
290*16467b97STreehugger Robot                    ['exitDecision', '1'],
291*16467b97STreehugger Robot                    ['enterAlt', '1'],
292*16467b97STreehugger Robot                    ['location', '6', '8'],
293*16467b97STreehugger Robot                    ['LT', '1', '2', '5', '0', '1', '2', '"1'],
294*16467b97STreehugger Robot                    ['consumeToken', '2', '5', '0', '1', '2', '"1'],
295*16467b97STreehugger Robot                    ['consumeHiddenToken', '3', '6', '99', '1', '3', '"'],
296*16467b97STreehugger Robot                    ['enterDecision', '1', '0'],
297*16467b97STreehugger Robot                    ['LT', '1', '4', '4', '0', '1', '4', '"b'],
298*16467b97STreehugger Robot                    ['exitDecision', '1'],
299*16467b97STreehugger Robot                    ['enterAlt', '1'],
300*16467b97STreehugger Robot                    ['location', '6', '8'],
301*16467b97STreehugger Robot                    ['LT', '1', '4', '4', '0', '1', '4', '"b'],
302*16467b97STreehugger Robot                    ['consumeToken', '4', '4', '0', '1', '4', '"b'],
303*16467b97STreehugger Robot                    ['consumeHiddenToken', '5', '6', '99', '1', '5', '"'],
304*16467b97STreehugger Robot                    ['enterDecision', '1', '0'],
305*16467b97STreehugger Robot                    ['LT', '1', '6', '4', '0', '1', '6', '"c'],
306*16467b97STreehugger Robot                    ['exitDecision', '1'],
307*16467b97STreehugger Robot                    ['enterAlt', '1'],
308*16467b97STreehugger Robot                    ['location', '6', '8'],
309*16467b97STreehugger Robot                    ['LT', '1', '6', '4', '0', '1', '6', '"c'],
310*16467b97STreehugger Robot                    ['consumeToken', '6', '4', '0', '1', '6', '"c'],
311*16467b97STreehugger Robot                    ['consumeHiddenToken', '7', '6', '99', '1', '7', '"'],
312*16467b97STreehugger Robot                    ['enterDecision', '1', '0'],
313*16467b97STreehugger Robot                    ['LT', '1', '8', '5', '0', '1', '8', '"3'],
314*16467b97STreehugger Robot                    ['exitDecision', '1'],
315*16467b97STreehugger Robot                    ['enterAlt', '1'],
316*16467b97STreehugger Robot                    ['location', '6', '8'],
317*16467b97STreehugger Robot                    ['LT', '1', '8', '5', '0', '1', '8', '"3'],
318*16467b97STreehugger Robot                    ['consumeToken', '8', '5', '0', '1', '8', '"3'],
319*16467b97STreehugger Robot                    ['enterDecision', '1', '0'],
320*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '9', '"<EOF>'],
321*16467b97STreehugger Robot                    ['exitDecision', '1'],
322*16467b97STreehugger Robot                    ['exitSubRule', '1'],
323*16467b97STreehugger Robot                    ['location', '6', '22'],
324*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '9', '"<EOF>'],
325*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '9', '"<EOF>'],
326*16467b97STreehugger Robot                    ['consumeToken', '-1', '-1', '0', '1', '9', '"<EOF>'],
327*16467b97STreehugger Robot                    ['location', '6', '25'],
328*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'a'],
329*16467b97STreehugger Robot                    ['terminate']]
330*16467b97STreehugger Robot
331*16467b97STreehugger Robot        self.assertListEqual(debugger.events, expected)
332*16467b97STreehugger Robot
333*16467b97STreehugger Robot
334*16467b97STreehugger Robot    def testClosureBlock(self):
335*16467b97STreehugger Robot        grammar = textwrap.dedent(
336*16467b97STreehugger Robot        r'''
337*16467b97STreehugger Robot        grammar T;
338*16467b97STreehugger Robot        options {
339*16467b97STreehugger Robot            language=Python3;
340*16467b97STreehugger Robot        }
341*16467b97STreehugger Robot        a : ID ( ID | INT )* EOF;
342*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
343*16467b97STreehugger Robot        INT : '0'..'9'+ ;
344*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
345*16467b97STreehugger Robot        ''')
346*16467b97STreehugger Robot
347*16467b97STreehugger Robot        debugger = self.execParser(
348*16467b97STreehugger Robot            grammar, 'a',
349*16467b97STreehugger Robot            input="a 1 b c 3",
350*16467b97STreehugger Robot            listener=None)
351*16467b97STreehugger Robot
352*16467b97STreehugger Robot        self.assertTrue(debugger.success)
353*16467b97STreehugger Robot        expected = [['enterRule', 'T.g', 'a'],
354*16467b97STreehugger Robot                    ['location', '6', '1'],
355*16467b97STreehugger Robot                    ['enterAlt', '1'],
356*16467b97STreehugger Robot                    ['location', '6', '5'],
357*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
358*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
359*16467b97STreehugger Robot                    ['consumeToken', '0', '4', '0', '1', '0', '"a'],
360*16467b97STreehugger Robot                    ['consumeHiddenToken', '1', '6', '99', '1', '1', '"'],
361*16467b97STreehugger Robot                    ['location', '6', '8'],
362*16467b97STreehugger Robot                    ['enterSubRule', '1'],
363*16467b97STreehugger Robot                    ['enterDecision', '1', '0'],
364*16467b97STreehugger Robot                    ['LT', '1', '2', '5', '0', '1', '2', '"1'],
365*16467b97STreehugger Robot                    ['exitDecision', '1'],
366*16467b97STreehugger Robot                    ['enterAlt', '1'],
367*16467b97STreehugger Robot                    ['location', '6', '8'],
368*16467b97STreehugger Robot                    ['LT', '1', '2', '5', '0', '1', '2', '"1'],
369*16467b97STreehugger Robot                    ['consumeToken', '2', '5', '0', '1', '2', '"1'],
370*16467b97STreehugger Robot                    ['consumeHiddenToken', '3', '6', '99', '1', '3', '"'],
371*16467b97STreehugger Robot                    ['enterDecision', '1', '0'],
372*16467b97STreehugger Robot                    ['LT', '1', '4', '4', '0', '1', '4', '"b'],
373*16467b97STreehugger Robot                    ['exitDecision', '1'],
374*16467b97STreehugger Robot                    ['enterAlt', '1'],
375*16467b97STreehugger Robot                    ['location', '6', '8'],
376*16467b97STreehugger Robot                    ['LT', '1', '4', '4', '0', '1', '4', '"b'],
377*16467b97STreehugger Robot                    ['consumeToken', '4', '4', '0', '1', '4', '"b'],
378*16467b97STreehugger Robot                    ['consumeHiddenToken', '5', '6', '99', '1', '5', '"'],
379*16467b97STreehugger Robot                    ['enterDecision', '1', '0'],
380*16467b97STreehugger Robot                    ['LT', '1', '6', '4', '0', '1', '6', '"c'],
381*16467b97STreehugger Robot                    ['exitDecision', '1'],
382*16467b97STreehugger Robot                    ['enterAlt', '1'],
383*16467b97STreehugger Robot                    ['location', '6', '8'],
384*16467b97STreehugger Robot                    ['LT', '1', '6', '4', '0', '1', '6', '"c'],
385*16467b97STreehugger Robot                    ['consumeToken', '6', '4', '0', '1', '6', '"c'],
386*16467b97STreehugger Robot                    ['consumeHiddenToken', '7', '6', '99', '1', '7', '"'],
387*16467b97STreehugger Robot                    ['enterDecision', '1', '0'],
388*16467b97STreehugger Robot                    ['LT', '1', '8', '5', '0', '1', '8', '"3'],
389*16467b97STreehugger Robot                    ['exitDecision', '1'],
390*16467b97STreehugger Robot                    ['enterAlt', '1'],
391*16467b97STreehugger Robot                    ['location', '6', '8'],
392*16467b97STreehugger Robot                    ['LT', '1', '8', '5', '0', '1', '8', '"3'],
393*16467b97STreehugger Robot                    ['consumeToken', '8', '5', '0', '1', '8', '"3'],
394*16467b97STreehugger Robot                    ['enterDecision', '1', '0'],
395*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '9', '"<EOF>'],
396*16467b97STreehugger Robot                    ['exitDecision', '1'],
397*16467b97STreehugger Robot                    ['exitSubRule', '1'],
398*16467b97STreehugger Robot                    ['location', '6', '22'],
399*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '9', '"<EOF>'],
400*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '9', '"<EOF>'],
401*16467b97STreehugger Robot                    ['consumeToken', '-1', '-1', '0', '1', '9', '"<EOF>'],
402*16467b97STreehugger Robot                    ['location', '6', '25'],
403*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'a'],
404*16467b97STreehugger Robot                    ['terminate']]
405*16467b97STreehugger Robot
406*16467b97STreehugger Robot        self.assertListEqual(debugger.events, expected)
407*16467b97STreehugger Robot
408*16467b97STreehugger Robot
409*16467b97STreehugger Robot    def testMismatchedSetException(self):
410*16467b97STreehugger Robot        grammar = textwrap.dedent(
411*16467b97STreehugger Robot        r'''
412*16467b97STreehugger Robot        grammar T;
413*16467b97STreehugger Robot        options {
414*16467b97STreehugger Robot            language=Python3;
415*16467b97STreehugger Robot        }
416*16467b97STreehugger Robot        a : ID ( ID | INT ) EOF;
417*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
418*16467b97STreehugger Robot        INT : '0'..'9'+ ;
419*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
420*16467b97STreehugger Robot        ''')
421*16467b97STreehugger Robot
422*16467b97STreehugger Robot        debugger = self.execParser(
423*16467b97STreehugger Robot            grammar, 'a',
424*16467b97STreehugger Robot            input="a",
425*16467b97STreehugger Robot            listener=None)
426*16467b97STreehugger Robot
427*16467b97STreehugger Robot        self.assertTrue(debugger.success)
428*16467b97STreehugger Robot        expected = [['enterRule', 'T.g', 'a'],
429*16467b97STreehugger Robot                    ['location', '6', '1'],
430*16467b97STreehugger Robot                    ['enterAlt', '1'],
431*16467b97STreehugger Robot                    ['location', '6', '5'],
432*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
433*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
434*16467b97STreehugger Robot                    ['consumeToken', '0', '4', '0', '1', '0', '"a'],
435*16467b97STreehugger Robot                    ['location', '6', '8'],
436*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '1', '"<EOF>'],
437*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '1', '"<EOF>'],
438*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '1', '"<EOF>'],
439*16467b97STreehugger Robot                    ['exception', 'MismatchedSetException', '1', '1', '1'],
440*16467b97STreehugger Robot                    ['exception', 'MismatchedSetException', '1', '1', '1'],
441*16467b97STreehugger Robot                    ['beginResync'],
442*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '1', '"<EOF>'],
443*16467b97STreehugger Robot                    ['endResync'],
444*16467b97STreehugger Robot                    ['location', '6', '24'],
445*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'a'],
446*16467b97STreehugger Robot                    ['terminate']]
447*16467b97STreehugger Robot
448*16467b97STreehugger Robot        self.assertListEqual(debugger.events, expected)
449*16467b97STreehugger Robot
450*16467b97STreehugger Robot
451*16467b97STreehugger Robot    def testBlock(self):
452*16467b97STreehugger Robot        grammar = textwrap.dedent(
453*16467b97STreehugger Robot        r'''
454*16467b97STreehugger Robot        grammar T;
455*16467b97STreehugger Robot        options {
456*16467b97STreehugger Robot            language=Python3;
457*16467b97STreehugger Robot        }
458*16467b97STreehugger Robot        a : ID ( b | c ) EOF;
459*16467b97STreehugger Robot        b : ID;
460*16467b97STreehugger Robot        c : INT;
461*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
462*16467b97STreehugger Robot        INT : '0'..'9'+ ;
463*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
464*16467b97STreehugger Robot        ''')
465*16467b97STreehugger Robot
466*16467b97STreehugger Robot        debugger = self.execParser(
467*16467b97STreehugger Robot            grammar, 'a',
468*16467b97STreehugger Robot            input="a 1",
469*16467b97STreehugger Robot            listener=None)
470*16467b97STreehugger Robot
471*16467b97STreehugger Robot        self.assertTrue(debugger.success)
472*16467b97STreehugger Robot        expected =  [['enterRule', 'T.g', 'a'],
473*16467b97STreehugger Robot                     ['location', '6', '1'],
474*16467b97STreehugger Robot                     ['enterAlt', '1'],
475*16467b97STreehugger Robot                     ['location', '6', '5'],
476*16467b97STreehugger Robot                     ['LT', '1', '0', '4', '0', '1', '0', '"a'],
477*16467b97STreehugger Robot                     ['LT', '1', '0', '4', '0', '1', '0', '"a'],
478*16467b97STreehugger Robot                     ['consumeToken', '0', '4', '0', '1', '0', '"a'],
479*16467b97STreehugger Robot                     ['consumeHiddenToken', '1', '6', '99', '1', '1', '"'],
480*16467b97STreehugger Robot                     ['location', '6', '8'],
481*16467b97STreehugger Robot                     ['enterSubRule', '1'],
482*16467b97STreehugger Robot                     ['enterDecision', '1', '0'],
483*16467b97STreehugger Robot                     ['LT', '1', '2', '5', '0', '1', '2', '"1'],
484*16467b97STreehugger Robot                     ['exitDecision', '1'],
485*16467b97STreehugger Robot                     ['enterAlt', '2'],
486*16467b97STreehugger Robot                     ['location', '6', '14'],
487*16467b97STreehugger Robot                     ['enterRule', 'T.g', 'c'],
488*16467b97STreehugger Robot                     ['location', '8', '1'],
489*16467b97STreehugger Robot                     ['enterAlt', '1'],
490*16467b97STreehugger Robot                     ['location', '8', '5'],
491*16467b97STreehugger Robot                     ['LT', '1', '2', '5', '0', '1', '2', '"1'],
492*16467b97STreehugger Robot                     ['LT', '1', '2', '5', '0', '1', '2', '"1'],
493*16467b97STreehugger Robot                     ['consumeToken', '2', '5', '0', '1', '2', '"1'],
494*16467b97STreehugger Robot                     ['location', '8', '8'],
495*16467b97STreehugger Robot                     ['exitRule', 'T.g', 'c'],
496*16467b97STreehugger Robot                     ['exitSubRule', '1'],
497*16467b97STreehugger Robot                     ['location', '6', '18'],
498*16467b97STreehugger Robot                     ['LT', '1', '-1', '-1', '0', '1', '3', '"<EOF>'],
499*16467b97STreehugger Robot                     ['LT', '1', '-1', '-1', '0', '1', '3', '"<EOF>'],
500*16467b97STreehugger Robot                     ['consumeToken', '-1', '-1', '0', '1', '3', '"<EOF>'],
501*16467b97STreehugger Robot                     ['location', '6', '21'],
502*16467b97STreehugger Robot                     ['exitRule', 'T.g', 'a'],
503*16467b97STreehugger Robot                     ['terminate']]
504*16467b97STreehugger Robot
505*16467b97STreehugger Robot        self.assertListEqual(debugger.events, expected)
506*16467b97STreehugger Robot
507*16467b97STreehugger Robot
508*16467b97STreehugger Robot    def testNoViableAlt(self):
509*16467b97STreehugger Robot        grammar = textwrap.dedent(
510*16467b97STreehugger Robot        r'''
511*16467b97STreehugger Robot        grammar T;
512*16467b97STreehugger Robot        options {
513*16467b97STreehugger Robot            language=Python3;
514*16467b97STreehugger Robot        }
515*16467b97STreehugger Robot        a : ID ( b | c ) EOF;
516*16467b97STreehugger Robot        b : ID;
517*16467b97STreehugger Robot        c : INT;
518*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
519*16467b97STreehugger Robot        INT : '0'..'9'+ ;
520*16467b97STreehugger Robot        BANG : '!' ;
521*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
522*16467b97STreehugger Robot        ''')
523*16467b97STreehugger Robot
524*16467b97STreehugger Robot        debugger = self.execParser(
525*16467b97STreehugger Robot            grammar, 'a',
526*16467b97STreehugger Robot            input="a !",
527*16467b97STreehugger Robot            listener=None)
528*16467b97STreehugger Robot
529*16467b97STreehugger Robot        self.assertTrue(debugger.success)
530*16467b97STreehugger Robot        expected =  [['enterRule', 'T.g', 'a'],
531*16467b97STreehugger Robot                     ['location', '6', '1'],
532*16467b97STreehugger Robot                     ['enterAlt', '1'],
533*16467b97STreehugger Robot                     ['location', '6', '5'],
534*16467b97STreehugger Robot                     ['LT', '1', '0', '5', '0', '1', '0', '"a'],
535*16467b97STreehugger Robot                     ['LT', '1', '0', '5', '0', '1', '0', '"a'],
536*16467b97STreehugger Robot                     ['consumeToken', '0', '5', '0', '1', '0', '"a'],
537*16467b97STreehugger Robot                     ['consumeHiddenToken', '1', '7', '99', '1', '1', '"'],
538*16467b97STreehugger Robot                     ['location', '6', '8'],
539*16467b97STreehugger Robot                     ['enterSubRule', '1'],
540*16467b97STreehugger Robot                     ['enterDecision', '1', '0'],
541*16467b97STreehugger Robot                     ['LT', '1', '2', '4', '0', '1', '2', '"!'],
542*16467b97STreehugger Robot                     ['LT', '1', '2', '4', '0', '1', '2', '"!'],
543*16467b97STreehugger Robot                     ['LT', '1', '2', '4', '0', '1', '2', '"!'],
544*16467b97STreehugger Robot                     ['exception', 'NoViableAltException', '2', '1', '2'],
545*16467b97STreehugger Robot                     ['exitDecision', '1'],
546*16467b97STreehugger Robot                     ['exitSubRule', '1'],
547*16467b97STreehugger Robot                     ['exception', 'NoViableAltException', '2', '1', '2'],
548*16467b97STreehugger Robot                     ['beginResync'],
549*16467b97STreehugger Robot                     ['LT', '1', '2', '4', '0', '1', '2', '"!'],
550*16467b97STreehugger Robot                     ['consumeToken', '2', '4', '0', '1', '2', '"!'],
551*16467b97STreehugger Robot                     ['LT', '1', '-1', '-1', '0', '1', '3', '"<EOF>'],
552*16467b97STreehugger Robot                     ['endResync'],
553*16467b97STreehugger Robot                     ['location', '6', '21'],
554*16467b97STreehugger Robot                     ['exitRule', 'T.g', 'a'],
555*16467b97STreehugger Robot                     ['terminate']]
556*16467b97STreehugger Robot
557*16467b97STreehugger Robot        self.assertListEqual(debugger.events, expected)
558*16467b97STreehugger Robot
559*16467b97STreehugger Robot
560*16467b97STreehugger Robot    def testRuleBlock(self):
561*16467b97STreehugger Robot        grammar = textwrap.dedent(
562*16467b97STreehugger Robot        r'''
563*16467b97STreehugger Robot        grammar T;
564*16467b97STreehugger Robot        options {
565*16467b97STreehugger Robot            language=Python3;
566*16467b97STreehugger Robot        }
567*16467b97STreehugger Robot        a : b | c;
568*16467b97STreehugger Robot        b : ID;
569*16467b97STreehugger Robot        c : INT;
570*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
571*16467b97STreehugger Robot        INT : '0'..'9'+ ;
572*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
573*16467b97STreehugger Robot        ''')
574*16467b97STreehugger Robot
575*16467b97STreehugger Robot        debugger = self.execParser(
576*16467b97STreehugger Robot            grammar, 'a',
577*16467b97STreehugger Robot            input="1",
578*16467b97STreehugger Robot            listener=None)
579*16467b97STreehugger Robot
580*16467b97STreehugger Robot        self.assertTrue(debugger.success)
581*16467b97STreehugger Robot        expected = [['enterRule', 'T.g', 'a'],
582*16467b97STreehugger Robot                    ['location', '6', '1'],
583*16467b97STreehugger Robot                    ['enterDecision', '1', '0'],
584*16467b97STreehugger Robot                    ['LT', '1', '0', '5', '0', '1', '0', '"1'],
585*16467b97STreehugger Robot                    ['exitDecision', '1'],
586*16467b97STreehugger Robot                    ['enterAlt', '2'],
587*16467b97STreehugger Robot                    ['location', '6', '9'],
588*16467b97STreehugger Robot                    ['enterRule', 'T.g', 'c'],
589*16467b97STreehugger Robot                    ['location', '8', '1'],
590*16467b97STreehugger Robot                    ['enterAlt', '1'],
591*16467b97STreehugger Robot                    ['location', '8', '5'],
592*16467b97STreehugger Robot                    ['LT', '1', '0', '5', '0', '1', '0', '"1'],
593*16467b97STreehugger Robot                    ['LT', '1', '0', '5', '0', '1', '0', '"1'],
594*16467b97STreehugger Robot                    ['consumeToken', '0', '5', '0', '1', '0', '"1'],
595*16467b97STreehugger Robot                    ['location', '8', '8'],
596*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'c'],
597*16467b97STreehugger Robot                    ['location', '6', '10'],
598*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'a'],
599*16467b97STreehugger Robot                    ['terminate']]
600*16467b97STreehugger Robot
601*16467b97STreehugger Robot        self.assertListEqual(debugger.events, expected)
602*16467b97STreehugger Robot
603*16467b97STreehugger Robot
604*16467b97STreehugger Robot    def testRuleBlockSingleAlt(self):
605*16467b97STreehugger Robot        grammar = textwrap.dedent(
606*16467b97STreehugger Robot        r'''
607*16467b97STreehugger Robot        grammar T;
608*16467b97STreehugger Robot        options {
609*16467b97STreehugger Robot            language=Python3;
610*16467b97STreehugger Robot        }
611*16467b97STreehugger Robot        a : b;
612*16467b97STreehugger Robot        b : ID;
613*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
614*16467b97STreehugger Robot        INT : '0'..'9'+ ;
615*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
616*16467b97STreehugger Robot        ''')
617*16467b97STreehugger Robot
618*16467b97STreehugger Robot        debugger = self.execParser(
619*16467b97STreehugger Robot            grammar, 'a',
620*16467b97STreehugger Robot            input="a",
621*16467b97STreehugger Robot            listener=None)
622*16467b97STreehugger Robot
623*16467b97STreehugger Robot        self.assertTrue(debugger.success)
624*16467b97STreehugger Robot        expected = [['enterRule', 'T.g', 'a'],
625*16467b97STreehugger Robot                    ['location', '6', '1'],
626*16467b97STreehugger Robot                    ['enterAlt', '1'],
627*16467b97STreehugger Robot                    ['location', '6', '5'],
628*16467b97STreehugger Robot                    ['enterRule', 'T.g', 'b'],
629*16467b97STreehugger Robot                    ['location', '7', '1'],
630*16467b97STreehugger Robot                    ['enterAlt', '1'],
631*16467b97STreehugger Robot                    ['location', '7', '5'],
632*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
633*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
634*16467b97STreehugger Robot                    ['consumeToken', '0', '4', '0', '1', '0', '"a'],
635*16467b97STreehugger Robot                    ['location', '7', '7'],
636*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'b'],
637*16467b97STreehugger Robot                    ['location', '6', '6'],
638*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'a'],
639*16467b97STreehugger Robot                    ['terminate']]
640*16467b97STreehugger Robot
641*16467b97STreehugger Robot        self.assertListEqual(debugger.events, expected)
642*16467b97STreehugger Robot
643*16467b97STreehugger Robot
644*16467b97STreehugger Robot    def testBlockSingleAlt(self):
645*16467b97STreehugger Robot        grammar = textwrap.dedent(
646*16467b97STreehugger Robot        r'''
647*16467b97STreehugger Robot        grammar T;
648*16467b97STreehugger Robot        options {
649*16467b97STreehugger Robot            language=Python3;
650*16467b97STreehugger Robot        }
651*16467b97STreehugger Robot        a : ( b );
652*16467b97STreehugger Robot        b : ID;
653*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
654*16467b97STreehugger Robot        INT : '0'..'9'+ ;
655*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
656*16467b97STreehugger Robot        ''')
657*16467b97STreehugger Robot
658*16467b97STreehugger Robot        debugger = self.execParser(
659*16467b97STreehugger Robot            grammar, 'a',
660*16467b97STreehugger Robot            input="a",
661*16467b97STreehugger Robot            listener=None)
662*16467b97STreehugger Robot
663*16467b97STreehugger Robot        self.assertTrue(debugger.success)
664*16467b97STreehugger Robot        expected = [['enterRule', 'T.g', 'a'],
665*16467b97STreehugger Robot                    ['location', '6', '1'],
666*16467b97STreehugger Robot                    ['enterAlt', '1'],
667*16467b97STreehugger Robot                    ['location', '6', '5'],
668*16467b97STreehugger Robot                    ['enterAlt', '1'],
669*16467b97STreehugger Robot                    ['location', '6', '7'],
670*16467b97STreehugger Robot                    ['enterRule', 'T.g', 'b'],
671*16467b97STreehugger Robot                    ['location', '7', '1'],
672*16467b97STreehugger Robot                    ['enterAlt', '1'],
673*16467b97STreehugger Robot                    ['location', '7', '5'],
674*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
675*16467b97STreehugger Robot                    ['LT', '1', '0', '4', '0', '1', '0', '"a'],
676*16467b97STreehugger Robot                    ['consumeToken', '0', '4', '0', '1', '0', '"a'],
677*16467b97STreehugger Robot                    ['location', '7', '7'],
678*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'b'],
679*16467b97STreehugger Robot                    ['location', '6', '10'],
680*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'a'],
681*16467b97STreehugger Robot                    ['terminate']]
682*16467b97STreehugger Robot
683*16467b97STreehugger Robot        self.assertListEqual(debugger.events, expected)
684*16467b97STreehugger Robot
685*16467b97STreehugger Robot
686*16467b97STreehugger Robot    def testDFA(self):
687*16467b97STreehugger Robot        grammar = textwrap.dedent(
688*16467b97STreehugger Robot        r'''
689*16467b97STreehugger Robot        grammar T;
690*16467b97STreehugger Robot        options {
691*16467b97STreehugger Robot            language=Python3;
692*16467b97STreehugger Robot        }
693*16467b97STreehugger Robot        a : ( b | c ) EOF;
694*16467b97STreehugger Robot        b : ID* INT;
695*16467b97STreehugger Robot        c : ID+ BANG;
696*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
697*16467b97STreehugger Robot        INT : '0'..'9'+ ;
698*16467b97STreehugger Robot        BANG : '!';
699*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
700*16467b97STreehugger Robot        ''')
701*16467b97STreehugger Robot
702*16467b97STreehugger Robot        debugger = self.execParser(
703*16467b97STreehugger Robot            grammar, 'a',
704*16467b97STreehugger Robot            input="a!",
705*16467b97STreehugger Robot            listener=None)
706*16467b97STreehugger Robot
707*16467b97STreehugger Robot        self.assertTrue(debugger.success)
708*16467b97STreehugger Robot        expected = [['enterRule', 'T.g', 'a'],
709*16467b97STreehugger Robot                    ['location', '6', '1'],
710*16467b97STreehugger Robot                    ['enterAlt', '1'],
711*16467b97STreehugger Robot                    ['location', '6', '5'],
712*16467b97STreehugger Robot                    ['enterSubRule', '1'],
713*16467b97STreehugger Robot                    ['enterDecision', '1', '0'],
714*16467b97STreehugger Robot                    ['mark', '0'],
715*16467b97STreehugger Robot                    ['LT', '1', '0', '5', '0', '1', '0', '"a'],
716*16467b97STreehugger Robot                    ['consumeToken', '0', '5', '0', '1', '0', '"a'],
717*16467b97STreehugger Robot                    ['LT', '1', '1', '4', '0', '1', '1', '"!'],
718*16467b97STreehugger Robot                    ['consumeToken', '1', '4', '0', '1', '1', '"!'],
719*16467b97STreehugger Robot                    ['rewind', '0'],
720*16467b97STreehugger Robot                    ['exitDecision', '1'],
721*16467b97STreehugger Robot                    ['enterAlt', '2'],
722*16467b97STreehugger Robot                    ['location', '6', '11'],
723*16467b97STreehugger Robot                    ['enterRule', 'T.g', 'c'],
724*16467b97STreehugger Robot                    ['location', '8', '1'],
725*16467b97STreehugger Robot                    ['enterAlt', '1'],
726*16467b97STreehugger Robot                    ['location', '8', '5'],
727*16467b97STreehugger Robot                    ['enterSubRule', '3'],
728*16467b97STreehugger Robot                    ['enterDecision', '3', '0'],
729*16467b97STreehugger Robot                    ['LT', '1', '0', '5', '0', '1', '0', '"a'],
730*16467b97STreehugger Robot                    ['exitDecision', '3'],
731*16467b97STreehugger Robot                    ['enterAlt', '1'],
732*16467b97STreehugger Robot                    ['location', '8', '5'],
733*16467b97STreehugger Robot                    ['LT', '1', '0', '5', '0', '1', '0', '"a'],
734*16467b97STreehugger Robot                    ['LT', '1', '0', '5', '0', '1', '0', '"a'],
735*16467b97STreehugger Robot                    ['consumeToken', '0', '5', '0', '1', '0', '"a'],
736*16467b97STreehugger Robot                    ['enterDecision', '3', '0'],
737*16467b97STreehugger Robot                    ['LT', '1', '1', '4', '0', '1', '1', '"!'],
738*16467b97STreehugger Robot                    ['exitDecision', '3'],
739*16467b97STreehugger Robot                    ['exitSubRule', '3'],
740*16467b97STreehugger Robot                    ['location', '8', '9'],
741*16467b97STreehugger Robot                    ['LT', '1', '1', '4', '0', '1', '1', '"!'],
742*16467b97STreehugger Robot                    ['LT', '1', '1', '4', '0', '1', '1', '"!'],
743*16467b97STreehugger Robot                    ['consumeToken', '1', '4', '0', '1', '1', '"!'],
744*16467b97STreehugger Robot                    ['location', '8', '13'],
745*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'c'],
746*16467b97STreehugger Robot                    ['exitSubRule', '1'],
747*16467b97STreehugger Robot                    ['location', '6', '15'],
748*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '2', '"<EOF>'],
749*16467b97STreehugger Robot                    ['LT', '1', '-1', '-1', '0', '1', '2', '"<EOF>'],
750*16467b97STreehugger Robot                    ['consumeToken', '-1', '-1', '0', '1', '2', '"<EOF>'],
751*16467b97STreehugger Robot                    ['location', '6', '18'],
752*16467b97STreehugger Robot                    ['exitRule', 'T.g', 'a'],
753*16467b97STreehugger Robot                    ['terminate']]
754*16467b97STreehugger Robot
755*16467b97STreehugger Robot        self.assertListEqual(debugger.events, expected)
756*16467b97STreehugger Robot
757*16467b97STreehugger Robot
758*16467b97STreehugger Robot    def testBasicAST(self):
759*16467b97STreehugger Robot        grammar = textwrap.dedent(
760*16467b97STreehugger Robot        r'''
761*16467b97STreehugger Robot        grammar T;
762*16467b97STreehugger Robot        options {
763*16467b97STreehugger Robot            language=Python3;
764*16467b97STreehugger Robot            output=AST;
765*16467b97STreehugger Robot        }
766*16467b97STreehugger Robot        a : ( b | c ) EOF!;
767*16467b97STreehugger Robot        b : ID* INT -> ^(INT ID*);
768*16467b97STreehugger Robot        c : ID+ BANG -> ^(BANG ID+);
769*16467b97STreehugger Robot        ID : 'a'..'z'+ ;
770*16467b97STreehugger Robot        INT : '0'..'9'+ ;
771*16467b97STreehugger Robot        BANG : '!';
772*16467b97STreehugger Robot        WS : (' '|'\n') {$channel=HIDDEN} ;
773*16467b97STreehugger Robot        ''')
774*16467b97STreehugger Robot
775*16467b97STreehugger Robot        listener = antlr3.debug.RecordDebugEventListener()
776*16467b97STreehugger Robot
777*16467b97STreehugger Robot        self.execParser(
778*16467b97STreehugger Robot            grammar, 'a',
779*16467b97STreehugger Robot            input="a!",
780*16467b97STreehugger Robot            listener=listener)
781*16467b97STreehugger Robot
782*16467b97STreehugger Robot        # don't check output for now (too dynamic), I'm satisfied if it
783*16467b97STreehugger Robot        # doesn't crash
784*16467b97STreehugger Robot
785*16467b97STreehugger Robot
786*16467b97STreehugger Robotif __name__ == '__main__':
787*16467b97STreehugger Robot    unittest.main()
788