Title: StringTemplate
1StringTemplate
- Terence Parr
- University of San Francisco
- parrt_at_cs.usfca.edu
2Outline
- What is StringTemplate
- Operations
- Semantics
- Example Java/XML Generation
- ANTLR 3.0 template
3What is StringTemplate?
- Template engine designed with Tom Burns (CEO,
jGuru.com) while building commercial sites over
many years in response to JSP - small 170k uncompressed binary (w/o test rig)
- Evolved from simple document with holes into a
functional language capable of generating large
class of languages - Well suited to generative programming as well as
dynamic page generation being used in new ANTLR
parser generator for code generation - Distinguishing characteristic strictly enforces
separation of model and view
4Argument for StringTemplate
- Car aerodynamics mostly trumps style today
- Similarly, the nature of generating text should
dominate design decisions use an output grammar - Dont have output grammars, we have programs with
print statements template engines arose to
encourage separation of logic/display. - Enforcing strict separation also leads to similar
grammar-like mechanism - Conclusion if youre generating text, you should
be using something akin to StringTemplate
5Canonical Operations
- Attribute referencelttypegt
- Template references (possibly recursive)ltstateme
ntList()gt - Apply template to multi-valued attributeltdeclsd
ecl()gt orltdeclsltit.typegt ltit.namegtgtltitemsr
ed(), blue(), green()gt - Conditional includeltif(superClass)gtextends
ltsuperClassgtltendifgtltif(name)gtName
ltnamegtltelsegtGuestltendifgt
6Semantics
- Side-effect free expressions
- No state
- No defined order of execution
- Lazy evaluation (crucial!)
- Dynamically scoped values inherited
- Template inheritance group to subgroup
- Recursive template instantiation
7Template Groups
- Set of mutually-referential templates with formal
arguments
group javaTemplates method(type,name,args,body)
ltlt public lttypegt ltnamegt( ltargsarg()
separator,gt ) ltbodygt gtgt assign(lhs,expr)
ltlhsgt ltexprgt if(expr,stat) if
(ltexprgt) ltstatgt call(name,args) ltnamegt(
ltargs separator,gt )
8Example Dump Java Class
class Dump public int i public
java.lang.String name public int data
public void main(class java.lang.String arg1)
public void foo(int arg1, float arg2)
public class java.lang.String bar()
9Dump Java Class Templates
group Java class(name,fields,methods)
ltlt class ltnamegt ltfieldsfield()
separator"\n"gt ltmethodsmethod()
separator"\n"gt gt gtgt field() "public
lttype(tit.type)gt ltit.namegt" method()
ltlt public ltit.returnTypegt ltit.namegt
(ltit.parameterTypeslttype(tit)gt argltigt
separator", "gt) gtgt type(t)
ltlt ltif(t.componentType)gtltt.componentTypegt ltelsegt
ltt.namegtltendifgt gtgt
10Dump Java Class Code
public class Dump public int i public
String name public int data public
static void main(String args) throws
IOException StringTemplateGroup group
new StringTemplateGroup(new
FileReader("Java.stg"),
AngleBracketTemplateLexer.class) Class c
Dump.class Field fields
c.getFields() Method methods
c.getDeclaredMethods() StringTemplate
classST group.getInstanceOf("class")
classST.setAttribute("name", c.getName())
classST.setAttribute("fields", fields)
classST.setAttribute("methods", methods)
System.out.println(classST) public
void foo(int x, float y) public String
bar() return ""
11Dump XML Instead
group XML class(name,fields,methods)
ltlt ltclassgt ltnamegtnamelt/namegt
fieldsfield() methodsmethod() lt/classgt gtgt
field() ltlt ltfieldgt lttypegttype(tit.type)lt
/typegtltnamegtit.namelt/namegt lt/fieldgt gtgt
ltclassgt ltnamegtDumplt/namegt ltfieldgt
lttypegtintlt/typegtltnamegtilt/namegt lt/fieldgt
lt/classgt
12Sample ANTLR 3.0 Template
- parser(name, tokens, rules, DFAs) ltlt
- class ltnamegt extends Parser
- lttokens
- public static final int
ltit.namegtltit.typegt - gt
- public ltnamegt(TokenStream input)
- super(input)
-
- ltrules separator"\n"gt
- ltDFAsgt
-
- gtgt
13ANTLR 3.0 Error Templates
- Internationalization use a template group for
each locale load appropriate templates
RULE_REDEFINITION(file,line,col,arg)
"ltloc()gtrule ltarggt redefinition UNDEFINED_RULE_RE
F(file,line,col,arg) "ltloc()gtreference to
undefined rule ltarggt loc()
"ltfilegtltlinegtltcolgt "
inherits file, line, col attributes from
enclosing template
14Language Translation
- MVC (parser unparser)
- model -- input stream and/or ASTs
- view -- templates
- controller -- parser
- Controller extracts data from model, provides to
view without worrying about details of output
structure - Maps abstract input concept to output concept
like assignment to assignment. - Abstract concepts represented by one or more
rules in parser grammar and one or more templates
in template file
15Translation grammarST
variable returns StringTemplate
codenull StringTemplate tnull,dnull
ttype ddeclarator SEMI if (
currentFunctionNamenull ) code
template("globalVariable")
else code template("variable")
code.setAttribute("type", t)
code.setAttribute("name", d)
declarator returns StringTemplate codenull
idID codetext(id.getText())
16Translation Templates
- Javavariable(type,name)"lttypegt
ltnamegtglobalVariable variable - Pythonvariable(type,name) " globalVariable
variable - Bytecodesvariable(type,name) ".var is
ltnamegt lttypegt" globalVariable(type,name)
".field ltnamegt lttypegtlt\ngt"
17Summary
- The nature of text generation and the enforcement
of model-view separation dominate tool
design-decisions - tools should resemble output grammars
- StringTemplate is a simple template engine that
evolved while building dynamic sites. It is
proving exceptionally well suited to code
generation tasks including ANTLR 3.0 - Open-source Java, BSD license (also a C port
python coming) - Links
- http//www.stringtemplate.org
- http//www.codegeneration.net/tiki-read_article.ph
p?articleId77