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 Line | Regex | Group 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.
Date: May 25, 2014
HTML generated with emacs org-mode & Toxic by [qb]