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 setUp(self): 10*16467b97STreehugger Robot self.oldPath = sys.path[:] 11*16467b97STreehugger Robot sys.path.insert(0, self.baseDir) 12*16467b97STreehugger Robot 13*16467b97STreehugger Robot 14*16467b97STreehugger Robot def tearDown(self): 15*16467b97STreehugger Robot sys.path = self.oldPath 16*16467b97STreehugger Robot 17*16467b97STreehugger Robot 18*16467b97STreehugger Robot def parserClass(self, base): 19*16467b97STreehugger Robot class TParser(base): 20*16467b97STreehugger Robot def __init__(self, *args, **kwargs): 21*16467b97STreehugger Robot super().__init__(*args, **kwargs) 22*16467b97STreehugger Robot 23*16467b97STreehugger Robot self._output = "" 24*16467b97STreehugger Robot 25*16467b97STreehugger Robot 26*16467b97STreehugger Robot def capture(self, t): 27*16467b97STreehugger Robot self._output += t 28*16467b97STreehugger Robot 29*16467b97STreehugger Robot 30*16467b97STreehugger Robot def traceIn(self, ruleName, ruleIndex): 31*16467b97STreehugger Robot self.traces.append('>'+ruleName) 32*16467b97STreehugger Robot 33*16467b97STreehugger Robot 34*16467b97STreehugger Robot def traceOut(self, ruleName, ruleIndex): 35*16467b97STreehugger Robot self.traces.append('<'+ruleName) 36*16467b97STreehugger Robot 37*16467b97STreehugger Robot 38*16467b97STreehugger Robot def recover(self, input, re): 39*16467b97STreehugger Robot # no error recovery yet, just crash! 40*16467b97STreehugger Robot raise 41*16467b97STreehugger Robot 42*16467b97STreehugger Robot return TParser 43*16467b97STreehugger Robot 44*16467b97STreehugger Robot 45*16467b97STreehugger Robot def lexerClass(self, base): 46*16467b97STreehugger Robot class TLexer(base): 47*16467b97STreehugger Robot def __init__(self, *args, **kwargs): 48*16467b97STreehugger Robot super().__init__(*args, **kwargs) 49*16467b97STreehugger Robot 50*16467b97STreehugger Robot self._output = "" 51*16467b97STreehugger Robot 52*16467b97STreehugger Robot 53*16467b97STreehugger Robot def capture(self, t): 54*16467b97STreehugger Robot self._output += t 55*16467b97STreehugger Robot 56*16467b97STreehugger Robot 57*16467b97STreehugger Robot def traceIn(self, ruleName, ruleIndex): 58*16467b97STreehugger Robot self.traces.append('>'+ruleName) 59*16467b97STreehugger Robot 60*16467b97STreehugger Robot 61*16467b97STreehugger Robot def traceOut(self, ruleName, ruleIndex): 62*16467b97STreehugger Robot self.traces.append('<'+ruleName) 63*16467b97STreehugger Robot 64*16467b97STreehugger Robot 65*16467b97STreehugger Robot def recover(self, input): 66*16467b97STreehugger Robot # no error recovery yet, just crash! 67*16467b97STreehugger Robot raise 68*16467b97STreehugger Robot 69*16467b97STreehugger Robot return TLexer 70*16467b97STreehugger Robot 71*16467b97STreehugger Robot 72*16467b97STreehugger Robot def execParser(self, grammar, grammarEntry, slaves, input): 73*16467b97STreehugger Robot for slave in slaves: 74*16467b97STreehugger Robot parserName = self.writeInlineGrammar(slave)[0] 75*16467b97STreehugger Robot # slave parsers are imported as normal python modules 76*16467b97STreehugger Robot # to force reloading current version, purge module from sys.modules 77*16467b97STreehugger Robot if parserName + 'Parser' in sys.modules: 78*16467b97STreehugger Robot del sys.modules[parserName + 'Parser'] 79*16467b97STreehugger Robot 80*16467b97STreehugger Robot lexerCls, parserCls = self.compileInlineGrammar(grammar) 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 getattr(parser, grammarEntry)() 87*16467b97STreehugger Robot 88*16467b97STreehugger Robot return parser._output 89*16467b97STreehugger Robot 90*16467b97STreehugger Robot 91*16467b97STreehugger Robot def execLexer(self, grammar, slaves, input): 92*16467b97STreehugger Robot for slave in slaves: 93*16467b97STreehugger Robot parserName = self.writeInlineGrammar(slave)[0] 94*16467b97STreehugger Robot # slave parsers are imported as normal python modules 95*16467b97STreehugger Robot # to force reloading current version, purge module from sys.modules 96*16467b97STreehugger Robot if parserName + 'Parser' in sys.modules: 97*16467b97STreehugger Robot del sys.modules[parserName + 'Parser'] 98*16467b97STreehugger Robot 99*16467b97STreehugger Robot lexerCls = self.compileInlineGrammar(grammar) 100*16467b97STreehugger Robot 101*16467b97STreehugger Robot cStream = antlr3.StringStream(input) 102*16467b97STreehugger Robot lexer = lexerCls(cStream) 103*16467b97STreehugger Robot 104*16467b97STreehugger Robot while True: 105*16467b97STreehugger Robot token = lexer.nextToken() 106*16467b97STreehugger Robot if token is None or token.type == antlr3.EOF: 107*16467b97STreehugger Robot break 108*16467b97STreehugger Robot 109*16467b97STreehugger Robot lexer._output += token.text 110*16467b97STreehugger Robot 111*16467b97STreehugger Robot return lexer._output 112*16467b97STreehugger Robot 113*16467b97STreehugger Robot 114*16467b97STreehugger Robot def testDelegatorInvokesDelegateRule(self): 115*16467b97STreehugger Robot slave = textwrap.dedent( 116*16467b97STreehugger Robot r''' 117*16467b97STreehugger Robot parser grammar S1; 118*16467b97STreehugger Robot options { 119*16467b97STreehugger Robot language=Python3; 120*16467b97STreehugger Robot } 121*16467b97STreehugger Robot @members { 122*16467b97STreehugger Robot def capture(self, t): 123*16467b97STreehugger Robot self.gM1.capture(t) 124*16467b97STreehugger Robot 125*16467b97STreehugger Robot } 126*16467b97STreehugger Robot 127*16467b97STreehugger Robot a : B { self.capture("S.a") } ; 128*16467b97STreehugger Robot ''') 129*16467b97STreehugger Robot 130*16467b97STreehugger Robot master = textwrap.dedent( 131*16467b97STreehugger Robot r''' 132*16467b97STreehugger Robot grammar M1; 133*16467b97STreehugger Robot options { 134*16467b97STreehugger Robot language=Python3; 135*16467b97STreehugger Robot } 136*16467b97STreehugger Robot import S1; 137*16467b97STreehugger Robot s : a ; 138*16467b97STreehugger Robot B : 'b' ; // defines B from inherited token space 139*16467b97STreehugger Robot WS : (' '|'\n') {self.skip()} ; 140*16467b97STreehugger Robot ''') 141*16467b97STreehugger Robot 142*16467b97STreehugger Robot found = self.execParser( 143*16467b97STreehugger Robot master, 's', 144*16467b97STreehugger Robot slaves=[slave], 145*16467b97STreehugger Robot input="b" 146*16467b97STreehugger Robot ) 147*16467b97STreehugger Robot 148*16467b97STreehugger Robot self.assertEqual("S.a", found) 149*16467b97STreehugger Robot 150*16467b97STreehugger Robot 151*16467b97STreehugger Robot def testDelegatorInvokesDelegateRuleWithArgs(self): 152*16467b97STreehugger Robot slave = textwrap.dedent( 153*16467b97STreehugger Robot r''' 154*16467b97STreehugger Robot parser grammar S2; 155*16467b97STreehugger Robot options { 156*16467b97STreehugger Robot language=Python3; 157*16467b97STreehugger Robot } 158*16467b97STreehugger Robot @members { 159*16467b97STreehugger Robot def capture(self, t): 160*16467b97STreehugger Robot self.gM2.capture(t) 161*16467b97STreehugger Robot } 162*16467b97STreehugger Robot a[x] returns [y] : B {self.capture("S.a"); $y="1000";} ; 163*16467b97STreehugger Robot ''') 164*16467b97STreehugger Robot 165*16467b97STreehugger Robot master = textwrap.dedent( 166*16467b97STreehugger Robot r''' 167*16467b97STreehugger Robot grammar M2; 168*16467b97STreehugger Robot options { 169*16467b97STreehugger Robot language=Python3; 170*16467b97STreehugger Robot } 171*16467b97STreehugger Robot import S2; 172*16467b97STreehugger Robot s : label=a[3] {self.capture($label.y);} ; 173*16467b97STreehugger Robot B : 'b' ; // defines B from inherited token space 174*16467b97STreehugger Robot WS : (' '|'\n') {self.skip()} ; 175*16467b97STreehugger Robot ''') 176*16467b97STreehugger Robot 177*16467b97STreehugger Robot found = self.execParser( 178*16467b97STreehugger Robot master, 's', 179*16467b97STreehugger Robot slaves=[slave], 180*16467b97STreehugger Robot input="b" 181*16467b97STreehugger Robot ) 182*16467b97STreehugger Robot 183*16467b97STreehugger Robot self.assertEqual("S.a1000", found) 184*16467b97STreehugger Robot 185*16467b97STreehugger Robot 186*16467b97STreehugger Robot def testDelegatorAccessesDelegateMembers(self): 187*16467b97STreehugger Robot slave = textwrap.dedent( 188*16467b97STreehugger Robot r''' 189*16467b97STreehugger Robot parser grammar S3; 190*16467b97STreehugger Robot options { 191*16467b97STreehugger Robot language=Python3; 192*16467b97STreehugger Robot } 193*16467b97STreehugger Robot @members { 194*16467b97STreehugger Robot def capture(self, t): 195*16467b97STreehugger Robot self.gM3.capture(t) 196*16467b97STreehugger Robot 197*16467b97STreehugger Robot def foo(self): 198*16467b97STreehugger Robot self.capture("foo") 199*16467b97STreehugger Robot } 200*16467b97STreehugger Robot a : B ; 201*16467b97STreehugger Robot ''') 202*16467b97STreehugger Robot 203*16467b97STreehugger Robot master = textwrap.dedent( 204*16467b97STreehugger Robot r''' 205*16467b97STreehugger Robot grammar M3; // uses no rules from the import 206*16467b97STreehugger Robot options { 207*16467b97STreehugger Robot language=Python3; 208*16467b97STreehugger Robot } 209*16467b97STreehugger Robot import S3; 210*16467b97STreehugger Robot s : 'b' {self.gS3.foo();} ; // gS is import pointer 211*16467b97STreehugger Robot WS : (' '|'\n') {self.skip()} ; 212*16467b97STreehugger Robot ''') 213*16467b97STreehugger Robot 214*16467b97STreehugger Robot found = self.execParser( 215*16467b97STreehugger Robot master, 's', 216*16467b97STreehugger Robot slaves=[slave], 217*16467b97STreehugger Robot input="b" 218*16467b97STreehugger Robot ) 219*16467b97STreehugger Robot 220*16467b97STreehugger Robot self.assertEqual("foo", found) 221*16467b97STreehugger Robot 222*16467b97STreehugger Robot 223*16467b97STreehugger Robot def testDelegatorInvokesFirstVersionOfDelegateRule(self): 224*16467b97STreehugger Robot slave = textwrap.dedent( 225*16467b97STreehugger Robot r''' 226*16467b97STreehugger Robot parser grammar S4; 227*16467b97STreehugger Robot options { 228*16467b97STreehugger Robot language=Python3; 229*16467b97STreehugger Robot } 230*16467b97STreehugger Robot @members { 231*16467b97STreehugger Robot def capture(self, t): 232*16467b97STreehugger Robot self.gM4.capture(t) 233*16467b97STreehugger Robot } 234*16467b97STreehugger Robot a : b {self.capture("S.a");} ; 235*16467b97STreehugger Robot b : B ; 236*16467b97STreehugger Robot ''') 237*16467b97STreehugger Robot 238*16467b97STreehugger Robot slave2 = textwrap.dedent( 239*16467b97STreehugger Robot r''' 240*16467b97STreehugger Robot parser grammar T4; 241*16467b97STreehugger Robot options { 242*16467b97STreehugger Robot language=Python3; 243*16467b97STreehugger Robot } 244*16467b97STreehugger Robot @members { 245*16467b97STreehugger Robot def capture(self, t): 246*16467b97STreehugger Robot self.gM4.capture(t) 247*16467b97STreehugger Robot } 248*16467b97STreehugger Robot a : B {self.capture("T.a");} ; // hidden by S.a 249*16467b97STreehugger Robot ''') 250*16467b97STreehugger Robot 251*16467b97STreehugger Robot master = textwrap.dedent( 252*16467b97STreehugger Robot r''' 253*16467b97STreehugger Robot grammar M4; 254*16467b97STreehugger Robot options { 255*16467b97STreehugger Robot language=Python3; 256*16467b97STreehugger Robot } 257*16467b97STreehugger Robot import S4,T4; 258*16467b97STreehugger Robot s : a ; 259*16467b97STreehugger Robot B : 'b' ; 260*16467b97STreehugger Robot WS : (' '|'\n') {self.skip()} ; 261*16467b97STreehugger Robot ''') 262*16467b97STreehugger Robot 263*16467b97STreehugger Robot found = self.execParser( 264*16467b97STreehugger Robot master, 's', 265*16467b97STreehugger Robot slaves=[slave, slave2], 266*16467b97STreehugger Robot input="b" 267*16467b97STreehugger Robot ) 268*16467b97STreehugger Robot 269*16467b97STreehugger Robot self.assertEqual("S.a", found) 270*16467b97STreehugger Robot 271*16467b97STreehugger Robot 272*16467b97STreehugger Robot def testDelegatesSeeSameTokenType(self): 273*16467b97STreehugger Robot slave = textwrap.dedent( 274*16467b97STreehugger Robot r''' 275*16467b97STreehugger Robot parser grammar S5; // A, B, C token type order 276*16467b97STreehugger Robot options { 277*16467b97STreehugger Robot language=Python3; 278*16467b97STreehugger Robot } 279*16467b97STreehugger Robot tokens { A; B; C; } 280*16467b97STreehugger Robot @members { 281*16467b97STreehugger Robot def capture(self, t): 282*16467b97STreehugger Robot self.gM5.capture(t) 283*16467b97STreehugger Robot } 284*16467b97STreehugger Robot x : A {self.capture("S.x ");} ; 285*16467b97STreehugger Robot ''') 286*16467b97STreehugger Robot 287*16467b97STreehugger Robot slave2 = textwrap.dedent( 288*16467b97STreehugger Robot r''' 289*16467b97STreehugger Robot parser grammar T5; 290*16467b97STreehugger Robot options { 291*16467b97STreehugger Robot language=Python3; 292*16467b97STreehugger Robot } 293*16467b97STreehugger Robot tokens { C; B; A; } /// reverse order 294*16467b97STreehugger Robot @members { 295*16467b97STreehugger Robot def capture(self, t): 296*16467b97STreehugger Robot self.gM5.capture(t) 297*16467b97STreehugger Robot } 298*16467b97STreehugger Robot y : A {self.capture("T.y");} ; 299*16467b97STreehugger Robot ''') 300*16467b97STreehugger Robot 301*16467b97STreehugger Robot master = textwrap.dedent( 302*16467b97STreehugger Robot r''' 303*16467b97STreehugger Robot grammar M5; 304*16467b97STreehugger Robot options { 305*16467b97STreehugger Robot language=Python3; 306*16467b97STreehugger Robot } 307*16467b97STreehugger Robot import S5,T5; 308*16467b97STreehugger Robot s : x y ; // matches AA, which should be "aa" 309*16467b97STreehugger Robot B : 'b' ; // another order: B, A, C 310*16467b97STreehugger Robot A : 'a' ; 311*16467b97STreehugger Robot C : 'c' ; 312*16467b97STreehugger Robot WS : (' '|'\n') {self.skip()} ; 313*16467b97STreehugger Robot ''') 314*16467b97STreehugger Robot 315*16467b97STreehugger Robot found = self.execParser( 316*16467b97STreehugger Robot master, 's', 317*16467b97STreehugger Robot slaves=[slave, slave2], 318*16467b97STreehugger Robot input="aa" 319*16467b97STreehugger Robot ) 320*16467b97STreehugger Robot 321*16467b97STreehugger Robot self.assertEqual("S.x T.y", found) 322*16467b97STreehugger Robot 323*16467b97STreehugger Robot 324*16467b97STreehugger Robot def testDelegatorRuleOverridesDelegate(self): 325*16467b97STreehugger Robot slave = textwrap.dedent( 326*16467b97STreehugger Robot r''' 327*16467b97STreehugger Robot parser grammar S6; 328*16467b97STreehugger Robot options { 329*16467b97STreehugger Robot language=Python3; 330*16467b97STreehugger Robot } 331*16467b97STreehugger Robot @members { 332*16467b97STreehugger Robot def capture(self, t): 333*16467b97STreehugger Robot self.gM6.capture(t) 334*16467b97STreehugger Robot } 335*16467b97STreehugger Robot a : b {self.capture("S.a");} ; 336*16467b97STreehugger Robot b : B ; 337*16467b97STreehugger Robot ''') 338*16467b97STreehugger Robot 339*16467b97STreehugger Robot master = textwrap.dedent( 340*16467b97STreehugger Robot r''' 341*16467b97STreehugger Robot grammar M6; 342*16467b97STreehugger Robot options { 343*16467b97STreehugger Robot language=Python3; 344*16467b97STreehugger Robot } 345*16467b97STreehugger Robot import S6; 346*16467b97STreehugger Robot b : 'b'|'c' ; 347*16467b97STreehugger Robot WS : (' '|'\n') {self.skip()} ; 348*16467b97STreehugger Robot ''') 349*16467b97STreehugger Robot 350*16467b97STreehugger Robot found = self.execParser( 351*16467b97STreehugger Robot master, 'a', 352*16467b97STreehugger Robot slaves=[slave], 353*16467b97STreehugger Robot input="c" 354*16467b97STreehugger Robot ) 355*16467b97STreehugger Robot 356*16467b97STreehugger Robot self.assertEqual("S.a", found) 357*16467b97STreehugger Robot 358*16467b97STreehugger Robot 359*16467b97STreehugger Robot # LEXER INHERITANCE 360*16467b97STreehugger Robot 361*16467b97STreehugger Robot def testLexerDelegatorInvokesDelegateRule(self): 362*16467b97STreehugger Robot slave = textwrap.dedent( 363*16467b97STreehugger Robot r''' 364*16467b97STreehugger Robot lexer grammar S7; 365*16467b97STreehugger Robot options { 366*16467b97STreehugger Robot language=Python3; 367*16467b97STreehugger Robot } 368*16467b97STreehugger Robot @members { 369*16467b97STreehugger Robot def capture(self, t): 370*16467b97STreehugger Robot self.gM7.capture(t) 371*16467b97STreehugger Robot } 372*16467b97STreehugger Robot A : 'a' {self.capture("S.A ");} ; 373*16467b97STreehugger Robot C : 'c' ; 374*16467b97STreehugger Robot ''') 375*16467b97STreehugger Robot 376*16467b97STreehugger Robot master = textwrap.dedent( 377*16467b97STreehugger Robot r''' 378*16467b97STreehugger Robot lexer grammar M7; 379*16467b97STreehugger Robot options { 380*16467b97STreehugger Robot language=Python3; 381*16467b97STreehugger Robot } 382*16467b97STreehugger Robot import S7; 383*16467b97STreehugger Robot B : 'b' ; 384*16467b97STreehugger Robot WS : (' '|'\n') {self.skip()} ; 385*16467b97STreehugger Robot ''') 386*16467b97STreehugger Robot 387*16467b97STreehugger Robot found = self.execLexer( 388*16467b97STreehugger Robot master, 389*16467b97STreehugger Robot slaves=[slave], 390*16467b97STreehugger Robot input="abc" 391*16467b97STreehugger Robot ) 392*16467b97STreehugger Robot 393*16467b97STreehugger Robot self.assertEqual("S.A abc", found) 394*16467b97STreehugger Robot 395*16467b97STreehugger Robot 396*16467b97STreehugger Robot def testLexerDelegatorRuleOverridesDelegate(self): 397*16467b97STreehugger Robot slave = textwrap.dedent( 398*16467b97STreehugger Robot r''' 399*16467b97STreehugger Robot lexer grammar S8; 400*16467b97STreehugger Robot options { 401*16467b97STreehugger Robot language=Python3; 402*16467b97STreehugger Robot } 403*16467b97STreehugger Robot @members { 404*16467b97STreehugger Robot def capture(self, t): 405*16467b97STreehugger Robot self.gM8.capture(t) 406*16467b97STreehugger Robot } 407*16467b97STreehugger Robot A : 'a' {self.capture("S.A")} ; 408*16467b97STreehugger Robot ''') 409*16467b97STreehugger Robot 410*16467b97STreehugger Robot master = textwrap.dedent( 411*16467b97STreehugger Robot r''' 412*16467b97STreehugger Robot lexer grammar M8; 413*16467b97STreehugger Robot options { 414*16467b97STreehugger Robot language=Python3; 415*16467b97STreehugger Robot } 416*16467b97STreehugger Robot import S8; 417*16467b97STreehugger Robot A : 'a' {self.capture("M.A ");} ; 418*16467b97STreehugger Robot WS : (' '|'\n') {self.skip()} ; 419*16467b97STreehugger Robot ''') 420*16467b97STreehugger Robot 421*16467b97STreehugger Robot found = self.execLexer( 422*16467b97STreehugger Robot master, 423*16467b97STreehugger Robot slaves=[slave], 424*16467b97STreehugger Robot input="a" 425*16467b97STreehugger Robot ) 426*16467b97STreehugger Robot 427*16467b97STreehugger Robot self.assertEqual("M.A a", found) 428*16467b97STreehugger Robot 429*16467b97STreehugger Robot 430*16467b97STreehugger Robotif __name__ == '__main__': 431*16467b97STreehugger Robot unittest.main() 432