blob: 157b63b7c5c10eb77eaf98be31546880f93588e3 [file] [log] [blame]
[/==============================================================================
Copyright (C) 2001-2010 Joel de Guzman
Copyright (C) 2001-2010 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]
Rules can have both consumed and inherited attributes. The rule'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 rule's consumed attribute and `A0` ... `AN` are the
rule's inherited attributes.
[heading Attributes]
The rule models a C++ function. The rule's consumed attribute is
analogous to the function return value as it is the type -exposed- by the rule.
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.
[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`: An __mpl_fwd_sequence__.
The first element is the Nonterminal's consumed attribute
type and the rest are the inherited attribute types.]]
[[`X::locals_type`] [The local variables of `X`: An __mpl_fwd_sequence__.]]
]
[heading Models]
* __karma_rule__
* __karma_grammar__
[endsect]
[endsect]