1 / 25

StringTemplate Overview

StringTemplate Overview. Terence Parr. Topics. Motivation and concepts Feature summary Model-view data transfer Canonical operations StringTemplate groups and inheritance Templates and attribute expressions Scoping Experience. Why use StringTemplate for generated structured text?.

murray
Télécharger la présentation

StringTemplate Overview

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. StringTemplate Overview Terence Parr

  2. Topics • Motivation and concepts • Feature summary • Model-view data transfer • Canonical operations • StringTemplate groups and inheritance • Templates and attribute expressions • Scoping • Experience

  3. Why use StringTemplate for generated structured text? • Most text generators are unstructured blobs of generation logic and print statements (this includes tree walking code emitters) • Template engines arose to encourage separation of logic/display (model-view separation) • Fearing weakness, engines support entanglement • Nature of problem dictates solution • Output is not random; it’s a language (format) • Separation goal requires restricted template expressions • Proper formalism is output grammar • Grammars are proper means of describing languages • Restricted templates are equivalent to CF grammars • StringTemplate embodies this philosophy

  4. Motivation for separation • Encapsulation; view and model isolated, unentangled • Clarity; Java and output not intertwined • Division of labor; templates, model developed in parallel • Component reuse; output factored into reusable templates • Single point-of-change; avoid errors from having multiple things to find, change • Maintenance; changing template is easier, safer than changing code • Interchangeable views; retarget code generators

  5. Rules of Separation • the view cannot modify the model (technically toString() method could erase hard drive) • cannot perform computations upon dependent data values • cannot compare dependent data values (except boolean) • cannot make type assumptions (to be practical, can assume objects have properties) • data from model cannot contain display, layout information (unenforceable)

  6. Equivalence to CFGs • Attributes = terminals, templates = rules • Can show grammar’s derivation tree for any sentence maps to a nested template tree structure Grammar Template prog : decl func ; decl : type ID ; func : type ID “()” “{“ body “}” … prog ::= “<decl()> <func()>” decl ::= “<type> <ID> ;” func : << <type> <ID>() { <body()> } >> …

  7. What’s a template? • A sentence or fragment conforming to an output language with embedded expressions evaluating to text at rendering-time • Differs from code that generates text; template is an exemplar not computation • Overall output: nested tree of templates • Expressions are functions of incoming attributes: name/value pairs • All attributes are available prior to rendering

  8. Getting started • Add stringtemplate-2.2.jar and antlr-2.7.5 to your path then compile and run. Output is QUERY: SELECT name FROM User; import org.antlr.stringtemplate.*; class Simple { public static void main(String[] args) { StringTemplate query = new StringTemplate("SELECT $column$ FROM $table$;"); query.setAttribute("column", "name"); query.setAttribute("table", "User"); System.out.println("QUERY: "+query.toString()); } }

  9. Model-view data transfer • Each template has an attribute table mapping attribute name to value • Code pushes attributes into template; template does not pull from model • Attribute value can be anything including another template or list of values • Properties of attribute are getters or fields<a.foo> tries a.getFoo() then tries a.foo • Special case: if a is of type Map<a.foo> invokes a.get(“foo”)

  10. Feature summary • Strictly enforces separation of model & view • Side-effect free expressions; no order of evaluation • Recursion (recall output structures are nested) • Dynamic attribute scoping • “Lazy-evaluation”; attributes resolve at toString time • Template inheritance/polymorphism • Output filters; e.g., auto-indent (the default) • Attribute renderer objects;e.g., how to render Date objects • Simple: No assignments, loops, arbitrary code, … • Small: 12,000 lines including generated parsers

  11. Canonical Operations • Attribute reference:<type> • Template references (possibly recursive):<statementList()> • Apply template to multi-valued attribute:<decls:decl()>or with closure-like blocks<decls:{d | <d.type> <d.name>;}> • Conditional include:<if(superClass)>extends <superClass><endif>

  12. StringTemplate groups • Set of mutually-referential templates • Either directory of template files or group file format with formal arguments: /** ANTLR Error Messages -- US english */ group en_US; DIR_NOT_FOUND(arg) ::= "directory not found: <arg>" OUTPUT_DIR_IS_FILE(arg) ::= "output directory is a file: <arg>” MISSING_RULE_ARGS(file,line,col,arg) ::= "<loc(…)>missing parameter(s) on rule reference: <arg>” loc(file,line,col) ::= "<file>:<line>:<col>: "

  13. Code generation group example group javaTemplates; method(type,name,args,body) ::= << public <type> <name>( <args:arg(); separator=“,”> ) { <statements> } >> assign(lhs,expr) ::= “<lhs> = <expr>;” if(expr,stat) ::= “if (<expr>) <stat>” call(name,args) ::= << <name>( <args; separator=“,”> ); >> Note: controller creates assign, if, call templates and sets The statements attribute of method etc…

  14. Template Polymorphism • Output: “y=1;” not “x=1;” because template instance’s group is subGroup group sup; slist() ::= “<assign()>” assign() ::= “x=1;” group sub; assign() ::= “y=1;” Late bind sub.setSuperGroup(sup); StringTemplate st = sub.getInstanceOf(”slist"); System.out.println(st.toString()); Group determines symbol resolution

  15. Attribute Expressions • <attribute>, <a.property>, <a.(expr)> • <multi-valued-attribute; separator=“…”> • empty attributes yield no output UNREACHABLE_ALTS(file,line,alts) ::= << <file>:<line>:unreachable: <alts; separator=","> >>

  16. Template inclusion • <template(args)>, <(expr)(args)> • Argument lists are parameter=expr pairs method(type,name,slist) ::= << public <type> <name>() { <debug(loc={enter method <name>})> <slist> }>> catch(exceptionName,slist) ::= << catch (<exceptionName>) { <debug(loc={catch <exceptionName>})> <slist> }>> debug(loc) ::= <<System.out.println(“at location <loc>”);>>

  17. Applying template to attribute • A crucial distinguishing feature! • Obviates the need for loops • <attributeExpr:templateExpr> • <names:bold()>, <names:bold(item=it)> • <names:(templateName)()> • <names:italics():bold()> • <vars:{v | <v.type> <v.id>;<\n>}> • <varTypes,varIDs:{t,id | <t> <id>;<\n>}>

  18. Translation maps • Want to translate string from language x to y • Must keep literals out of code so can’t have hashtable in code with mapping • ST 2.2 feature: <typeInitMap.int> is “0” also <typeInitMap.(typeName)> typeInitMap ::= [ "int":"0", "float":"0.0", "boolean":"false", default:"null" // anything else ]

  19. Lists • Combines attributes into list:<[userDefined,implicitlyDefined]:decl()><[boys,girls,other]:{Attendee: <it>.<\n>}> • Operators: first, rest, last • ops on empty attributes yield an empty value • rest(a) is empty and tail(a) == first(a) if a is single valued <first(numbers):{ n | int sum = <n>;}> <rest(numbers):{ n | sum += <n>;}>

  20. Recursively walking a list • Using rest and tail recursion, print out each element of x recurse(x) ::= “<x><rest(x):recurse()>”

  21. Attribute Scoping • Dynamically not lexically scoped • Template can see all attributes from enclosing templates unless a formal argument hides an enclosing value • Look up a in template t: • Look in t's attribute table • Look in t's arguments • Look recursively up t's enclosing template instance chain • Look recursively up t's group / supergroup chain for a map

  22. Best practice • Design templates top-down • Construct bottom-up • model = input token streamcontroller = parserview = template engine + template files • Controller extracts data from model, gives to view • Controller maps input constructs to output constructs such as assignment to assignment • Abstract concepts represented by one or more rules in the parser grammar and one or more templates in the template file. • View says what abstract concept looks like in target

  23. Experience with ANTLR v3 • Tree walker (controller) collects data from AST (model), pushes data into templates (view) • Lazy evaluation decouples order of computation from order of output (this is huge) • Enforced separation guarantees easy retargeting, no code duplication, … • no code in template • no output strings in code generator • Previous code generator hopelessly entangled • Group file format (output grammar) is great! “Executable document”

  24. Simplified ANTLR v3 Template parser(name, tokens, rules, DFAs) ::= << class <name> extends Parser { <tokens:{t | public static final int <t.name>=<t.type>;}> public <name>(TokenStream input) { super(input); } <rules; separator="\n"> <DFAs:{dfa | protected DFA<dfa.decisionNum> dfa<dfa.decisionNum> = new DFA<dfa.decisionNum>(); }> <DFAs> } >>

  25. Summary

More Related