432 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			432 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Python
		
	
	
	
| import unittest
 | |
| import textwrap
 | |
| import antlr3
 | |
| import antlr3.tree
 | |
| import testbase
 | |
| import sys
 | |
| 
 | |
| class T(testbase.ANTLRTest):
 | |
|     def setUp(self):
 | |
|         self.oldPath = sys.path[:]
 | |
|         sys.path.insert(0, self.baseDir)
 | |
| 
 | |
| 
 | |
|     def tearDown(self):
 | |
|         sys.path = self.oldPath
 | |
| 
 | |
| 
 | |
|     def parserClass(self, base):
 | |
|         class TParser(base):
 | |
|             def __init__(self, *args, **kwargs):
 | |
|                 super().__init__(*args, **kwargs)
 | |
| 
 | |
|                 self._output = ""
 | |
| 
 | |
| 
 | |
|             def capture(self, t):
 | |
|                 self._output += t
 | |
| 
 | |
| 
 | |
|             def traceIn(self, ruleName, ruleIndex):
 | |
|                 self.traces.append('>'+ruleName)
 | |
| 
 | |
| 
 | |
|             def traceOut(self, ruleName, ruleIndex):
 | |
|                 self.traces.append('<'+ruleName)
 | |
| 
 | |
| 
 | |
|             def recover(self, input, re):
 | |
|                 # no error recovery yet, just crash!
 | |
|                 raise
 | |
| 
 | |
|         return TParser
 | |
| 
 | |
| 
 | |
|     def lexerClass(self, base):
 | |
|         class TLexer(base):
 | |
|             def __init__(self, *args, **kwargs):
 | |
|                 super().__init__(*args, **kwargs)
 | |
| 
 | |
|                 self._output = ""
 | |
| 
 | |
| 
 | |
|             def capture(self, t):
 | |
|                 self._output += t
 | |
| 
 | |
| 
 | |
|             def traceIn(self, ruleName, ruleIndex):
 | |
|                 self.traces.append('>'+ruleName)
 | |
| 
 | |
| 
 | |
|             def traceOut(self, ruleName, ruleIndex):
 | |
|                 self.traces.append('<'+ruleName)
 | |
| 
 | |
| 
 | |
|             def recover(self, input):
 | |
|                 # no error recovery yet, just crash!
 | |
|                 raise
 | |
| 
 | |
|         return TLexer
 | |
| 
 | |
| 
 | |
|     def execParser(self, grammar, grammarEntry, slaves, input):
 | |
|         for slave in slaves:
 | |
|             parserName = self.writeInlineGrammar(slave)[0]
 | |
|             # slave parsers are imported as normal python modules
 | |
|             # to force reloading current version, purge module from sys.modules
 | |
|             if parserName + 'Parser' in sys.modules:
 | |
|                 del sys.modules[parserName + 'Parser']
 | |
| 
 | |
|         lexerCls, parserCls = self.compileInlineGrammar(grammar)
 | |
| 
 | |
|         cStream = antlr3.StringStream(input)
 | |
|         lexer = lexerCls(cStream)
 | |
|         tStream = antlr3.CommonTokenStream(lexer)
 | |
|         parser = parserCls(tStream)
 | |
|         getattr(parser, grammarEntry)()
 | |
| 
 | |
|         return parser._output
 | |
| 
 | |
| 
 | |
|     def execLexer(self, grammar, slaves, input):
 | |
|         for slave in slaves:
 | |
|             parserName = self.writeInlineGrammar(slave)[0]
 | |
|             # slave parsers are imported as normal python modules
 | |
|             # to force reloading current version, purge module from sys.modules
 | |
|             if parserName + 'Parser' in sys.modules:
 | |
|                 del sys.modules[parserName + 'Parser']
 | |
| 
 | |
|         lexerCls = self.compileInlineGrammar(grammar)
 | |
| 
 | |
|         cStream = antlr3.StringStream(input)
 | |
|         lexer = lexerCls(cStream)
 | |
| 
 | |
|         while True:
 | |
|             token = lexer.nextToken()
 | |
|             if token is None or token.type == antlr3.EOF:
 | |
|                 break
 | |
| 
 | |
|             lexer._output += token.text
 | |
| 
 | |
|         return lexer._output
 | |
| 
 | |
| 
 | |
|     def testDelegatorInvokesDelegateRule(self):
 | |
