/*============================================================================= Copyright (c) 2001-2013 Joel de Guzman Copyright (c) 2001-2011 Hartmut Kaiser 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) =============================================================================*/ #include //~ #include #include #include #include //~ #include #include #include #include #include #include #include "test.hpp" //~ struct test_action //~ { //~ test_action(char last) //~ : last_(last) {} //~ void operator()(std::vector const& v //~ , boost::spirit::x3::unused_type //~ , boost::spirit::x3::unused_type) const //~ { //~ BOOST_TEST(v.size() == 4 && //~ v[0] == 'a' && v[1] == 'b' && v[2] == '1' && v[3] == last_); //~ } //~ char last_; //~ }; //~ struct test_action_2 //~ { //~ typedef std::vector > result_type; //~ void operator()(result_type const& v //~ , boost::spirit::x3::unused_type //~ , boost::spirit::x3::unused_type) const //~ { //~ BOOST_TEST(v.size() == 5 && //~ !v[0] && v[1] == 'a' && v[2] == 'b' && v[3] == '1' && v[4] == '2'); //~ } //~ }; struct di_ignore { std::string text; }; struct di_include { std::string FileName; }; BOOST_FUSION_ADAPT_STRUCT( di_ignore, (std::string, text) ) BOOST_FUSION_ADAPT_STRUCT( di_include, (std::string, FileName) ) struct undefined {}; int main() { using spirit_test::test; using spirit_test::test_attr; using boost::spirit::x3::char_; using boost::spirit::x3::int_; using boost::spirit::x3::lit; using boost::spirit::x3::unused_type; using boost::spirit::x3::unused; using boost::spirit::x3::omit; { BOOST_TEST((test("a", char_ | char_))); BOOST_TEST((test("x", lit('x') | lit('i')))); BOOST_TEST((test("i", lit('x') | lit('i')))); BOOST_TEST((!test("z", lit('x') | lit('o')))); BOOST_TEST((test("rock", lit("rock") | lit("roll")))); BOOST_TEST((test("roll", lit("rock") | lit("roll")))); BOOST_TEST((test("rock", lit("rock") | int_))); BOOST_TEST((test("12345", lit("rock") | int_))); } { typedef boost::variant attr_type; attr_type v; BOOST_TEST((test_attr("12345", int_ | char_, v))); BOOST_TEST(boost::get(v) == 12345); BOOST_TEST((test_attr("12345", lit("rock") | int_ | char_, v))); BOOST_TEST(boost::get(v) == 12345); v = attr_type(); BOOST_TEST((test_attr("rock", lit("rock") | int_ | char_, v))); BOOST_TEST(v.which() == 0); BOOST_TEST((test_attr("x", lit("rock") | int_ | char_, v))); BOOST_TEST(boost::get(v) == 'x'); } { // Make sure that we are using the actual supplied attribute types // from the variant and not the expected type. boost::variant v; BOOST_TEST((test_attr("12345", int_ | +char_, v))); BOOST_TEST(boost::get(v) == 12345); BOOST_TEST((test_attr("abc", int_ | +char_, v))); BOOST_TEST(boost::get(v) == "abc"); BOOST_TEST((test_attr("12345", +char_ | int_, v))); BOOST_TEST(boost::get(v) == "12345"); } //~ { // test action //~ namespace phx = boost::phoenix; //~ boost::optional > v; //~ BOOST_TEST((test("12345", (lit("rock") | int_ | char_)[phx::ref(v) = _1]))); //~ BOOST_TEST(boost::get(boost::get(v)) == 12345); //~ BOOST_TEST((test("rock", (lit("rock") | int_ | char_)[phx::ref(v) = _1]))); //~ BOOST_TEST(!v); //~ } { unused_type x; BOOST_TEST((test_attr("rock", lit("rock") | lit('x'), x))); } { // test if alternatives with all components having unused // attributes have an unused attribute using boost::fusion::vector; using boost::fusion::at_c; vector v; BOOST_TEST((test_attr("abc", char_ >> (omit[char_] | omit[char_]) >> char_, v))); BOOST_TEST((at_c<0>(v) == 'a')); BOOST_TEST((at_c<1>(v) == 'c')); } { // Test that we can still pass a "compatible" attribute to // an alternate even if its "expected" attribute is unused type. std::string s; BOOST_TEST((test_attr("...", *(char_('.') | char_(',')), s))); BOOST_TEST(s == "..."); } // $$$ Not yet implemented //~ { // make sure collapsing eps works as expected //~ // (compile check only) //~ using boost::spirit::x3::rule; //~ using boost::spirit::x3::eps; //~ rule r1; //~ rule r2; //~ rule r3; //~ r3 = ((eps >> r1))[_val += _1]; //~ r3 = ((r1 ) | r2)[_val += _1]; //~ r3 = ((eps >> r1) | r2); //~ } //~ // make sure the attribute of an alternative gets properly collapsed //~ { //~ using boost::spirit::x3::lexeme; //~ using boost::spirit::x3::ascii::alnum; //~ using boost::spirit::x3::ascii::alpha; //~ using boost::spirit::x3::ascii::digit; //~ using boost::spirit::x3::ascii::string; //~ namespace phx = boost::phoenix; //~ BOOST_TEST( (test("ab1_", (*(alnum | char_('_')))[test_action('_')])) ); //~ BOOST_TEST( (test("ab12", (*(alpha | digit))[test_action('2')])) ); //~ BOOST_TEST( (test("abcab12", (*("abc" | alnum))[test_action_2()])) ); //~ std::vector > v; //~ BOOST_TEST( (test("x,y,z", (*(',' | char_))[phx::ref(v) = _1])) ); //~ BOOST_ASSERT(v[0] == 'x'); //~ BOOST_ASSERT(!v[1]); //~ BOOST_ASSERT(v[2] == 'y'); //~ BOOST_ASSERT(!v[3]); //~ BOOST_ASSERT(v[4] == 'z'); //~ } { std::string s; using boost::spirit::x3::eps; // test having a variant BOOST_TEST( (test_attr("a,b", (char_ % ',') | eps, s )) ); BOOST_TEST(s == "ab"); } { using boost::spirit::x3::eps; // testing a sequence taking a container as attribute std::string s; BOOST_TEST( (test_attr("abc,a,b,c", char_ >> char_ >> (char_ % ','), s )) ); BOOST_TEST(s == "abcabc"); // test having an optional inside a sequence s.erase(); BOOST_TEST( (test_attr("ab", char_ >> char_ >> -(char_ % ','), s )) ); BOOST_TEST(s == "ab"); // test having a variant inside a sequence s.erase(); BOOST_TEST( (test_attr("ab", char_ >> char_ >> ((char_ % ',') | eps), s )) ); BOOST_TEST(s == "ab"); s.erase(); BOOST_TEST( (test_attr("abc", char_ >> char_ >> ((char_ % ',') | eps), s )) ); BOOST_TEST(s == "abc"); } //~ { //~ using boost::spirit::x3::int_; //~ int i = 0; //~ BOOST_TEST( (test_attr("10", int_(5) | int_(10), i)) ); //~ BOOST_TEST(i == 10); //~ } // $$$ No longer relevant? $$$ { //compile test only (bug_march_10_2011_8_35_am) typedef boost::variant value_type; using boost::spirit::x3::rule; using boost::spirit::x3::eps; rule r1; auto r1_ = r1 = r1 | eps; // left recursive! unused = r1_; // silence unused local warning } { using boost::spirit::x3::rule; typedef boost::variant d_line; rule ignore; rule include; rule line; auto start = line = include | ignore; unused = start; // silence unused local warning } // single-element fusion vector tests { boost::fusion::vector> fv; BOOST_TEST((test_attr("12345", int_ | +char_, fv))); BOOST_TEST(boost::get(boost::fusion::at_c<0>(fv)) == 12345); boost::fusion::vector> fvi; BOOST_TEST((test_attr("12345", int_ | int_, fvi))); BOOST_TEST(boost::get(boost::fusion::at_c<0>(fvi)) == 12345); } return boost::report_errors(); }