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