optional.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  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. #if !defined(SPIRIT_OPTIONAL_MARCH_23_2007_1117PM)
  8. #define SPIRIT_OPTIONAL_MARCH_23_2007_1117PM
  9. #if defined(_MSC_VER)
  10. #pragma once
  11. #endif
  12. #include <boost/spirit/home/support/unused.hpp>
  13. #include <boost/spirit/home/qi/detail/attributes.hpp>
  14. #include <boost/spirit/home/support/has_semantic_action.hpp>
  15. #include <boost/spirit/home/support/handles_container.hpp>
  16. #include <boost/spirit/home/support/info.hpp>
  17. #include <boost/spirit/home/support/container.hpp>
  18. #include <boost/spirit/home/qi/parser.hpp>
  19. #include <boost/spirit/home/qi/meta_compiler.hpp>
  20. #include <boost/spirit/home/qi/detail/assign_to.hpp>
  21. #include <boost/optional.hpp>
  22. #include <vector>
  23. namespace boost { namespace spirit
  24. {
  25. ///////////////////////////////////////////////////////////////////////////
  26. // Enablers
  27. ///////////////////////////////////////////////////////////////////////////
  28. template <>
  29. struct use_operator<qi::domain, proto::tag::negate> // enables -p
  30. : mpl::true_ {};
  31. }}
  32. namespace boost { namespace spirit { namespace qi
  33. {
  34. template <typename Subject>
  35. struct optional : unary_parser<optional<Subject> >
  36. {
  37. typedef Subject subject_type;
  38. template <typename Context, typename Iterator>
  39. struct attribute
  40. {
  41. // Build a boost::optional from the subject's attribute. Note
  42. // that boost::optional may return unused_type if the
  43. // subject's attribute is an unused_type.
  44. typedef typename
  45. traits::build_optional<
  46. typename traits::
  47. attribute_of<Subject, Context, Iterator>::type
  48. >::type
  49. type;
  50. };
  51. optional(Subject const& subject_)
  52. : subject(subject_) {}
  53. template <typename Iterator, typename Context
  54. , typename Skipper, typename Attribute>
  55. bool parse_impl(Iterator& first, Iterator const& last
  56. , Context& context, Skipper const& skipper
  57. , Attribute& attr_, mpl::false_) const
  58. {
  59. // create a local value if Attribute is not unused_type
  60. typename spirit::result_of::optional_value<Attribute>::type val =
  61. typename spirit::result_of::optional_value<Attribute>::type();
  62. if (subject.parse(first, last, context, skipper, val))
  63. {
  64. // assign the parsed value into our attribute
  65. spirit::traits::assign_to(val, attr_);
  66. }
  67. return true;
  68. }
  69. template <typename Iterator, typename Context
  70. , typename Skipper, typename Attribute>
  71. bool parse_impl(Iterator& first, Iterator const& last
  72. , Context& context, Skipper const& skipper
  73. , Attribute& attr_, mpl::true_) const
  74. {
  75. subject.parse(first, last, context, skipper, attr_);
  76. return true;
  77. }
  78. template <typename Iterator, typename Context
  79. , typename Skipper, typename Attribute>
  80. bool parse(Iterator& first, Iterator const& last
  81. , Context& context, Skipper const& skipper
  82. , Attribute& attr_) const
  83. {
  84. typedef typename spirit::result_of::optional_value<Attribute>::type
  85. attribute_type;
  86. return parse_impl(first, last, context, skipper, attr_
  87. , traits::is_container<attribute_type>());
  88. }
  89. template <typename Context>
  90. info what(Context& context) const
  91. {
  92. return info("optional", subject.what(context));
  93. }
  94. Subject subject;
  95. };
  96. ///////////////////////////////////////////////////////////////////////////
  97. // Parser generators: make_xxx function (objects)
  98. ///////////////////////////////////////////////////////////////////////////
  99. template <typename Elements, typename Modifiers>
  100. struct make_composite<proto::tag::negate, Elements, Modifiers>
  101. : make_unary_composite<Elements, optional>
  102. {};
  103. }}}
  104. namespace boost { namespace spirit { namespace traits
  105. {
  106. ///////////////////////////////////////////////////////////////////////////
  107. template <typename Subject>
  108. struct has_semantic_action<qi::optional<Subject> >
  109. : unary_has_semantic_action<Subject> {};
  110. ///////////////////////////////////////////////////////////////////////////
  111. template <typename Subject, typename Attribute, typename Context
  112. , typename Iterator>
  113. struct handles_container<qi::optional<Subject>, Attribute
  114. , Context, Iterator>
  115. : mpl::true_ {};
  116. }}}
  117. #endif