// Copyright (C) 2018 T. Zachary Laine // // 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 using namespace boost::parser; constexpr rule flat_rule = "flat_rule"; constexpr auto flat_rule_def = string("abc") | string("def"); BOOST_PARSER_DEFINE_RULES(flat_rule); constexpr rule recursive_rule = "recursive_rule"; constexpr auto recursive_rule_def = string("abc") >> -('a' >> recursive_rule); BOOST_PARSER_DEFINE_RULES(recursive_rule); TEST(parser, no_attribute_rules) { { std::string const str = "xyz"; EXPECT_FALSE(parse(str, flat_rule)); EXPECT_FALSE(parse(str, recursive_rule)); } { std::string const str = "def"; bool const flat_result{parse(str, flat_rule)}; EXPECT_TRUE(flat_result); EXPECT_FALSE(parse(str, recursive_rule)); } { std::string const str = "abc"; EXPECT_TRUE(parse(str, flat_rule)); EXPECT_TRUE(parse(str, recursive_rule)); } { std::string const str = "abcaabc"; EXPECT_TRUE(parse(str, flat_rule)); EXPECT_TRUE(parse(str, recursive_rule)); } } constexpr rule flat_string_rule = "flat_string_rule"; constexpr auto flat_string_rule_def = string("abc") | string("def"); BOOST_PARSER_DEFINE_RULES(flat_string_rule); constexpr rule recursive_string_rule = "recursive_string_rule"; constexpr auto recursive_string_rule_def = string("abc") >> -('a' >> recursive_string_rule); BOOST_PARSER_DEFINE_RULES(recursive_string_rule); TEST(parser, string_attribute_rules) { { std::string const str = "xyz"; EXPECT_FALSE(parse(str, flat_string_rule)); EXPECT_FALSE(parse(str, recursive_string_rule)); } { std::string const str = "def"; auto const flat_result = parse(str, flat_string_rule); EXPECT_TRUE(flat_result); EXPECT_EQ(*flat_result, "def"); EXPECT_FALSE(parse(str, recursive_string_rule)); } { std::string const str = "abc"; EXPECT_EQ(*parse(str, flat_string_rule), "abc"); EXPECT_EQ(*parse(str, recursive_string_rule), "abc"); } { std::string const str = "abcaabc"; EXPECT_EQ(*parse(str, flat_string_rule), "abc"); EXPECT_EQ(*parse(str, recursive_string_rule), "abcabc"); } } constexpr rule> flat_vector_rule = "flat_vector_rule"; constexpr auto flat_vector_rule_def = string("abc") | string("def"); BOOST_PARSER_DEFINE_RULES(flat_vector_rule); TEST(parser, vector_attribute_rules) { { std::string const str = "xyz"; std::vector chars; EXPECT_FALSE(parse(str, flat_vector_rule, chars)); } { std::string const str = "def"; std::vector chars; EXPECT_TRUE(parse(str, flat_vector_rule, chars)); EXPECT_EQ(chars, std::vector({'d', 'e', 'f'})); } { std::string const str = "abc"; EXPECT_EQ( *parse(str, flat_vector_rule), std::vector({'a', 'b', 'c'})); } { std::string const str = "abcaabc"; EXPECT_EQ( *parse(str, flat_vector_rule), std::vector({'a', 'b', 'c'})); } { std::string const str = "abcaabc"; EXPECT_EQ(callback_parse(str, flat_vector_rule, int{}), true); } } constexpr callback_rule> callback_vector_rule = "callback_vector_rule"; constexpr auto callback_vector_rule_def = string("abc") | string("def"); BOOST_PARSER_DEFINE_RULES(callback_vector_rule); constexpr callback_rule callback_void_rule = "callback_void_rule"; constexpr auto callback_void_rule_def = string("abc") | string("def"); BOOST_PARSER_DEFINE_RULES(callback_void_rule); struct callbacks_t { void operator()( boost::hana::basic_type, std::vector && vec) const { all_results.push_back(std::move(vec)); } void operator()(boost::hana::basic_type) const { void_callback_called = true; } mutable std::vector> all_results; mutable bool void_callback_called = false; }; TEST(parser, callback_rules) { { std::string const str = "xyz"; callbacks_t callbacks; EXPECT_FALSE(callback_parse(str, callback_vector_rule, callbacks)); EXPECT_EQ(callbacks.all_results.size(), 0u); } { std::string const str = "abc"; callbacks_t callbacks; EXPECT_TRUE(callback_parse(str, callback_vector_rule, callbacks)); EXPECT_EQ(callbacks.all_results.size(), 1u); EXPECT_EQ(callbacks.all_results[0], std::vector({'a', 'b', 'c'})); } { std::string const str = "def"; callbacks_t callbacks; EXPECT_TRUE(callback_parse(str, callback_vector_rule, callbacks)); EXPECT_EQ(callbacks.all_results.size(), 1u); EXPECT_EQ(callbacks.all_results[0], std::vector({'d', 'e', 'f'})); } { std::string const str = "xyz"; callbacks_t callbacks; EXPECT_FALSE(callback_parse(str, callback_void_rule, callbacks)); EXPECT_FALSE(callbacks.void_callback_called); } { std::string const str = "abc"; callbacks_t callbacks; EXPECT_TRUE(callback_parse(str, callback_void_rule, callbacks)); EXPECT_TRUE(callbacks.void_callback_called); } { std::string const str = "def"; callbacks_t callbacks; EXPECT_TRUE(callback_parse(str, callback_void_rule, callbacks)); EXPECT_TRUE(callbacks.void_callback_called); } { std::string const str = "xyz"; std::vector> all_results; auto record_results = [&all_results](std::vector && vec) { all_results.push_back(std::move(vec)); }; auto callbacks = boost::hana::make_map(boost::hana::make_pair( boost::hana::type_c, record_results)); EXPECT_FALSE(callback_parse(str, callback_vector_rule, callbacks)); EXPECT_EQ(all_results.size(), 0u); } { std::string const str = "abc"; std::vector> all_results; auto record_results = [&all_results](std::vector && vec) { all_results.push_back(std::move(vec)); }; auto callbacks = boost::hana::make_map(boost::hana::make_pair( boost::hana::type_c, record_results)); EXPECT_TRUE(callback_parse(str, callback_vector_rule, callbacks)); EXPECT_EQ(all_results.size(), 1u); EXPECT_EQ(all_results[0], std::vector({'a', 'b', 'c'})); } { std::string const str = "def"; std::vector> all_results; auto callbacks = boost::hana::make_map(boost::hana::make_pair( boost::hana::type_c, [&all_results](std::vector && vec) { all_results.push_back(std::move(vec)); })); EXPECT_TRUE(callback_parse(str, callback_vector_rule, callbacks)); EXPECT_EQ(all_results.size(), 1u); EXPECT_EQ(all_results[0], std::vector({'d', 'e', 'f'})); } { std::string const str = "xyz"; bool void_callback_called = false; auto record_results = [&void_callback_called]() { void_callback_called = true; }; auto callbacks = boost::hana::make_map(boost::hana::make_pair( boost::hana::type_c, record_results)); EXPECT_FALSE(callback_parse(str, callback_void_rule, callbacks)); EXPECT_FALSE(void_callback_called); } { std::string const str = "abc"; bool void_callback_called = false; auto record_results = [&void_callback_called]() { void_callback_called = true; }; auto callbacks = boost::hana::make_map(boost::hana::make_pair( boost::hana::type_c, record_results)); EXPECT_TRUE(callback_parse(str, callback_void_rule, callbacks)); EXPECT_TRUE(void_callback_called); } { std::string const str = "def"; bool void_callback_called = false; auto callbacks = boost::hana::make_map(boost::hana::make_pair( boost::hana::type_c, [&void_callback_called]() { void_callback_called = true; })); EXPECT_TRUE(callback_parse(str, callback_void_rule, callbacks)); EXPECT_TRUE(void_callback_called); } } TEST(parser, callback_rules_normal_parse) { { std::string const str = "xyz"; std::vector chars; EXPECT_FALSE(parse(str, callback_vector_rule, chars)); } { std::string const str = "abc"; std::vector chars; EXPECT_TRUE(parse(str, callback_vector_rule, chars)); EXPECT_EQ(chars, std::vector({'a', 'b', 'c'})); } { std::string const str = "def"; std::vector chars; EXPECT_TRUE(parse(str, callback_vector_rule, chars)); EXPECT_EQ(chars, std::vector({'d', 'e', 'f'})); } { std::string const str = "def"; EXPECT_TRUE(parse(str, callback_void_rule)); } { std::string const str = "xyz"; auto const chars = parse(str, callback_vector_rule); EXPECT_FALSE(chars); } { std::string const str = "abc"; auto const chars = parse(str, callback_vector_rule); EXPECT_TRUE(chars); EXPECT_EQ(chars, std::vector({'a', 'b', 'c'})); } { std::string const str = "def"; auto const chars = parse(str, callback_vector_rule); EXPECT_TRUE(chars); EXPECT_EQ(chars, std::vector({'d', 'e', 'f'})); } { std::string const str = "xyz"; EXPECT_FALSE(parse(str, callback_vector_rule)); } { std::string const str = "abc"; EXPECT_TRUE(parse(str, callback_vector_rule)); } { std::string const str = "def"; EXPECT_TRUE(parse(str, callback_vector_rule)); } }