list.hpp 4.6 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_LIST_HPP
  8. #define BOOST_SPIRIT_QI_OPERATOR_LIST_HPP
  9. #if defined(_MSC_VER)
  10. #pragma once
  11. #endif
  12. #include <boost/spirit/home/qi/meta_compiler.hpp>
  13. #include <boost/spirit/home/qi/parser.hpp>
  14. #include <boost/spirit/home/support/container.hpp>
  15. #include <boost/spirit/home/qi/detail/attributes.hpp>
  16. #include <boost/spirit/home/qi/detail/fail_function.hpp>
  17. #include <boost/spirit/home/qi/detail/pass_container.hpp>
  18. #include <boost/spirit/home/support/has_semantic_action.hpp>
  19. #include <boost/spirit/home/support/handles_container.hpp>
  20. #include <boost/spirit/home/support/info.hpp>
  21. #include <boost/proto/operators.hpp>
  22. #include <boost/proto/tags.hpp>
  23. #include <vector>
  24. namespace boost { namespace spirit
  25. {
  26. ///////////////////////////////////////////////////////////////////////////
  27. // Enablers
  28. ///////////////////////////////////////////////////////////////////////////
  29. template <>
  30. struct use_operator<qi::domain, proto::tag::modulus> // enables p % d
  31. : mpl::true_ {};
  32. }}
  33. namespace boost { namespace spirit { namespace qi
  34. {
  35. template <typename Left, typename Right>
  36. struct list : binary_parser<list<Left, Right> >
  37. {
  38. typedef Left left_type;
  39. typedef Right right_type;
  40. template <typename Context, typename Iterator>
  41. struct attribute
  42. {
  43. // Build a std::vector from the LHS's attribute. Note
  44. // that build_std_vector may return unused_type if the
  45. // subject's attribute is an unused_type.
  46. typedef typename
  47. traits::build_std_vector<
  48. typename traits::
  49. attribute_of<Left, Context, Iterator>::type
  50. >::type
  51. type;
  52. };
  53. list(Left const& left_, Right const& right_)
  54. : left(left_), right(right_) {}
  55. template <typename F>
  56. bool parse_container(F f) const
  57. {
  58. // in order to succeed we need to match at least one element
  59. if (f (left))
  60. return false;
  61. typename F::iterator_type save = f.f.first;
  62. while (right.parse(f.f.first, f.f.last, f.f.context, f.f.skipper, unused)
  63. && !f (left))
  64. {
  65. save = f.f.first;
  66. }
  67. f.f.first = save;
  68. return true;
  69. }
  70. template <typename Iterator, typename Context
  71. , typename Skipper, typename Attribute>
  72. bool parse(Iterator& first, Iterator const& last
  73. , Context& context, Skipper const& skipper
  74. , Attribute& attr_) const
  75. {
  76. typedef detail::fail_function<Iterator, Context, Skipper>
  77. fail_function;
  78. // ensure the attribute is actually a container type
  79. traits::make_container(attr_);
  80. Iterator iter = first;
  81. fail_function f(iter, last, context, skipper);
  82. if (!parse_container(detail::make_pass_container(f, attr_)))
  83. return false;
  84. first = f.first;
  85. return true;
  86. }
  87. template <typename Context>
  88. info what(Context& context) const
  89. {
  90. return info("list",
  91. std::make_pair(left.what(context), right.what(context)));
  92. }
  93. Left left;
  94. Right right;
  95. };
  96. ///////////////////////////////////////////////////////////////////////////
  97. // Parser generators: make_xxx function (objects)
  98. ///////////////////////////////////////////////////////////////////////////
  99. template <typename Elements, typename Modifiers>
  100. struct make_composite<proto::tag::modulus, Elements, Modifiers>
  101. : make_binary_composite<Elements, list>
  102. {};
  103. }}}
  104. namespace boost { namespace spirit { namespace traits
  105. {
  106. ///////////////////////////////////////////////////////////////////////////
  107. template <typename Left, typename Right>
  108. struct has_semantic_action<qi::list<Left, Right> >
  109. : binary_has_semantic_action<Left, Right> {};
  110. ///////////////////////////////////////////////////////////////////////////
  111. template <typename Left, typename Right, typename Attribute
  112. , typename Context, typename Iterator>
  113. struct handles_container<qi::list<Left, Right>, Attribute, Context
  114. , Iterator>
  115. : mpl::true_ {};
  116. }}}
  117. #endif