| /*============================================================================= |
| Copyright (c) 2001-2014 Joel de Guzman |
| |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| =============================================================================*/ |
| |
| // this file deliberately contains non-ascii characters |
| // boostinspect:noascii |
| |
| #include <boost/detail/lightweight_test.hpp> |
| #include <boost/spirit/home/x3.hpp> |
| #include <boost/fusion/include/vector.hpp> |
| #include <boost/fusion/include/at.hpp> |
| //~ #include <boost/fusion/include/std_pair.hpp> |
| |
| #include <string> |
| #include <cstring> |
| #include <iostream> |
| #include "test.hpp" |
| |
| namespace x3 = boost::spirit::x3; |
| |
| int got_it = 0; |
| |
| struct my_rule_class |
| { |
| template <typename Iterator, typename Exception, typename Context> |
| x3::error_handler_result |
| on_error(Iterator&, Iterator const& last, Exception const& x, Context const& context) |
| { |
| std::cout |
| << "Error! Expecting: " |
| << x.which() |
| << ", got: \"" |
| << std::string(x.where(), last) |
| << "\"" |
| << std::endl |
| ; |
| return x3::error_handler_result::fail; |
| } |
| |
| template <typename Iterator, typename Attribute, typename Context> |
| inline void |
| on_success(Iterator const&, Iterator const&, Attribute&, Context const&) |
| { |
| ++got_it; |
| } |
| }; |
| |
| int |
| main() |
| { |
| using spirit_test::test_attr; |
| using spirit_test::test; |
| |
| using namespace boost::spirit::x3::ascii; |
| //~ using boost::spirit::x3::locals; |
| using boost::spirit::x3::rule; |
| using boost::spirit::x3::int_; |
| //~ using boost::spirit::x3::uint_; |
| using boost::spirit::x3::lit; |
| |
| //~ namespace phx = boost::phoenix; |
| |
| { // show that ra = rb and ra %= rb works as expected |
| rule<class a, int> ra; |
| rule<class b, int> rb; |
| int attr; |
| |
| auto ra_def = (ra %= int_); |
| BOOST_TEST(test_attr("123", ra_def, attr)); |
| BOOST_TEST(attr == 123); |
| |
| auto rb_def = (rb %= ra_def); |
| BOOST_TEST(test_attr("123", rb_def, attr)); |
| BOOST_TEST(attr == 123); |
| |
| auto rb_def2 = (rb = ra_def); |
| BOOST_TEST(test_attr("123", rb_def2, attr)); |
| BOOST_TEST(attr == 123); |
| } |
| |
| |
| { // std::string as container attribute with auto rules |
| |
| std::string attr; |
| |
| // $$$ Maybe no longer relevant $$$ |
| //~ rule<char const*, std::string()> text; |
| //~ text %= +(!char_(')') >> !char_('>') >> char_); |
| //~ BOOST_TEST(test_attr("x", text, attr)); |
| //~ BOOST_TEST(attr == "x"); |
| |
| // test deduced auto rule behavior |
| |
| auto text = rule<class text, std::string>() |
| = +(!char_(')') >> !char_('>') >> char_); |
| |
| attr.clear(); |
| BOOST_TEST(test_attr("x", text, attr)); |
| BOOST_TEST(attr == "x"); |
| } |
| |
| { // error handling |
| |
| auto r = rule<my_rule_class, char const*>() |
| = '(' > int_ > ',' > int_ > ')'; |
| |
| BOOST_TEST(test("(123,456)", r)); |
| BOOST_TEST(!test("(abc,def)", r)); |
| BOOST_TEST(!test("(123,456]", r)); |
| BOOST_TEST(!test("(123;456)", r)); |
| BOOST_TEST(!test("[123,456]", r)); |
| |
| BOOST_TEST(got_it == 1); |
| } |
| |
| // $$$ No longer relevant $$$ |
| // $$$ Do we support rule encoding? $$$ |
| //~ #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) |
| //~ #pragma setlocale("french") |
| //~ #endif |
| //~ { // specifying the encoding |
| |
| //~ typedef boost::spirit::char_encoding::iso8859_1 iso8859_1; |
| //~ rule<char const*, iso8859_1> r; |
| |
| //~ r = no_case['á']; |
| //~ BOOST_TEST(test("Á", r)); |
| //~ r = no_case[char_('á')]; |
| //~ BOOST_TEST(test("Á", r)); |
| |
| //~ r = no_case[char_("å-ï")]; |
| //~ BOOST_TEST(test("É", r)); |
| //~ BOOST_TEST(!test("ÿ", r)); |
| |
| //~ r = no_case["áÁ"]; |
| //~ BOOST_TEST(test("Áá", r)); |
| //~ r = no_case[lit("áÁ")]; |
| //~ BOOST_TEST(test("Áá", r)); |
| //~ } |
| |
| //~ #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) |
| //~ #pragma setlocale("") |
| //~ #endif |
| |
| { |
| typedef boost::variant<double, int> v_type; |
| auto r1 = rule<class r1, v_type>() |
| = int_; |
| v_type v; |
| BOOST_TEST(test_attr("1", r1, v) && v.which() == 1 && |
| boost::get<int>(v) == 1); |
| |
| typedef boost::optional<int> ov_type; |
| auto r2 = rule<class r2, ov_type>() |
| = int_; |
| ov_type ov; |
| BOOST_TEST(test_attr("1", r2, ov) && ov && boost::get<int>(ov) == 1); |
| } |
| |
| // test handling of single element fusion sequences |
| { |
| using boost::fusion::vector; |
| using boost::fusion::at_c; |
| auto r = rule<class r, vector<int>>() |
| = int_; |
| |
| vector<int> v(0); |
| BOOST_TEST(test_attr("1", r, v) && at_c<0>(v) == 1); |
| } |
| |
| // $$$ This test does not seem to add anything from the previous test above $$$ |
| //~ { |
| //~ using boost::fusion::vector; |
| //~ using boost::fusion::at_c; |
| //~ rule<const char*, vector<unsigned int>()> r = uint_; |
| |
| //~ vector<unsigned int> v(0); |
| //~ BOOST_TEST(test_attr("1", r, v) && at_c<0>(v) == 1); |
| //~ } |
| |
| // $$$ No longer relevant $$$ |
| //~ { |
| //~ using boost::spirit::x3::int_; |
| //~ using boost::spirit::x3::_1; |
| //~ using boost::spirit::x3::_val; |
| //~ using boost::spirit::x3::space; |
| //~ using boost::spirit::x3::space_type; |
| |
| //~ rule<const char*, int()> r1 = int_; |
| //~ rule<const char*, int(), space_type> r2 = int_; |
| |
| //~ int i = 0; |
| //~ int j = 0; |
| //~ BOOST_TEST(test_attr("456", r1[_val = _1], i) && i == 456); |
| //~ BOOST_TEST(test_attr(" 456", r2[_val = _1], j, space) && j == 456); |
| //~ } |
| |
| |
| /// $$$ disabling test (can't fix): '_' has unused attribute $$$ |
| //~ { |
| //~ using boost::spirit::x3::lexeme; |
| //~ using boost::spirit::x3::alnum; |
| |
| //~ auto literal_ = rule<class literal_, std::string>() |
| //~ = lexeme[ +(alnum | '_') ]; |
| |
| //~ std::string attr; |
| //~ BOOST_TEST(test_attr("foo_bar", literal_, attr) && attr == "foo_bar"); |
| //~ std::cout << attr << std::endl; |
| //~ } |
| |
| { // attribute compatibility test |
| using boost::spirit::x3::rule; |
| using boost::spirit::x3::int_; |
| |
| auto const expr = int_; |
| |
| short i; |
| BOOST_TEST(test_attr("1", expr, i) && i == 1); // ok |
| |
| const rule< class int_rule, int > int_rule( "int_rule" ); |
| auto const int_rule_def = int_; |
| auto const start = int_rule = int_rule_def; |
| |
| short j; |
| BOOST_TEST(test_attr("1", start, j) && j == 1); // error |
| } |
| |
| return boost::report_errors(); |
| } |