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