469 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			469 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
| import unittest
 | |
| import re
 | |
| import textwrap
 | |
| import antlr3
 | |
| import testbase
 | |
| 
 | |
| 
 | |
| # Left-recursion resolution is not yet enabled in the tool.
 | |
| 
 | |
| # class TestLeftRecursion(testbase.ANTLRTest):
 | |
| #     def parserClass(self, base):
 | |
| #         class TParser(base):
 | |
| #             def __init__(self, *args, **kwargs):
 | |
| #                 super().__init__(*args, **kwargs)
 | |
| 
 | |
| #                 self._output = ""
 | |
| 
 | |
| 
 | |
| #             def capture(self, t):
 | |
| #                 self._output += str(t)
 | |
| 
 | |
| 
 | |
| #             def recover(self, input, re):
 | |
| #                 # no error recovery yet, just crash!
 | |
| #                 raise
 | |
| 
 | |
| #         return TParser
 | |
| 
 | |
| 
 | |
| #     def execParser(self, grammar, grammarEntry, input):
 | |
| #         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 runTests(self, grammar, tests, grammarEntry):
 | |
| #         lexerCls, parserCls = self.compileInlineGrammar(grammar)
 | |
| 
 | |
| #         build_ast = re.search(r'output\s*=\s*AST', grammar)
 | |
| 
 | |
| #         for input, expecting in tests:
 | |
| #             cStream = antlr3.StringStream(input)
 | |
| #             lexer = lexerCls(cStream)
 | |
| #             tStream = antlr3.CommonTokenStream(lexer)
 | |
| #             parser = parserCls(tStream)
 | |
| #             r = getattr(parser, grammarEntry)()
 | |
| #             found = parser._output
 | |
| #             if build_ast:
 | |
| #               found += r.tree.toStringTree()
 | |
| 
 | |
| #             self.assertEqual(
 | |
| #                 expecting, found,
 | |
| #                 "{!r} != {!r} (for input {!r})".format(expecting, found, input))
 | |
| 
 | |
| 
 | |
| #     def testSimple(self):
 | |
| #         grammar = textwrap.dedent(
 | |
| #             r"""
 | |
| #             grammar T;
 | |
| #             options {
 | |
| #                 language=Python3;
 | |
| #             }
 | |
| #             s : a { self.capture($a.text) } ;
 | |
| #             a : a ID
 | |
| #               | ID
 | |
| #               ;
 | |
| #             ID : 'a'..'z'+ ;
 | |
| #             WS : (' '|'\n') {self.skip()} ;
 | |
| #             """)
 | |
| 
 | |
| #         found = self.execParser(grammar, 's', 'a b c')
 | |
| #         expecting = "abc"
 | |
| #         self.assertEqual(expecting, found)
 | |
| 
 | |
| 
 | |
| #     def testSemPred(self):
 | |
| #         grammar = textwrap.dedent(
 | |
| #             r"""
 | |
| #             grammar T;
 | |
| #             options {
 | |
| #                 language=Python3;
 | |
| #             }
 | |
| #             s : a { self.capture($a.text) } ;
 | |
| #             a : a {True}? ID
 | |
| #               | ID
 | |
| #               ;
 | |
| #             ID : 'a'..'z'+ ;
 | |
| #             WS : (' '|'\n') {self.skip()} ;
 | |
| #             """)
 | |
| 
 | |
| #         found = self.execParser(grammar, "s", "a b c")
 | |
| #         expecting = "abc"
 | |
| #         self.assertEqual(expecting, found)
 | |
| 
 | |
| #     def testTernaryExpr(self):
 | |
| #         grammar = textwrap.dedent(
 | |
| #             r"""
 | |
| #             grammar T;
 | |
| #             options {
 | |
| #                 language=Python3;
 | |
| #                 output=AST;
 | |
| #             }
 | |
| #             e : e '*'^ e
 | |
| #               | e '+'^ e
 | |
| #               | e '?'<assoc=right>^ e ':'! e
 | |
| #               | e '='<assoc=right>^ e
 | |
| #               | ID
 | |
| #               ;
 | |
| #             ID : 'a'..'z'+ ;
 | |
| #             WS : (' '|'\n') {self.skip()} ;
 | |
| #             """)
 | |
| 
 | |
| #         tests = [
 | |
