| Home | Libraries | People | FAQ | More

##### Nonterminal

###### Description

A Nonterminal is a symbol in a Parsing Expression Grammar 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 parsing.

###### Refinement of

> `Parser`

###### Signature

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

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

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

###### Attributes

The Nonterminal models a C++ function. The Nonterminal's synthesized attribute is analogous to the function return value and its inherited attributes are analogous to function arguments. The inherited attributes (arguments) can be passed in just like any Lazy Argument, e.g.:

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

###### `_val`

The `boost::spirit::qi::_val` placeholder can be used in Phoenix semantic actions anywhere in the Nonterminal's definition. This Phoenix placeholder refers to the Nonterminal's (synthesized) attribute. The `_val` placeholder acts like a mutable reference to the Nonterminal's attribute.

###### `_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.

###### Locals

Nonterminals can have local variables that will be created on the stack at parse time. 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`.

Notation

`x`

  A Nonterminal

`X`

  A Nonterminal type

`arg1`, `arg2`, ..., `argN`

  Lazy Arguments that evaluate to each of the Nonterminal's inherited attributes.

###### Valid Expressions

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

Expression | Semantics | Return type
--- | --- | ---
`x` | In a parser expression, invoke Nonterminal `x` | `X`
`x(arg1, arg2, ..., argN)` | In a parser expression, invoke Nonterminal `r` passing in inherited attributes `arg1` ... `argN` | `X`
`x.name(name)` | Naming a Nonterminal. | `void`
`x.name()` | Getting the name of a Nonterminal. | `std::string`
debug(x) | Debug Nonterminal `x`. | `void`

###### Type Expressions

Expression | Description
--- | ---
`X::sig_type` | The Signature of `X`: An MPL Forward Sequence. The first element is the Nonterminal's synthesized attribute type and the rest are the inherited attribute types.
`X::locals_type` | The local variables of `X`: An MPL Forward Sequence.

###### Models

- rule
- grammar