1*16467b97STreehugger Robotimport unittest 2*16467b97STreehugger Robotimport textwrap 3*16467b97STreehugger Robotimport antlr3 4*16467b97STreehugger Robotimport antlr3.tree 5*16467b97STreehugger Robotimport testbase 6*16467b97STreehugger Robotimport sys 7*16467b97STreehugger Robot 8*16467b97STreehugger Robotclass T(testbase.ANTLRTest): 9*16467b97STreehugger Robot def parserClass(self, base): 10*16467b97STreehugger Robot class TParser(base): 11*16467b97STreehugger Robot def __init__(self, *args, **kwargs): 12*16467b97STreehugger Robot super().__init__(*args, **kwargs) 13*16467b97STreehugger Robot 14*16467b97STreehugger Robot self._output = "" 15*16467b97STreehugger Robot 16*16467b97STreehugger Robot 17*16467b97STreehugger Robot def capture(self, t): 18*16467b97STreehugger Robot self._output += t 19*16467b97STreehugger Robot 20*16467b97STreehugger Robot 21*16467b97STreehugger Robot def traceIn(self, ruleName, ruleIndex): 22*16467b97STreehugger Robot self.traces.append('>'+ruleName) 23*16467b97STreehugger Robot 24*16467b97STreehugger Robot 25*16467b97STreehugger Robot def traceOut(self, ruleName, ruleIndex): 26*16467b97STreehugger Robot self.traces.append('<'+ruleName) 27*16467b97STreehugger Robot 28*16467b97STreehugger Robot 29*16467b97STreehugger Robot def recover(self, input, re): 30*16467b97STreehugger Robot # no error recovery yet, just crash! 31*16467b97STreehugger Robot raise 32*16467b97STreehugger Robot 33*16467b97STreehugger Robot return TParser 34*16467b97STreehugger Robot 35*16467b97STreehugger Robot 36*16467b97STreehugger Robot def lexerClass(self, base): 37*16467b97STreehugger Robot class TLexer(base): 38*16467b97STreehugger Robot def __init__(self, *args, **kwargs): 39*16467b97STreehugger Robot super().__init__(*args, **kwargs) 40*16467b97STreehugger Robot 41*16467b97STreehugger Robot self._output = "" 42*16467b97STreehugger Robot 43*16467b97STreehugger Robot 44*16467b97STreehugger Robot def capture(self, t): 45*16467b97STreehugger Robot self._output += t 46*16467b97STreehugger Robot 47*16467b97STreehugger Robot 48*16467b97STreehugger Robot def traceIn(self, ruleName, ruleIndex): 49*16467b97STreehugger Robot self.traces.append('>'+ruleName) 50*16467b97STreehugger Robot 51*16467b97STreehugger Robot 52*16467b97STreehugger Robot def traceOut(self, ruleName, ruleIndex): 53*16467b97STreehugger Robot self.traces.append('<'+ruleName) 54*16467b97STreehugger Robot 55*16467b97STreehugger Robot 56*16467b97STreehugger Robot def recover(self, input, re): 57*16467b97STreehugger Robot # no error recovery yet, just crash! 58*16467b97STreehugger Robot raise 59*16467b97STreehugger Robot 60*16467b97STreehugger Robot return TLexer 61*16467b97STreehugger Robot 62*16467b97STreehugger Robot 63*16467b97STreehugger Robot def execParser(self, grammar, grammarEntry, input): 64*16467b97STreehugger Robot lexerCls, parserCls = self.compileInlineGrammar(grammar) 65*16467b97STreehugger Robot 66*16467b97STreehugger Robot cStream = antlr3.StringStream(input) 67*16467b97STreehugger Robot lexer = lexerCls(cStream) 68*16467b97STreehugger Robot tStream = antlr3.CommonTokenStream(lexer) 69*16467b97STreehugger Robot parser = parserCls(tStream) 70*16467b97STreehugger Robot r = getattr(parser, grammarEntry)() 71*16467b97STreehugger Robot 72*16467b97STreehugger Robot if r: 73*16467b97STreehugger Robot return r.tree.toStringTree() 74*16467b97STreehugger Robot 75*16467b97STreehugger Robot return "" 76*16467b97STreehugger Robot 77*16467b97STreehugger Robot 78*16467b97STreehugger Robot def execTreeParser(self, grammar, grammarEntry, treeGrammar, treeEntry, input): 79*16467b97STreehugger Robot lexerCls, parserCls = self.compileInlineGrammar(grammar) 80*16467b97STreehugger Robot walkerCls = self.compileInlineGrammar(treeGrammar) 81*16467b97STreehugger Robot 82*16467b97STreehugger Robot cStream = antlr3.StringStream(input) 83*16467b97STreehugger Robot lexer = lexerCls(cStream) 84*16467b97STreehugger Robot tStream = antlr3.CommonTokenStream(lexer) 85*16467b97STreehugger Robot parser = parserCls(tStream) 86*16467b97STreehugger Robot r = getattr(parser, grammarEntry)() 87*16467b97STreehugger Robot nodes = antlr3.tree.CommonTreeNodeStream(r.tree) 88*16467b97STreehugger Robot nodes.setTokenStream(tStream) 89*16467b97STreehugger Robot walker = walkerCls(nodes) 90*16467b97STreehugger Robot r = getattr(walker, treeEntry)() 91*16467b97STreehugger Robot 92*16467b97STreehugger Robot if r: 93*16467b97STreehugger Robot return r.tree.toStringTree() 94*16467b97STreehugger Robot 95*16467b97STreehugger Robot return "" 96*16467b97STreehugger Robot 97*16467b97STreehugger Robot 98*16467b97STreehugger Robot # PARSERS -- AUTO AST 99*16467b97STreehugger Robot 100*16467b97STreehugger Robot def testToken(self): 101*16467b97STreehugger Robot grammar = textwrap.dedent( 102*16467b97STreehugger Robot r''' 103*16467b97STreehugger Robot grammar T1; 104*16467b97STreehugger Robot options { 105*16467b97STreehugger Robot language=Python3; 106*16467b97STreehugger Robot output=AST; 107*16467b97STreehugger Robot } 108*16467b97STreehugger Robot @header { 109*16467b97STreehugger Robot class V(CommonTree): 110*16467b97STreehugger Robot def toString(self): 111*16467b97STreehugger Robot return self.token.text + "<V>" 112*16467b97STreehugger Robot __str__ = toString 113*16467b97STreehugger Robot 114*16467b97STreehugger Robot } 115*16467b97STreehugger Robot a : ID<V> ; 116*16467b97STreehugger Robot ID : 'a'..'z'+ ; 117*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 118*16467b97STreehugger Robot ''') 119*16467b97STreehugger Robot 120*16467b97STreehugger Robot found = self.execParser( 121*16467b97STreehugger Robot grammar, 'a', 122*16467b97STreehugger Robot input="a" 123*16467b97STreehugger Robot ) 124*16467b97STreehugger Robot 125*16467b97STreehugger Robot self.assertEqual("a<V>", found) 126*16467b97STreehugger Robot 127*16467b97STreehugger Robot 128*16467b97STreehugger Robot def testTokenCommonTree(self): 129*16467b97STreehugger Robot grammar = textwrap.dedent( 130*16467b97STreehugger Robot r''' 131*16467b97STreehugger Robot grammar T; 132*16467b97STreehugger Robot options { 133*16467b97STreehugger Robot language=Python3; 134*16467b97STreehugger Robot output=AST; 135*16467b97STreehugger Robot } 136*16467b97STreehugger Robot a : ID<CommonTree> ; 137*16467b97STreehugger Robot ID : 'a'..'z'+ ; 138*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 139*16467b97STreehugger Robot ''') 140*16467b97STreehugger Robot 141*16467b97STreehugger Robot found = self.execParser( 142*16467b97STreehugger Robot grammar, 'a', 143*16467b97STreehugger Robot input="a") 144*16467b97STreehugger Robot 145*16467b97STreehugger Robot self.assertEqual("a", found) 146*16467b97STreehugger Robot 147*16467b97STreehugger Robot 148*16467b97STreehugger Robot def testTokenWithQualifiedType(self): 149*16467b97STreehugger Robot grammar = textwrap.dedent( 150*16467b97STreehugger Robot r''' 151*16467b97STreehugger Robot grammar T; 152*16467b97STreehugger Robot options { 153*16467b97STreehugger Robot language=Python3; 154*16467b97STreehugger Robot output=AST; 155*16467b97STreehugger Robot } 156*16467b97STreehugger Robot @members { 157*16467b97STreehugger Robot class V(CommonTree): 158*16467b97STreehugger Robot def toString(self): 159*16467b97STreehugger Robot return self.token.text + "<V>" 160*16467b97STreehugger Robot __str__ = toString 161*16467b97STreehugger Robot } 162*16467b97STreehugger Robot a : ID<TParser.V> ; // TParser.V is qualified name 163*16467b97STreehugger Robot ID : 'a'..'z'+ ; 164*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 165*16467b97STreehugger Robot ''') 166*16467b97STreehugger Robot 167*16467b97STreehugger Robot found = self.execParser( 168*16467b97STreehugger Robot grammar, 'a', 169*16467b97STreehugger Robot input="a" 170*16467b97STreehugger Robot ) 171*16467b97STreehugger Robot 172*16467b97STreehugger Robot self.assertEqual("a<V>", found) 173*16467b97STreehugger Robot 174*16467b97STreehugger Robot 175*16467b97STreehugger Robot def testNamedType(self): 176*16467b97STreehugger Robot grammar = textwrap.dedent( 177*16467b97STreehugger Robot r""" 178*16467b97STreehugger Robot grammar $T; 179*16467b97STreehugger Robot options { 180*16467b97STreehugger Robot language=Python3; 181*16467b97STreehugger Robot output=AST; 182*16467b97STreehugger Robot } 183*16467b97STreehugger Robot @header { 184*16467b97STreehugger Robot class V(CommonTree): 185*16467b97STreehugger Robot def toString(self): 186*16467b97STreehugger Robot return self.token.text + "<V>" 187*16467b97STreehugger Robot __str__ = toString 188*16467b97STreehugger Robot } 189*16467b97STreehugger Robot a : ID<node=V> ; 190*16467b97STreehugger Robot ID : 'a'..'z'+ ; 191*16467b97STreehugger Robot WS : (' '|'\\n') {$channel=HIDDEN;} ; 192*16467b97STreehugger Robot """) 193*16467b97STreehugger Robot 194*16467b97STreehugger Robot found = self.execParser(grammar, 'a', input="a") 195*16467b97STreehugger Robot self.assertEqual("a<V>", found) 196*16467b97STreehugger Robot 197*16467b97STreehugger Robot 198*16467b97STreehugger Robot def testTokenWithLabel(self): 199*16467b97STreehugger Robot grammar = textwrap.dedent( 200*16467b97STreehugger Robot r''' 201*16467b97STreehugger Robot grammar T2; 202*16467b97STreehugger Robot options { 203*16467b97STreehugger Robot language=Python3; 204*16467b97STreehugger Robot output=AST; 205*16467b97STreehugger Robot } 206*16467b97STreehugger Robot @header { 207*16467b97STreehugger Robot class V(CommonTree): 208*16467b97STreehugger Robot def toString(self): 209*16467b97STreehugger Robot return self.token.text + "<V>" 210*16467b97STreehugger Robot __str__ = toString 211*16467b97STreehugger Robot 212*16467b97STreehugger Robot } 213*16467b97STreehugger Robot a : x=ID<V> ; 214*16467b97STreehugger Robot ID : 'a'..'z'+ ; 215*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 216*16467b97STreehugger Robot ''') 217*16467b97STreehugger Robot 218*16467b97STreehugger Robot found = self.execParser( 219*16467b97STreehugger Robot grammar, 'a', 220*16467b97STreehugger Robot input="a" 221*16467b97STreehugger Robot ) 222*16467b97STreehugger Robot 223*16467b97STreehugger Robot self.assertEqual("a<V>", found) 224*16467b97STreehugger Robot 225*16467b97STreehugger Robot 226*16467b97STreehugger Robot def testTokenWithListLabel(self): 227*16467b97STreehugger Robot grammar = textwrap.dedent( 228*16467b97STreehugger Robot r''' 229*16467b97STreehugger Robot grammar T3; 230*16467b97STreehugger Robot options { 231*16467b97STreehugger Robot language=Python3; 232*16467b97STreehugger Robot output=AST; 233*16467b97STreehugger Robot } 234*16467b97STreehugger Robot @header { 235*16467b97STreehugger Robot class V(CommonTree): 236*16467b97STreehugger Robot def toString(self): 237*16467b97STreehugger Robot return self.token.text + "<V>" 238*16467b97STreehugger Robot __str__ = toString 239*16467b97STreehugger Robot 240*16467b97STreehugger Robot } 241*16467b97STreehugger Robot a : x+=ID<V> ; 242*16467b97STreehugger Robot ID : 'a'..'z'+ ; 243*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 244*16467b97STreehugger Robot ''') 245*16467b97STreehugger Robot 246*16467b97STreehugger Robot found = self.execParser( 247*16467b97STreehugger Robot grammar, 'a', 248*16467b97STreehugger Robot input="a" 249*16467b97STreehugger Robot ) 250*16467b97STreehugger Robot 251*16467b97STreehugger Robot self.assertEqual("a<V>", found) 252*16467b97STreehugger Robot 253*16467b97STreehugger Robot 254*16467b97STreehugger Robot def testTokenRoot(self): 255*16467b97STreehugger Robot grammar = textwrap.dedent( 256*16467b97STreehugger Robot r''' 257*16467b97STreehugger Robot grammar T4; 258*16467b97STreehugger Robot options { 259*16467b97STreehugger Robot language=Python3; 260*16467b97STreehugger Robot output=AST; 261*16467b97STreehugger Robot } 262*16467b97STreehugger Robot @header { 263*16467b97STreehugger Robot class V(CommonTree): 264*16467b97STreehugger Robot def toString(self): 265*16467b97STreehugger Robot return self.token.text + "<V>" 266*16467b97STreehugger Robot __str__ = toString 267*16467b97STreehugger Robot 268*16467b97STreehugger Robot } 269*16467b97STreehugger Robot a : ID<V>^ ; 270*16467b97STreehugger Robot ID : 'a'..'z'+ ; 271*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 272*16467b97STreehugger Robot ''') 273*16467b97STreehugger Robot 274*16467b97STreehugger Robot found = self.execParser( 275*16467b97STreehugger Robot grammar, 'a', 276*16467b97STreehugger Robot input="a" 277*16467b97STreehugger Robot ) 278*16467b97STreehugger Robot 279*16467b97STreehugger Robot self.assertEqual("a<V>", found) 280*16467b97STreehugger Robot 281*16467b97STreehugger Robot 282*16467b97STreehugger Robot def testTokenRootWithListLabel(self): 283*16467b97STreehugger Robot grammar = textwrap.dedent( 284*16467b97STreehugger Robot r''' 285*16467b97STreehugger Robot grammar T5; 286*16467b97STreehugger Robot options { 287*16467b97STreehugger Robot language=Python3; 288*16467b97STreehugger Robot output=AST; 289*16467b97STreehugger Robot } 290*16467b97STreehugger Robot @header { 291*16467b97STreehugger Robot class V(CommonTree): 292*16467b97STreehugger Robot def toString(self): 293*16467b97STreehugger Robot return self.token.text + "<V>" 294*16467b97STreehugger Robot __str__ = toString 295*16467b97STreehugger Robot 296*16467b97STreehugger Robot } 297*16467b97STreehugger Robot a : x+=ID<V>^ ; 298*16467b97STreehugger Robot ID : 'a'..'z'+ ; 299*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 300*16467b97STreehugger Robot ''') 301*16467b97STreehugger Robot 302*16467b97STreehugger Robot found = self.execParser( 303*16467b97STreehugger Robot grammar, 'a', 304*16467b97STreehugger Robot input="a" 305*16467b97STreehugger Robot ) 306*16467b97STreehugger Robot 307*16467b97STreehugger Robot self.assertEqual("a<V>", found) 308*16467b97STreehugger Robot 309*16467b97STreehugger Robot 310*16467b97STreehugger Robot def testString(self): 311*16467b97STreehugger Robot grammar = textwrap.dedent( 312*16467b97STreehugger Robot r''' 313*16467b97STreehugger Robot grammar T6; 314*16467b97STreehugger Robot options { 315*16467b97STreehugger Robot language=Python3; 316*16467b97STreehugger Robot output=AST; 317*16467b97STreehugger Robot } 318*16467b97STreehugger Robot @header { 319*16467b97STreehugger Robot class V(CommonTree): 320*16467b97STreehugger Robot def toString(self): 321*16467b97STreehugger Robot return self.token.text + "<V>" 322*16467b97STreehugger Robot __str__ = toString 323*16467b97STreehugger Robot 324*16467b97STreehugger Robot } 325*16467b97STreehugger Robot a : 'begin'<V> ; 326*16467b97STreehugger Robot ID : 'a'..'z'+ ; 327*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 328*16467b97STreehugger Robot ''') 329*16467b97STreehugger Robot 330*16467b97STreehugger Robot found = self.execParser( 331*16467b97STreehugger Robot grammar, 'a', 332*16467b97STreehugger Robot input="begin" 333*16467b97STreehugger Robot ) 334*16467b97STreehugger Robot 335*16467b97STreehugger Robot self.assertEqual("begin<V>", found) 336*16467b97STreehugger Robot 337*16467b97STreehugger Robot 338*16467b97STreehugger Robot def testStringRoot(self): 339*16467b97STreehugger Robot grammar = textwrap.dedent( 340*16467b97STreehugger Robot r''' 341*16467b97STreehugger Robot grammar T7; 342*16467b97STreehugger Robot options { 343*16467b97STreehugger Robot language=Python3; 344*16467b97STreehugger Robot output=AST; 345*16467b97STreehugger Robot } 346*16467b97STreehugger Robot @header { 347*16467b97STreehugger Robot class V(CommonTree): 348*16467b97STreehugger Robot def toString(self): 349*16467b97STreehugger Robot return self.token.text + "<V>" 350*16467b97STreehugger Robot __str__ = toString 351*16467b97STreehugger Robot 352*16467b97STreehugger Robot } 353*16467b97STreehugger Robot a : 'begin'<V>^ ; 354*16467b97STreehugger Robot ID : 'a'..'z'+ ; 355*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 356*16467b97STreehugger Robot ''') 357*16467b97STreehugger Robot 358*16467b97STreehugger Robot found = self.execParser( 359*16467b97STreehugger Robot grammar, 'a', 360*16467b97STreehugger Robot input="begin" 361*16467b97STreehugger Robot ) 362*16467b97STreehugger Robot 363*16467b97STreehugger Robot self.assertEqual("begin<V>", found) 364*16467b97STreehugger Robot 365*16467b97STreehugger Robot 366*16467b97STreehugger Robot # PARSERS -- REWRITE AST 367*16467b97STreehugger Robot 368*16467b97STreehugger Robot def testRewriteToken(self): 369*16467b97STreehugger Robot grammar = textwrap.dedent( 370*16467b97STreehugger Robot r''' 371*16467b97STreehugger Robot grammar T8; 372*16467b97STreehugger Robot options { 373*16467b97STreehugger Robot language=Python3; 374*16467b97STreehugger Robot output=AST; 375*16467b97STreehugger Robot } 376*16467b97STreehugger Robot @header { 377*16467b97STreehugger Robot class V(CommonTree): 378*16467b97STreehugger Robot def toString(self): 379*16467b97STreehugger Robot return self.token.text + "<V>" 380*16467b97STreehugger Robot __str__ = toString 381*16467b97STreehugger Robot 382*16467b97STreehugger Robot } 383*16467b97STreehugger Robot a : ID -> ID<V> ; 384*16467b97STreehugger Robot ID : 'a'..'z'+ ; 385*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 386*16467b97STreehugger Robot ''') 387*16467b97STreehugger Robot 388*16467b97STreehugger Robot found = self.execParser( 389*16467b97STreehugger Robot grammar, 'a', 390*16467b97STreehugger Robot input="a" 391*16467b97STreehugger Robot ) 392*16467b97STreehugger Robot 393*16467b97STreehugger Robot self.assertEqual("a<V>", found) 394*16467b97STreehugger Robot 395*16467b97STreehugger Robot 396*16467b97STreehugger Robot def testRewriteTokenWithArgs(self): 397*16467b97STreehugger Robot grammar = textwrap.dedent( 398*16467b97STreehugger Robot r''' 399*16467b97STreehugger Robot grammar T9; 400*16467b97STreehugger Robot options { 401*16467b97STreehugger Robot language=Python3; 402*16467b97STreehugger Robot output=AST; 403*16467b97STreehugger Robot } 404*16467b97STreehugger Robot @header { 405*16467b97STreehugger Robot class V(CommonTree): 406*16467b97STreehugger Robot def __init__(self, *args): 407*16467b97STreehugger Robot if len(args) == 4: 408*16467b97STreehugger Robot ttype = args[0] 409*16467b97STreehugger Robot x = args[1] 410*16467b97STreehugger Robot y = args[2] 411*16467b97STreehugger Robot z = args[3] 412*16467b97STreehugger Robot token = CommonToken(type=ttype, text="") 413*16467b97STreehugger Robot 414*16467b97STreehugger Robot elif len(args) == 3: 415*16467b97STreehugger Robot ttype = args[0] 416*16467b97STreehugger Robot token = args[1] 417*16467b97STreehugger Robot x = args[2] 418*16467b97STreehugger Robot y, z = 0, 0 419*16467b97STreehugger Robot 420*16467b97STreehugger Robot else: 421*16467b97STreehugger Robot raise TypeError("Invalid args {!r}".format(args)) 422*16467b97STreehugger Robot 423*16467b97STreehugger Robot super().__init__(token) 424*16467b97STreehugger Robot self.x = x 425*16467b97STreehugger Robot self.y = y 426*16467b97STreehugger Robot self.z = z 427*16467b97STreehugger Robot 428*16467b97STreehugger Robot def toString(self): 429*16467b97STreehugger Robot txt = "" 430*16467b97STreehugger Robot if self.token: 431*16467b97STreehugger Robot txt += self.token.text 432*16467b97STreehugger Robot txt +="<V>;{0.x}{0.y}{0.z}".format(self) 433*16467b97STreehugger Robot return txt 434*16467b97STreehugger Robot __str__ = toString 435*16467b97STreehugger Robot 436*16467b97STreehugger Robot } 437*16467b97STreehugger Robot a : ID -> ID<V>[42,19,30] ID<V>[$ID,99]; 438*16467b97STreehugger Robot ID : 'a'..'z'+ ; 439*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 440*16467b97STreehugger Robot ''') 441*16467b97STreehugger Robot 442*16467b97STreehugger Robot found = self.execParser( 443*16467b97STreehugger Robot grammar, 'a', 444*16467b97STreehugger Robot input="a" 445*16467b97STreehugger Robot ) 446*16467b97STreehugger Robot 447*16467b97STreehugger Robot self.assertEqual("<V>;421930 a<V>;9900", found) 448*16467b97STreehugger Robot 449*16467b97STreehugger Robot 450*16467b97STreehugger Robot def testRewriteTokenRoot(self): 451*16467b97STreehugger Robot grammar = textwrap.dedent( 452*16467b97STreehugger Robot r''' 453*16467b97STreehugger Robot grammar T10; 454*16467b97STreehugger Robot options { 455*16467b97STreehugger Robot language=Python3; 456*16467b97STreehugger Robot output=AST; 457*16467b97STreehugger Robot } 458*16467b97STreehugger Robot @header { 459*16467b97STreehugger Robot class V(CommonTree): 460*16467b97STreehugger Robot def toString(self): 461*16467b97STreehugger Robot return self.token.text + "<V>" 462*16467b97STreehugger Robot __str__ = toString 463*16467b97STreehugger Robot 464*16467b97STreehugger Robot } 465*16467b97STreehugger Robot a : ID INT -> ^(ID<V> INT) ; 466*16467b97STreehugger Robot ID : 'a'..'z'+ ; 467*16467b97STreehugger Robot INT : '0'..'9'+ ; 468*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 469*16467b97STreehugger Robot ''') 470*16467b97STreehugger Robot 471*16467b97STreehugger Robot found = self.execParser( 472*16467b97STreehugger Robot grammar, 'a', 473*16467b97STreehugger Robot input="a 2" 474*16467b97STreehugger Robot ) 475*16467b97STreehugger Robot 476*16467b97STreehugger Robot self.assertEqual("(a<V> 2)", found) 477*16467b97STreehugger Robot 478*16467b97STreehugger Robot 479*16467b97STreehugger Robot def testRewriteString(self): 480*16467b97STreehugger Robot grammar = textwrap.dedent( 481*16467b97STreehugger Robot r''' 482*16467b97STreehugger Robot grammar T11; 483*16467b97STreehugger Robot options { 484*16467b97STreehugger Robot language=Python3; 485*16467b97STreehugger Robot output=AST; 486*16467b97STreehugger Robot } 487*16467b97STreehugger Robot @header { 488*16467b97STreehugger Robot class V(CommonTree): 489*16467b97STreehugger Robot def toString(self): 490*16467b97STreehugger Robot return self.token.text + "<V>" 491*16467b97STreehugger Robot __str__ = toString 492*16467b97STreehugger Robot 493*16467b97STreehugger Robot } 494*16467b97STreehugger Robot a : 'begin' -> 'begin'<V> ; 495*16467b97STreehugger Robot ID : 'a'..'z'+ ; 496*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 497*16467b97STreehugger Robot ''') 498*16467b97STreehugger Robot 499*16467b97STreehugger Robot found = self.execParser( 500*16467b97STreehugger Robot grammar, 'a', 501*16467b97STreehugger Robot input="begin" 502*16467b97STreehugger Robot ) 503*16467b97STreehugger Robot 504*16467b97STreehugger Robot self.assertEqual("begin<V>", found) 505*16467b97STreehugger Robot 506*16467b97STreehugger Robot 507*16467b97STreehugger Robot def testRewriteStringRoot(self): 508*16467b97STreehugger Robot grammar = textwrap.dedent( 509*16467b97STreehugger Robot r''' 510*16467b97STreehugger Robot grammar T12; 511*16467b97STreehugger Robot options { 512*16467b97STreehugger Robot language=Python3; 513*16467b97STreehugger Robot output=AST; 514*16467b97STreehugger Robot } 515*16467b97STreehugger Robot @header { 516*16467b97STreehugger Robot class V(CommonTree): 517*16467b97STreehugger Robot def toString(self): 518*16467b97STreehugger Robot return self.token.text + "<V>" 519*16467b97STreehugger Robot __str__ = toString 520*16467b97STreehugger Robot 521*16467b97STreehugger Robot } 522*16467b97STreehugger Robot a : 'begin' INT -> ^('begin'<V> INT) ; 523*16467b97STreehugger Robot ID : 'a'..'z'+ ; 524*16467b97STreehugger Robot INT : '0'..'9'+ ; 525*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 526*16467b97STreehugger Robot ''') 527*16467b97STreehugger Robot 528*16467b97STreehugger Robot found = self.execParser( 529*16467b97STreehugger Robot grammar, 'a', 530*16467b97STreehugger Robot input="begin 2" 531*16467b97STreehugger Robot ) 532*16467b97STreehugger Robot 533*16467b97STreehugger Robot self.assertEqual("(begin<V> 2)", found) 534*16467b97STreehugger Robot 535*16467b97STreehugger Robot def testRewriteRuleResults(self): 536*16467b97STreehugger Robot grammar = textwrap.dedent( 537*16467b97STreehugger Robot r''' 538*16467b97STreehugger Robot grammar T; 539*16467b97STreehugger Robot options { 540*16467b97STreehugger Robot language=Python3; 541*16467b97STreehugger Robot output=AST; 542*16467b97STreehugger Robot } 543*16467b97STreehugger Robot tokens {LIST;} 544*16467b97STreehugger Robot @header { 545*16467b97STreehugger Robot class V(CommonTree): 546*16467b97STreehugger Robot def toString(self): 547*16467b97STreehugger Robot return self.token.text + "<V>" 548*16467b97STreehugger Robot __str__ = toString 549*16467b97STreehugger Robot 550*16467b97STreehugger Robot class W(CommonTree): 551*16467b97STreehugger Robot def __init__(self, tokenType, txt): 552*16467b97STreehugger Robot super().__init__( 553*16467b97STreehugger Robot CommonToken(type=tokenType, text=txt)) 554*16467b97STreehugger Robot 555*16467b97STreehugger Robot def toString(self): 556*16467b97STreehugger Robot return self.token.text + "<W>" 557*16467b97STreehugger Robot __str__ = toString 558*16467b97STreehugger Robot 559*16467b97STreehugger Robot } 560*16467b97STreehugger Robot a : id (',' id)* -> ^(LIST<W>["LIST"] id+); 561*16467b97STreehugger Robot id : ID -> ID<V>; 562*16467b97STreehugger Robot ID : 'a'..'z'+ ; 563*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 564*16467b97STreehugger Robot ''') 565*16467b97STreehugger Robot 566*16467b97STreehugger Robot found = self.execParser( 567*16467b97STreehugger Robot grammar, 'a', 568*16467b97STreehugger Robot input="a,b,c") 569*16467b97STreehugger Robot 570*16467b97STreehugger Robot self.assertEqual("(LIST<W> a<V> b<V> c<V>)", found) 571*16467b97STreehugger Robot 572*16467b97STreehugger Robot def testCopySemanticsWithHetero(self): 573*16467b97STreehugger Robot grammar = textwrap.dedent( 574*16467b97STreehugger Robot r''' 575*16467b97STreehugger Robot grammar T; 576*16467b97STreehugger Robot options { 577*16467b97STreehugger Robot language=Python3; 578*16467b97STreehugger Robot output=AST; 579*16467b97STreehugger Robot } 580*16467b97STreehugger Robot @header { 581*16467b97STreehugger Robot class V(CommonTree): 582*16467b97STreehugger Robot def dupNode(self): 583*16467b97STreehugger Robot return V(self) 584*16467b97STreehugger Robot 585*16467b97STreehugger Robot def toString(self): 586*16467b97STreehugger Robot return self.token.text + "<V>" 587*16467b97STreehugger Robot __str__ = toString 588*16467b97STreehugger Robot 589*16467b97STreehugger Robot } 590*16467b97STreehugger Robot a : type ID (',' ID)* ';' -> ^(type ID)+; 591*16467b97STreehugger Robot type : 'int'<V> ; 592*16467b97STreehugger Robot ID : 'a'..'z'+ ; 593*16467b97STreehugger Robot INT : '0'..'9'+; 594*16467b97STreehugger Robot WS : (' '|'\\n') {$channel=HIDDEN;} ; 595*16467b97STreehugger Robot ''') 596*16467b97STreehugger Robot 597*16467b97STreehugger Robot found = self.execParser( 598*16467b97STreehugger Robot grammar, 'a', 599*16467b97STreehugger Robot input="int a, b, c;") 600*16467b97STreehugger Robot self.assertEqual("(int<V> a) (int<V> b) (int<V> c)", found) 601*16467b97STreehugger Robot 602*16467b97STreehugger Robot # TREE PARSERS -- REWRITE AST 603*16467b97STreehugger Robot 604*16467b97STreehugger Robot def testTreeParserRewriteFlatList(self): 605*16467b97STreehugger Robot grammar = textwrap.dedent( 606*16467b97STreehugger Robot r''' 607*16467b97STreehugger Robot grammar T13; 608*16467b97STreehugger Robot options { 609*16467b97STreehugger Robot language=Python3; 610*16467b97STreehugger Robot output=AST; 611*16467b97STreehugger Robot } 612*16467b97STreehugger Robot a : ID INT; 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 treeGrammar = textwrap.dedent( 619*16467b97STreehugger Robot r''' 620*16467b97STreehugger Robot tree grammar TP13; 621*16467b97STreehugger Robot options { 622*16467b97STreehugger Robot language=Python3; 623*16467b97STreehugger Robot output=AST; 624*16467b97STreehugger Robot ASTLabelType=CommonTree; 625*16467b97STreehugger Robot tokenVocab=T13; 626*16467b97STreehugger Robot } 627*16467b97STreehugger Robot @header { 628*16467b97STreehugger Robot class V(CommonTree): 629*16467b97STreehugger Robot def toString(self): 630*16467b97STreehugger Robot return self.token.text + "<V>" 631*16467b97STreehugger Robot __str__ = toString 632*16467b97STreehugger Robot 633*16467b97STreehugger Robot class W(CommonTree): 634*16467b97STreehugger Robot def toString(self): 635*16467b97STreehugger Robot return self.token.text + "<W>" 636*16467b97STreehugger Robot __str__ = toString 637*16467b97STreehugger Robot 638*16467b97STreehugger Robot } 639*16467b97STreehugger Robot a : ID INT -> INT<V> ID<W> 640*16467b97STreehugger Robot ; 641*16467b97STreehugger Robot ''') 642*16467b97STreehugger Robot 643*16467b97STreehugger Robot found = self.execTreeParser( 644*16467b97STreehugger Robot grammar, 'a', 645*16467b97STreehugger Robot treeGrammar, 'a', 646*16467b97STreehugger Robot input="abc 34" 647*16467b97STreehugger Robot ) 648*16467b97STreehugger Robot 649*16467b97STreehugger Robot self.assertEqual("34<V> abc<W>", found) 650*16467b97STreehugger Robot 651*16467b97STreehugger Robot 652*16467b97STreehugger Robot def testTreeParserRewriteTree(self): 653*16467b97STreehugger Robot grammar = textwrap.dedent( 654*16467b97STreehugger Robot r''' 655*16467b97STreehugger Robot grammar T14; 656*16467b97STreehugger Robot options { 657*16467b97STreehugger Robot language=Python3; 658*16467b97STreehugger Robot output=AST; 659*16467b97STreehugger Robot } 660*16467b97STreehugger Robot a : ID INT; 661*16467b97STreehugger Robot ID : 'a'..'z'+ ; 662*16467b97STreehugger Robot INT : '0'..'9'+; 663*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 664*16467b97STreehugger Robot ''') 665*16467b97STreehugger Robot 666*16467b97STreehugger Robot treeGrammar = textwrap.dedent( 667*16467b97STreehugger Robot r''' 668*16467b97STreehugger Robot tree grammar TP14; 669*16467b97STreehugger Robot options { 670*16467b97STreehugger Robot language=Python3; 671*16467b97STreehugger Robot output=AST; 672*16467b97STreehugger Robot ASTLabelType=CommonTree; 673*16467b97STreehugger Robot tokenVocab=T14; 674*16467b97STreehugger Robot } 675*16467b97STreehugger Robot @header { 676*16467b97STreehugger Robot class V(CommonTree): 677*16467b97STreehugger Robot def toString(self): 678*16467b97STreehugger Robot return self.token.text + "<V>" 679*16467b97STreehugger Robot __str__ = toString 680*16467b97STreehugger Robot 681*16467b97STreehugger Robot class W(CommonTree): 682*16467b97STreehugger Robot def toString(self): 683*16467b97STreehugger Robot return self.token.text + "<W>" 684*16467b97STreehugger Robot __str__ = toString 685*16467b97STreehugger Robot 686*16467b97STreehugger Robot } 687*16467b97STreehugger Robot a : ID INT -> ^(INT<V> ID<W>) 688*16467b97STreehugger Robot ; 689*16467b97STreehugger Robot ''') 690*16467b97STreehugger Robot 691*16467b97STreehugger Robot found = self.execTreeParser( 692*16467b97STreehugger Robot grammar, 'a', 693*16467b97STreehugger Robot treeGrammar, 'a', 694*16467b97STreehugger Robot input="abc 34" 695*16467b97STreehugger Robot ) 696*16467b97STreehugger Robot 697*16467b97STreehugger Robot self.assertEqual("(34<V> abc<W>)", found) 698*16467b97STreehugger Robot 699*16467b97STreehugger Robot 700*16467b97STreehugger Robot def testTreeParserRewriteImaginary(self): 701*16467b97STreehugger Robot grammar = textwrap.dedent( 702*16467b97STreehugger Robot r''' 703*16467b97STreehugger Robot grammar T15; 704*16467b97STreehugger Robot options { 705*16467b97STreehugger Robot language=Python3; 706*16467b97STreehugger Robot output=AST; 707*16467b97STreehugger Robot } 708*16467b97STreehugger Robot a : ID ; 709*16467b97STreehugger Robot ID : 'a'..'z'+ ; 710*16467b97STreehugger Robot INT : '0'..'9'+; 711*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 712*16467b97STreehugger Robot ''') 713*16467b97STreehugger Robot 714*16467b97STreehugger Robot treeGrammar = textwrap.dedent( 715*16467b97STreehugger Robot r''' 716*16467b97STreehugger Robot tree grammar TP15; 717*16467b97STreehugger Robot options { 718*16467b97STreehugger Robot language=Python3; 719*16467b97STreehugger Robot output=AST; 720*16467b97STreehugger Robot ASTLabelType=CommonTree; 721*16467b97STreehugger Robot tokenVocab=T15; 722*16467b97STreehugger Robot } 723*16467b97STreehugger Robot tokens { ROOT; } 724*16467b97STreehugger Robot @header { 725*16467b97STreehugger Robot class V(CommonTree): 726*16467b97STreehugger Robot def __init__(self, tokenType): 727*16467b97STreehugger Robot super().__init__(CommonToken(tokenType)) 728*16467b97STreehugger Robot 729*16467b97STreehugger Robot def toString(self): 730*16467b97STreehugger Robot return tokenNames[self.token.type] + "<V>" 731*16467b97STreehugger Robot __str__ = toString 732*16467b97STreehugger Robot 733*16467b97STreehugger Robot 734*16467b97STreehugger Robot } 735*16467b97STreehugger Robot a : ID -> ROOT<V> ID 736*16467b97STreehugger Robot ; 737*16467b97STreehugger Robot ''') 738*16467b97STreehugger Robot 739*16467b97STreehugger Robot found = self.execTreeParser( 740*16467b97STreehugger Robot grammar, 'a', 741*16467b97STreehugger Robot treeGrammar, 'a', 742*16467b97STreehugger Robot input="abc" 743*16467b97STreehugger Robot ) 744*16467b97STreehugger Robot 745*16467b97STreehugger Robot self.assertEqual("ROOT<V> abc", found) 746*16467b97STreehugger Robot 747*16467b97STreehugger Robot 748*16467b97STreehugger Robot def testTreeParserRewriteImaginaryWithArgs(self): 749*16467b97STreehugger Robot grammar = textwrap.dedent( 750*16467b97STreehugger Robot r''' 751*16467b97STreehugger Robot grammar T16; 752*16467b97STreehugger Robot options { 753*16467b97STreehugger Robot language=Python3; 754*16467b97STreehugger Robot output=AST; 755*16467b97STreehugger Robot } 756*16467b97STreehugger Robot a : ID ; 757*16467b97STreehugger Robot ID : 'a'..'z'+ ; 758*16467b97STreehugger Robot INT : '0'..'9'+; 759*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 760*16467b97STreehugger Robot ''') 761*16467b97STreehugger Robot 762*16467b97STreehugger Robot treeGrammar = textwrap.dedent( 763*16467b97STreehugger Robot r''' 764*16467b97STreehugger Robot tree grammar TP16; 765*16467b97STreehugger Robot options { 766*16467b97STreehugger Robot language=Python3; 767*16467b97STreehugger Robot output=AST; 768*16467b97STreehugger Robot ASTLabelType=CommonTree; 769*16467b97STreehugger Robot tokenVocab=T16; 770*16467b97STreehugger Robot } 771*16467b97STreehugger Robot tokens { ROOT; } 772*16467b97STreehugger Robot @header { 773*16467b97STreehugger Robot class V(CommonTree): 774*16467b97STreehugger Robot def __init__(self, tokenType, x): 775*16467b97STreehugger Robot super().__init__(CommonToken(tokenType)) 776*16467b97STreehugger Robot self.x = x 777*16467b97STreehugger Robot 778*16467b97STreehugger Robot def toString(self): 779*16467b97STreehugger Robot return tokenNames[self.token.type] + "<V>;" + str(self.x) 780*16467b97STreehugger Robot __str__ = toString 781*16467b97STreehugger Robot 782*16467b97STreehugger Robot } 783*16467b97STreehugger Robot a : ID -> ROOT<V>[42] ID 784*16467b97STreehugger Robot ; 785*16467b97STreehugger Robot ''') 786*16467b97STreehugger Robot 787*16467b97STreehugger Robot found = self.execTreeParser( 788*16467b97STreehugger Robot grammar, 'a', 789*16467b97STreehugger Robot treeGrammar, 'a', 790*16467b97STreehugger Robot input="abc" 791*16467b97STreehugger Robot ) 792*16467b97STreehugger Robot 793*16467b97STreehugger Robot self.assertEqual("ROOT<V>;42 abc", found) 794*16467b97STreehugger Robot 795*16467b97STreehugger Robot 796*16467b97STreehugger Robot def testTreeParserRewriteImaginaryRoot(self): 797*16467b97STreehugger Robot grammar = textwrap.dedent( 798*16467b97STreehugger Robot r''' 799*16467b97STreehugger Robot grammar T17; 800*16467b97STreehugger Robot options { 801*16467b97STreehugger Robot language=Python3; 802*16467b97STreehugger Robot output=AST; 803*16467b97STreehugger Robot } 804*16467b97STreehugger Robot a : ID ; 805*16467b97STreehugger Robot ID : 'a'..'z'+ ; 806*16467b97STreehugger Robot INT : '0'..'9'+; 807*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 808*16467b97STreehugger Robot ''') 809*16467b97STreehugger Robot 810*16467b97STreehugger Robot treeGrammar = textwrap.dedent( 811*16467b97STreehugger Robot r''' 812*16467b97STreehugger Robot tree grammar TP17; 813*16467b97STreehugger Robot options { 814*16467b97STreehugger Robot language=Python3; 815*16467b97STreehugger Robot output=AST; 816*16467b97STreehugger Robot ASTLabelType=CommonTree; 817*16467b97STreehugger Robot tokenVocab=T17; 818*16467b97STreehugger Robot } 819*16467b97STreehugger Robot tokens { ROOT; } 820*16467b97STreehugger Robot @header { 821*16467b97STreehugger Robot class V(CommonTree): 822*16467b97STreehugger Robot def __init__(self, tokenType): 823*16467b97STreehugger Robot super().__init__(CommonToken(tokenType)) 824*16467b97STreehugger Robot 825*16467b97STreehugger Robot def toString(self): 826*16467b97STreehugger Robot return tokenNames[self.token.type] + "<V>" 827*16467b97STreehugger Robot __str__ = toString 828*16467b97STreehugger Robot 829*16467b97STreehugger Robot } 830*16467b97STreehugger Robot a : ID -> ^(ROOT<V> ID) 831*16467b97STreehugger Robot ; 832*16467b97STreehugger Robot ''') 833*16467b97STreehugger Robot 834*16467b97STreehugger Robot found = self.execTreeParser( 835*16467b97STreehugger Robot grammar, 'a', 836*16467b97STreehugger Robot treeGrammar, 'a', 837*16467b97STreehugger Robot input="abc" 838*16467b97STreehugger Robot ) 839*16467b97STreehugger Robot 840*16467b97STreehugger Robot self.assertEqual("(ROOT<V> abc)", found) 841*16467b97STreehugger Robot 842*16467b97STreehugger Robot 843*16467b97STreehugger Robot def testTreeParserRewriteImaginaryFromReal(self): 844*16467b97STreehugger Robot grammar = textwrap.dedent( 845*16467b97STreehugger Robot r''' 846*16467b97STreehugger Robot grammar T18; 847*16467b97STreehugger Robot options { 848*16467b97STreehugger Robot language=Python3; 849*16467b97STreehugger Robot output=AST; 850*16467b97STreehugger Robot } 851*16467b97STreehugger Robot a : ID ; 852*16467b97STreehugger Robot ID : 'a'..'z'+ ; 853*16467b97STreehugger Robot INT : '0'..'9'+; 854*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 855*16467b97STreehugger Robot ''') 856*16467b97STreehugger Robot 857*16467b97STreehugger Robot treeGrammar = textwrap.dedent( 858*16467b97STreehugger Robot r''' 859*16467b97STreehugger Robot tree grammar TP18; 860*16467b97STreehugger Robot options { 861*16467b97STreehugger Robot language=Python3; 862*16467b97STreehugger Robot output=AST; 863*16467b97STreehugger Robot ASTLabelType=CommonTree; 864*16467b97STreehugger Robot tokenVocab=T18; 865*16467b97STreehugger Robot } 866*16467b97STreehugger Robot tokens { ROOT; } 867*16467b97STreehugger Robot @header { 868*16467b97STreehugger Robot class V(CommonTree): 869*16467b97STreehugger Robot def __init__(self, tokenType, tree=None): 870*16467b97STreehugger Robot if tree is None: 871*16467b97STreehugger Robot super().__init__(CommonToken(tokenType)) 872*16467b97STreehugger Robot else: 873*16467b97STreehugger Robot super().__init__(tree) 874*16467b97STreehugger Robot self.token.type = tokenType 875*16467b97STreehugger Robot 876*16467b97STreehugger Robot def toString(self): 877*16467b97STreehugger Robot return tokenNames[self.token.type]+"<V>@"+str(self.token.line) 878*16467b97STreehugger Robot __str__ = toString 879*16467b97STreehugger Robot 880*16467b97STreehugger Robot } 881*16467b97STreehugger Robot a : ID -> ROOT<V>[$ID] 882*16467b97STreehugger Robot ; 883*16467b97STreehugger Robot ''') 884*16467b97STreehugger Robot 885*16467b97STreehugger Robot found = self.execTreeParser( 886*16467b97STreehugger Robot grammar, 'a', 887*16467b97STreehugger Robot treeGrammar, 'a', 888*16467b97STreehugger Robot input="abc" 889*16467b97STreehugger Robot ) 890*16467b97STreehugger Robot 891*16467b97STreehugger Robot self.assertEqual("ROOT<V>@1", found) 892*16467b97STreehugger Robot 893*16467b97STreehugger Robot 894*16467b97STreehugger Robot def testTreeParserAutoHeteroAST(self): 895*16467b97STreehugger Robot grammar = textwrap.dedent( 896*16467b97STreehugger Robot r''' 897*16467b97STreehugger Robot grammar T; 898*16467b97STreehugger Robot options { 899*16467b97STreehugger Robot language=Python3; 900*16467b97STreehugger Robot output=AST; 901*16467b97STreehugger Robot } 902*16467b97STreehugger Robot a : ID ';' ; 903*16467b97STreehugger Robot ID : 'a'..'z'+ ; 904*16467b97STreehugger Robot INT : '0'..'9'+; 905*16467b97STreehugger Robot WS : (' '|'\n') {$channel=HIDDEN;} ; 906*16467b97STreehugger Robot ''') 907*16467b97STreehugger Robot 908*16467b97STreehugger Robot treeGrammar = textwrap.dedent( 909*16467b97STreehugger Robot r''' 910*16467b97STreehugger Robot tree grammar TP; 911*16467b97STreehugger Robot options { 912*16467b97STreehugger Robot language=Python3; 913*16467b97STreehugger Robot output=AST; 914*16467b97STreehugger Robot ASTLabelType=CommonTree; 915*16467b97STreehugger Robot tokenVocab=T; 916*16467b97STreehugger Robot } 917*16467b97STreehugger Robot tokens { ROOT; } 918*16467b97STreehugger Robot @header { 919*16467b97STreehugger Robot class V(CommonTree): 920*16467b97STreehugger Robot def toString(self): 921*16467b97STreehugger Robot return CommonTree.toString(self) + "<V>" 922*16467b97STreehugger Robot __str__ = toString 923*16467b97STreehugger Robot 924*16467b97STreehugger Robot } 925*16467b97STreehugger Robot 926*16467b97STreehugger Robot a : ID<V> ';'<V>; 927*16467b97STreehugger Robot ''') 928*16467b97STreehugger Robot 929*16467b97STreehugger Robot found = self.execTreeParser( 930*16467b97STreehugger Robot grammar, 'a', 931*16467b97STreehugger Robot treeGrammar, 'a', 932*16467b97STreehugger Robot input="abc;" 933*16467b97STreehugger Robot ) 934*16467b97STreehugger Robot 935*16467b97STreehugger Robot self.assertEqual("abc<V> ;<V>", found) 936*16467b97STreehugger Robot 937*16467b97STreehugger Robot 938*16467b97STreehugger Robotif __name__ == '__main__': 939*16467b97STreehugger Robot unittest.main() 940