| #             ("a", "a"),
 | |
| #             ("a+b", "(+ a b)"),
 | |
| #             ("a*b", "(* a b)"),
 | |
| #             ("a?b:c", "(? a b c)"),
 | |
| #             ("a=b=c", "(= a (= b c))"),
 | |
| #             ("a?b+c:d", "(? a (+ b c) d)"),
 | |
| #             ("a?b=c:d", "(? a (= b c) d)"),
 | |
| #             ("a? b?c:d : e", "(? a (? b c d) e)"),
 | |
| #             ("a?b: c?d:e", "(? a b (? c d e))"),
 | |
| #             ]
 | |
| #         self.runTests(grammar, tests, "e")
 | |
| 
 | |
| 
 | |
| #     def testDeclarationsUsingASTOperators(self):
 | |
| #         grammar = textwrap.dedent(
 | |
| #             r"""
 | |
| #             grammar T;
 | |
| #             options {
 | |
| #                 language=Python3;
 | |
| #                 output=AST;
 | |
| #             }
 | |
| #             declarator
 | |
| #                     : declarator '['^ e ']'!
 | |
| #                     | declarator '['^ ']'!
 | |
| #                     | declarator '('^ ')'!
 | |
| #                     | '*'^ declarator // binds less tight than suffixes
 | |
| #                     | '('! declarator ')'!
 | |
| #                     | ID
 | |
| #                     ;
 | |
| #             e : INT ;
 | |
| #             ID : 'a'..'z'+ ;
 | |
| #             INT : '0'..'9'+ ;
 | |
| #             WS : (' '|'\n') {self.skip()} ;
 | |
| #             """)
 | |
| 
 | |
| #         tests = [
 | |
| #             ("a", "a"),
 | |
| #             ("*a", "(* a)"),
 | |
| #             ("**a", "(* (* a))"),
 | |
| #             ("a[3]", "([ a 3)"),
 | |
| #             ("b[]", "([ b)"),
 | |
| #             ("(a)", "a"),
 | |
| #             ("a[]()", "(( ([ a))"),
 | |
| #             ("a[][]", "([ ([ a))"),
 | |
| #             ("*a[]", "(* ([ a))"),
 | |
| #             ("(*a)[]", "([ (* a))"),
 | |
| #             ]
 | |
| #         self.runTests(grammar, tests, "declarator")
 | |
| 
 | |
| 
 | |
| #     def testDeclarationsUsingRewriteOperators(self):
 | |
| #         grammar = textwrap.dedent(
 | |
| #             r"""
 | |
| #             grammar T;
 | |
| #             options {
 | |
| #                 language=Python3;
 | |
| #                 output=AST;
 | |
| #             }
 | |
| #             declarator
 | |
| #                     : declarator '[' e ']' -> ^('[' declarator e)
 | |
| #                     | declarator '[' ']' -> ^('[' declarator)
 | |
| #                     | declarator '(' ')' -> ^('(' declarator)
 | |
| #                     | '*' declarator -> ^('*' declarator)  // binds less tight than suffixes
 | |
| #                     | '(' declarator ')' -> declarator
 | |
| #                     | ID -> ID
 | |
| #                     ;
 | |
| #             e : INT ;
 | |
| #             ID : 'a'..'z'+ ;
 | |
| #             INT : '0'..'9'+ ;
 | |
| #             WS : (' '|'\n') {self.skip()} ;
 | |
| #             """)
 | |
| 
 | |
| #         tests = [
 | |
| #             ("a", "a"),
 | |
| #             ("*a", "(* a)"),
 | |
| #             ("**a", "(* (* a))"),
 | |
| #             ("a[3]", "([ a 3)"),
 | |
| #             ("b[]", "([ b)"),
 | |
| #             ("(a)", "a"),
 | |
| #             ("a[]()", "(( ([ a))"),
 | |
| #             ("a[][]", "([ ([ a))"),
 | |
| #             ("*a[]", "(* ([ a))"),
 | |
| #             ("(*a)[]", "([ (* a))"),
 | |
| #             ]
 | |
| #         self.runTests(grammar, tests, "declarator")
 | |
| 
 | |
| 
 | |
| #     def testExpressionsUsingASTOperators(self):
 | |
| #         grammar = textwrap.dedent(
 | |
