attributes.qbk 8.9 KB

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