|         slave = textwrap.dedent(
 | |
|         r'''
 | |
|         parser grammar S1;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         @members {
 | |
|             def capture(self, t):
 | |
|                 self.gM1.capture(t)
 | |
| 
 | |
|         }
 | |
| 
 | |
|         a : B { self.capture("S.a") } ;
 | |
|         ''')
 | |
| 
 | |
|         master = textwrap.dedent(
 | |
|         r'''
 | |
|         grammar M1;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         import S1;
 | |
|         s : a ;
 | |
|         B : 'b' ; // defines B from inherited token space
 | |
|         WS : (' '|'\n') {self.skip()} ;
 | |
|         ''')
 | |
| 
 | |
|         found = self.execParser(
 | |
|             master, 's',
 | |
|             slaves=[slave],
 | |
|             input="b"
 | |
|             )
 | |
| 
 | |
|         self.assertEqual("S.a", found)
 | |
| 
 | |
| 
 | |
|     def testDelegatorInvokesDelegateRuleWithArgs(self):
 | |
|         slave = textwrap.dedent(
 | |
|         r'''
 | |
|         parser grammar S2;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         @members {
 | |
|             def capture(self, t):
 | |
|                 self.gM2.capture(t)
 | |
|         }
 | |
|         a[x] returns [y] : B {self.capture("S.a"); $y="1000";} ;
 | |
|         ''')
 | |
| 
 | |
|         master = textwrap.dedent(
 | |
|         r'''
 | |
|         grammar M2;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         import S2;
 | |
|         s : label=a[3] {self.capture($label.y);} ;
 | |
|         B : 'b' ; // defines B from inherited token space
 | |
|         WS : (' '|'\n') {self.skip()} ;
 | |
|         ''')
 | |
| 
 | |
|         found = self.execParser(
 | |
|             master, 's',
 | |
|             slaves=[slave],
 | |
|             input="b"
 | |
|             )
 | |
| 
 | |
|         self.assertEqual("S.a1000", found)
 | |
| 
 | |
| 
 | |
|     def testDelegatorAccessesDelegateMembers(self):
 | |
|         slave = textwrap.dedent(
 | |
|         r'''
 | |
|         parser grammar S3;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         @members {
 | |
|             def capture(self, t):
 | |
|                 self.gM3.capture(t)
 | |
| 
 | |
|             def foo(self):
 | |
|                 self.capture("foo")
 | |
|         }
 | |
|         a : B ;
 | |
|         ''')
 | |
| 
 | |
|         master = textwrap.dedent(
 | |
|         r'''
 | |
|         grammar M3;        // uses no rules from the import
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         import S3;
 | |
|         s : 'b' {self.gS3.foo();} ; // gS is import pointer
 | |
|         WS : (' '|'\n') {self.skip()} ;
 | |
|         ''')
 | |
| 
 | |
|         found = self.execParser(
 | |
|             master, 's',
 | |
|             slaves=[slave],
 | |
|             input="b"
 | |
|             )
 | |
| 
 | |
|         self.assertEqual("foo", found)
 | |
| 
 | |
| 
 | |
|     def testDelegatorInvokesFirstVersionOfDelegateRule(self):
 | |
|         slave = textwrap.dedent(
 | |
|         r'''
 | |
|         parser grammar S4;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         @members {
 | |
|             def capture(self, t):
 | |
|                 self.gM4.capture(t)
 | |
|         }
 | |
|         a : b {self.capture("S.a");} ;
 | |
|         b : B ;
 | |
|         ''')
 | |
| 
 | |
|         slave2 = textwrap.dedent(
 | |
|         r'''
 | |
|         parser grammar T4;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         @members {
 | |
|             def capture(self, t):
 | |
|                 self.gM4.capture(t)
 | |
|         }
 | |
|         a : B {self.capture("T.a");} ; // hidden by S.a
 | |
|         ''')
 | |
| 
 | |
|         master = textwrap.dedent(
 | |
|         r'''
 | |
|         grammar M4;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         import S4,T4;
 | |
|         s : a ;
 | |
|         B : 'b' ;
 | |
|         WS : (' '|'\n') {self.skip()} ;
 | |
|         ''')
 | |
| 
 | |
|         found = self.execParser(
 | |
|             master, 's',
 | |
|             slaves=[slave, slave2],
 | |
|             input="b"
 | |
|             )
 | |
| 
 | |
|         self.assertEqual("S.a", found)
 | |
| 
 | |
| 
 | |
|     def testDelegatesSeeSameTokenType(self):
 | |
