Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

libs/spirit/doc/karma/concepts.qbk

[/==============================================================================
    Copyright (C) 2001-2011 Joel de Guzman
    Copyright (C) 2001-2011 Hartmut Kaiser

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
===============================================================================/]

[section Generator Concepts]

__karma__ generators fall into a couple of generalized __concepts__. The
/Generator/ is the most fundamental concept. All __karma__ generators are
models of the /Generator/ concept. /PrimitiveGenerator/, /UnaryGenerator/,
/BinaryGenerator/, /NaryGenerator/, and /Nonterminal/ are all refinements of 
the /Generator/ concept.

The following sections provide details on these concepts.

[/////////////////////////////////////////////////////////////////////////////]
[section Generator]

[heading Description]

The /Generator/ is the most fundamental concept. A Generator has a member
function, `generate`, that accepts an `OutputIterator` and
returns bool as its result. The iterator receives the data being generated.
The Generator's `generate` member function returns `true` if the generator
succeeds. Each Generator can represent a specific pattern or algorithm, or it 
can be a more complex generator formed as a composition of other Generators.

[variablelist Notation
    [[`g`]              [A `Generator`.]]
    [[`G`]              [A `Generator` type.]]
    [[`OutIter`]        [An `OutputIterator` type.]]
    [[`sink`]           [An `OutputIterator` instance.]]
    [[`Context`]        [The generator's __karma_context__ type.]]
    [[`context`]        [The generator's __karma_context__, or __unused__.]]
    [[`delimit`]        [A delimiter Generator, or __unused__.]]
    [[`attrib`]         [A __karma_compatible_attribute__, or __unused__.]]
]

[heading Valid Expressions]

In the expressions below, the behavior of the generator, `g`, as well as how 
`delimit` and `attrib` are handled by `g`, are left unspecified in the base 
`Generator` concept. These are specified in subsequent, more refined concepts 
and by the actual models thereof.

For any Generator the following expressions must be valid:

[table
    [[Expression]           [Semantics]                         [Return type]]
    [[
``g.generate(sink, context, delimit, attrib)``]
                            [Generate the output sequence by inserting the
                             generated characters/tokens into `sink`. Use the
                             `delimit` generator for delimiting. Return
                            `true` if successful, otherwise
                            return `false`.]                       [`bool`]]
    [[`g.what(context)`]    [Get information about a Generator.]   [__info__]]
]

[heading Type Expressions]

[table
    [[Expression]                                   [Description]]
    [[`G::template attribute<Context>::type`]       [The Generator's attribute.]]
    [[`traits::is_generator<G>::type`]              [Metafunction that evaluates to `mpl::true_` if 
                                                     a certain type, `G` is a Generator, `mpl::false_`  
                                                     otherwise (See __mpl_boolean_constant__).]]
    [[`G::properties`]                              [An `mpl::int_` (See __mpl_int_constant__) holding 
                                                     a value from the `karma::generator_properties` 
                                                     enumeration. The default value is 
                                                     `generator_properties::no_properties`]]
]

[heading Postcondition]

Upon return from `g.generate` the following post conditions should hold:

* On successful generation, `sink` receives the generated characters/tokens
  sequence.
* No pre-delimits: `delimit` characters/tokens will not be emitted in front of 
  any other output.
* The attribute `attrib` has not been modified.

[heading Models]

All generators in __karma__ are models of the /Generator/ concept.

[endsect] [/ Generator Concept]

[/////////////////////////////////////////////////////////////////////////////]
[section PrimitiveGenerator]

[heading Description]

/PrimitiveGenerator/ is the most basic building block that the client uses
to build more complex generators. 

[heading Refinement of]

[:__generator_concept__]

[heading Post-delimit]

Before exiting the `generate` member function, a PrimitiveGenerator is required
to do a post-delimit. This will generate a single delimiting character/token 
sequence. Only PrimitiveGenerator's are required to perform this post-delimit.
This is typically carried out through a call to `karma::delimit_out`:

    karma::delimit_out(sink, delimit);

[heading Type Expressions]

[table
    [[Expression]                                   [Description]]
    [[`traits::is_primitive_generator<G>::type`]    [Metafunction that evaluates to `mpl::true_` if 
                                                    a certain type, `G`, is a PrimitiveGenerator, `mpl::false_`  
                                                    otherwise (See __mpl_boolean_constant__).]]
]

[heading Models] 

The following generators conform to this model: 

* __karma_eol__,
* __karma_eps__,
* [link spirit.karma.reference.numeric Numeric generators],
* [karma_char Character generators].

__fixme__ Add more links to /PrimitiveGenerator/ models here.

[endsect] [/ PrimitiveGenerator Concept]

[/////////////////////////////////////////////////////////////////////////////]
[section UnaryGenerator]

[heading Description]

/UnaryGenerator/ is a composite generator that has a single subject. The
UnaryGenerator may change the behavior of its subject following the
__delegate_pattern__. 

[heading Refinement of]

[:__generator_concept__]

[variablelist Notation
    [[`g`]              [A UnaryGenerator.]]
    [[`G`]              [A UnaryGenerator type.]]
]

[heading Valid Expressions]

In addition to the requirements defined in __generator_concept__, for any
UnaryGenerator the following must be met:

[table
    [[Expression]       [Semantics]             [Return type]]
    [[`g.subject`]      [Subject generator.]    [__generator_concept__]]
]

[heading Type Expressions]

[table
    [[Expression]           [Description]]
    [[`G::subject_type`]    [The subject generator type.]]
    [[`traits::is_unary_generator<G>::type`]    [Metafunction that evaluates to `mpl::true_` if 
                                                a certain type, `G` is a UnaryGenerator, `mpl::false_`  
                                                otherwise (See __mpl_boolean_constant__).]]
]

[heading Invariants]

For any UnaryGenerator, `G`, the following invariant always holds:

* `traits::is_generator<G::subject_type>::type` evaluates to `mpl::true_`

[heading Models]

The following generators conform to this model: 

* [karma_kleene Kleene Star (unary `*`)] operator, 
* __karma_plus__ operator,
* __karma_optional__ operator,
* __karma_and_predicate__ and __karma_not_predicate__ operators,
* [karma_align `left_align`], [karma_align `center`], and [karma_align `right_align`] directives,
* [karma_repeat `repeat`] directive,
* __karma_verbatim__ directive,
* [karma_delimit `delimit`] directive,
* [karma_upperlower `lower`] and [karma_upperlower `upper`] directives,
* [karma_maxwidth `maxwidth`] directive,
* __karma_buffer__ directive,
* __karma_omit__ directive.


__fixme__ Add more links to models of UnaryGenerator concept

[endsect] [/ UnaryGenerator Concept]

[/////////////////////////////////////////////////////////////////////////////]
[section BinaryGenerator]

[heading Description]

/BinaryGenerator/ is a composite generator that has a two subjects, `left` and
`right`. The BinaryGenerator allows its subjects to be treated in the same
way as a single instance of a __generator_concept__ following the
__composite_pattern__. 

[heading Refinement of]

[:__generator_concept__]

[variablelist Notation
    [[`g`]              [A BinaryGenerator.]]
    [[`G`]              [A BinaryGenerator type.]]
]

[heading Valid Expressions]

In addition to the requirements defined in __generator_concept__, for any
BinaryGenerator the following must be met:

[table
    [[Expression]       [Semantics]             [Return type]]
    [[`g.left`]         [Left generator.]       [__generator_concept__]]
    [[`g.right`]        [Right generator.]      [__generator_concept__]]
]

[heading Type Expressions]

[table
    [[Expression]           [Description]]
    [[`G::left_type`]       [The left generator type.]]
    [[`G::right_type`]      [The right generator type.]]
    [[`traits::is_binary_generator<G>::type`]   [Metafunction that evaluates to `mpl::true_` if 
                                                a certain type, `G` is a BinaryGenerator, `mpl::false_`  
                                                otherwise (See __mpl_boolean_constant__).]]
]

[heading Invariants]

For any BinaryGenerator, `G`, the following invariants always hold:

* `traits::is_generator<G::left_type>::type` evaluates to `mpl::true_`
* `traits::is_generator<G::right_type>::type` evaluates to `mpl::true_`

[heading Models]

The following generators conform to this model: 

* __karma_list__.

__fixme__ Add more links to models of BinaryGenerator concept

[endsect] [/ BinaryGenerator Concept]

[/////////////////////////////////////////////////////////////////////////////]
[section NaryGenerator]

[heading Description]

/NaryGenerator/ is a composite generator that has one or more subjects. The
NaryGenerator allows its subjects to be treated in the same way as a single
instance of a __generator_concept__ following the __composite_pattern__. 

[heading Refinement of] 

[:__generator_concept__]

[variablelist Notation
    [[`g`]              [A NaryGenerator.]]
    [[`G`]              [A NaryGenerator type.]]
]

[heading Valid Expressions]

In addition to the requirements defined in __generator_concept__, for any
NaryGenerator the following must be met:

[table
    [[Expression]       [Semantics]                 [Return type]]
    [[`g.elements`]     [The tuple of elements.]    [A __fusion__ Sequence of __generator_concept__ types.]]
]

[heading Type Expressions]

[table
    [[Expression]           [Description]]
    [[`g.elements_type`]    [Elements tuple type.]]
    [[`traits::is_nary_generator<G>::type`]         [Metafunction that evaluates to `mpl::true_` if 
                                                    a certain type, `G` is a NaryGenerator, `mpl::false_`  
                                                    otherwise (See __mpl_boolean_constant__).]]
]

[heading Invariants]

For each element, `E`, in any NaryGenerator, `G`, the following
invariant always holds: 
  
* `traits::is_generator<E>::type` evaluates to `mpl::true_`

[heading Models]

The following generators conform to this model: 

* __karma_sequence__, 
* __karma_alternative__.

__fixme__ Add more links to models of NaryGenerator concept

[endsect] [/ NaryGenerator Concept]

[/////////////////////////////////////////////////////////////////////////////]
[section Nonterminal]

[heading Description]

A Nonterminal is a symbol in a __peg__ production that represents a
grammar fragment. Nonterminals may self reference to specify recursion.
This is one of the most important concepts and the reason behind the
word "recursive" in recursive descent generation.

[heading Refinement of]

[:__generator_concept__]

[heading Signature]

Nonterminals can have both consumed and inherited attributes. The
Nonterminal's /Signature/ specifies both the consumed and inherited
attributes. The specification uses the function declarator syntax: 

    RT(A0, A1, A2, ..., AN)

where `RT` is the Nonterminal's consumed attribute and `A0` ... `AN`
are the Nonterminal's inherited attributes.

The default value is `void()` (no consumed and inherited attributes).

[heading Attributes]

The Nonterminal models a C++ function. The Nonterminal's consumed attribute is
analogous to the function return value as it is the type -exposed- by the
Nonterminal. Its inherited attributes are analogous to function arguments.
The inherited attributes (arguments) can be passed in just like any
__karma_lazy_argument__, e.g.:

    r(expr) // Evaluate expr at parse time and pass the result to the Nonterminal r

[heading `_val`]

The `boost::spirit::karma::_val` placeholder can be used in __phoenix__
semantic actions anywhere in the Nonterminal's definition. This
__phoenix__ placeholder refers to the Nonterminal's (consumed)
attribute. The `_val` placeholder acts like an immutable reference to the
Nonterminal's attribute.

[note Starting with __spirit__ V2.5 (distributed with Boost V1.47) the 
      placeholder `_val` can be used in semantic actions attached to top level
      generator components as well. See __generator_api__ for more information.]

[heading `_r1`...`r10`]

The `boost::spirit::_r1`...`boost::spirit::r10` placeholders can be used
in __phoenix__ semantic actions anywhere in the Nonterminal's
definition. These __phoenix__ placeholders refer to the Nonterminal's
inherited attributes.

[heading Locals]

Nonterminals can have local variables that will be created on the stack
at runtime. A locals descriptor added to the Nonterminal declaration
will give the Nonterminal local variables: 

    template <typename T0, typename T1, typename T2, ..., typename TN>
    struct locals;

where `T0` ... `TN` are the types of local variables accessible in your
__phoenix__ semantic actions using the placeholders: 

* `boost::spirit::_a`
* `boost::spirit::_b` 
* `boost::spirit::_c`
* `boost::spirit::_d` 
* `boost::spirit::_e` 
* `boost::spirit::_f` 
* `boost::spirit::_g`
* `boost::spirit::_h` 
* `boost::spirit::_i` 
* `boost::spirit::_j` 
    
which correspond to the Nonterminal's local variables `T0` ... `T9`.

[variablelist Notation
    [[`x`]                          [A Nonterminal]]
    [[`X`]                          [A Nonterminal type]]
    [[`arg1`, `arg2`, ..., `argN`]  [__karma_lazy_arguments__ that evaluate to each of 
                                    the Nonterminal's inherited attributes.]]
]

[heading Valid Expressions]

In addition to the requirements defined in __generator_concept__, for any
Nonterminal the following must be met:

[table
    [[Expression]               [Semantics]                                         [Return type]]
    [[`x`]                      [In a generator expression, invoke Nonterminal `x`] [`X`]]
    [[`x(arg1, arg2, ..., argN)`][In a generator expression, invoke Nonterminal `x` 
                                passing in inherited attributes
                                `arg1`...`argN`]                                    [`X`]]
    [[`x.name(name)`]           [Set the name of a Nonterminal]                     [`void`]]
    [[`x.name()`]               [Get the name of a Nonterminal]                     [`std::string`]]
]

[heading Type Expressions]

[table
    [[Expression]       [Description]]
    [[`X::sig_type`]    [The Signature of `X`: In a function signature form
                        as described above in the Signature paragraph.]]
    [[`X::locals_type`] [The local variables of `X`: An __mpl_fwd_sequence__.]]
]

[heading Models]

* __karma_rule__
* __karma_grammar__

[endsect]

[endsect]