| 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() |