|         slave = textwrap.dedent(
 | |
|         r'''
 | |
|         parser grammar S5; // A, B, C token type order
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         tokens { A; B; C; }
 | |
|         @members {
 | |
|             def capture(self, t):
 | |
|                 self.gM5.capture(t)
 | |
|         }
 | |
|         x : A {self.capture("S.x ");} ;
 | |
|         ''')
 | |
| 
 | |
|         slave2 = textwrap.dedent(
 | |
|         r'''
 | |
|         parser grammar T5;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         tokens { C; B; A; } /// reverse order
 | |
|         @members {
 | |
|             def capture(self, t):
 | |
|                 self.gM5.capture(t)
 | |
|         }
 | |
|         y : A {self.capture("T.y");} ;
 | |
|         ''')
 | |
| 
 | |
|         master = textwrap.dedent(
 | |
|         r'''
 | |
|         grammar M5;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         import S5,T5;
 | |
|         s : x y ; // matches AA, which should be "aa"
 | |
|         B : 'b' ; // another order: B, A, C
 | |
|         A : 'a' ;
 | |
|         C : 'c' ;
 | |
|         WS : (' '|'\n') {self.skip()} ;
 | |
|         ''')
 | |
| 
 | |
|         found = self.execParser(
 | |
|             master, 's',
 | |
|             slaves=[slave, slave2],
 | |
|             input="aa"
 | |
|             )
 | |
| 
 | |
|         self.assertEqual("S.x T.y", found)
 | |
| 
 | |
| 
 | |
|     def testDelegatorRuleOverridesDelegate(self):
 | |
|         slave = textwrap.dedent(
 | |
|         r'''
 | |
|         parser grammar S6;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         @members {
 | |
|             def capture(self, t):
 | |
|                 self.gM6.capture(t)
 | |
|         }
 | |
|         a : b {self.capture("S.a");} ;
 | |
|         b : B ;
 | |
|         ''')
 | |
| 
 | |
|         master = textwrap.dedent(
 | |
|         r'''
 | |
|         grammar M6;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         import S6;
 | |
|         b : 'b'|'c' ;
 | |
|         WS : (' '|'\n') {self.skip()} ;
 | |
|         ''')
 | |
| 
 | |
|         found = self.execParser(
 | |
|             master, 'a',
 | |
|             slaves=[slave],
 | |
|             input="c"
 | |
|             )
 | |
| 
 | |
|         self.assertEqual("S.a", found)
 | |
| 
 | |
| 
 | |
|     # LEXER INHERITANCE
 | |
| 
 | |
|     def testLexerDelegatorInvokesDelegateRule(self):
 | |
|         slave = textwrap.dedent(
 | |
|         r'''
 | |
|         lexer grammar S7;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         @members {
 | |
|             def capture(self, t):
 | |
|                 self.gM7.capture(t)
 | |
|         }
 | |
|         A : 'a' {self.capture("S.A ");} ;
 | |
|         C : 'c' ;
 | |
|         ''')
 | |
| 
 | |
|         master = textwrap.dedent(
 | |
|         r'''
 | |
|         lexer grammar M7;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         import S7;
 | |
|         B : 'b' ;
 | |
|         WS : (' '|'\n') {self.skip()} ;
 | |
|         ''')
 | |
| 
 | |
|         found = self.execLexer(
 | |
|             master,
 | |
|             slaves=[slave],
 | |
|             input="abc"
 | |
|             )
 | |
| 
 | |
|         self.assertEqual("S.A abc", found)
 | |
| 
 | |
| 
 | |
|     def testLexerDelegatorRuleOverridesDelegate(self):
 | |
|         slave = textwrap.dedent(
 | |
|         r'''
 | |
|         lexer grammar S8;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         @members {
 | |
|             def capture(self, t):
 | |
|                 self.gM8.capture(t)
 | |
|         }
 | |
|         A : 'a' {self.capture("S.A")} ;
 | |
|         ''')
 | |
| 
 | |
|         master = textwrap.dedent(
 | |
|         r'''
 | |
|         lexer grammar M8;
 | |
|         options {
 | |
|             language=Python3;
 | |
|         }
 | |
|         import S8;
 | |
|         A : 'a' {self.capture("M.A ");} ;
 | |
|         WS : (' '|'\n') {self.skip()} ;
 | |
|         ''')
 | |
| 
 | |
|         found = self.execLexer(
 | |
|             master,
 | |
|             slaves=[slave],
 | |
|             input="a"
 | |
|             )
 | |
| 
 | |
|         self.assertEqual("M.A a", found)
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     unittest.main()
 |