utree1.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. // Copyright (c) 2001-2011 Joel de Guzman
  3. // Copyright (c) 2010 Bryce Lelbach
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #include <boost/config/warning_disable.hpp>
  8. #include <boost/detail/lightweight_test.hpp>
  9. #include <boost/mpl/print.hpp>
  10. #include <boost/spirit/include/qi.hpp>
  11. #include <boost/spirit/include/support_utree.hpp>
  12. #include <sstream>
  13. #include "test.hpp"
  14. inline bool check(boost::spirit::utree const& val, std::string expected)
  15. {
  16. std::stringstream s;
  17. s << val;
  18. if (s.str() == expected + " ")
  19. return true;
  20. std::cerr << "got result: " << s.str()
  21. << ", expected: " << expected << std::endl;
  22. return false;
  23. }
  24. int main()
  25. {
  26. using spirit_test::test_attr;
  27. using boost::spirit::utree;
  28. using boost::spirit::utree_type;
  29. using boost::spirit::utf8_string_range_type;
  30. using boost::spirit::utf8_symbol_type;
  31. using boost::spirit::utf8_string_type;
  32. using boost::spirit::qi::real_parser;
  33. using boost::spirit::qi::strict_real_policies;
  34. using boost::spirit::qi::digit;
  35. using boost::spirit::qi::char_;
  36. using boost::spirit::qi::string;
  37. using boost::spirit::qi::int_;
  38. using boost::spirit::qi::double_;
  39. using boost::spirit::qi::space;
  40. using boost::spirit::qi::space_type;
  41. using boost::spirit::qi::rule;
  42. using boost::spirit::qi::as;
  43. using boost::spirit::qi::lexeme;
  44. // primitive data types
  45. {
  46. utree ut;
  47. BOOST_TEST(test_attr("x", char_, ut) &&
  48. ut.which() == utree_type::string_type && check(ut, "\"x\""));
  49. ut.clear();
  50. BOOST_TEST(test_attr("123", int_, ut) &&
  51. ut.which() == utree_type::int_type && check(ut, "123"));
  52. ut.clear();
  53. BOOST_TEST(test_attr("123.45", double_, ut) &&
  54. ut.which() == utree_type::double_type && check(ut, "123.45"));
  55. ut.clear();
  56. rule<char const*, utf8_string_type()> r1 = lexeme[*char_];
  57. BOOST_TEST(test_attr("foo", r1, ut) &&
  58. ut.which() == utree_type::string_type && check(ut, "\"foo\""));
  59. ut.clear();
  60. rule<char const*, utf8_symbol_type()> r2 = lexeme[*char_];
  61. BOOST_TEST(test_attr("xyz", r2, ut) &&
  62. ut.which() == utree_type::symbol_type && check(ut, "xyz"));
  63. }
  64. // single character parsers
  65. {
  66. utree ut;
  67. // this rule returns a utree string
  68. rule<char const*, utree()> r1 = char_("abc");
  69. // this rule forces a utree list to be returned
  70. rule<char const*, utree::list_type()> r2 = char_("abc");
  71. BOOST_TEST(test_attr("a", r1, ut) &&
  72. ut.which() == utree_type::string_type && check(ut, "\"a\""));
  73. ut.clear();
  74. BOOST_TEST(test_attr("a", r2, ut) &&
  75. ut.which() == utree_type::list_type && check(ut, "( \"a\" )"));
  76. }
  77. // sequences
  78. {
  79. using boost::spirit::qi::as_string;
  80. utree ut;
  81. BOOST_TEST(test_attr("xy", char_ >> char_, ut) &&
  82. ut.which() == utree_type::list_type && check(ut, "( \"x\" \"y\" )"));
  83. ut.clear();
  84. BOOST_TEST(test_attr("123 456", int_ >> int_, ut, space) &&
  85. ut.which() == utree_type::list_type && check(ut, "( 123 456 )"));
  86. ut.clear();
  87. BOOST_TEST(test_attr("1.23 4.56", double_ >> double_, ut, space) &&
  88. ut.which() == utree_type::list_type && check(ut, "( 1.23 4.56 )"));
  89. ut.clear();
  90. BOOST_TEST(test_attr("1.2ab", double_ >> *char_, ut) &&
  91. ut.which() == utree_type::list_type && check(ut, "( 1.2 \"a\" \"b\" )"));
  92. ut.clear();
  93. BOOST_TEST(test_attr("ab1.2", *~digit >> double_, ut) &&
  94. ut.which() == utree_type::list_type && check(ut, "( \"a\" \"b\" 1.2 )"));
  95. // forces a utree list
  96. rule<char const*, utree::list_type()> r1 = double_;
  97. ut.clear();
  98. BOOST_TEST(test_attr("1.2ab", r1 >> *char_, ut) &&
  99. ut.which() == utree_type::list_type && check(ut, "( ( 1.2 ) \"a\" \"b\" )"));
  100. ut.clear();
  101. BOOST_TEST(test_attr("ab1.2", *~digit >> r1, ut) &&
  102. ut.which() == utree_type::list_type && check(ut, "( \"a\" \"b\" ( 1.2 ) )"));
  103. ut.clear();
  104. // implicitly a utree list, because of sequence attribute rules
  105. rule<char const*, utree()> r2 = int_ >> char_("!") >> double_;
  106. BOOST_TEST(test_attr("17!3.14", r2, ut) &&
  107. ut.which() == utree_type::list_type && check(ut, "( 17 \"!\" 3.14 )"));
  108. ut.clear();
  109. rule<char const*, utree()> r3 = double_ >> as_string[string("foo")] >> int_;
  110. BOOST_TEST(test_attr("0.5foo5", r3, ut) &&
  111. ut.which() == utree_type::list_type && check(ut, "( 0.5 \"foo\" 5 )"));
  112. }
  113. {
  114. utree ut;
  115. rule<char const*, utree()> r1 = char_;
  116. rule<char const*, utree::list_type()> r2 = double_;
  117. rule<char const*, utree::list_type()> r3 = char_;
  118. BOOST_TEST(test_attr("a25.5b", r1 >> r2 >> r3, ut));
  119. BOOST_TEST(ut.which() == utree_type::list_type);
  120. BOOST_TEST(check(ut, "( \"a\" ( 25.5 ) ( \"b\" ) )"));
  121. ut.clear();
  122. BOOST_TEST(test_attr("a25.5b", r3 >> r2 >> r1, ut));
  123. BOOST_TEST(ut.which() == utree_type::list_type);
  124. BOOST_TEST(check(ut, "( ( \"a\" ) ( 25.5 ) \"b\" )"));
  125. ut.clear();
  126. BOOST_TEST(test_attr("a25.5b", char_ >> r2 >> r3, ut));
  127. BOOST_TEST(ut.which() == utree_type::list_type);
  128. BOOST_TEST(check(ut, "( \"a\" ( 25.5 ) ( \"b\" ) )"));
  129. ut.clear();
  130. BOOST_TEST(test_attr("a25.5b", r3 >> r2 >> char_, ut));
  131. BOOST_TEST(ut.which() == utree_type::list_type);
  132. BOOST_TEST(check(ut, "( ( \"a\" ) ( 25.5 ) \"b\" )"));
  133. ut.clear();
  134. #if defined(BOOST_CLANG)
  135. #pragma clang diagnostic push
  136. #pragma clang diagnostic ignored "-Woverloaded-shift-op-parentheses"
  137. #endif
  138. BOOST_TEST(test_attr("a25.5b", r1 > r2 >> r3, ut));
  139. BOOST_TEST(ut.which() == utree_type::list_type);
  140. BOOST_TEST(check(ut, "( \"a\" ( 25.5 ) ( \"b\" ) )"));
  141. ut.clear();
  142. BOOST_TEST(test_attr("a25.5b", r3 >> r2 > r1, ut));
  143. BOOST_TEST(ut.which() == utree_type::list_type);
  144. BOOST_TEST(check(ut, "( ( \"a\" ) ( 25.5 ) \"b\" )"));
  145. ut.clear();
  146. BOOST_TEST(test_attr("a25.5b", char_ > r2 >> r3, ut));
  147. BOOST_TEST(ut.which() == utree_type::list_type);
  148. BOOST_TEST(check(ut, "( \"a\" ( 25.5 ) ( \"b\" ) )"));
  149. ut.clear();
  150. BOOST_TEST(test_attr("a25.5b", r3 >> r2 > char_, ut));
  151. BOOST_TEST(ut.which() == utree_type::list_type);
  152. BOOST_TEST(check(ut, "( ( \"a\" ) ( 25.5 ) \"b\" )"));
  153. #if defined(BOOST_CLANG)
  154. #pragma clang diagnostic pop
  155. #endif
  156. }
  157. return boost::report_errors();
  158. }