confix.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright (c) 2009 Chris Hoeppler
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #if !defined(BOOST_SPIRIT_REPOSITORY_QI_CONFIX_JUN_22_2009_1041AM)
  6. #define BOOST_SPIRIT_REPOSITORY_QI_CONFIX_JUN_22_2009_1041AM
  7. #if defined(_MSC_VER)
  8. #pragma once
  9. #endif
  10. #include <boost/spirit/home/qi/domain.hpp>
  11. #include <boost/spirit/home/qi/meta_compiler.hpp>
  12. #include <boost/spirit/home/qi/auxiliary/lazy.hpp>
  13. #include <boost/spirit/home/support/common_terminals.hpp>
  14. #include <boost/spirit/home/support/info.hpp>
  15. #include <boost/spirit/home/support/unused.hpp>
  16. #include <boost/spirit/home/qi/detail/attributes.hpp>
  17. #include <boost/spirit/repository/home/support/confix.hpp>
  18. #include <boost/fusion/include/vector.hpp>
  19. #include <boost/mpl/or.hpp>
  20. ///////////////////////////////////////////////////////////////////////////////
  21. namespace boost { namespace spirit
  22. {
  23. ///////////////////////////////////////////////////////////////////////////
  24. // Enablers
  25. ///////////////////////////////////////////////////////////////////////////
  26. // enables confix(..., ...)[]
  27. template <typename Prefix, typename Suffix>
  28. struct use_directive<qi::domain
  29. , terminal_ex<repository::tag::confix, fusion::vector2<Prefix, Suffix> > >
  30. : mpl::true_ {};
  31. // enables *lazy* confix(..., ...)[]
  32. template <>
  33. struct use_lazy_directive<qi::domain, repository::tag::confix, 2>
  34. : mpl::true_ {};
  35. }}
  36. ///////////////////////////////////////////////////////////////////////////////
  37. namespace boost { namespace spirit { namespace repository { namespace qi
  38. {
  39. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  40. using repository::confix;
  41. #endif
  42. using repository::confix_type;
  43. ///////////////////////////////////////////////////////////////////////////
  44. // the confix() generated parser
  45. template <typename Subject, typename Prefix, typename Suffix>
  46. struct confix_parser
  47. : spirit::qi::unary_parser<confix_parser<Subject, Prefix, Suffix> >
  48. {
  49. typedef Subject subject_type;
  50. template <typename Context, typename Iterator>
  51. struct attribute
  52. : traits::attribute_of<subject_type, Context, Iterator>
  53. {};
  54. confix_parser(Subject const& subject, Prefix const& prefix
  55. , Suffix const& suffix)
  56. : subject(subject), prefix(prefix), suffix(suffix) {}
  57. template <typename Iterator, typename Context
  58. , typename Skipper, typename Attribute>
  59. bool parse(Iterator& first, Iterator const& last
  60. , Context& context, Skipper const& skipper
  61. , Attribute& attr) const
  62. {
  63. Iterator iter = first;
  64. if (!(prefix.parse(iter, last, context, skipper, unused) &&
  65. subject.parse(iter, last, context, skipper, attr) &&
  66. suffix.parse(iter, last, context, skipper, unused)))
  67. {
  68. return false;
  69. }
  70. first = iter;
  71. return true;
  72. }
  73. template <typename Context>
  74. info what(Context const& ctx) const
  75. {
  76. return info("confix", subject.what(ctx));
  77. }
  78. Subject subject;
  79. Prefix prefix;
  80. Suffix suffix;
  81. };
  82. }}}}
  83. ///////////////////////////////////////////////////////////////////////////////
  84. namespace boost { namespace spirit { namespace qi
  85. {
  86. ///////////////////////////////////////////////////////////////////////////
  87. // Parser generators: make_xxx function (objects)
  88. ///////////////////////////////////////////////////////////////////////////
  89. // creates confix(..., ...)[] directive
  90. template <typename Prefix, typename Suffix, typename Subject
  91. , typename Modifiers>
  92. struct make_directive<
  93. terminal_ex<repository::tag::confix, fusion::vector2<Prefix, Suffix> >
  94. , Subject, Modifiers>
  95. {
  96. typedef typename
  97. result_of::compile<qi::domain, Prefix, Modifiers>::type
  98. prefix_type;
  99. typedef typename
  100. result_of::compile<qi::domain, Suffix, Modifiers>::type
  101. suffix_type;
  102. typedef repository::qi::confix_parser<
  103. Subject, prefix_type, suffix_type> result_type;
  104. template <typename Terminal>
  105. result_type operator()(Terminal const& term, Subject const& subject
  106. , Modifiers const& modifiers) const
  107. {
  108. return result_type(subject
  109. , compile<qi::domain>(fusion::at_c<0>(term.args), modifiers)
  110. , compile<qi::domain>(fusion::at_c<1>(term.args), modifiers));
  111. }
  112. };
  113. }}}
  114. namespace boost { namespace spirit { namespace traits
  115. {
  116. template <typename Subject, typename Prefix, typename Suffix>
  117. struct has_semantic_action<
  118. repository::qi::confix_parser<Subject, Prefix, Suffix> >
  119. : mpl::or_<
  120. has_semantic_action<Subject>
  121. , has_semantic_action<Prefix>
  122. , has_semantic_action<Suffix>
  123. > {};
  124. }}}
  125. #endif