• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[/==============================================================================
2    Copyright (C) 2001-2015 Hartmut Kaiser
3    Copyright (C) 2001-2011 Joel de Guzman
4
5    Distributed under the Boost Software License, Version 1.0. (See accompanying
6    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7===============================================================================/]
8
9[/////////////////////////////////////////////////////////////////////////////]
10[section:primitive_attributes Attributes of Primitive Components]
11
12Parsers in __spirit__ are fully attributed. __x3__ parsers always /expose/ an
13attribute specific to their type. This is called /synthesized attribute/ as it
14is returned from a successful match representing the matched input sequence. For
15instance, numeric parsers, such as `int_` or `double_`, return the `int` or
16`double` value converted from the matched input sequence. Other primitive parser
17components have other intuitive attribute types, such as for instance `int_`
18which has `int`, or `ascii::char_` which has `char`. Primitive parsers apply the
19normal C++ convertibility rules: you can use any C++ type to receive the parsed
20value as long as the attribute type of the parser is convertible to the type
21provided. The following example shows how a synthesized parser attribute (the
22`int` value) is extracted by calling the API function `x3::parse`:
23
24    int value = 0;
25    std::string str("123");
26    std::string::iterator strbegin = str.begin();
27    x3::parse(strbegin, str.end(), int_, value);   // value == 123
28
29For a full list of available parser primitives and their attribute types please
30see the sections __sec_x3_primitive__.
31
32[endsect]
33
34[/////////////////////////////////////////////////////////////////////////////]
35[section:compound_attributes Attributes of Compound Components]
36
37__x3__ implement well defined attribute type propagation rules for all compound
38parsers, such as sequences, alternatives, Kleene star, etc. The main attribute
39propagation rule for a sequences is for instance:
40
41    a: A, b: B --> (a >> b): tuple<A, B>
42
43which reads as:
44
45[:Given `a` and `b` are parsers, and `A` is the attribute type of `a`, and `B`
46is the attribute type of `b`, then the attribute type of `a >> b` (`a << b`)
47will be `tuple<A, B>`.]
48
49[note The notation `tuple<A, B>` is used as a placeholder expression for any
50      fusion sequence holding the types A and B, such as `boost::fusion::tuple<A, B>`
51      or `std::pair<A, B>` (for more information see __fusion__).]
52
53As you can see, in order for a type to be compatible with the attribute type
54of a compound expression it has to
55
56* either be convertible to the attribute type,
57* or it has to expose certain functionalities, i.e. it needs to conform to a
58  concept compatible with the component.
59
60Each compound component implements its own set of attribute propagation rules.
61For a full list of how the different compound parsers consume attributes
62see the sections __sec_x3_compound__.
63
64[heading The Attribute of Sequence Parsers]
65
66Sequences require an attribute type to expose the concept of a fusion sequence,
67where all elements of that fusion sequence have to be compatible with the
68corresponding element of the component sequence. For example, the expression:
69
70    double_ >> double_
71
72is compatible with any fusion sequence holding two types, where both types have
73to be compatible with `double`. The first element of the fusion sequence has to
74be compatible with the attribute of the first `double_`, and the second element
75of the fusion sequence has to be compatible with the attribute of the second
76`double_`. If we assume to have an instance of a `std::pair<double, double>`,
77we can directly use the expressions above to do both, parse input to fill the
78attribute:
79
80    // the following parses "1.0 2.0" into a pair of double
81    std::string input("1.0 2.0");
82    std::string::iterator strbegin = input.begin();
83    std::pair<double, double> p;
84    x3::phrase_parse(strbegin, input.end(),
85        x3::double_ >> x3::double_,       // parser grammar
86        x3::space,                        // delimiter grammar
87        p);                               // attribute to fill while parsing
88
89[tip  *For sequences only:* To keep it simple, unlike __Spirit.qi__, __x3__ does
90       not support more than one attribute anymore in the `parse` and `phrase_parse` function.
91       Just use `std:tuple'. Be sure to include `boost/fusion/adapted/std_tuple.hpp' in this case.
92
93]
94
95[heading The Attribute of Alternative Parsers]
96
97Alternative parsers are all about - well - alternatives. In
98order to store possibly different result (attribute) types from the different
99alternatives we use the data type __boost_variant__. The main attribute
100propagation rule of these components is:
101
102    a: A, b: B --> (a | b): variant<A, B>
103
104Alternatives have a second very important attribute propagation rule:
105
106    a: A, b: A --> (a | b): A
107
108often simplifying things significantly. If all sub expressions of
109an alternative expose the same attribute type, the overall alternative
110will expose exactly the same attribute type as well.
111
112[endsect]
113
114[/////////////////////////////////////////////////////////////////////////////]
115[section:more_compound_attributes More About Attributes of Compound Components]
116
117While parsing input, it is often desirable to combine some
118constant elements with variable parts. For instance, let us look at the example
119of parsing or formatting a complex number, which is written as `(real, imag)`,
120where `real` and `imag` are the variables representing the real and imaginary
121parts of our complex number. This can be achieved by writing:
122
123    '(' >> double_ >> ", " >> double_ >> ')'
124
125Literals (such as `'('` and `", "`) do /not/ expose any attribute
126(well actually, they do expose the special type `unused_type`, but in this
127context `unused_type` is interpreted as if the component does not expose any
128attribute at all). It is very important to understand that the literals don't
129consume any of the elements of a fusion sequence passed to this component
130sequence. As said, they just don't expose any attribute and don't produce
131(consume) any data. The following example shows this:
132
133    // the following parses "(1.0, 2.0)" into a pair of double
134    std::string input("(1.0, 2.0)");
135    std::string::iterator strbegin = input.begin();
136    std::pair<double, double> p;
137    x3::parse(strbegin, input.end(),
138        '(' >> x3::double_ >> ", " >> x3::double_ >> ')', // parser grammar
139        p);                                               // attribute to fill while parsing
140
141where the first element of the pair passed in as the data to generate is still
142associated with the first `double_`, and the second element is associated with
143the second `double_` parser.
144
145This behavior should be familiar as it conforms to the way other input and
146output formatting libraries such as `scanf`, `printf` or `boost::format` are
147handling their variable parts. In this context you can think about __x3__'s
148primitive components (such as the `double_` above) as of being
149type safe placeholders for the attribute values.
150
151[tip  *For sequences only:* To keep it simple, unlike __Spirit.qi__, __x3__ does
152       not support more than one attribute anymore in the `parse` and `phrase_parse` function.
153       Just use `std:tuple'. Be sure to include `boost/fusion/adapted/std_tuple.hpp' in this case.
154
155]
156
157Let's take a look at this from a more formal perspective:
158
159    a: A, b: Unused --> (a >> b): A
160
161which reads as:
162
163[:Given `a` and `b` are parsers, and `A` is the attribute type of
164  `a`, and `unused_type` is the attribute type of `b`, then the attribute type
165  of `a >> b` (`a << b`) will be `A` as well. This rule applies regardless of
166  the position the element exposing the `unused_type` is at.]
167
168This rule is the key to the understanding of the attribute handling in
169sequences as soon as literals are involved. It is as if elements with
170`unused_type` attributes 'disappeared' during attribute propagation. Notably,
171this is not only true for sequences but for any compound components. For
172instance, for alternative components the corresponding rule is:
173
174    a: A, b: Unused --> (a | b): A
175
176again, allowing to simplify the overall attribute type of an expression.
177
178[endsect]
179
180[/////////////////////////////////////////////////////////////////////////////]
181[section:nonterminal_attributes Attributes of Nonterminals]
182
183Nonterminals are the main means of constructing more complex parsers out of
184simpler ones. The nonterminals in the parser world are very similar to functions
185in an imperative programming language. They can be used to encapsulate parser
186expressions for a particular input sequence. After being defined, the
187nonterminals can be used as 'normal' parsers in more complex expressions
188whenever the encapsulated input needs to be recognized. Parser nonterminals in
189__x3__ usually return a value (the synthesized attribute).
190
191The type of the synthesized attribute as to be explicitly specified while
192defining the particular nonterminal. Example (ignore ID for now):
193
194    x3::rule<ID, int> r;
195
196[endsect]
197
198