toy.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #include <iostream>
  2. #include <utility>
  3. #include <cstring>
  4. #include <boost/mpl/identity.hpp>
  5. namespace boost { namespace spirit { namespace x3
  6. {
  7. template <typename Derived>
  8. struct parser
  9. {
  10. Derived const& derived() const
  11. {
  12. return *static_cast<Derived const*>(this);
  13. }
  14. };
  15. template <typename Char>
  16. struct char_parser : parser<char_parser<Char>>
  17. {
  18. char_parser(Char ch) : ch(ch) {}
  19. template <typename Iterator, typename Context>
  20. bool parse(Iterator& first, Iterator last, Context const& ctx) const
  21. {
  22. if (first != last && *first == ch)
  23. {
  24. ++first;
  25. return true;
  26. }
  27. return false;
  28. }
  29. Char ch;
  30. };
  31. template <typename Char>
  32. inline char_parser<Char> char_(Char ch)
  33. {
  34. return char_parser<Char>(ch);
  35. };
  36. template <typename Left, typename Right>
  37. struct sequence_parser : parser<sequence_parser<Left, Right>>
  38. {
  39. sequence_parser(Left left, Right right)
  40. : left(left), right(right) {}
  41. template <typename Iterator, typename Context>
  42. bool parse(Iterator& first, Iterator last, Context const& ctx) const
  43. {
  44. return left.parse(first, last, ctx)
  45. && right.parse(first, last, ctx);
  46. }
  47. Left left;
  48. Right right;
  49. };
  50. template <typename Left, typename Right>
  51. inline sequence_parser<Left, Right> operator>>(
  52. parser<Left> const& left, parser<Right> const& right)
  53. {
  54. return sequence_parser<Left, Right>(
  55. left.derived(), right.derived());
  56. }
  57. template <typename Left, typename Right>
  58. struct alternative_parser : parser<alternative_parser<Left, Right>>
  59. {
  60. alternative_parser(Left left, Right right)
  61. : left(left), right(right) {}
  62. template <typename Iterator, typename Context>
  63. bool parse(Iterator& first, Iterator last, Context const& ctx) const
  64. {
  65. if (left.parse(first, last, ctx))
  66. return true;
  67. return right.parse(first, last, ctx);
  68. }
  69. Left left;
  70. Right right;
  71. };
  72. template <typename Left, typename Right>
  73. inline alternative_parser<Left, Right> operator|(
  74. parser<Left> const& left, parser<Right> const& right)
  75. {
  76. return alternative_parser<Left, Right>(
  77. left.derived(), right.derived());
  78. }
  79. template <typename ID, typename T, typename NextContext>
  80. struct context
  81. {
  82. context(T const& val, NextContext const& next_ctx)
  83. : val(val), next_ctx(next_ctx) {}
  84. T const& get(mpl::identity<ID>) const
  85. {
  86. return val;
  87. }
  88. template <typename Identity>
  89. decltype(std::declval<NextContext>().get(Identity()))
  90. get(Identity id) const
  91. {
  92. return next_ctx.get(id);
  93. }
  94. T const& val;
  95. NextContext const& next_ctx;
  96. };
  97. struct empty_context
  98. {
  99. struct undefined {};
  100. template <typename ID>
  101. undefined get(ID) const
  102. {
  103. return undefined();
  104. }
  105. };
  106. template <typename ID, typename RHS>
  107. struct rule_definition : parser<rule_definition<ID, RHS>>
  108. {
  109. rule_definition(RHS rhs)
  110. : rhs(rhs) {}
  111. template <typename Iterator, typename Context>
  112. bool parse(Iterator& first, Iterator last, Context const& ctx) const
  113. {
  114. context<ID, RHS, Context> this_ctx(rhs, ctx);
  115. return rhs.parse(first, last, this_ctx);
  116. }
  117. RHS rhs;
  118. };
  119. template <typename ID>
  120. struct rule : parser<rule<ID>>
  121. {
  122. template <typename Derived>
  123. rule_definition<ID, Derived>
  124. operator=(parser<Derived> const& definition) const
  125. {
  126. return rule_definition<ID, Derived>(definition.derived());
  127. }
  128. template <typename Iterator, typename Context>
  129. bool parse(Iterator& first, Iterator last, Context const& ctx) const
  130. {
  131. return ctx.get(mpl::identity<ID>()).parse(first, last, ctx);
  132. }
  133. };
  134. template <typename Iterator, typename Derived>
  135. inline bool parse(parser<Derived> const& p, Iterator& first, Iterator last)
  136. {
  137. empty_context ctx;
  138. return p.derived().parse(first, last, ctx);
  139. }
  140. }}}
  141. ///////////////////////////////////////////////////////////////////////////////
  142. // test code
  143. template <typename Parser>
  144. bool test_parse(Parser const& p, char const* in)
  145. {
  146. return parse(p, in, in + std::strlen(in));
  147. }
  148. namespace parser
  149. {
  150. using namespace boost::spirit::x3;
  151. namespace g_definition
  152. {
  153. auto const x = rule<class x>();
  154. auto const ax = char_('a') >> x;
  155. auto const g =
  156. x = char_('x') | ax;
  157. }
  158. using g_definition::g;
  159. }
  160. int main()
  161. {
  162. { // a non-recursive parser
  163. using namespace boost::spirit::x3;
  164. auto abc = char_('a') >> char_('b') >> char_('c');
  165. std::cout << test_parse(abc, "abc") << std::endl;
  166. std::cout << test_parse(abc, "abx") << std::endl;
  167. std::cout << "==========================================" << std::endl;
  168. }
  169. { // a recursive rule
  170. using namespace boost::spirit::x3;
  171. auto const x = rule<class x>();
  172. auto const ax = char_('a') >> x;
  173. auto const start = (x = char_('x') | ax);
  174. std::cout << test_parse(start, "x") << std::endl;
  175. std::cout << test_parse(start, "ax") << std::endl;
  176. std::cout << test_parse(start, "aaaaax") << std::endl;
  177. std::cout << test_parse(start, "aaz") << std::endl;
  178. std::cout << "==========================================" << std::endl;
  179. }
  180. { // a grammar ( gcc and clang only: see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3582.html )
  181. using namespace boost::spirit::x3;
  182. auto g = []()
  183. {
  184. rule<class x> x;
  185. auto ax = char_('a') >> x;
  186. return x = char_('x') | ax;
  187. }();
  188. std::cout << test_parse(g, "x") << std::endl;
  189. std::cout << test_parse(g, "ax") << std::endl;
  190. std::cout << test_parse(g, "aaaaax") << std::endl;
  191. std::cout << test_parse(g, "aaz") << std::endl;
  192. std::cout << "==========================================" << std::endl;
  193. }
  194. { // another grammar using namespaces (standard c++, see grammar g definition above in namespace parser.)
  195. using parser::g;
  196. std::cout << test_parse(g, "x") << std::endl;
  197. std::cout << test_parse(g, "ax") << std::endl;
  198. std::cout << test_parse(g, "aaaaax") << std::endl;
  199. std::cout << test_parse(g, "aaz") << std::endl;
  200. std::cout << "==========================================" << std::endl;
  201. }
  202. return 0;
  203. }