| #             r"""
 | |
| #             grammar T;
 | |
| #             options {
 | |
| #                 language=Python3;
 | |
| #                 output=AST;
 | |
| #             }
 | |
| #             e : e '.'^ ID
 | |
| #               | e '.'^ 'this'
 | |
| #               | '-'^ e
 | |
| #               | e '*'^ e
 | |
| #               | e ('+'^|'-'^) e
 | |
| #               | INT
 | |
| #               | ID
 | |
| #               ;
 | |
| #             ID : 'a'..'z'+ ;
 | |
| #             INT : '0'..'9'+ ;
 | |
| #             WS : (' '|'\n') {self.skip()} ;
 | |
| #             """)
 | |
| 
 | |
| #         tests = [
 | |
| #             ("a", "a"),
 | |
| #             ("1", "1"),
 | |
| #             ("a+1", "(+ a 1)"),
 | |
| #             ("a*1", "(* a 1)"),
 | |
| #             ("a.b", "(. a b)"),
 | |
| #             ("a.this", "(. a this)"),
 | |
| #             ("a-b+c", "(+ (- a b) c)"),
 | |
| #             ("a+b*c", "(+ a (* b c))"),
 | |
| #             ("a.b+1", "(+ (. a b) 1)"),
 | |
| #             ("-a", "(- a)"),
 | |
| #             ("-a+b", "(+ (- a) b)"),
 | |
| #             ("-a.b", "(- (. a b))"),
 | |
| #             ]
 | |
| #         self.runTests(grammar, tests, "e")
 | |
| 
 | |
| 
 | |
| #     @testbase.broken(
 | |
| #         "Grammar compilation returns errors", testbase.GrammarCompileError)
 | |
| #     def testExpressionsUsingRewriteOperators(self):
 | |
| #         grammar = textwrap.dedent(
 | |
| #             r"""
 | |
| #             grammar T;
 | |
| #             options {
 | |
| #                 language=Python3;
 | |
| #                 output=AST;
 | |
| #             }
 | |
| #             e : e '.' ID                   -> ^('.' e ID)
 | |
| #               | e '.' 'this'               -> ^('.' e 'this')
 | |
| #               | '-' e                      -> ^('-' e)
 | |
| #               | e '*' b=e                  -> ^('*' e $b)
 | |
| #               | e (op='+'|op='-') b=e      -> ^($op e $b)
 | |
| #               | INT                        -> INT
 | |
| #               | ID                         -> ID
 | |
| #               ;
 | |
| #             ID : 'a'..'z'+ ;
 | |
| #             INT : '0'..'9'+ ;
 | |
| #             WS : (' '|'\n') {self.skip()} ;
 | |
| #             """)
 | |
| 
 | |
| #         tests = [
 | |
| #             ("a", "a"),
 | |
| #             ("1", "1"),
 | |
| #             ("a+1", "(+ a 1)"),
 | |
| #             ("a*1", "(* a 1)"),
 | |
| #             ("a.b", "(. a b)"),
 | |
| #             ("a.this", "(. a this)"),
 | |
| #             ("a+b*c", "(+ a (* b c))"),
 | |
| #             ("a.b+1", "(+ (. a b) 1)"),
 | |
| #             ("-a", "(- a)"),
 | |
| #             ("-a+b", "(+ (- a) b)"),
 | |
| #             ("-a.b", "(- (. a b))"),
 | |
| #             ]
 | |
| #         self.runTests(grammar, tests, "e")
 | |
| 
 | |
| 
 | |
| #     def testExpressionAssociativity(self):
 | |
| #         grammar = textwrap.dedent(
 | |
| #             r"""
 | |
| #             grammar T;
 | |
| #             options {
 | |
| #                 language=Python3;
 | |
| #                 output=AST;
 | |
| #             }
 | |
| #             e
 | |
| #               : e '.'^ ID
 | |
| #               | '-'^ e
 | |
| #               | e '^'<assoc=right>^ e
 | |
| #               | e '*'^ e
 | |
| #               | e ('+'^|'-'^) e
 | |
| #               | e ('='<assoc=right>^ |'+='<assoc=right>^) e
 | |
| #               | INT
 | |
| #               | ID
 | |
| #               ;
 | |
| #             ID : 'a'..'z'+ ;
 | |
