| Home | Libraries | People | FAQ | More

##### Symbols Generator (`symbols`)

###### Description

The class `symbols` implements an 'inverse' symbol table: an associative container (or map) of key-value pairs where the values are (most of the time) strings. It maps the value to be generated (the key) to any other value which will be emitted instead of the original key.

The Karma symbol table class `symbols` is-a generator, an instance of which may be used anywhere in the grammar specification. It is an example of a dynamic generator. A dynamic generator is characterized by its ability to modify its behavior at run time. Initially, an empty symbols object will emit nothing. At any time, symbols may be added, thus, dynamically altering its behavior.

###### Header

    // forwards to <boost/spirit/home/karma/string/symbols.hpp>
    #include <boost/spirit/include/karma_symbols.hpp>

Also, see Include Structure.

###### Namespace

Name
`boost::spirit::karma::symbols`

###### Synopsis

    template <typename Attrib, typename T, typename Lookup
      , typename CharEncoding, typename Tag>
    struct symbols;

###### Template parameters

Parameter | Description | Default
--- | --- | ---
`Attrib` | The type of the original attribute to be used as the key into the symbol generator (the symbol). | `char`
`T` | The data type associated with each key. | `unused_type`
`Lookup` | The symbol search implementation | if T is `unused_type`, `std::set<Attrib>`, and `std::map<Attrib, T>` otherwise
`CharEncoding` | Used for character set selection, normally not used by end user. | `unused_type`
`Tag` | Used for character set selection, normally not used by end user. | `unused_type`

###### Model of

> `PrimitiveGenerator`

Notation

`Sym`

  A `symbols` type.

`Attrib`

  An attribute type.

`T`

  A data type.

`sym`, `sym2`

  `symbols` objects.

`sseq`

  An STL container of strings.

`dseq`

  An STL container of data with `value_type` `T`.

`s1`...`sN`

  A String.

`d1`...`dN`

  Objects of type `T`.

`f`

  A callable function or function object.

`f`, `l`

  `ForwardIterator` first/last pair.

###### Expression Semantics

Semantics of an expression is defined only where it differs from, or is not defined in `PrimitiveGenerator`.

Expression | Semantics
--- | ---
`Sym()` | Construct an empty symbols object instance named `"symbols"`.
`Sym(name)` | Construct an empty symbols object instance named `name`.
`Sym(sym2)` | Copy construct a symbols from `sym2` (Another `symbols` object).
`Sym(sseq)` | Construct symbols from `sseq` (An STL container of symbols of type `Attrib`) named `"symbols"`.
`Sym(sseq, name)` | Construct symbols from `sseq` (an STL container of symbols of type `Attrib`) named `name`.
`Sym(sseq, dseq)` | Construct symbols from `sseq` and `dseq` (An STL container of symbols of type `Attrib` and an STL container of data with `value_type` `T`) which is named `"symbols"`.
`Sym(sseq, dseq, name)` | Construct symbols from `sseq` and `dseq` (An STL container of symbols of type `Attrib` and an STL container of data with `value_type` `T`) which is named `name`.
`sym = sym2` | Assign `sym2` to `sym`.
`sym = s1, s2, ..., sN` | Assign one or more symbols (`s1`...`sN`) to `sym`. The associated data values of type `T` are default constructed.
`sym += s1, s2, ..., sN` | Add one or more symbols (`s1`...`sN`) to `sym`. The associated data values of type `T` are default constructed.
`sym.add(s1)(s2)...(sN)` | Add one or more symbols (`s1`...`sN`) to `sym`. The associated data values of type `T` are default constructed.
`sym.add(s1, d1)(s2, d2)...(sN, dN)` | Add one or more symbols (`s1`...`sN`) with associated data (`d1`...`dN`) to `sym`.
`sym -= s1, s2, ..., sN` | Remove one or more symbols (`s1`...`sN`) from `sym`.
`sym.remove(s1)(s2)...(sN)` | Remove one or more symbols (`s1`...`sN`) from `sym`.
`sym.clear()` | Erase all of the symbols in `sym`.
`sym.at(s)` | Return a reference to the object associated with symbol, `s`. If `sym` does not already contain such an object, `at` inserts the default object `T()`.
`sym.find(s)` | Return a pointer to the object associated with symbol, `s`. If `sym` does not already contain such an object, `find` returns a null pointer.
`sym.for_each(f)` | For each symbol in `sym` `s` invoke `f(typename Lookup::value_type)`.
`sym.name()` | Retrieve the current name of the symbols object.
`sym.name(name)` | Set the current name of the symbols object to be `name`.

The symbols generator uses the supplied attribute as the key to be looked up in the internal associative container. If the key exists the generator emits the associated value and succeeds (unless the underlying output stream reports an error). If the value type stored in the symbol generator is `unused_type` it will emit the key instead. If the key does not exist the generator fails while not emitting anything.

###### Attributes

The attribute of `symbol<Attrib, T>` is `Attrib`.

If the supplied attribute is a Boost.Fusion sequence, then the symbol table generator will use the first element of that Boost.Fusion sequence as the key to be used for lookup. The type of that first element needs to be convertible to `Attrib`. In this case the second element of the Boost.Fusion sequence is used as the attribute while calling a generator derived from the value stored in the symbol table for the found entry.

If the supplied attribute is a container type (`traits::is_container` resolves to `mpl::true_`), then the symbol table generator will use the first element stored in that container as the key to be used for lookup. The `value_type` (returned by `traits::container_value`) has to be convertible to `Attrib`. In this case the second element stored in that container is used as the attribute while calling a generator derived from the value stored in the symbol table for the found entry.

If the supplied attribute is not a Boost.Fusion sequence and not a container type, the supplied attribute is directly used as the key for item lookup. The attribute is used as the attribute while calling a generator derived from the value stored in the symbol table for the found entry.

In any case, because the supplied key (i.e. either the first element of the Boost.Fusion sequence, the first container element, or the attribute otherwise) is passed as the attribute to a generator derived from the value stored in the symbol table for the found entry, the symbol table may store generators, which will produce output based on that value. For instance:

    // The symbol table maps a single character key to a rule<>
    // The rule<> exposes an attribute of char as well
    rule<output_iterator_type, char()> r1 = char_;

    symbols<char, rule<output_iterator_type, char()> > sym;
    sym.add
        ('j', r1.alias())
        ('h', r1.alias())
        ('t', r1.alias())
        ('k', r1.alias())
    ;

    // Supplying a fusion vector as the attribute will use the first element
    // (the 'j') as the key to be looked up, while the second element (the 'J')
    // is passed on as the attribute to the rule<> stored in the symbol table.
    // Consequently, the example generates a single 'J'.
    BOOST_ASSERT(test("J", sym, make_vector('j', 'J')));

###### Complexity

The default implementation uses a `std::map<>` or a `std::set<>` with a complexity of:

> O(log n)

Where n is the number of stored symbols.

###### Example

| Note
The test harness for the example(s) below is presented in the Basics Examples section.

Some includes:

    #include <boost/spirit/include/karma.hpp>
    #include <boost/spirit/include/support_utree.hpp>
    #include <boost/spirit/include/phoenix_core.hpp>
    #include <boost/spirit/include/phoenix_operator.hpp>
    #include <boost/fusion/include/std_pair.hpp>
    #include <iostream>
    #include <string>

Some using declarations:

    using boost::spirit::karma::symbols;

Basic usage of `symbol` generators:

    symbols<char, char const*> sym;

    sym.add
        ('a', "Apple")
        ('b', "Banana")
        ('o', "Orange")
    ;

    test_generator_attr("Banana", sym, 'b');