optional.hpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /*=============================================================================
  2. Copyright (c) 2001-2014 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  4. Copyright (c) 2017 wanghan02
  5. Copyright (c) 2024 Nana Sakisaka
  6. Distributed under the Boost Software License, Version 1.0. (See accompanying
  7. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. =============================================================================*/
  9. #if !defined(BOOST_SPIRIT_X3_OPTIONAL_MARCH_23_2007_1117PM)
  10. #define BOOST_SPIRIT_X3_OPTIONAL_MARCH_23_2007_1117PM
  11. #include <boost/spirit/home/x3/core/proxy.hpp>
  12. #include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
  13. #include <boost/spirit/home/x3/support/expectation.hpp>
  14. #include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
  15. #include <boost/spirit/home/x3/support/traits/move_to.hpp>
  16. #include <boost/spirit/home/x3/support/traits/optional_traits.hpp>
  17. #include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
  18. namespace boost { namespace spirit { namespace x3
  19. {
  20. template <typename Subject>
  21. struct optional : proxy<Subject, optional<Subject>>
  22. {
  23. typedef proxy<Subject, optional<Subject>> base_type;
  24. static bool const is_pass_through_unary = false;
  25. static bool const handles_container = true;
  26. constexpr optional(Subject const& subject)
  27. : base_type(subject) {}
  28. using base_type::parse_subject;
  29. // Attribute is a container
  30. template <typename Iterator, typename Context
  31. , typename RContext, typename Attribute>
  32. bool parse_subject(Iterator& first, Iterator const& last
  33. , Context const& context, RContext& rcontext, Attribute& attr
  34. , traits::container_attribute) const
  35. {
  36. detail::parse_into_container(
  37. this->subject, first, last, context, rcontext, attr);
  38. return !has_expectation_failure(context);
  39. }
  40. // Attribute is an optional
  41. template <typename Iterator, typename Context
  42. , typename RContext, typename Attribute>
  43. bool parse_subject(Iterator& first, Iterator const& last
  44. , Context const& context, RContext& rcontext, Attribute& attr
  45. , traits::optional_attribute) const
  46. {
  47. typedef typename
  48. x3::traits::optional_value<Attribute>::type
  49. value_type;
  50. // create a local value
  51. value_type val{};
  52. if (this->subject.parse(first, last, context, rcontext, val))
  53. {
  54. // assign the parsed value into our attribute
  55. x3::traits::move_to(val, attr);
  56. } else {
  57. return !has_expectation_failure(context);
  58. }
  59. return true;
  60. }
  61. };
  62. template <typename Subject>
  63. constexpr optional<typename extension::as_parser<Subject>::value_type>
  64. operator-(Subject const& subject)
  65. {
  66. return { as_parser(subject) };
  67. }
  68. }}}
  69. namespace boost { namespace spirit { namespace x3 { namespace traits
  70. {
  71. template <typename Subject, typename Context>
  72. struct attribute_of<x3::optional<Subject>, Context>
  73. : build_optional<
  74. typename attribute_of<Subject, Context>::type> {};
  75. }}}}
  76. #endif