import unittest
import textwrap
import antlr3
import antlr3.tree
import stringtemplate3
import testbase
import sys
import os
from StringIO import StringIO
class T(testbase.ANTLRTest):
def execParser(self, grammar, grammarEntry, input, group=None):
lexerCls, parserCls = self.compileInlineGrammar(grammar)
cStream = antlr3.StringStream(input)
lexer = lexerCls(cStream)
tStream = antlr3.CommonTokenStream(lexer)
parser = parserCls(tStream)
if group is not None:
parser.templateLib = group
result = getattr(parser, grammarEntry)()
if result.st is not None:
return result.st.toString()
return None
def testInlineTemplate(self):
grammar = textwrap.dedent(
r'''grammar T;
options {
language=Python;
output=template;
}
a : ID INT
-> template(id={$ID.text}, int={$INT.text})
"id=<id>, int=<int>"
;
ID : 'a'..'z'+;
INT : '0'..'9'+;
WS : (' '|'\n') {$channel=HIDDEN;} ;
'''
)
found = self.execParser(
grammar, 'a',
"abc 34"
)
self.failUnlessEqual("id=abc, int=34", found)
def testExternalTemplate(self):
templates = textwrap.dedent(
'''\
group T;
expr(args, op) ::= <<
[<args; separator={<op>}>]
>>
'''
)
group = stringtemplate3.StringTemplateGroup(
file=StringIO(templates),
lexer='angle-bracket'
)
grammar = textwrap.dedent(
r'''grammar T2;
options {
language=Python;
output=template;
}
a : r+=arg OP r+=arg
-> expr(op={$OP.text}, args={$r})
;
arg: ID -> template(t={$ID.text}) "<t>";
ID : 'a'..'z'+;
OP: '+';
WS : (' '|'\n') {$channel=HIDDEN;} ;
'''
)
found = self.execParser(
grammar, 'a',
"a + b",
group
)
self.failUnlessEqual("[a+b]", found)
def testEmptyTemplate(self):
grammar = textwrap.dedent(
r'''grammar T;
options {
language=Python;
output=template;
}
a : ID INT
->
;
ID : 'a'..'z'+;
INT : '0'..'9'+;
WS : (' '|'\n') {$channel=HIDDEN;} ;
'''
)
found = self.execParser(
grammar, 'a',
"abc 34"
)
self.failUnless(found is None)
def testList(self):
grammar = textwrap.dedent(
r'''grammar T;
options {
language=Python;
output=template;
}
a: (r+=b)* EOF
-> template(r={$r})
"<r; separator=\",\">"
;
b: ID
-> template(t={$ID.text}) "<t>"
;
ID : 'a'..'z'+;
WS : (' '|'\n') {$channel=HIDDEN;} ;
'''
)
found = self.execParser(
grammar, 'a',
"abc def ghi"
)
self.failUnlessEqual("abc,def,ghi", found)
def testAction(self):
grammar = textwrap.dedent(
r'''grammar T;
options {
language=Python;
output=template;
}
a: ID
-> { stringtemplate3.StringTemplate("hello") }
;
ID : 'a'..'z'+;
WS : (' '|'\n') {$channel=HIDDEN;} ;
'''
)
found = self.execParser(
grammar, 'a',
"abc"
)
self.failUnlessEqual("hello", found)
def testTemplateExpressionInAction(self):
grammar = textwrap.dedent(
r'''grammar T;
options {
language=Python;
output=template;
}
a: ID
{ $st = %{"hello"} }
;
ID : 'a'..'z'+;
WS : (' '|'\n') {$channel=HIDDEN;} ;
'''
)
found = self.execParser(
grammar, 'a',
"abc"
)
self.failUnlessEqual("hello", found)
def testTemplateExpressionInAction2(self):
grammar = textwrap.dedent(
r'''grammar T;
options {
language=Python;
output=template;
}
a: ID
{
res = %{"hello <foo>"}
%res.foo = "world";
}
-> { res }
;
ID : 'a'..'z'+;
WS : (' '|'\n') {$channel=HIDDEN;} ;
'''
)
found = self.execParser(
grammar, 'a',
"abc"
)
self.failUnlessEqual("hello world", found)
def testIndirectTemplateConstructor(self):
templates = textwrap.dedent(
'''\
group T;
expr(args, op) ::= <<
[<args; separator={<op>}>]
>>
'''
)
group = stringtemplate3.StringTemplateGroup(
file=StringIO(templates),
lexer='angle-bracket'
)
grammar = textwrap.dedent(
r'''grammar T;
options {
language=Python;
output=template;
}
a: ID
{
$st = %({"expr"})(args={[1, 2, 3]}, op={"+"})
}
;
ID : 'a'..'z'+;
WS : (' '|'\n') {$channel=HIDDEN;} ;
'''
)
found = self.execParser(
grammar, 'a',
"abc",
group
)
self.failUnlessEqual("[1+2+3]", found)
def testPredicates(self):
grammar = textwrap.dedent(
r'''grammar T3;
options {
language=Python;
output=template;
}
a : ID INT
-> {$ID.text=='a'}? template(int={$INT.text})
"A: <int>"
-> {$ID.text=='b'}? template(int={$INT.text})
"B: <int>"
-> template(int={$INT.text})
"C: <int>"
;
ID : 'a'..'z'+;
INT : '0'..'9'+;
WS : (' '|'\n') {$channel=HIDDEN;} ;
'''
)
found = self.execParser(
grammar, 'a',
"b 34"
)
self.failUnlessEqual("B: 34", found)
def testBacktrackingMode(self):
grammar = textwrap.dedent(
r'''grammar T4;
options {
language=Python;
output=template;
backtrack=true;
}
a : (ID INT)=> ID INT
-> template(id={$ID.text}, int={$INT.text})
"id=<id>, int=<int>"
;
ID : 'a'..'z'+;
INT : '0'..'9'+;
WS : (' '|'\n') {$channel=HIDDEN;} ;
'''
)
found = self.execParser(
grammar, 'a',
"abc 34"
)
self.failUnlessEqual("id=abc, int=34", found)
def testRewrite(self):
grammar = textwrap.dedent(
r'''grammar T5;
options {
language=Python;
output=template;
rewrite=true;
}
prog: stat+;
stat
: 'if' '(' expr ')' stat
| 'return' return_expr ';'
| '{' stat* '}'
| ID '=' expr ';'
;
return_expr
: expr
-> template(t={$text}) <<boom(<t>)>>
;
expr
: ID
| INT
;
ID: 'a'..'z'+;
INT: '0'..'9'+;
WS: (' '|'\n')+ {$channel=HIDDEN;} ;
COMMENT: '/*' (options {greedy=false;} : .)* '*/' {$channel = HIDDEN;} ;
'''
)
input = textwrap.dedent(
'''\
if ( foo ) {
b = /* bla */ 2;
return 1 /* foo */;
}
/* gnurz */
return 12;
'''
)
lexerCls, parserCls = self.compileInlineGrammar(grammar)
cStream = antlr3.StringStream(input)
lexer = lexerCls(cStream)
tStream = antlr3.TokenRewriteStream(lexer)
parser = parserCls(tStream)
result = parser.prog()
found = tStream.toString()
expected = textwrap.dedent(
'''\
if ( foo ) {
b = /* bla */ 2;
return boom(1) /* foo */;
}
/* gnurz */
return boom(12);
'''
)
self.failUnlessEqual(expected, found)
def testTreeRewrite(self):
grammar = textwrap.dedent(
r'''grammar T6;
options {
language=Python;
output=AST;
}
tokens {
BLOCK;
ASSIGN;
}
prog: stat+;
stat
: IF '(' e=expr ')' s=stat
-> ^(IF $e $s)
| RETURN expr ';'
-> ^(RETURN expr)
| '{' stat* '}'
-> ^(BLOCK stat*)
| ID '=' expr ';'
-> ^(ASSIGN ID expr)
;
expr
: ID
| INT
;
IF: 'if';
RETURN: 'return';
ID: 'a'..'z'+;
INT: '0'..'9'+;
WS: (' '|'\n')+ {$channel=HIDDEN;} ;
COMMENT: '/*' (options {greedy=false;} : .)* '*/' {$channel = HIDDEN;} ;
'''
)
treeGrammar = textwrap.dedent(
r'''tree grammar T6Walker;
options {
language=Python;
tokenVocab=T6;
ASTLabelType=CommonTree;
output=template;
rewrite=true;
}
prog: stat+;
stat
: ^(IF expr stat)
| ^(RETURN return_expr)
| ^(BLOCK stat*)
| ^(ASSIGN ID expr)
;
return_expr
: expr
-> template(t={$text}) <<boom(<t>)>>
;
expr
: ID
| INT
;
'''
)
input = textwrap.dedent(
'''\
if ( foo ) {
b = /* bla */ 2;
return 1 /* foo */;
}
/* gnurz */
return 12;
'''
)
lexerCls, parserCls = self.compileInlineGrammar(grammar)
walkerCls = self.compileInlineGrammar(treeGrammar)
cStream = antlr3.StringStream(input)
lexer = lexerCls(cStream)
tStream = antlr3.TokenRewriteStream(lexer)
parser = parserCls(tStream)
tree = parser.prog().tree
nodes = antlr3.tree.CommonTreeNodeStream(tree)
nodes.setTokenStream(tStream)
walker = walkerCls(nodes)
walker.prog()
found = tStream.toString()
expected = textwrap.dedent(
'''\
if ( foo ) {
b = /* bla */ 2;
return boom(1) /* foo */;
}
/* gnurz */
return boom(12);
'''
)
self.failUnlessEqual(expected, found)
if __name__ == '__main__':
unittest.main()