optional.hpp 4.9 KB

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