Converting the ANTLR v3 runtime to use ST v4 instead of ST v3

I changed these files to make it happen:

tool/src/main/resources/org/antlr/codegen/templates/Java/ST.stg
runtime/Java/src/main/java/org/antlr/runtime/tree/DOTTreeGenerator.java

You can ignore the following files that I had to change because they are part of my test suite:

tool/src/test/java/org/antlr/test/BaseTest.java
tool/src/test/java/org/antlr/test/TestRewriteTemplates.java
tool/src/test/java/org/antlr/test/TestTemplates.java
tool/src/test/java/org/antlr/test/TestTreeParsing.java

In general, these are the changes I had to make:

  • StringTemplate -> ST
  • StringTemplateGroup -> STGroup
  • setAttribute() -> add()
  • import org.antlr.stringtemplate.StringTemplate; ->
    import org.stringtemplate.v4.ST;
  • anST.getInstanceOf() -> new ST(anST); the only difference here is that the v4 version copies all of the attributes from anST to the new one.
  • references to $...$ become \<...>
  • kill import org.antlr.stringtemplate.language.*;
  • convert references to toString() to render(); note that there are a number of places that get toString() called implicitly. For example, in the ST.stg files, I converted replaceTextInLine() template to call render() explicitly:
    ((TokenRewriteStream)input).replace(
      ((Token)retval.start).getTokenIndex(),
      input.LT(-1).getTokenIndex(),
      retval.st.render());  <--------------- was just retval.st
    
  • new StringTemplateGroup("<name>Templates", AngleBracketTemplateLexer.class) creates a named group; we don't name them in v4 so that becomes new STGroup().

So, in a nutshell, there are a few changes in one runtime support file for generating DOT from trees. All of the magic happens in the ST.stg file, if your target supports output=template option. Here is a play-by-play:

  • change the imports to the new package for ST
  • change the members of a rules return scope to use ST not StringTemplate. Also change toString() method to call render.
  • we need a blank library of templates to avoid a null pointer if someone forgets to set the library. change:
    protected StringTemplateGroup templateLib =
      new StringTemplateGroup("<name>Templates", AngleBracketTemplateLexer.class);
    
    to
    protected STGroup templateLib = new STGroup();
    
  • get rid of the definition of STAttrMap altogether; we don't need it anymore because ST.add() it allows us to chain calls to add multiple attributes as part of a single expression.
  • the previous item lets us convert:
    rewriteExternalTemplate(name,args) ::= <<
    templateLib.getInstanceOf("<name>"<if(args)>,
      new STAttrMap()<args:{a | .put("<a.name>", <a.value>)}>
      <endif>)
    >>
    
    to
    rewriteExternalTemplate(name,args) ::= <<
    templateLib.getInstanceOf("<name>")
      <if(args)><args:{a | .add("<a.name>", <a.value>)}><endif>
    >>
    
    There are three methods like that.

If you look at an ST.stg difference, there's not much to do. (smile)