| #             INT : '0'..'9'+ ;
 | |
| #             WS : (' '|'\n') {self.skip()} ;
 | |
| #             """)
 | |
| 
 | |
| #         tests = [
 | |
| #             ("a", "a"),
 | |
| #             ("1", "1"),
 | |
| #             ("a+1", "(+ a 1)"),
 | |
| #             ("a*1", "(* a 1)"),
 | |
| #             ("a.b", "(. a b)"),
 | |
| #             ("a-b+c", "(+ (- a b) c)"),
 | |
| #             ("a+b*c", "(+ a (* b c))"),
 | |
| #             ("a.b+1", "(+ (. a b) 1)"),
 | |
| #             ("-a", "(- a)"),
 | |
| #             ("-a+b", "(+ (- a) b)"),
 | |
| #             ("-a.b", "(- (. a b))"),
 | |
| #             ("a^b^c", "(^ a (^ b c))"),
 | |
| #             ("a=b=c", "(= a (= b c))"),
 | |
| #             ("a=b=c+d.e", "(= a (= b (+ c (. d e))))"),
 | |
| #             ]
 | |
| #         self.runTests(grammar, tests, "e")
 | |
| 
 | |
| 
 | |
| #     def testJavaExpressions(self):
 | |
| #       grammar = textwrap.dedent(
 | |
| #             r"""
 | |
| #             grammar T;
 | |
| #             options {
 | |
| #                 language=Python3;
 | |
| #                 output=AST;
 | |
| #             }
 | |
| #             expressionList
 | |
| #                 :   e (','! e)*
 | |
| #                 ;
 | |
| #             e   :   '('! e ')'!
 | |
| #                 |   'this'
 | |
| #                 |   'super'
 | |
| #                 |   INT
 | |
| #                 |   ID
 | |
| #                 |   type '.'^ 'class'
 | |
| #                 |   e '.'^ ID
 | |
| #                 |   e '.'^ 'this'
 | |
| #                 |   e '.'^ 'super' '('^ expressionList? ')'!
 | |
| #                 |   e '.'^ 'new'^ ID '('! expressionList? ')'!
 | |
| #                 |       'new'^ type ( '(' expressionList? ')'! | (options {k=1;}:'[' e ']'!)+) // ugly; simplified
 | |
| #                 |   e '['^ e ']'!
 | |
| #                 |   '('^ type ')'! e
 | |
| #                 |   e ('++'^ | '--'^)
 | |
| #                 |   e '('^ expressionList? ')'!
 | |
| #                 |   ('+'^|'-'^|'++'^|'--'^) e
 | |
| #                 |   ('~'^|'!'^) e
 | |
| #                 |   e ('*'^|'/'^|'%'^) e
 | |
| #                 |   e ('+'^|'-'^) e
 | |
| #                 |   e ('<'^ '<' | '>'^ '>' '>' | '>'^ '>') e
 | |
| #                 |   e ('<='^ | '>='^ | '>'^ | '<'^) e
 | |
| #                 |   e 'instanceof'^ e
 | |
| #                 |   e ('=='^ | '!='^) e
 | |
| #                 |   e '&'^ e
 | |
| #                 |   e '^'<assoc=right>^ e
 | |
| #                 |   e '|'^ e
 | |
| #                 |   e '&&'^ e
 | |
| #                 |   e '||'^ e
 | |
| #                 |   e '?' e ':' e
 | |
| #                 |   e ('='<assoc=right>^
 | |
| #                       |'+='<assoc=right>^
 | |
| #                       |'-='<assoc=right>^
 | |
| #                       |'*='<assoc=right>^
 | |
| #                       |'/='<assoc=right>^
 | |
| #                       |'&='<assoc=right>^
 | |
| #                       |'|='<assoc=right>^
 | |
| #                       |'^='<assoc=right>^
 | |
| #                       |'>>='<assoc=right>^
 | |
| #                       |'>>>='<assoc=right>^
 | |
| #                       |'<<='<assoc=right>^
 | |
| #                       |'%='<assoc=right>^) e
 | |
| #                 ;
 | |
| #             type: ID
 | |
| #                 | ID '['^ ']'!
 | |
| #                 | 'int'
 | |
| #                 | 'int' '['^ ']'!
 | |
