Nested Code Templates

Table of Contents

General Structure

As you might already have noticed in the introductory example the NcTemplateParser – the one that parses Nested Code Templates – uses comment lines of the code, e.g. in // >>> replace-me <<<, to

  • mark lines that are used as placeholders and
  • mark the beginnings and ends of nested templates.

Also it is possible to nest templates within templates which has no special effect neither on the nested nor on the enclosing template. The nested template has no content from its enclosing template and vice versa, i.e. even an enclosing template only consist those lines that are not part of any nested template. E.g. in

 1:  // May this be C++ code
 2:  static int i = -7;
 3:  // >>> enclosing >>>
 4:  template<typename T>
 5:  class Foo {
 6:  public:
 7:    // >>> nested >>>
 8:    std::string get_attribute( void ) const { return att_; }
 9:    // <<< nested <<<
10:  private:
11:    std::string att_;
12:  };
13:  // <<< enclosing <<<
14:  #define some_more things

The enclosing template is exactly the same as in:

1:  // >>> enclosing >>>
2:  template<typename T>
3:  class Foo {
4:  public:
5:  private:
6:    std::string att_;
7:  };
8:  // <<< enclosing <<<

The most important point of nesting is, that one can put many templates in one template file that resembles the structure of the code for which the templates shall be used. Without the nesting one could have written a template file

 1:  // May this be C++ code
 2:  static int i = -7;
 3:  #define some_more things
 4:  // >>> enclosing >>>
 5:  template<typename T>
 6:  class Foo {
 7:  public:
 8:  private:
 9:    std::string att_;
10:  };
11:  // <<< enclosing <<<
12:    // >>> nested >>>
13:    std::string get_attribute( void ) const { return att_; }
14:    // <<< nested <<<

that also contains the global template lines of the file, the enclosing and the nested template. One more thing is that with nesting one also has a hierarchical namespace for templates.

Until now, the whole thing might seem a little pointless because we have not seen any placeholder yet. NcTemplates only support line-placeholders, i.e. the complete placeholder-line is replaced by some other content. Note that this is not such a big problem because NcTemplates can easily be combined with text templates which support placeholders within text lines.

A simple template with one placeholder could look like this:

1:  #include <iostream>
2:  
3:  // >>> placeholder <<<
4:  
5:  int main( int argc, char *argv[] )
6:  {
7:    std::cout << magic << std::endl;
8:    return 0;
9:  }

Then we could replace line 3, the placeholder named placeholder, with a definition for magic and we could get some valid C++ code.

Comment Line Syntax

The current Java implementation of the NcTemplateParser is rather flexible about the recognized comment line syntax. It uses three regular expressions with grouping to extract the name of the placeholder or template. Currently convenience constructors for line-end-comments are available that use the following (Java) regular expressions:

Comment LineRegexGroup Index
Placeholder[ \t]*{comment}[ \t]+>>> (\\p{Graph}+) <<<[ \t]*1
Start Template[ \t]*{comment}[ \t]+>>> (\\p{Graph}+) >>>[ \t]*1
End Template[ \t]*{comment}[ \t]+<<< (\\p{Graph}+) <<<[ \t]*1

Note that one has to replace the {comment} part with the line-end-comment delimiter that is passed to the constructor.

NcTemplates + TextTemplates

So far the NcTemplate only works on a text line basis which makes them not very useful for real-world tasks. But as mentioned before a NcTemplatePraser can easily be configured to use another TemplatePraser to parse non-comment lines. This was designed with the TextTemplateParser in mind. That one finds placeholders within text lines. With such a combined parser it is possible to do serious code generation as it is shown in one of the introductory examples.

Author: Marcus Perlick

Date: May 25, 2014

HTML generated with emacs org-mode & Toxic by [qb]