...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
The Spirit.Karma confix
generator is a generator directive component allowing to embed any generated
output inside an opening (a prefix) and a closing (a suffix). A simple
example is a C comment: /* This is a C comment
*/
which can be generated using the confix
generator as: confix("/*",
"*/")["This is a C comment"]
.
The general syntax for using the confix
is:
confix(prefix, suffix)[subject]
which results in generating a sequence equivalent to
prefix << subject << suffix
Using the confix
component
instead of the explicit sequence has the advantage of being able to encapsulate
the prefix and the suffix into a separate generator construct. The following
code snippet illustrates the idea:
// Define a metafunction allowing to compute the type of the confix() // construct namespace traits { using namespace boost::spirit; template <typename Prefix, typename Suffix = Prefix> struct confix_spec : spirit::result_of::terminal<repository::tag::confix(Prefix, Suffix)> {}; }; // Define a helper function allowing to create a confix() construct from // arbitrary prefix and suffix generators template <typename Prefix, typename Suffix> typename traits::confix_spec<Prefix, Suffix>::type confix_spec(Prefix const& prefix, Suffix const& suffix) { using namespace boost::spirit; return repository::confix(prefix, suffix); } // Define a helper function to construct a HTML tag from the tag name inline typename traits::confix_spec<std::string>::type tag (std::string const& tagname) { return confix_spec("<" + tagname + ">", "</" + tagname + ">"); } // Define generators for different HTML tags the HTML tag typedef traits::confix_spec<std::string>::type ol = tag("ol"); // <ol>...</ol> typedef traits::confix_spec<std::string>::type li = tag("li"); // <li>...</li>
Now, for instance, the above definitions allow to generate the HTML 'ol'
tag using a simple: ol["Some text"]
(which results in <ol>Some text</ol>
).
// forwards to <boost/spirit/repository/home/karma/directive/confix.hpp> #include <boost/spirit/repository/include/karma_confix.hpp>
confix(prefix, suffix)[subject]
Parameter |
Description |
---|---|
|
The generator construct to use to format the opening (the prefix).
The prefix is the part generated before
any output as generated by the |
|
The generator construct to use to format the ending (the suffix).
The suffix is the part generated after any
output as generated by the |
|
The generator construct to use to format the actual output in
between the |
All three parameters can be arbitrary complex generators themselves.
The confix
component exposes
the attribute type of its subject as its own attribute type. If the subject
does not expose any attribute
(the type is unused_type
),
then the confix
does not
expose any attribute either.
a: A --> confix(p, s)[a]: A
Note | |
---|---|
This notation is used all over the Spirit documentation and reads as:
Given, |
The following example shows simple use cases of the confix
generator. We will illustrate its usage by generating different comment
styles and a function prototype (for the full example code see here: confix.cpp)
In addition to the main header file needed to include the core components
implemented in Spirit.Karma we add the header file
needed for the new confix
generator.
#include <boost/spirit/include/karma.hpp> #include <boost/spirit/repository/include/karma_confix.hpp>
To make all the code below more readable we introduce the following namespaces.
using namespace boost::spirit; using namespace boost::spirit::ascii; using boost::spirit::repository::confix;
We will show how to generate different comment styles. First we will generate a C++ comment:
// C++ comment std::cout << karma::format_delimited( confix("//", eol)[string], // format description space, // delimiter "This is a comment" // data ) << std::endl;
This code snippet will obviouly generate //
This is a comment \n
. Similarly generating a 'C'-style
comment proves to be straightforward:
// C comment std::cout << karma::format_delimited( confix("/*", "*/")[string], // format description space, // delimiter "This is a comment" // data ) << std::endl;
which again will generate /* This is a comment
*/
.
Generating a function prototype given a function name a vector or parameter names is simple as well:
// Generate a function call with an arbitrary parameter list std::vector<std::string> parameters; parameters.push_back("par1"); parameters.push_back("par2"); parameters.push_back("par3"); std::cout << karma::format( string << confix('(', ')')[string % ','], // format description "func", // function name parameters // parameter names ) << std::endl;
which generates the expected output: func(par1,par2,par3)
.