| #                 ;
 | |
| #             ID : ('a'..'z'|'A'..'Z'|'_'|'$')+;
 | |
| #             INT : '0'..'9'+ ;
 | |
| #             WS : (' '|'\n') {self.skip()} ;
 | |
| #             """)
 | |
| 
 | |
| #       tests = [
 | |
| #           ("a", "a"),
 | |
| #           ("1", "1"),
 | |
| #           ("a+1", "(+ a 1)"),
 | |
| #           ("a*1", "(* a 1)"),
 | |
| #           ("a.b", "(. a b)"),
 | |
| #           ("a-b+c", "(+ (- a b) c)"),
 | |
| #           ("a+b*c", "(+ a (* b c))"),
 | |
| #           ("a.b+1", "(+ (. a b) 1)"),
 | |
| #           ("-a", "(- a)"),
 | |
| #           ("-a+b", "(+ (- a) b)"),
 | |
| #           ("-a.b", "(- (. a b))"),
 | |
| #           ("a^b^c", "(^ a (^ b c))"),
 | |
| #           ("a=b=c", "(= a (= b c))"),
 | |
| #           ("a=b=c+d.e", "(= a (= b (+ c (. d e))))"),
 | |
| #           ("a|b&c", "(| a (& b c))"),
 | |
| #           ("(a|b)&c", "(& (| a b) c)"),
 | |
| #           ("a > b", "(> a b)"),
 | |
| #           ("a >> b", "(> a b)"),  # text is from one token
 | |
| #           ("a < b", "(< a b)"),
 | |
| #           ("(T)x", "(( T x)"),
 | |
| #           ("new A().b", "(. (new A () b)"),
 | |
| #           ("(T)t.f()", "(( (( T (. t f)))"),
 | |
| #           ("a.f(x)==T.c", "(== (( (. a f) x) (. T c))"),
 | |
| #           ("a.f().g(x,1)", "(( (. (( (. a f)) g) x 1)"),
 | |
| #           ("new T[((n-1) * x) + 1]", "(new T [ (+ (* (- n 1) x) 1))"),
 | |
| #           ]
 | |
| #       self.runTests(grammar, tests, "e")
 | |
| 
 | |
| 
 | |
| #     def testReturnValueAndActions(self):
 | |
| #         grammar = textwrap.dedent(
 | |
| #             r"""
 | |
| #             grammar T;
 | |
| #             options {
 | |
| #                 language=Python3;
 | |
| #             }
 | |
| #             s : e { self.capture($e.v) } ;
 | |
| #             e returns [v, ignored]
 | |
| #               : e '*' b=e {$v *= $b.v;}
 | |
| #               | e '+' b=e {$v += $b.v;}
 | |
| #               | INT {$v = int($INT.text);}
 | |
| #               ;
 | |
| #             INT : '0'..'9'+ ;
 | |
| #             WS : (' '|'\n') {self.skip()} ;
 | |
| #             """)
 | |
| 
 | |
| #         tests = [
 | |
| #             ("4", "4"),
 | |
| #             ("1+2", "3")
 | |
| #             ]
 | |
| #         self.runTests(grammar, tests, "s")
 | |
| 
 | |
| 
 | |
| #     def testReturnValueAndActionsAndASTs(self):
 | |
| #         grammar = textwrap.dedent(
 | |
| #             r"""
 | |
| #             grammar T;
 | |
| #             options {
 | |
| #                 language=Python3;
 | |
| #                 output=AST;
 | |
| #             }
 | |
| #             s : e { self.capture("v={}, ".format($e.v)) } ;
 | |
| #             e returns [v, ignored]
 | |
| #               : e '*'^ b=e {$v *= $b.v;}
 | |
| #               | e '+'^ b=e {$v += $b.v;}
 | |
| #               | INT {$v = int($INT.text);}
 | |
| #               ;
 | |
| #             INT : '0'..'9'+ ;
 | |
| #             WS : (' '|'\n') {self.skip()} ;
 | |
| #             """)
 | |
| 
 | |
| #         tests = [
 | |
| #             ("4", "v=4, 4"),
 | |
| #             ("1+2", "v=3, (+ 1 2)"),
 | |
| #             ]
 | |
| #         self.runTests(grammar, tests, "s")
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     unittest.main()
 |