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