Class StringTemplate

java.lang.Object
org.antlr.stringtemplate.StringTemplate

public class StringTemplate extends Object
A StringTemplate is a "document" with holes in it where you can stick values. StringTemplate breaks up your template into chunks of text and attribute expressions. StringTemplate ignores everything outside of attribute expressions, treating it as just text to spit out when you call StringTemplate.toString().
  • Field Details

    • VERSION

      public static final String VERSION
      See Also:
    • REGION_IMPLICIT

      public static final int REGION_IMPLICIT
      invalid input: '<'@r()>
      See Also:
    • REGION_EMBEDDED

      public static final int REGION_EMBEDDED
      invalid input: '<'@r>...invalid input: '<'@end>
      See Also:
    • REGION_EXPLICIT

      public static final int REGION_EXPLICIT
      See Also:
    • ANONYMOUS_ST_NAME

      public static final String ANONYMOUS_ST_NAME
      See Also:
    • referencedAttributes

      protected List referencedAttributes
    • name

      protected String name
      What's the name of this template?
    • templateID

      protected int templateID
    • enclosingInstance

      protected StringTemplate enclosingInstance
      Enclosing instance if I'm embedded within another template. IF-subtemplates are considered embedded as well.
    • argumentContext

      protected Map argumentContext
      If this template is an embedded template such as when you apply a template to an attribute, then the arguments passed to this template represent the argument context--a set of values computed by walking the argument assignment list. For example, invalid input: '<'name:bold(item=name, foo="x")> would result in an argument context of {[item=name], [foo="x"]} for this template. This template would be the bold() template and the enclosingInstance would point at the template that held that invalid input: '<'name:bold(...)> template call. When you want to get an attribute value, you first check the attributes for the 'self' template then the arg context then the enclosingInstance like resolving variables in pascal-like language with nested procedures. With multi-valued attributes such as invalid input: '<'faqList:briefFAQDisplay()> attribute "i" is set to 1..n.
    • argumentsAST

      protected StringTemplateAST argumentsAST
      If this template is embedded in another template, the arguments must be evaluated just before each application when applying template to a list of values. The "it" attribute must change with each application so that $names:bold(item=it)$ works. If you evaluate once before starting the application loop then it has a single fixed value. Eval.g saves the AST rather than evaluating before invoking applyListOfAlternatingTemplates(). Each iteration of a template application to a multi-valued attribute, these args are re-evaluated with an initial context of {[it=...], [i=...]}.
    • formalArguments

      protected LinkedHashMap formalArguments
      When templates are defined in a group file format, the attribute list is provided including information about attribute cardinality such as present, optional, ... When this information is available, rawSetAttribute should do a quick existence check as should the invocation of other templates. So if you ref bold(item="foo") but item is not defined in bold(), then an exception should be thrown. When actually rendering the template, the cardinality is checked. This is a Mapinvalid input: '<'String,FormalArgument>.
    • numberOfDefaultArgumentValues

      protected int numberOfDefaultArgumentValues
      How many formal arguments to this template have default values specified?
    • passThroughAttributes

      protected boolean passThroughAttributes
      Normally, formal parameters hide any attributes inherited from the enclosing template with the same name. This is normally what you want, but makes it hard to invoke another template passing in all the data. Use notation now: invalid input: '<'otherTemplate(...)> to say "pass in all data". Works great. Can also say invalid input: '<'otherTemplate(foo="xxx",...)>
    • nativeGroup

      protected StringTemplateGroup nativeGroup
      What group originally defined the prototype for this template? This affects the set of templates I can refer to. super.t() must always refer to the super of the original group. group base; t ::= "base"; group sub; t ::= "super.t()2" group subsub; t ::= "super.t()3"
    • group

      protected StringTemplateGroup group
      This template was created as part of what group? Even if this template was created from a prototype in a supergroup, its group will be the subgroup. That's the way polymorphism works.
    • groupFileLine

      protected int groupFileLine
      If this template is defined within a group file, what line number?
    • pattern

      protected String pattern
      The original, immutable pattern/language (not really used again after initial "compilation", setup/parsing).
    • attributes

      protected Map attributes
      Map an attribute name to its value(s). These values are set by outside code via st.setAttribute(name, value). StringTemplate is like self in that a template is both the "class def" and "instance". When you create a StringTemplate or setTemplate, the text is broken up into chunks (i.e., compiled down into a series of chunks that can be evaluated later). You can have multiple
    • attributeRenderers

      protected Map attributeRenderers
      A Mapinvalid input: '<'Class,Object> that allows people to register a renderer for a particular kind of object to be displayed in this template. This overrides any renderer set for this template's group. Most of the time this map is not used because the StringTemplateGroup has the general renderer map for all templates in that group. Sometimes though you want to override the group's renderers.
    • chunks

      protected List chunks
      A list of alternating string and ASTExpr references. This is compiled to when the template is loaded/defined and walked to write out a template instance.
    • regionDefType

      protected int regionDefType
      If someone refs invalid input: '<'@r()> in template t, an implicit
    • isRegion

      protected boolean isRegion
      Does this template come from a invalid input: '<'@region>...invalid input: '<'@end> embedded in another template?
    • regions

      protected Set regions
      Set of implicit and embedded regions for this template
    • defaultGroup

      public static StringTemplateGroup defaultGroup
  • Constructor Details

    • StringTemplate

      public StringTemplate()
      Create a blank template with no pattern and no attributes
    • StringTemplate

      public StringTemplate(String template)
      Create an anonymous template. It has no name just chunks (which point to this anonymous template) and attributes.
    • StringTemplate

      public StringTemplate(String template, Class lexer)
    • StringTemplate

      public StringTemplate(StringTemplateGroup group, String template)
      Create an anonymous template with no name, but with a group
    • StringTemplate

      public StringTemplate(StringTemplateGroup group, String template, HashMap attributes)
  • Method Details

    • resetTemplateCounter

      public static void resetTemplateCounter()
      reset the template ID counter to 0; public so that testing routine can access but not really of interest to the user.
    • dup

      protected void dup(StringTemplate from, StringTemplate to)
      Make the 'to' template look exactly like the 'from' template except for the attributes. This is like creating an instance of a class in that the executable code is the same (the template chunks), but the instance data is blank (the attributes). Do not copy the enclosingInstance pointer since you will want this template to eval in a context different from the examplar.
    • getInstanceOf

      public StringTemplate getInstanceOf()
      Make an instance of this template; it contains an exact copy of everything (except the attributes and enclosing instance pointer). So the new template refers to the previously compiled chunks of this template but does not have any attribute values.
    • getEnclosingInstance

      public StringTemplate getEnclosingInstance()
    • getOutermostEnclosingInstance

      public StringTemplate getOutermostEnclosingInstance()
    • setEnclosingInstance

      public void setEnclosingInstance(StringTemplate enclosingInstance)
    • getArgumentContext

      public Map getArgumentContext()
    • setArgumentContext

      public void setArgumentContext(Map ac)
    • getArgumentsAST

      public StringTemplateAST getArgumentsAST()
    • setArgumentsAST

      public void setArgumentsAST(StringTemplateAST argumentsAST)
    • getName

      public String getName()
    • getOutermostName

      public String getOutermostName()
    • setName

      public void setName(String name)
    • getGroup

      public StringTemplateGroup getGroup()
    • setGroup

      public void setGroup(StringTemplateGroup group)
    • getNativeGroup

      public StringTemplateGroup getNativeGroup()
    • setNativeGroup

      public void setNativeGroup(StringTemplateGroup nativeGroup)
    • getGroupFileLine

      public int getGroupFileLine()
      Return the outermost template's group file line number
    • setGroupFileLine

      public void setGroupFileLine(int groupFileLine)
    • setTemplate

      public void setTemplate(String template)
    • getTemplate

      public String getTemplate()
    • setErrorListener

      public void setErrorListener(StringTemplateErrorListener listener)
    • getErrorListener

      public StringTemplateErrorListener getErrorListener()
    • reset

      public void reset()
    • setPredefinedAttributes

      public void setPredefinedAttributes()
    • removeAttribute

      public void removeAttribute(String name)
    • setAttribute

      public void setAttribute(String name, Object value)
      Set an attribute for this template. If you set the same attribute more than once, you get a multi-valued attribute. If you send in a StringTemplate object as a value, it's enclosing instance (where it will inherit values from) is set to 'this'. This would be the normal case, though you can set it back to null after this call if you want. If you send in a List plus other values to the same attribute, they all get flattened into one List of values. This will be a new list object so that incoming objects are not altered. If you send in an array, it is converted to an ArrayIterator.
    • setAttribute

      public void setAttribute(String name, int value)
      Convenience method to box ints
    • setAttribute

      public void setAttribute(String aggrSpec, Object v1, Object v2)
      Set an aggregate attribute with two values. The attribute name must have the format: "name.{propName1,propName2}".
    • setAttribute

      public void setAttribute(String aggrSpec, Object v1, Object v2, Object v3)
    • setAttribute

      public void setAttribute(String aggrSpec, Object v1, Object v2, Object v3, Object v4)
    • setAttribute

      public void setAttribute(String aggrSpec, Object v1, Object v2, Object v3, Object v4, Object v5)
    • setAttribute

      protected void setAttribute(String aggrSpec, Object[] values)
      Create an aggregate from the list of properties in aggrSpec and fill with values from values array. This is not publically visible because it conflicts semantically with setAttribute("foo",new Object[] {...});
    • parseAggregateAttributeSpec

      protected String parseAggregateAttributeSpec(String aggrSpec, List properties)
      Split "aggrName.{propName1,propName2}" into list [propName1,propName2] and the aggrName. Space is allowed around ','.
    • rawSetAttribute

      protected void rawSetAttribute(Map attributes, String name, Object value)
      Map a value to a named attribute. Throw NoSuchElementException if the named attribute is not formally defined in self's specific template and a formal argument list exists.
    • rawSetArgumentAttribute

      public void rawSetArgumentAttribute(StringTemplate embedded, Map attributes, String name, Object value)
      Argument evaluation such as foo(x=y), x must be checked against foo's argument list not this's (which is the enclosing context). So far, only eval.g uses arg self as something other than "this".
    • getAttribute

      public Object getAttribute(String name)
    • write

      public int write(StringTemplateWriter out) throws IOException
      Walk the chunks, asking them to write themselves out according to attribute values of 'this.attributes'. This is like evaluating or interpreting the StringTemplate as a program using the attributes. The chunks will be identical (point at same list) for all instances of this template.
      Throws:
      IOException
    • get

      public Object get(StringTemplate self, String attribute)
      Resolve an attribute reference. It can be in four possible places: 1. the attribute list for the current template 2. if self is an embedded template, somebody invoked us possibly with arguments--check the argument context 3. if self is an embedded template, the attribute list for the enclosing instance (recursively up the enclosing instance chain) 4. if nothing is found in the enclosing instance chain, then it might be a map defined in the group or the its supergroup etc... Attribute references are checked for validity. If an attribute has a value, its validity was checked before template rendering. If the attribute has no value, then we must check to ensure it is a valid reference. Somebody could reference any random value like $xyz$; formal arg checks before rendering cannot detect this--only the ref can initiate a validity check. So, if no value, walk up the enclosed template tree again, this time checking formal parameters not attributes Map. The formal definition must exist even if no value. To avoid infinite recursion in toString(), we have another condition to check regarding attribute values. If your template has a formal argument, foo, then foo will hide any value available from "above" in order to prevent infinite recursion. This method is not static so people can override functionality.
    • breakTemplateIntoChunks

      protected void breakTemplateIntoChunks()
      Walk a template, breaking it into a list of chunks: Strings and actions/expressions.
    • parseAction

      public ASTExpr parseAction(String action)
    • getTemplateID

      public int getTemplateID()
    • getAttributes

      public Map getAttributes()
    • getChunks

      public List getChunks()
      Get a list of the strings and subtemplates and attribute refs in a template.
    • addChunk

      public void addChunk(Expr e)
    • setAttributes

      public void setAttributes(Map attributes)
    • getFormalArguments

      public Map getFormalArguments()
    • setFormalArguments

      public void setFormalArguments(LinkedHashMap args)
    • setDefaultArgumentValues

      public void setDefaultArgumentValues()
      Set any default argument values that were not set by the invoking template or by setAttribute directly. Note that the default values may be templates. Their evaluation context is the template itself and, hence, can see attributes within the template, any arguments, and any values inherited by the template. Default values are stored in the argument context rather than the template attributes table just for consistency's sake.
    • lookupFormalArgument

      public FormalArgument lookupFormalArgument(String name)
      From this template upward in the enclosing template tree, recursively look for the formal parameter.
    • getFormalArgument

      public FormalArgument getFormalArgument(String name)
    • defineEmptyFormalArgumentList

      public void defineEmptyFormalArgumentList()
    • defineFormalArgument

      public void defineFormalArgument(String name)
    • defineFormalArguments

      public void defineFormalArguments(List names)
    • defineFormalArgument

      public void defineFormalArgument(String name, StringTemplate defaultValue)
    • setPassThroughAttributes

      public void setPassThroughAttributes(boolean passThroughAttributes)
      Normally if you call template y from x, y cannot see any attributes of x that are defined as formal parameters of y. Setting this passThroughAttributes to true, will override that and allow a template to see through the formal arg list to inherited values.
    • setAttributeRenderers

      public void setAttributeRenderers(Map renderers)
      Specify a complete map of what object classes should map to which renderer objects.
    • registerRenderer

      public void registerRenderer(Class attributeClassType, AttributeRenderer renderer)
      Register a renderer for all objects of a particular type. This overrides any renderer set in the group for this class type.
    • getAttributeRenderer

      public AttributeRenderer getAttributeRenderer(Class attributeClassType)
      What renderer is registered for this attributeClassType for this template. If not found, the template's group is queried.
    • error

      public void error(String msg)
    • warning

      public void warning(String msg)
    • error

      public void error(String msg, Throwable e)
    • setLintMode

      public static void setLintMode(boolean lint)
      Make StringTemplate check your work as it evaluates templates. Problems are sent to error listener. Currently warns when you set attributes that are not used.
    • inLintMode

      public static boolean inLintMode()
    • trackAttributeReference

      protected void trackAttributeReference(String name)
      Indicates that 'name' has been referenced in this template.
    • isRecursiveEnclosingInstance

      public static boolean isRecursiveEnclosingInstance(StringTemplate st)
      Look up the enclosing instance chain (and include this) to see if st is a template already in the enclosing instance chain.
    • getEnclosingInstanceStackTrace

      public String getEnclosingInstanceStackTrace()
    • getTemplateDeclaratorString

      public String getTemplateDeclaratorString()
    • getTemplateHeaderString

      protected String getTemplateHeaderString(boolean showAttributes)
    • checkNullAttributeAgainstFormalArguments

      protected void checkNullAttributeAgainstFormalArguments(StringTemplate self, String attribute)
      A reference to an attribute with no value, must be compared against the formal parameter to see if it exists; if it exists all is well, but if not, throw an exception. Don't do the check if no formal parameters exist for this template; ask enclosing.
    • checkForTrouble

      protected void checkForTrouble()
      Executed after evaluating a template. For now, checks for setting of attributes not reference.
    • getEnclosingInstanceStackString

      public String getEnclosingInstanceStackString()
      If an instance of x is enclosed in a y which is in a z, return a String of these instance names in order from topmost to lowest; here that would be "[z y x]".
    • isRegion

      public boolean isRegion()
    • setIsRegion

      public void setIsRegion(boolean isRegion)
    • addRegionName

      public void addRegionName(String name)
    • containsRegionName

      public boolean containsRegionName(String name)
      Does this template ref or embed region name?
    • getRegionDefType

      public int getRegionDefType()
    • setRegionDefType

      public void setRegionDefType(int regionDefType)
    • toDebugString

      public String toDebugString()
    • toStructureString

      public String toStructureString()
      Don't print values, just report the nested structure with attribute names. Follow (nest) attributes that are templates only.
    • toStructureString

      public String toStructureString(int indent)
    • getDOTForDependencyGraph

      public StringTemplate getDOTForDependencyGraph(boolean showAttributes)
      Generate a DOT file for displaying the template enclosure graph; e.g., digraph prof { "t1" -> "t2" "t1" -> "t3" "t4" -> "t5" }
    • getDependencyGraph

      public void getDependencyGraph(Map edges, boolean showAttributes)
      Get a list of n->m edges where template n contains template m. The map you pass in is filled with edges: key->value. Useful for having DOT print out an enclosing template graph. It finds all direct template invocations too like invalid input: '<'foo()> but not indirect ones like invalid input: '<'(name)()>. Ack, I just realized that this is done statically and hence cannot see runtime arg values on statically included templates. Hmm...someday figure out to do this dynamically as if we were evaluating the templates. There will be extra nodes in the tree because we are static like method and method[...] with args.
    • putToMultiValuedMap

      protected void putToMultiValuedMap(Map map, Object key, Object value)
      Manage a hash table like it has multiple unique values. Mapinvalid input: '<'Object,Set>.
    • printDebugString

      public void printDebugString()
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • toString

      public String toString(int lineWidth)