diff options
Diffstat (limited to '')
74 files changed, 8683 insertions, 0 deletions
diff --git a/src/boost/libs/spirit/test/x3/Jamfile b/src/boost/libs/spirit/test/x3/Jamfile new file mode 100644 index 00000000..875c06a3 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/Jamfile @@ -0,0 +1,134 @@ +#============================================================================== +# Copyright (c) 2001-2013 Joel de Guzman +# Copyright (c) 2001-2012 Hartmut Kaiser +# Copyright (c) 2011 Bryce Lelbach +# +# Use, modification and distribution is subject to 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) +#============================================================================== + +import config : requires ; +import modules ; +import feature ; +import testing ; + +############################################################################### + +project spirit-x3 + : requirements + <include>. + <c++-template-depth>512 + [ requires + # Assume all the cxx11 checks succeed if any of cxx14 does. + #cxx14_binary_literals # grep -Er "[0-9]+b[0-9]+" * + #cxx14_constexpr + cxx14_decltype_auto # grep -r "decltype(auto)" * + #cxx14_digit_separators # grep -Er "[0-9]+'[0-9]+" * + cxx14_generic_lambdas # grep -Er "]\s*\\([^\\)]*auto" * + #cxx14_hdr_shared_mutex # grep -r "shared_mutex" * + #cxx14_initialized_lambda_captures # grep -Er "\\[[^=\\]]+=" * + #cxx14_aggregate_nsdmi + cxx14_return_type_deduction # grep -Er "auto[^\\(=\\)]+\(" * + #cxx14_std_exchange # grep -r "exchange" * + cxx14_variable_templates + ] + ; + +############################################################################### + +local subproject-name = x3 ; + +rule run ( sources + : args * : input-files * + : requirements * : target-name ? : default-build * ) +{ + target-name ?= $(subproject-name)_$(sources[1]:D=:S=) ; + return [ testing.run $(sources) : $(args) : $(input-files) + : $(requirements) : $(target-name) : $(default-build) ] ; +} + +rule compile ( sources + : requirements * : target-name ? ) +{ + target-name ?= $(subproject-name)_$(sources[1]:D=:S=) ; + return [ testing.compile $(sources) + : $(requirements) : $(target-name) ] ; +} + +rule compile-fail ( sources + : requirements * : target-name ? ) +{ + target-name ?= $(subproject-name)_$(sources[1]:D=:S=) ; + return [ testing.compile-fail $(sources) + : $(requirements) : $(target-name) ] ; +} + +############################################################################### + +run actions.cpp ; +run alternative.cpp ; +run and_predicate.cpp ; +run any_parser.cpp ; +run attr.cpp ; +run binary.cpp ; +run bool.cpp ; +run char1.cpp ; +run char_class.cpp ; +run container_support.cpp ; +run debug.cpp ; +run difference.cpp ; +run eoi.cpp ; +run eol.cpp ; +run eps.cpp ; +run expect.cpp ; +run extract_int.cpp ; +run int1.cpp ; +run kleene.cpp ; +run lexeme.cpp ; +run lit1.cpp ; +run lit2.cpp ; +run list.cpp ; +run matches.cpp ; +run no_case.cpp ; +run no_skip.cpp ; +run not_predicate.cpp ; +run omit.cpp ; +run optional.cpp ; +run plus.cpp ; +run with.cpp ; + +run raw.cpp ; +run real1.cpp ; +run real2.cpp ; +run real3.cpp ; +run real4.cpp ; +run rule1.cpp ; +run rule2.cpp ; +run rule3.cpp ; +run rule4.cpp ; +run sequence.cpp ; +run skip.cpp ; +run symbols1.cpp ; +run symbols2.cpp ; +run symbols3.cpp ; +run tst.cpp ; + +run uint1.cpp ; +run uint_radix.cpp ; + +run confix.cpp ; +run repeat.cpp ; +run seek.cpp ; + +run unused_type.cpp ; +run attribute_type_check.cpp ; +run fusion_map.cpp ; +run x3_variant.cpp ; +run error_handler.cpp /boost//filesystem ; +run iterator_check.cpp ; + +run to_utf8.cpp ; + +obj rule_separate_tu_grammar : rule_separate_tu_grammar.cpp ; +run rule_separate_tu.cpp rule_separate_tu_grammar ; + +obj grammar_linker : grammar.cpp ; +run grammar_linker.cpp grammar_linker ; diff --git a/src/boost/libs/spirit/test/x3/actions.cpp b/src/boost/libs/spirit/test/x3/actions.cpp new file mode 100644 index 00000000..f033e27e --- /dev/null +++ b/src/boost/libs/spirit/test/x3/actions.cpp @@ -0,0 +1,108 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <cstring> +#include <functional> + +#include "test.hpp" + + +namespace x3 = boost::spirit::x3; + +int x = 0; + +auto fun1 = + [](auto& ctx) + { + x += x3::_attr(ctx); + } +; + +struct fun_action +{ + template <typename Context> + void operator()(Context const& ctx) const + { + x += x3::_attr(ctx); + } +}; + +auto fail = + [](auto& ctx) + { + x3::_pass(ctx) = false; + } +; + +struct setnext +{ + setnext(char& next) : next(next) {} + + template <typename Context> + void operator()(Context const& ctx) const + { + next = x3::_attr(ctx); + } + + char& next; +}; + + +struct stationary : boost::noncopyable +{ + explicit stationary(int i) : val{i} {} + stationary& operator=(int i) { val = i; return *this; } + + int val; +}; + + +int main() +{ + using spirit_test::test; + using spirit_test::test_attr; + + using x3::int_; + + { + char const *s1 = "{42}", *e1 = s1 + std::strlen(s1); + x3::parse(s1, e1, '{' >> int_[fun1] >> '}'); + } + + + { + char const *s1 = "{42}", *e1 = s1 + std::strlen(s1); + x3::parse(s1, e1, '{' >> int_[fun_action()] >> '}'); + } + + { + using namespace std::placeholders; + char const *s1 = "{42}", *e1 = s1 + std::strlen(s1); + x3::parse(s1, e1, '{' >> int_[std::bind(fun_action(), _1)] >> '}'); + } + + BOOST_TEST(x == (42*3)); + + { + std::string input("1234 6543"); + char next = '\0'; + BOOST_TEST(x3::phrase_parse(input.begin(), input.end(), + x3::int_[fail] | x3::digit[setnext(next)], x3::space)); + BOOST_TEST(next == '1'); + } + + { // ensure no unneded synthesization, copying and moving occured + auto p = '{' >> int_ >> '}'; + + stationary st { 0 }; + BOOST_TEST(test_attr("{42}", p[([]{})], st)); + BOOST_TEST_EQ(st.val, 42); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/alternative.cpp b/src/boost/libs/spirit/test/x3/alternative.cpp new file mode 100644 index 00000000..9162e943 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/alternative.cpp @@ -0,0 +1,253 @@ +/*============================================================================= + Copyright (c) 2001-2015 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 <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/include/adapt_struct.hpp> +#include <boost/variant.hpp> +#include <boost/fusion/include/vector.hpp> +#include <boost/fusion/include/at.hpp> + +#include <string> +#include <iostream> +#include <vector> +#include "test.hpp" + +struct di_ignore +{ + std::string text; +}; + +struct di_include +{ + std::string FileName; +}; + +BOOST_FUSION_ADAPT_STRUCT(di_ignore, + text +) + +BOOST_FUSION_ADAPT_STRUCT(di_include, + FileName +) + +struct undefined {}; + + +struct stationary : boost::noncopyable +{ + explicit stationary(int i) : val{i} {} + // TODO: fix unneeded self move in alternative + stationary& operator=(stationary&&) { std::abort(); } + stationary& operator=(int i) { val = i; return *this; } + + int val; +}; + + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + + using boost::spirit::x3::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; + using boost::spirit::x3::eps; + + + { + 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<undefined, int, char> attr_type; + attr_type v; + + BOOST_TEST((test_attr("12345", int_ | char_, v))); + BOOST_TEST(boost::get<int>(v) == 12345); + + BOOST_TEST((test_attr("12345", lit("rock") | int_ | char_, v))); + BOOST_TEST(boost::get<int>(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<char>(v) == 'x'); + } + + { // Make sure that we are using the actual supplied attribute types + // from the variant and not the expected type. + boost::variant<int, std::string> v; + BOOST_TEST((test_attr("12345", int_ | +char_, v))); + BOOST_TEST(boost::get<int>(v) == 12345); + + BOOST_TEST((test_attr("abc", int_ | +char_, v))); + BOOST_TEST(boost::get<std::string>(v) == "abc"); + + BOOST_TEST((test_attr("12345", +char_ | int_, v))); + BOOST_TEST(boost::get<std::string>(v) == "12345"); + } + + { + 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<char, char> 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 == "..."); + } + + { // make sure collapsing eps works as expected + // (compile check only) + + using boost::spirit::x3::rule; + using boost::spirit::x3::eps; + using boost::spirit::x3::_attr; + using boost::spirit::x3::_val; + + rule<class r1, wchar_t> r1; + rule<class r2, wchar_t> r2; + rule<class r3, wchar_t> r3; + + auto f = [&](auto& ctx){ _val(ctx) = _attr(ctx); }; + + r3 = ((eps >> r1))[f]; + r3 = ((r1) | r2)[f]; + r3 = ((eps >> r1) | r2); + } + + { + std::string s; + using boost::spirit::x3::eps; + + // test having a variant<container, ...> + 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<container> inside a sequence + s.erase(); + BOOST_TEST( (test_attr("ab", + char_ >> char_ >> -(char_ % ','), s )) ); + BOOST_TEST(s == "ab"); + + // test having a variant<container, ...> 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"); + } + + { + //compile test only (bug_march_10_2011_8_35_am) + typedef boost::variant<double, std::string> value_type; + + using boost::spirit::x3::rule; + using boost::spirit::x3::eps; + + rule<class r1, value_type> r1; + auto r1_ = r1 = r1 | eps; // left recursive! + + unused = r1_; // silence unused local warning + } + + { + using boost::spirit::x3::rule; + typedef boost::variant<di_ignore, di_include> d_line; + + rule<class ignore, di_ignore> ignore; + rule<class include, di_include> include; + rule<class line, d_line> line; + + auto start = + line = include | ignore; + + unused = start; // silence unused local warning + } + + // single-element fusion vector tests + { + boost::fusion::vector<boost::variant<int, std::string>> fv; + BOOST_TEST((test_attr("12345", int_ | +char_, fv))); + BOOST_TEST(boost::get<int>(boost::fusion::at_c<0>(fv)) == 12345); + + boost::fusion::vector<boost::variant<int, std::string>> fvi; + BOOST_TEST((test_attr("12345", int_ | int_, fvi))); + BOOST_TEST(boost::get<int>(boost::fusion::at_c<0>(fvi)) == 12345); + } + + // alternative over single element sequences as part of another sequence + { + auto key1 = lit("long") >> attr(long()); + auto key2 = lit("char") >> attr(char()); + auto keys = key1 | key2; + auto pair = keys >> lit("=") >> +char_; + + boost::fusion::deque<boost::variant<long, char>, std::string> attr_; + + BOOST_TEST(test_attr("long=ABC", pair, attr_)); + BOOST_TEST(boost::get<long>(&boost::fusion::front(attr_)) != nullptr); + BOOST_TEST(boost::get<char>(&boost::fusion::front(attr_)) == nullptr); + } + + { // ensure no unneded synthesization, copying and moving occured + auto p = '{' >> int_ >> '}'; + + stationary st { 0 }; + BOOST_TEST(test_attr("{42}", p | eps | p, st)); + BOOST_TEST_EQ(st.val, 42); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/and_predicate.cpp b/src/boost/libs/spirit/test/x3/and_predicate.cpp new file mode 100644 index 00000000..b2a44d10 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/and_predicate.cpp @@ -0,0 +1,25 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + using boost::spirit::x3::int_; + + { + BOOST_TEST((test("1234", &int_, false))); + BOOST_TEST((!test("abcd", &int_))); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/any_parser.cpp b/src/boost/libs/spirit/test/x3/any_parser.cpp new file mode 100644 index 00000000..9f46492f --- /dev/null +++ b/src/boost/libs/spirit/test/x3/any_parser.cpp @@ -0,0 +1,159 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + Copyright (c) 2013-2014 Agustin Berge + + 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 <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <string> +#include <cstring> +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test_attr; + using spirit_test::test; + + using namespace boost::spirit::x3::ascii; + using boost::spirit::x3::any_parser; + using boost::spirit::x3::make_context; + using boost::spirit::x3::lit; + using boost::spirit::x3::unused_type; + using boost::spirit::x3::phrase_parse; + using boost::spirit::x3::skip_flag; + using boost::spirit::x3::skipper_tag; + using boost::spirit::x3::_attr; + + typedef char const* iterator_type; + typedef decltype(make_context<skipper_tag>(space)) context_type; + { // basic tests + + auto a = lit('a'); + auto b = lit('b'); + auto c = lit('c'); + + { + any_parser<iterator_type> start = + *(a | b | c); + + BOOST_TEST(test("abcabcacb", start)); + } + } + + { // basic tests w/ skipper + + auto a = lit('a'); + auto b = lit('b'); + auto c = lit('c'); + + { + any_parser<iterator_type, unused_type, context_type> start = + *(a | b | c); + + BOOST_TEST(test(" a b c a b c a c b ", start, space)); + } + } + + { // basic tests w/ skipper but no final post-skip + + any_parser<iterator_type, unused_type, context_type> a = lit('a'); + any_parser<iterator_type, unused_type, context_type> b = lit('b'); + any_parser<iterator_type, unused_type, context_type> c = lit('c'); + + { + any_parser<iterator_type, unused_type, context_type> start = *(a | b) >> c; + + char const *s1 = " a b a a b b a c ... " + , *const e1 = s1 + std::strlen(s1); + BOOST_TEST(phrase_parse(s1, e1, start, space, skip_flag::dont_post_skip) + && s1 == e1 - 5); + } + } + + { // context tests + + char ch; + any_parser<iterator_type, char> a = alpha; + + // this semantic action requires both the context and attribute + //!!auto f = [&](auto&, char attr){ ch = attr; }; + //!!BOOST_TEST(test("x", a[f])); + //!!BOOST_TEST(ch == 'x'); + + // the semantic action may have the context passed + auto f2 = [&](auto&){ ch = 'y'; }; + BOOST_TEST(test("x", a[f2])); + BOOST_TEST(ch == 'y'); + + // the semantic action may optionally not have any arguments at all + auto f3 = [&]{ ch = 'z'; }; + BOOST_TEST(test("x", a[f3])); + BOOST_TEST(ch == 'z'); + + BOOST_TEST(test_attr("z", a, ch)); // attribute is given. + BOOST_TEST(ch == 'z'); + } + + { // auto rules tests + + char ch = '\0'; + any_parser<iterator_type, char> a = alpha; + auto f = [&](auto& ctx){ ch = _attr(ctx); }; + + BOOST_TEST(test("x", a[f])); + BOOST_TEST(ch == 'x'); + ch = '\0'; + BOOST_TEST(test_attr("z", a, ch)); // attribute is given. + BOOST_TEST(ch == 'z'); + + ch = '\0'; + BOOST_TEST(test("x", a[f])); + BOOST_TEST(ch == 'x'); + ch = '\0'; + BOOST_TEST(test_attr("z", a, ch)); // attribute is given. + BOOST_TEST(ch == 'z'); + } + + { // auto rules tests: allow stl containers as attributes to + // sequences (in cases where attributes of the elements + // are convertible to the value_type of the container or if + // the element itself is an stl container with value_type + // that is convertible to the value_type of the attribute). + + std::string s; + auto f = [&](auto& ctx){ s = _attr(ctx); }; + + { + any_parser<iterator_type, std::string> r + = char_ >> *(',' >> char_) + ; + + BOOST_TEST(test("a,b,c,d,e,f", r[f])); + BOOST_TEST(s == "abcdef"); + } + + { + any_parser<iterator_type, std::string> r + = char_ >> *(',' >> char_); + s.clear(); + BOOST_TEST(test("a,b,c,d,e,f", r[f])); + BOOST_TEST(s == "abcdef"); + } + + { + any_parser<iterator_type, std::string> r + = char_ >> char_ >> char_ >> char_ >> char_ >> char_; + s.clear(); + BOOST_TEST(test("abcdef", r[f])); + BOOST_TEST(s == "abcdef"); + } + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/attr.cpp b/src/boost/libs/spirit/test/x3/attr.cpp new file mode 100644 index 00000000..ead8d49f --- /dev/null +++ b/src/boost/libs/spirit/test/x3/attr.cpp @@ -0,0 +1,53 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + + Distributed under the Boost Software License, Version 1. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <boost/fusion/include/std_pair.hpp> +#include <vector> + +#include "test.hpp" + +int main() +{ + using spirit_test::test_attr; + using boost::spirit::x3::attr; + using boost::spirit::x3::int_; + + { + int d = 0; + BOOST_TEST(test_attr("", attr(1), d) && d == 1); + + int d1 = 1; + BOOST_TEST(test_attr("", attr(d1), d) && d == 1); + + std::pair<int, int> p; + BOOST_TEST(test_attr("1", int_ >> attr(1), p) && + p.first == 1 && p.second == 1); + + char c = '\0'; + BOOST_TEST(test_attr("", attr('a'), c) && c == 'a'); + + // $$$ Needs some special is_convertible support, or + // str ends up with an explicit null-terminator... $$$ + //~ std::string str; + //~ BOOST_TEST(test_attr("", attr("test"), str) && str == "test"); + + int array[] = {0, 1, 2}; + std::vector<int> vec; + BOOST_TEST(test_attr("", attr(array), vec) && vec.size() == 3 && + vec[0] == 0 && vec[1] == 1 && vec[2] == 2); + } + + { + std::string s; + BOOST_TEST(test_attr("s", "s" >> attr(std::string("123")), s) && + s == "123"); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/attribute_type_check.cpp b/src/boost/libs/spirit/test/x3/attribute_type_check.cpp new file mode 100644 index 00000000..26f028a3 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/attribute_type_check.cpp @@ -0,0 +1,113 @@ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/include/vector.hpp> +#include <boost/fusion/include/make_vector.hpp> +#include <boost/fusion/include/equal_to.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/optional.hpp> +#include <string> + +namespace x3 = boost::spirit::x3; + +// just an `attr` with added type checker +template <typename Value, typename Expected> +struct checked_attr_parser : x3::attr_parser<Value> +{ + using base_t = x3::attr_parser<Value>; + + checked_attr_parser(Value const& value) : base_t(value) {} + checked_attr_parser(Value&& value) : base_t(std::move(value)) {} + + template <typename Iterator, typename Context + , typename RuleContext, typename Attribute> + bool parse(Iterator& first, Iterator const& last + , Context const& ctx, RuleContext& rctx, Attribute& attr_) const + { + static_assert(boost::is_same<Expected, Attribute>::value, + "attribute type check failed"); + return base_t::parse(first, last, ctx, rctx, attr_); + } +}; + +template <typename Expected, typename Value> +static inline checked_attr_parser<boost::decay_t<Value>, Expected> +checked_attr(Value&& value) { return { std::forward<Value>(value) }; } + +// instantiate our type checker +// (checks attribute value just to be sure we are ok) +template <typename Value, typename Expr> +static void test_expr(Value const& v, Expr&& expr) +{ + char const* it = ""; + Value r; + BOOST_TEST((x3::parse(it, it, std::forward<Expr>(expr), r))); + BOOST_TEST((r == v)); +} + +template <typename Expr, typename Attribute> +static void gen_sequence(Attribute const& attribute, Expr&& expr) +{ + test_expr(attribute, expr); + test_expr(attribute, expr >> x3::eps); +} + +template <typename Expected, typename... ExpectedTail, typename Attribute, typename Expr, typename Value, typename... Tail> +static void gen_sequence(Attribute const& attribute, Expr&& expr, Value const& v, Tail const&... tail) +{ + gen_sequence<ExpectedTail...>(attribute, expr >> checked_attr<Expected>(v), tail...); + gen_sequence<ExpectedTail...>(attribute, expr >> x3::eps >> checked_attr<Expected>(v), tail...); + gen_sequence<ExpectedTail...>(attribute, expr >> (x3::eps >> checked_attr<Expected>(v)), tail...); +} + +template <typename Expected, typename... ExpectedTail, typename Attribute, typename Value, typename... Tail> +static void gen_sequence_tests(Attribute const& attribute, Value const& v, Tail const&... tail) +{ + gen_sequence<ExpectedTail...>(attribute, checked_attr<Expected>(v), tail...); + gen_sequence<ExpectedTail...>(attribute, x3::eps >> checked_attr<Expected>(v), tail...); +} + +template <typename Expected, typename Value> +static void gen_single_item_tests(Value const& v) +{ + Expected attribute(v); + gen_sequence(attribute, checked_attr<Expected>(v)); + gen_sequence(attribute, x3::eps >> checked_attr<Expected>(v)); +} + +template <typename Expected, typename... ExpectedTail, typename Value, typename... Tail> +static void gen_single_item_tests(Value const& v, Tail const&... tail) +{ + gen_single_item_tests<Expected>(v); + gen_single_item_tests<ExpectedTail...>(tail...); +} + +template <typename... Expected, typename... Values> +static void gen_tests(Values const&... values) +{ + gen_single_item_tests<Expected...>(values...); + + boost::fusion::vector<Expected...> attribute = boost::fusion::make_vector(values...); + gen_sequence_tests<Expected...>(attribute, values...); +} + +template <typename... Attributes> +void make_test(Attributes const&... attrs) +{ + // I would like to place all of this in a single call + // but it requires tremendous amount of heap to compile + gen_tests<Attributes...>(attrs...); + gen_tests< + boost::optional<Attributes>... + , boost::fusion::vector<Attributes>... + >(attrs..., attrs...); + gen_tests< + boost::optional<boost::fusion::vector<Attributes>>... + , boost::fusion::vector<boost::optional<Attributes>>... + >(boost::fusion::vector<Attributes>(attrs)..., attrs...); +} + +int main() +{ + make_test<int, std::string>(123, "hello"); + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/binary.cpp b/src/boost/libs/spirit/test/x3/binary.cpp new file mode 100644 index 00000000..12878429 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/binary.cpp @@ -0,0 +1,155 @@ +/*============================================================================= + 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 <boost/detail/lightweight_test.hpp> + +#include <boost/spirit/home/x3/binary.hpp> +#include <boost/cstdint.hpp> +#include <boost/predef/other/endian.h> +#include "test.hpp" + +/////////////////////////////////////////////////////////////////////////////// +int main() +{ + using spirit_test::test_attr; + using spirit_test::test; + using spirit_test::binary_test; + using spirit_test::binary_test_attr; + + using boost::spirit::x3::byte_; + using boost::spirit::x3::word; + using boost::spirit::x3::dword; + using boost::spirit::x3::big_word; + using boost::spirit::x3::big_dword; + using boost::spirit::x3::little_word; + using boost::spirit::x3::little_dword; +#ifdef BOOST_HAS_LONG_LONG + using boost::spirit::x3::qword; + using boost::spirit::x3::big_qword; + using boost::spirit::x3::little_qword; +#endif +// using boost::spirit::x3::bin_float; +// using boost::spirit::x3::big_bin_float; +// using boost::spirit::x3::little_bin_float; +// using boost::spirit::x3::bin_double; +// using boost::spirit::x3::big_bin_double; +// using boost::spirit::x3::little_bin_double; + + boost::uint8_t uc; + boost::uint16_t us; + boost::uint32_t ui; +#ifdef BOOST_HAS_LONG_LONG + boost::uint64_t ul; +#endif +// float f; +// double d; + + { // test native endian binaries +#if BOOST_ENDIAN_LITTLE_BYTE + BOOST_TEST(test_attr("\x01", byte_, uc) && uc == 0x01); + BOOST_TEST(test_attr("\x01\x02", word, us) && us == 0x0201); + BOOST_TEST(test_attr("\x01\x02\x03\x04", dword, ui) && ui == 0x04030201); +#ifdef BOOST_HAS_LONG_LONG + BOOST_TEST(test_attr("\x01\x02\x03\x04\x05\x06\x07\x08", qword, ul) && + ul == 0x0807060504030201LL); +#endif +// BOOST_TEST(binary_test_attr("\x00\x00\x80\x3f", 4, bin_float, f) && +// f == 1.0f); +// BOOST_TEST(binary_test_attr("\x00\x00\x00\x00\x00\x00\xf0\x3f", +// 8, bin_double, d) && f == 1.0); +#else + BOOST_TEST(test_attr("\x01", byte_, uc) && uc == 0x01); + BOOST_TEST(test_attr("\x01\x02", word, us) && us == 0x0102); + BOOST_TEST(test_attr("\x01\x02\x03\x04", dword, ui) && ui == 0x01020304); +#ifdef BOOST_HAS_LONG_LONG + BOOST_TEST(test_attr("\x01\x02\x03\x04\x05\x06\x07\x08", qword, ul) && + ul == 0x0102030405060708LL); +#endif +// BOOST_TEST(binary_test_attr("\x3f\x80\x00\x00", 4, bin_float, f) && +// f == 1.0f); +// BOOST_TEST(binary_test_attr("\x3f\xf0\x00\x00\x00\x00\x00\x00", +// 8, bin_double, d) && f == 1.0); +#endif + } + + { // test native endian binaries +#if BOOST_ENDIAN_LITTLE_BYTE + BOOST_TEST(test("\x01", byte_(0x01))); + BOOST_TEST(test("\x01\x02", word(0x0201))); + BOOST_TEST(test("\x01\x02\x03\x04", dword(0x04030201))); +#ifdef BOOST_HAS_LONG_LONG + BOOST_TEST(test("\x01\x02\x03\x04\x05\x06\x07\x08", + qword(0x0807060504030201LL))); +#endif +// BOOST_TEST(binary_test("\x00\x00\x80\x3f", 4, bin_float(1.0f))); +// BOOST_TEST(binary_test("\x00\x00\x00\x00\x00\x00\xf0\x3f", 8, +// bin_double(1.0))); +#else + BOOST_TEST(test("\x01", byte_(0x01))); + BOOST_TEST(test("\x01\x02", word(0x0102))); + BOOST_TEST(test("\x01\x02\x03\x04", dword(0x01020304))); +#ifdef BOOST_HAS_LONG_LONG + BOOST_TEST(test("\x01\x02\x03\x04\x05\x06\x07\x08", + qword(0x0102030405060708LL))); +#endif +// BOOST_TEST(binary_test("\x3f\x80\x00\x00", 4, bin_float(1.0f))); +// BOOST_TEST(binary_test("\x3f\x80\x00\x00\x00\x00\x00\x00", 8, +// bin_double(1.0))); +#endif + } + + { // test big endian binaries + BOOST_TEST(test_attr("\x01\x02", big_word, us) && us == 0x0102); + BOOST_TEST(test_attr("\x01\x02\x03\x04", big_dword, ui) && ui == 0x01020304); +#ifdef BOOST_HAS_LONG_LONG + BOOST_TEST(test_attr("\x01\x02\x03\x04\x05\x06\x07\x08", big_qword, ul) + && ul == 0x0102030405060708LL); +#endif +// BOOST_TEST(binary_test_attr("\x3f\x80\x00\x00", 4, big_bin_float, f) && +// f == 1.0f); +// BOOST_TEST(binary_test_attr("\x3f\xf0\x00\x00\x00\x00\x00\x00", +// 8, big_bin_double, d) && f == 1.0); + } + + { + BOOST_TEST(test("\x01\x02", big_word(0x0102))); + BOOST_TEST(test("\x01\x02\x03\x04", big_dword(0x01020304))); +#ifdef BOOST_HAS_LONG_LONG + BOOST_TEST(test("\x01\x02\x03\x04\x05\x06\x07\x08", + big_qword(0x0102030405060708LL))); +#endif +// BOOST_TEST(binary_test("\x3f\x80\x00\x00", 4, big_bin_float(1.0f))); +// BOOST_TEST(binary_test("\x3f\xf0\x00\x00\x00\x00\x00\x00", 8, +// big_bin_double(1.0))); + } + + { // test little endian binaries + BOOST_TEST(test_attr("\x01\x02", little_word, us) && us == 0x0201); + BOOST_TEST(test_attr("\x01\x02\x03\x04", little_dword, ui) && ui == 0x04030201); +#ifdef BOOST_HAS_LONG_LONG + BOOST_TEST(test_attr("\x01\x02\x03\x04\x05\x06\x07\x08", little_qword, ul) + && ul == 0x0807060504030201LL); +#endif +// BOOST_TEST(binary_test_attr("\x00\x00\x80\x3f", 4, +// little_bin_float, f) && f == 1.0f); +// BOOST_TEST(binary_test_attr("\x00\x00\x00\x00\x00\x00\xf0\x3f", +// 8, little_bin_double, d) && f == 1.0); + } + + { + BOOST_TEST(test("\x01\x02", little_word(0x0201))); + BOOST_TEST(test("\x01\x02\x03\x04", little_dword(0x04030201))); +#ifdef BOOST_HAS_LONG_LONG + BOOST_TEST(test("\x01\x02\x03\x04\x05\x06\x07\x08", + little_qword(0x0807060504030201LL))); +#endif +// BOOST_TEST(binary_test("\x00\x00\x80\x3f", 4, little_bin_float(1.0f))); +// BOOST_TEST(binary_test("\x00\x00\x00\x00\x00\x00\xf0\x3f", 8, +// little_bin_double(1.0))); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/bool.cpp b/src/boost/libs/spirit/test/x3/bool.cpp new file mode 100644 index 00000000..61c357f8 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/bool.cpp @@ -0,0 +1,83 @@ +/*============================================================================= + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2011 Bryce Lelbach + + 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 "bool.hpp" + +int main() +{ + using spirit_test::test_attr; + using spirit_test::test; + using boost::spirit::x3::bool_; + + { + BOOST_TEST(test("true", bool_)); + BOOST_TEST(test("false", bool_)); + BOOST_TEST(!test("fasle", bool_)); + } + + { + using boost::spirit::x3::true_; + using boost::spirit::x3::false_; + + BOOST_TEST(test("true", true_)); + BOOST_TEST(!test("true", false_)); + BOOST_TEST(test("false", false_)); + BOOST_TEST(!test("false", true_)); + } + + { + using boost::spirit::x3::true_; + using boost::spirit::x3::false_; + using boost::spirit::x3::no_case; + + BOOST_TEST(test("True", no_case[bool_])); + BOOST_TEST(test("False", no_case[bool_])); + BOOST_TEST(test("True", no_case[true_])); + BOOST_TEST(test("False", no_case[false_])); + } + + { + bool b = false; + BOOST_TEST(test_attr("true", bool_, b) && b); + BOOST_TEST(test_attr("false", bool_, b) && !b); + BOOST_TEST(!test_attr("fasle", bool_, b)); + } + + { + typedef boost::spirit::x3::bool_parser<bool, boost::spirit::char_encoding::standard, backwards_bool_policies> + backwards_bool_type; + backwards_bool_type const backwards_bool = backwards_bool_type(); + + BOOST_TEST(test("true", backwards_bool)); + BOOST_TEST(test("eurt", backwards_bool)); + BOOST_TEST(!test("false", backwards_bool)); + BOOST_TEST(!test("fasle", backwards_bool)); + + bool b = false; + BOOST_TEST(test_attr("true", backwards_bool, b) && b); + BOOST_TEST(test_attr("eurt", backwards_bool, b) && !b); + BOOST_TEST(!test_attr("false", backwards_bool, b)); + BOOST_TEST(!test_attr("fasle", backwards_bool, b)); + } + + { + typedef boost::spirit::x3::bool_parser<test_bool_type, boost::spirit::char_encoding::standard> + bool_test_type; + bool_test_type const test_bool = bool_test_type(); + + BOOST_TEST(test("true", test_bool)); + BOOST_TEST(test("false", test_bool)); + BOOST_TEST(!test("fasle", test_bool)); + + test_bool_type b = false; + BOOST_TEST(test_attr("true", test_bool, b) && b.b); + BOOST_TEST(test_attr("false", test_bool, b) && !b.b); + BOOST_TEST(!test_attr("fasle", test_bool, b)); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/bool.hpp b/src/boost/libs/spirit/test/x3/bool.hpp new file mode 100644 index 00000000..f06b884c --- /dev/null +++ b/src/boost/libs/spirit/test/x3/bool.hpp @@ -0,0 +1,41 @@ +/*============================================================================= + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2011 Bryce Lelbach + + 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) +==============================================================================*/ +#if !defined(BOOST_SPIRIT_TEST_QI_BOOL) +#define BOOST_SPIRIT_TEST_QI_BOOL + +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include "test.hpp" + +/////////////////////////////////////////////////////////////////////////////// +struct backwards_bool_policies : boost::spirit::x3::bool_policies<> +{ + // we want to interpret a 'true' spelled backwards as 'false' + template <typename Iterator, typename Attribute, typename CaseCompare> + static bool + parse_false(Iterator& first, Iterator const& last, Attribute& attr, CaseCompare const& case_compare) + { + namespace spirit = boost::spirit; + namespace x3 = boost::spirit::x3; + if (x3::detail::string_parse("eurt", first, last, x3::unused, case_compare)) + { + x3::traits::move_to(false, attr); // result is false + return true; + } + return false; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +struct test_bool_type +{ + test_bool_type(bool b = false) : b(b) {} // provide conversion + bool b; +}; + +#endif diff --git a/src/boost/libs/spirit/test/x3/char1.cpp b/src/boost/libs/spirit/test/x3/char1.cpp new file mode 100644 index 00000000..b835e48d --- /dev/null +++ b/src/boost/libs/spirit/test/x3/char1.cpp @@ -0,0 +1,198 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2019 Christian Mazakas + + 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) +=============================================================================*/ + +#define BOOST_SPIRIT_X3_UNICODE + +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <boost/utility/string_view.hpp> + +#include <iostream> +#include <vector> +#include <algorithm> + +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + + { + using namespace boost::spirit::x3::ascii; + + BOOST_TEST(test("x", 'x')); + BOOST_TEST(test(L"x", L'x')); + BOOST_TEST(!test("y", 'x')); + BOOST_TEST(!test(L"y", L'x')); + + BOOST_TEST(test("x", char_)); + BOOST_TEST(test("x", char_('x'))); + BOOST_TEST(!test("x", char_('y'))); + BOOST_TEST(test("x", char_('a', 'z'))); + BOOST_TEST(!test("x", char_('0', '9'))); + + BOOST_TEST(test("0", char_('0', '9'))); + BOOST_TEST(test("9", char_('0', '9'))); + BOOST_TEST(!test("0", ~char_('0', '9'))); + BOOST_TEST(!test("9", ~char_('0', '9'))); + + BOOST_TEST(!test("x", ~char_)); + BOOST_TEST(!test("x", ~char_('x'))); + BOOST_TEST(test(" ", ~char_('x'))); + BOOST_TEST(test("X", ~char_('x'))); + BOOST_TEST(!test("x", ~char_('b', 'y'))); + BOOST_TEST(test("a", ~char_('b', 'y'))); + BOOST_TEST(test("z", ~char_('b', 'y'))); + + BOOST_TEST(test("x", ~~char_)); + BOOST_TEST(test("x", ~~char_('x'))); + BOOST_TEST(!test(" ", ~~char_('x'))); + BOOST_TEST(!test("X", ~~char_('x'))); + BOOST_TEST(test("x", ~~char_('b', 'y'))); + BOOST_TEST(!test("a", ~~char_('b', 'y'))); + BOOST_TEST(!test("z", ~~char_('b', 'y'))); + } + + { + using namespace boost::spirit::x3::ascii; + + BOOST_TEST(test(" x", 'x', space)); + BOOST_TEST(test(L" x", L'x', space)); + + BOOST_TEST(test(" x", char_, space)); + BOOST_TEST(test(" x", char_('x'), space)); + BOOST_TEST(!test(" x", char_('y'), space)); + BOOST_TEST(test(" x", char_('a', 'z'), space)); + BOOST_TEST(!test(" x", char_('0', '9'), space)); + } + + { + using namespace boost::spirit::x3::standard_wide; + + BOOST_TEST(test(L"x", char_)); + BOOST_TEST(test(L"x", char_(L'x'))); + BOOST_TEST(!test(L"x", char_(L'y'))); + BOOST_TEST(test(L"x", char_(L'a', L'z'))); + BOOST_TEST(!test(L"x", char_(L'0', L'9'))); + + BOOST_TEST(!test(L"x", ~char_)); + BOOST_TEST(!test(L"x", ~char_(L'x'))); + BOOST_TEST(test(L" ", ~char_(L'x'))); + BOOST_TEST(test(L"X", ~char_(L'x'))); + BOOST_TEST(!test(L"x", ~char_(L'b', L'y'))); + BOOST_TEST(test(L"a", ~char_(L'b', L'y'))); + BOOST_TEST(test(L"z", ~char_(L'b', L'y'))); + + BOOST_TEST(test(L"x", ~~char_)); + BOOST_TEST(test(L"x", ~~char_(L'x'))); + BOOST_TEST(!test(L" ", ~~char_(L'x'))); + BOOST_TEST(!test(L"X", ~~char_(L'x'))); + BOOST_TEST(test(L"x", ~~char_(L'b', L'y'))); + BOOST_TEST(!test(L"a", ~~char_(L'b', L'y'))); + BOOST_TEST(!test(L"z", ~~char_(L'b', L'y'))); + } + + // unicode (normal ASCII) + { + using namespace boost::spirit::x3::unicode; + + BOOST_TEST(test(U"abcd", +char_(U"abcd"))); + BOOST_TEST(!test(U"abcd", +char_(U"qwer"))); + + auto const sub_delims = char_(U"!$&'()*+,;="); + + auto const delims = + std::vector<boost::u32string_view>{U"!", U"$", U"&", U"'", U"(", U")", U"*", U"+", + U",", U";", U"="}; + + auto const matched_all_sub_delims = + std::all_of(delims.begin(), delims.end(), [&](auto const delim) -> bool { + return test(delim, sub_delims); + }); + + BOOST_TEST(matched_all_sub_delims); + } + + // unicode (escaped Unicode char literals) + { + using namespace boost::spirit::x3::unicode; + + auto const chars = char_(U"\u0024\u00a2\u0939\u20ac\U00010348"); + + auto const test_strings = + std::vector<boost::u32string_view>{U"\u0024", U"\u00a2", U"\u0939", U"\u20ac", + U"\U00010348"}; + + auto const bad_test_strings = std::vector<boost::u32string_view>{U"a", U"B", U"c", U"\u0409"}; + + auto const all_matched = + std::all_of(test_strings.begin(), test_strings.end(), [&](auto const test_str) -> bool { + return test(test_str, chars); + }); + + auto const none_matched = + std::all_of(bad_test_strings.begin(), bad_test_strings.end(), [&](auto const bad_test_str) -> bool { + return !test(bad_test_str, chars); + }); + + BOOST_TEST(all_matched); + BOOST_TEST(none_matched); + } + + + { // single char strings! + namespace ascii = boost::spirit::x3::ascii; + namespace wide = boost::spirit::x3::standard_wide; + + BOOST_TEST(test("x", "x")); + BOOST_TEST(test(L"x", L"x")); + BOOST_TEST(test("x", ascii::char_("x"))); + BOOST_TEST(test(L"x", wide::char_(L"x"))); + + BOOST_TEST(test("x", ascii::char_("a", "z"))); + BOOST_TEST(test(L"x", wide::char_(L"a", L"z"))); + } + + { + // chsets + namespace ascii = boost::spirit::x3::ascii; + namespace wide = boost::spirit::x3::standard_wide; + + BOOST_TEST(test("x", ascii::char_("a-z"))); + BOOST_TEST(!test("1", ascii::char_("a-z"))); + BOOST_TEST(test("1", ascii::char_("a-z0-9"))); + + BOOST_TEST(test("x", wide::char_(L"a-z"))); + BOOST_TEST(!test("1", wide::char_(L"a-z"))); + BOOST_TEST(test("1", wide::char_(L"a-z0-9"))); + + std::string set = "a-z0-9"; + BOOST_TEST(test("x", ascii::char_(set))); + +#ifdef SPIRIT_NO_COMPILE_CHECK + test("", ascii::char_(L"a-z0-9")); +#endif + } + + { + namespace ascii = boost::spirit::x3::ascii; + char const* input = "\x80"; + + // ascii > 7 bits (this should fail, not assert!) + BOOST_TEST(!test(input, ascii::char_)); + BOOST_TEST(!test(input, ascii::char_('a'))); + BOOST_TEST(!test(input, ascii::alnum)); + BOOST_TEST(!test(input, ascii::char_("a-z"))); + BOOST_TEST(!test(input, ascii::char_('0', '9'))); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/char_class.cpp b/src/boost/libs/spirit/test/x3/char_class.cpp new file mode 100644 index 00000000..a151d5c8 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/char_class.cpp @@ -0,0 +1,248 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + Copyright (c) 2001-2010 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) +=============================================================================*/ + +#define BOOST_SPIRIT_X3_UNICODE + +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/type_traits/is_same.hpp> + +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + using spirit_test::test_failure; + using spirit_test::test_attr; + + using boost::spirit::x3::unused_type; + + { + using namespace boost::spirit::x3::ascii; + BOOST_TEST(test("1", alnum)); + BOOST_TEST(!test(" ", alnum)); + BOOST_TEST(!test("1", alpha)); + BOOST_TEST(test("x", alpha)); + BOOST_TEST(test(" ", blank)); + BOOST_TEST(!test("x", blank)); + BOOST_TEST(test("1", digit)); + BOOST_TEST(!test("x", digit)); + BOOST_TEST(test("a", lower)); + BOOST_TEST(!test("A", lower)); + BOOST_TEST(test("!", punct)); + BOOST_TEST(!test("x", punct)); + BOOST_TEST(test(" ", space)); + BOOST_TEST(test("\n", space)); + BOOST_TEST(test("\r", space)); + BOOST_TEST(test("\t", space)); + BOOST_TEST(test("A", upper)); + BOOST_TEST(!test("a", upper)); + BOOST_TEST(test("A", xdigit)); + BOOST_TEST(test("0", xdigit)); + BOOST_TEST(test("f", xdigit)); + BOOST_TEST(!test("g", xdigit)); + } + + { + using namespace boost::spirit::x3::ascii; + BOOST_TEST(!test("1", ~alnum)); + BOOST_TEST(test(" ", ~alnum)); + BOOST_TEST(test("1", ~alpha)); + BOOST_TEST(!test("x", ~alpha)); + BOOST_TEST(!test(" ", ~blank)); + BOOST_TEST(test("x", ~blank)); + BOOST_TEST(!test("1", ~digit)); + BOOST_TEST(test("x", ~digit)); + BOOST_TEST(!test("a", ~lower)); + BOOST_TEST(test("A", ~lower)); + BOOST_TEST(!test("!", ~punct)); + BOOST_TEST(test("x", ~punct)); + BOOST_TEST(!test(" ", ~space)); + BOOST_TEST(!test("\n", ~space)); + BOOST_TEST(!test("\r", ~space)); + BOOST_TEST(!test("\t", ~space)); + BOOST_TEST(!test("A", ~upper)); + BOOST_TEST(test("a", ~upper)); + BOOST_TEST(!test("A", ~xdigit)); + BOOST_TEST(!test("0", ~xdigit)); + BOOST_TEST(!test("f", ~xdigit)); + BOOST_TEST(test("g", ~xdigit)); + } + + { + using namespace boost::spirit::x3::iso8859_1; + BOOST_TEST(test("1", alnum)); + BOOST_TEST(!test(" ", alnum)); + BOOST_TEST(!test("1", alpha)); + BOOST_TEST(test("x", alpha)); + BOOST_TEST(test(" ", blank)); + BOOST_TEST(!test("x", blank)); + BOOST_TEST(test("1", digit)); + BOOST_TEST(!test("x", digit)); + BOOST_TEST(test("a", lower)); + BOOST_TEST(!test("A", lower)); + BOOST_TEST(test("!", punct)); + BOOST_TEST(!test("x", punct)); + BOOST_TEST(test(" ", space)); + BOOST_TEST(test("\n", space)); + BOOST_TEST(test("\r", space)); + BOOST_TEST(test("\t", space)); + BOOST_TEST(test("A", upper)); + BOOST_TEST(!test("a", upper)); + BOOST_TEST(test("A", xdigit)); + BOOST_TEST(test("0", xdigit)); + BOOST_TEST(test("f", xdigit)); + BOOST_TEST(!test("g", xdigit)); + + // test extended ASCII characters + BOOST_TEST(test("\xE9", alpha)); + BOOST_TEST(test("\xE9", lower)); + BOOST_TEST(!test("\xE9", upper)); + } + + { + using namespace boost::spirit::x3::standard; + BOOST_TEST(test("1", alnum)); + BOOST_TEST(!test(" ", alnum)); + BOOST_TEST(!test("1", alpha)); + BOOST_TEST(test("x", alpha)); + BOOST_TEST(test(" ", blank)); + BOOST_TEST(!test("x", blank)); + BOOST_TEST(test("1", digit)); + BOOST_TEST(!test("x", digit)); + BOOST_TEST(test("a", lower)); + BOOST_TEST(!test("A", lower)); + BOOST_TEST(test("!", punct)); + BOOST_TEST(!test("x", punct)); + BOOST_TEST(test(" ", space)); + BOOST_TEST(test("\n", space)); + BOOST_TEST(test("\r", space)); + BOOST_TEST(test("\t", space)); + BOOST_TEST(test("A", upper)); + BOOST_TEST(!test("a", upper)); + BOOST_TEST(test("A", xdigit)); + BOOST_TEST(test("0", xdigit)); + BOOST_TEST(test("f", xdigit)); + BOOST_TEST(!test("g", xdigit)); + } + + { + using namespace boost::spirit::x3::standard_wide; + BOOST_TEST(test(L"1", alnum)); + BOOST_TEST(!test(L" ", alnum)); + BOOST_TEST(!test(L"1", alpha)); + BOOST_TEST(test(L"x", alpha)); + BOOST_TEST(test(L" ", blank)); + BOOST_TEST(!test(L"x", blank)); + BOOST_TEST(test(L"1", digit)); + BOOST_TEST(!test(L"x", digit)); + BOOST_TEST(test(L"a", lower)); + BOOST_TEST(!test(L"A", lower)); + BOOST_TEST(test(L"!", punct)); + BOOST_TEST(!test(L"x", punct)); + BOOST_TEST(test(L" ", space)); + BOOST_TEST(test(L"\n", space)); + BOOST_TEST(test(L"\r", space)); + BOOST_TEST(test(L"\t", space)); + BOOST_TEST(test(L"A", upper)); + BOOST_TEST(!test(L"a", upper)); + BOOST_TEST(test(L"A", xdigit)); + BOOST_TEST(test(L"0", xdigit)); + BOOST_TEST(test(L"f", xdigit)); + BOOST_TEST(!test(L"g", xdigit)); + } + + { + using namespace boost::spirit::x3::unicode; + BOOST_TEST(test(L"1", alnum)); + BOOST_TEST(!test(L" ", alnum)); + BOOST_TEST(!test(L"1", alpha)); + BOOST_TEST(test(L"x", alpha)); + BOOST_TEST(test(L" ", blank)); + BOOST_TEST(!test(L"x", blank)); + BOOST_TEST(test(L"1", digit)); + BOOST_TEST(!test(L"x", digit)); + BOOST_TEST(test(L"a", lower)); + BOOST_TEST(!test(L"A", lower)); + BOOST_TEST(test(L"!", punct)); + BOOST_TEST(!test(L"x", punct)); + BOOST_TEST(test(L" ", space)); + BOOST_TEST(test(L"\n", space)); + BOOST_TEST(test(L"\r", space)); + BOOST_TEST(test(L"\t", space)); + BOOST_TEST(test(L"A", upper)); + BOOST_TEST(!test(L"a", upper)); + BOOST_TEST(test(L"A", xdigit)); + BOOST_TEST(test(L"0", xdigit)); + BOOST_TEST(test(L"f", xdigit)); + BOOST_TEST(!test(L"g", xdigit)); + + BOOST_TEST(test(L"A", alphabetic)); + BOOST_TEST(test(L"9", decimal_number)); + BOOST_TEST(test(L"\u2800", braille)); + BOOST_TEST(!test(L" ", braille)); + BOOST_TEST(test(L" ", ~braille)); + // $$$ TODO $$$ Add more unicode tests + } + + { // test invalid unicode literals + using namespace boost::spirit::x3::unicode; + + auto const invalid_unicode = char32_t{0x7FFFFFFF}; + auto const input = boost::u32string_view(&invalid_unicode, 1); + + BOOST_TEST(test_failure(input, char_)); + + // force unicode category lookup + // related issue: https://github.com/boostorg/spirit/issues/524 + BOOST_TEST(test_failure(input, alpha)); + BOOST_TEST(test_failure(input, upper)); + BOOST_TEST(test_failure(input, lower)); + } + + { // test attribute extraction + using boost::spirit::x3::traits::attribute_of; + using boost::spirit::x3::iso8859_1::alpha; + using boost::spirit::x3::iso8859_1::alpha_type; + + static_assert( + boost::is_same< + attribute_of<alpha_type, unused_type>::type + , unsigned char>::value + , "Wrong attribute type!" + ); + + int attr = 0; + BOOST_TEST(test_attr("a", alpha, attr)); + BOOST_TEST(attr == 'a'); + } + + { // test attribute extraction + using boost::spirit::x3::iso8859_1::alpha; + using boost::spirit::x3::iso8859_1::space; + char attr = 0; + BOOST_TEST(test_attr(" a", alpha, attr, space)); + BOOST_TEST(attr == 'a'); + } + + { // test action + using namespace boost::spirit::x3::ascii; + using boost::spirit::x3::_attr; + char ch; + auto f = [&](auto& ctx){ ch = _attr(ctx); }; + + BOOST_TEST(test("x", alnum[f])); + BOOST_TEST(ch == 'x'); + BOOST_TEST(test(" A", alnum[f], space)); + BOOST_TEST(ch == 'A'); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/confix.cpp b/src/boost/libs/spirit/test/x3/confix.cpp new file mode 100644 index 00000000..40bce11b --- /dev/null +++ b/src/boost/libs/spirit/test/x3/confix.cpp @@ -0,0 +1,84 @@ +/*============================================================================= + Copyright (c) 2009 Chris Hoeppler + Copyright (c) 2014 Lee Clagett + + 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 <boost/detail/lightweight_test.hpp> + +#include <boost/spirit/home/x3/char.hpp> +#include <boost/spirit/home/x3/core.hpp> +#include <boost/spirit/home/x3/numeric.hpp> +#include <boost/spirit/home/x3/operator.hpp> +#include <boost/spirit/home/x3/string.hpp> +#include <boost/spirit/home/x3/directive/confix.hpp> + +#include "test.hpp" + +int main() +{ + namespace x3 = boost::spirit::x3; + using namespace spirit_test; + + { + const auto comment = x3::confix("/*", "*/"); + + BOOST_TEST(test_failure("/abcdef*/", comment["abcdef"])); + BOOST_TEST(test_failure("/* abcdef*/", comment["abcdef"])); + BOOST_TEST(test_failure("/*abcdef */", comment["abcdef"])); + BOOST_TEST(test("/*abcdef*/", comment["abcdef"])); + + { + unsigned value = 0; + BOOST_TEST( + test_attr(" /* 123 */ ", comment[x3::uint_], value, x3::space)); + BOOST_TEST(value == 123); + + using x3::_attr; + value = 0; + const auto lambda = [&value](auto& ctx ){ value = _attr(ctx) + 1; }; + BOOST_TEST(test_attr("/*123*/", comment[x3::uint_][lambda], value)); + BOOST_TEST(value == 124); + } + } + { + const auto array = x3::confix('[', ']'); + + { + std::vector<unsigned> values; + + BOOST_TEST(test("[0,2,4,6,8]", array[x3::uint_ % ','])); + BOOST_TEST(test_attr("[0,2,4,6,8]", array[x3::uint_ % ','], values)); + BOOST_TEST( + values.size() == 5 && + values[0] == 0 && + values[1] == 2 && + values[2] == 4 && + values[3] == 6 && + values[4] == 8); + } + { + std::vector<std::vector<unsigned>> values; + BOOST_TEST( + test("[[1,3,5],[0,2,4]]", array[array[x3::uint_ % ','] % ','])); + BOOST_TEST( + test_attr( + "[[1,3,5],[0,2,4]]", + array[array[x3::uint_ % ','] % ','], + values)); + BOOST_TEST( + values.size() == 2 && + values[0].size() == 3 && + values[0][0] == 1 && + values[0][1] == 3 && + values[0][2] == 5 && + values[1].size() == 3 && + values[1][0] == 0 && + values[1][1] == 2 && + values[1][2] == 4); + } + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/container_support.cpp b/src/boost/libs/spirit/test/x3/container_support.cpp new file mode 100644 index 00000000..f8c79f1d --- /dev/null +++ b/src/boost/libs/spirit/test/x3/container_support.cpp @@ -0,0 +1,248 @@ +/*============================================================================= + Copyright (c) 2001-2015 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 <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/include/std_pair.hpp> + +#include <iostream> +#include <map> +#include <unordered_map> +#include <boost/unordered_map.hpp> +#include <vector> +#include <list> +#include <deque> +#include <set> +#include <unordered_set> +#include <boost/unordered_set.hpp> +#include <string> +#include "test.hpp" + +namespace x3 = boost::spirit::x3; + +x3::rule<class pair_rule, std::pair<std::string,std::string>> const pair_rule("pair"); +x3::rule<class string_rule, std::string> const string_rule("string"); + +auto const pair_rule_def = string_rule > x3::lit('=') > string_rule; +auto const string_rule_def = x3::lexeme[*x3::alnum]; + +BOOST_SPIRIT_DEFINE(pair_rule, string_rule) + +template <typename Container> +void test_map_support() +{ + using spirit_test::test_attr; + + Container container; + Container const compare {{"k1", "v1"}, {"k2", "v2"}}; + auto const rule = pair_rule % x3::lit(','); + + BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", rule, container)); + BOOST_TEST(container.size() == 2); + BOOST_TEST(container == compare); + + // test sequences parsing into containers + auto const seq_rule = pair_rule >> ',' >> pair_rule >> ',' >> pair_rule; + container.clear(); + BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", seq_rule, container)); + + // test parsing container into container + auto const cic_rule = pair_rule >> +(',' >> pair_rule); + container.clear(); + BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", cic_rule, container)); +} + +template <typename Container> +void test_multimap_support() +{ + using spirit_test::test_attr; + + Container container; + Container const compare {{"k1", "v1"}, {"k2", "v2"}, {"k2", "v3"}}; + auto const rule = pair_rule % x3::lit(','); + + BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", rule, container)); + BOOST_TEST(container.size() == 3); + BOOST_TEST(container == compare); + + // test sequences parsing into containers + auto const seq_rule = pair_rule >> ',' >> pair_rule >> ',' >> pair_rule; + container.clear(); + BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", seq_rule, container)); + + // test parsing container into container + auto const cic_rule = pair_rule >> +(',' >> pair_rule); + container.clear(); + BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", cic_rule, container)); +} + +template <typename Container> +void test_sequence_support() +{ + using spirit_test::test_attr; + + Container container; + Container const compare {"e1", "e2", "e2"}; + auto const rule = string_rule % x3::lit(','); + + BOOST_TEST(test_attr("e1,e2,e2", rule, container)); + BOOST_TEST(container.size() == 3); + BOOST_TEST(container == compare); + + // test sequences parsing into containers + auto const seq_rule = string_rule >> ',' >> string_rule >> ',' >> string_rule; + container.clear(); + BOOST_TEST(test_attr("e1,e2,e2", seq_rule, container)); + + // test parsing container into container + auto const cic_rule = string_rule >> +(',' >> string_rule); + container.clear(); + BOOST_TEST(test_attr("e1,e2,e2", cic_rule, container)); +} + +template <typename Container> +void test_set_support() +{ + using spirit_test::test_attr; + + Container container; + Container const compare {"e1", "e2"}; + auto const rule = string_rule % x3::lit(','); + + BOOST_TEST(test_attr("e1,e2,e2", rule, container)); + BOOST_TEST(container.size() == 2); + BOOST_TEST(container == compare); + + // test sequences parsing into containers + auto const seq_rule = string_rule >> ',' >> string_rule >> ',' >> string_rule; + container.clear(); + BOOST_TEST(test_attr("e1,e2,e2", seq_rule, container)); + + // test parsing container into container + auto const cic_rule = string_rule >> +(',' >> string_rule); + container.clear(); + BOOST_TEST(test_attr("e1,e2,e2", cic_rule, container)); +} + +template <typename Container> +void test_multiset_support() +{ + using spirit_test::test_attr; + + Container container; + Container const compare {"e1", "e2", "e2"}; + auto const rule = string_rule % x3::lit(','); + + BOOST_TEST(test_attr("e1,e2,e2", rule, container)); + BOOST_TEST(container.size() == 3); + BOOST_TEST(container == compare); + + // test sequences parsing into containers + auto const seq_rule = string_rule >> ',' >> string_rule >> ',' >> string_rule; + container.clear(); + BOOST_TEST(test_attr("e1,e2,e2", seq_rule, container)); + + // test parsing container into container + auto const cic_rule = string_rule >> +(',' >> string_rule); + container.clear(); + BOOST_TEST(test_attr("e1,e2,e2", cic_rule, container)); +} + +template <typename Container> +void test_string_support() +{ + using spirit_test::test_attr; + + Container container; + Container const compare {"e1e2e2"}; + auto const rule = string_rule % x3::lit(','); + + BOOST_TEST(test_attr("e1,e2,e2", rule, container)); + BOOST_TEST(container.size() == 6); + BOOST_TEST(container == compare); + + // test sequences parsing into containers + auto const seq_rule = string_rule >> ',' >> string_rule >> ',' >> string_rule; + container.clear(); + BOOST_TEST(test_attr("e1,e2,e2", seq_rule, container)); + + // test parsing container into container + auto const cic_rule = string_rule >> +(',' >> string_rule); + container.clear(); + BOOST_TEST(test_attr("e1,e2,e2", cic_rule, container)); +} + +int +main() +{ + using x3::traits::is_associative; + using x3::traits::is_reservable; + + static_assert(is_reservable<std::vector<int>>::value, "is_reservable problem"); + static_assert(is_reservable<std::string>::value, "is_reservable problem"); + static_assert(is_reservable<std::unordered_set<int>>::value, "is_reservable problem"); + static_assert(is_reservable<boost::unordered_set<int>>::value, "is_reservable problem"); + static_assert(is_reservable<std::unordered_multiset<int>>::value, "is_reservable problem"); + static_assert(is_reservable<boost::unordered_multiset<int>>::value, "is_reservable problem"); + static_assert(is_reservable<std::unordered_map<int,int>>::value, "is_reservable problem"); + static_assert(is_reservable<boost::unordered_map<int,int>>::value, "is_reservable problem"); + static_assert(is_reservable<std::unordered_multimap<int,int>>::value, "is_reservable problem"); + static_assert(is_reservable<boost::unordered_multimap<int,int>>::value, "is_reservable problem"); + + static_assert(!is_reservable<std::deque<int>>::value, "is_reservable problem"); + static_assert(!is_reservable<std::list<int>>::value, "is_reservable problem"); + static_assert(!is_reservable<std::set<int>>::value, "is_reservable problem"); + static_assert(!is_reservable<std::multiset<int>>::value, "is_reservable problem"); + static_assert(!is_reservable<std::map<int,int>>::value, "is_reservable problem"); + static_assert(!is_reservable<std::multimap<int,int>>::value, "is_reservable problem"); + + // ------------------------------------------------------------------ + + static_assert(is_associative<std::set<int>>::value, "is_associative problem"); + static_assert(is_associative<std::unordered_set<int>>::value, "is_associative problem"); + static_assert(is_associative<boost::unordered_set<int>>::value, "is_associative problem"); + static_assert(is_associative<std::multiset<int>>::value, "is_associative problem"); + static_assert(is_associative<std::unordered_multiset<int>>::value, "is_associative problem"); + static_assert(is_associative<boost::unordered_multiset<int>>::value, "is_associative problem"); + static_assert(is_associative<std::map<int,int>>::value, "is_associative problem"); + static_assert(is_associative<std::unordered_map<int,int>>::value, "is_associative problem"); + static_assert(is_associative<boost::unordered_map<int,int>>::value, "is_associative problem"); + static_assert(is_associative<std::multimap<int,int>>::value, "is_associative problem"); + static_assert(is_associative<std::unordered_multimap<int,int>>::value, "is_associative problem"); + static_assert(is_associative<boost::unordered_multimap<int,int>>::value, "is_associative problem"); + + static_assert(!is_associative<std::vector<int>>::value, "is_associative problem"); + static_assert(!is_associative<std::string>::value, "is_associative problem"); + static_assert(!is_associative<std::deque<int>>::value, "is_associative problem"); + static_assert(!is_associative<std::list<int>>::value, "is_associative problem"); + + // ------------------------------------------------------------------ + + test_string_support<std::string>(); + + test_sequence_support<std::vector<std::string>>(); + test_sequence_support<std::list<std::string>>(); + test_sequence_support<std::deque<std::string>>(); + + test_set_support<std::set<std::string>>(); + test_set_support<std::unordered_set<std::string>>(); + test_set_support<boost::unordered_set<std::string>>(); + + test_multiset_support<std::multiset<std::string>>(); + test_multiset_support<std::unordered_multiset<std::string>>(); + test_multiset_support<boost::unordered_multiset<std::string>>(); + + test_map_support<std::map<std::string,std::string>>(); + test_map_support<std::unordered_map<std::string,std::string>>(); + test_map_support<boost::unordered_map<std::string,std::string>>(); + + test_multimap_support<std::multimap<std::string,std::string>>(); + test_multimap_support<std::unordered_multimap<std::string,std::string>>(); + test_multimap_support<boost::unordered_multimap<std::string,std::string>>(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/debug.cpp b/src/boost/libs/spirit/test/x3/debug.cpp new file mode 100644 index 00000000..5d3508ac --- /dev/null +++ b/src/boost/libs/spirit/test/x3/debug.cpp @@ -0,0 +1,144 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#define BOOST_SPIRIT_X3_DEBUG + +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/include/std_pair.hpp> +#include <boost/fusion/include/vector.hpp> + +#include <vector> +#include <string> +#include <cstring> +#include <iostream> +#include "test.hpp" + +struct my_error_handler +{ + template <typename Iterator, typename Exception, typename Context> + boost::spirit::x3::error_handler_result + operator()(Iterator&, Iterator const& last, Exception const& x, Context const&) const + { + std::cout + << "Error! Expecting: " + << x.which() + << ", got: \"" + << std::string(x.where(), last) + << "\"" + << std::endl; + return boost::spirit::x3::error_handler_result::fail; + } +}; + +struct my_attribute +{ + bool alive = true; + + void access() const + { + BOOST_TEST(alive); + } + ~my_attribute() + { + alive = false; + } + + friend std::ostream & operator << (std::ostream & os, my_attribute const & attr) + { + attr.access(); + return os << "my_attribute"; + } +}; + +int +main() +{ + using spirit_test::test_attr; + using spirit_test::test; + + using namespace boost::spirit::x3::ascii; + using boost::spirit::x3::rule; + using boost::spirit::x3::symbols; + using boost::spirit::x3::int_; + using boost::spirit::x3::alpha; + + { // basic tests + + auto a = rule<class a>("a") = 'a'; + auto b = rule<class b>("b") = 'b'; + auto c = rule<class c>("c") = 'c'; + + { + auto start = *(a | b | c); + BOOST_TEST(test("abcabcacb", start)); + } + + { + rule<class start> start("start"); + auto start_def = + start = (a | b) >> (start | b); + + BOOST_TEST(test("aaaabababaaabbb", start_def)); + BOOST_TEST(test("aaaabababaaabba", start_def, false)); + } + } + + { // basic tests w/ skipper + + auto a = rule<class a>("a") = 'a'; + auto b = rule<class b>("b") = 'b'; + auto c = rule<class c>("c") = 'c'; + + { + auto start = *(a | b | c); + BOOST_TEST(test(" a b c a b c a c b ", start, space)); + } + + { + rule<class start> start("start"); + auto start_def = + start = (a | b) >> (start | b); + + BOOST_TEST(test(" a a a a b a b a b a a a b b b ", start_def, space)); + BOOST_TEST(test(" a a a a b a b a b a a a b b a ", start_def, space, false)); + } + } + + { // std::container attributes + + typedef boost::fusion::vector<int, char> fs; + rule<class start, std::vector<fs>> start("start"); + auto start_def = + start = *(int_ >> alpha); + + BOOST_TEST(test("1 a 2 b 3 c", start_def, space)); + } + + { // error handling + + auto r_def = '(' > int_ > ',' > int_ > ')'; + auto r = r_def.on_error(my_error_handler()); + + 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)); + } + + { + symbols<my_attribute> a{{{ "a", my_attribute{} }}}; + + auto b = rule<struct b, my_attribute>("b") = a; + + my_attribute attr; + + BOOST_TEST(test_attr("a", b, attr)); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/difference.cpp b/src/boost/libs/spirit/test/x3/difference.cpp new file mode 100644 index 00000000..5581cdea --- /dev/null +++ b/src/boost/libs/spirit/test/x3/difference.cpp @@ -0,0 +1,66 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <string> +#include <iostream> +#include "test.hpp" + +int +main() +{ + using boost::spirit::x3::ascii::char_; + using boost::spirit::x3::ascii::space; + using boost::spirit::x3::lit; + using spirit_test::test; + using spirit_test::test_attr; + + // Basic tests + { + BOOST_TEST(test("b", char_ - 'a')); + BOOST_TEST(!test("a", char_ - 'a')); + BOOST_TEST(test("/* abcdefghijk */", "/*" >> *(char_ - "*/") >> "*/")); + BOOST_TEST(!test("switch", lit("switch") - "switch")); + } + + // Test attributes + { + char attr; + BOOST_TEST(test_attr("xg", (char_ - 'g') >> 'g', attr)); + BOOST_TEST(attr == 'x'); + } + + // Test handling of container attributes + { + std::string attr; + BOOST_TEST(test_attr("abcdefg", *(char_ - 'g') >> 'g', attr)); + BOOST_TEST(attr == "abcdef"); + } + + { + using boost::spirit::x3::_attr; + + std::string s; + + BOOST_TEST(test( + "/*abcdefghijk*/" + , "/*" >> *(char_ - "*/")[([&](auto& ctx){ s += _attr(ctx); })] >> "*/" + )); + BOOST_TEST(s == "abcdefghijk"); + s.clear(); + + BOOST_TEST(test( + " /*abcdefghijk*/" + , "/*" >> *(char_ - "*/")[([&](auto& ctx){ s += _attr(ctx); })] >> "*/" + , space + )); + BOOST_TEST(s == "abcdefghijk"); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/eoi.cpp b/src/boost/libs/spirit/test/x3/eoi.cpp new file mode 100644 index 00000000..41de6d04 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/eoi.cpp @@ -0,0 +1,29 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + using boost::spirit::x3::eoi; + + { + BOOST_TEST((test("", eoi))); + BOOST_TEST(!(test("x", eoi))); + } + + { + BOOST_TEST(what(eoi) == "eoi"); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/eol.cpp b/src/boost/libs/spirit/test/x3/eol.cpp new file mode 100644 index 00000000..d363a621 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/eol.cpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + using boost::spirit::x3::eol; + + { + BOOST_TEST((test("\r\n", eol))); + BOOST_TEST((test("\r", eol))); + BOOST_TEST((test("\n", eol))); + BOOST_TEST((!test("\n\r", eol))); + BOOST_TEST((!test("", eol))); + } + + { + BOOST_TEST(what(eol) == "eol"); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/eps.cpp b/src/boost/libs/spirit/test/x3/eps.cpp new file mode 100644 index 00000000..d4bfac28 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/eps.cpp @@ -0,0 +1,44 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + using boost::spirit::x3::eps; + using boost::spirit::x3::unused_type; + + { + BOOST_TEST((test("", eps))); + BOOST_TEST((test("xxx", eps, false))); + //~ BOOST_TEST((!test("", !eps))); // not predicate $$$ Implement me! $$$ + } + + { // test non-lazy semantic predicate + + BOOST_TEST((test("", eps(true)))); + BOOST_TEST((!test("", eps(false)))); + BOOST_TEST((test("", !eps(false)))); + } + + { // test lazy semantic predicate + + auto true_ = [](unused_type) { return true; }; + auto false_ = [](unused_type) { return false; }; + + BOOST_TEST((test("", eps(true_)))); + BOOST_TEST((!test("", eps(false_)))); + BOOST_TEST((test("", !eps(false_)))); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/error_handler.cpp b/src/boost/libs/spirit/test/x3/error_handler.cpp new file mode 100644 index 00000000..d22949fd --- /dev/null +++ b/src/boost/libs/spirit/test/x3/error_handler.cpp @@ -0,0 +1,57 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ + +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/spirit/home/x3/support/utility/annotate_on_success.hpp> +#include <string> +#include <sstream> + +namespace x3 = boost::spirit::x3; + +struct error_handler_base +{ + template <typename Iterator, typename Exception, typename Context> + x3::error_handler_result on_error( + Iterator&, Iterator const& + , Exception const& x, Context const& context) const + { + std::string message = "Error! Expecting: " + x.which() + " here:"; + auto& error_handler = x3::get<x3::error_handler_tag>(context).get(); + error_handler(x.where(), message); + return x3::error_handler_result::fail; + } +}; + +struct test_rule_class : x3::annotate_on_success, error_handler_base {}; + +x3::rule<test_rule_class> const test_rule; +auto const test_rule_def = x3::lit("foo") > x3::lit("bar") > x3::lit("git"); + +BOOST_SPIRIT_DEFINE(test_rule) + +void test(std::string const& line_break) { + std::string const input("foo" + line_break + " foo" + line_break + "git"); + auto const begin = std::begin(input); + auto const end = std::end(input); + + std::stringstream stream; + x3::error_handler<std::string::const_iterator> error_handler{begin, end, stream}; + + auto const parser = x3::with<x3::error_handler_tag>(std::ref(error_handler))[test_rule]; + x3::phrase_parse(begin, end, parser, x3::space); + + BOOST_TEST_EQ(stream.str(), "In line 2:\nError! Expecting: \"bar\" here:\n foo\n__^_\n"); +} + +int main() { + test("\n"); + test("\r"); + test("\r\n"); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/expect.cpp b/src/boost/libs/spirit/test/x3/expect.cpp new file mode 100644 index 00000000..82422a3b --- /dev/null +++ b/src/boost/libs/spirit/test/x3/expect.cpp @@ -0,0 +1,147 @@ +/*============================================================================= + Copyright (c) 2001-2013 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) +=============================================================================*/ +#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 <string> +#include <iostream> +#include "test.hpp" + +int +main() +{ + using namespace boost::spirit; + using namespace boost::spirit::x3::ascii; + using boost::spirit::x3::lit; + using boost::spirit::x3::expect; + using spirit_test::test; + using spirit_test::test_attr; + using boost::spirit::x3::expectation_failure; + + { + try + { + BOOST_TEST((test("aa", char_ >> expect[char_]))); + BOOST_TEST((test("aaa", char_ >> expect[char_ >> char_('a')]))); + BOOST_TEST((test("xi", char_('x') >> expect[char_('i')]))); + BOOST_TEST((!test("xi", char_('y') >> expect[char_('o')]))); // should not throw! + BOOST_TEST((test("xin", char_('x') >> expect[char_('i') >> char_('n')]))); + BOOST_TEST((!test("xi", char_('x') >> expect[char_('o')]))); + } + catch (expectation_failure<char const*> const& x) + { + std::cout << "expected: " << x.which(); + std::cout << " got: \"" << x.where() << '"' << std::endl; + } + } + + { + try + { + BOOST_TEST((test("aa", char_ > char_))); + BOOST_TEST((test("aaa", char_ > char_ > char_('a')))); + BOOST_TEST((test("xi", char_('x') > char_('i')))); + BOOST_TEST((!test("xi", char_('y') > char_('o')))); // should not throw! + BOOST_TEST((test("xin", char_('x') > char_('i') > char_('n')))); + BOOST_TEST((!test("xi", char_('x') > char_('o')))); + } + catch (expectation_failure<char const*> const& x) + { + std::cout << "expected: " << x.which(); + std::cout << " got: \"" << x.where() << '"' << std::endl; + } + } + + { + try + { + BOOST_TEST((!test("ay:a", char_ > char_('x') >> ':' > 'a'))); + } + catch (expectation_failure<char const*> const& x) + { + std::cout << "expected: " << x.which(); + std::cout << " got: \"" << x.where() << '"' << std::endl; + } + } + +#if defined(BOOST_CLANG) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Woverloaded-shift-op-parentheses" +#endif + { // Test that attributes with > (sequences) work just like >> (sequences) + + using boost::fusion::vector; + using boost::fusion::at_c; + + { + vector<char, char, char> attr; + BOOST_TEST((test_attr(" a\n b\n c", + char_ > char_ > char_, attr, space))); + BOOST_TEST((at_c<0>(attr) == 'a')); + BOOST_TEST((at_c<1>(attr) == 'b')); + BOOST_TEST((at_c<2>(attr) == 'c')); + } + + { + vector<char, char, char> attr; + BOOST_TEST((test_attr(" a\n b\n c", + char_ > char_ >> char_, attr, space))); + BOOST_TEST((at_c<0>(attr) == 'a')); + BOOST_TEST((at_c<1>(attr) == 'b')); + BOOST_TEST((at_c<2>(attr) == 'c')); + } + + { + vector<char, char, char> attr; + BOOST_TEST((test_attr(" a, b, c", + char_ >> ',' > char_ >> ',' > char_, attr, space))); + BOOST_TEST((at_c<0>(attr) == 'a')); + BOOST_TEST((at_c<1>(attr) == 'b')); + BOOST_TEST((at_c<2>(attr) == 'c')); + } + + { + std::string attr; + BOOST_TEST((test_attr("'azaaz'", + "'" > *(char_("a") | char_("z")) > "'", attr, space))); + BOOST_TEST(attr == "azaaz"); + } + } +#if defined(BOOST_CLANG) +#pragma clang diagnostic pop +#endif + + { + try + { + BOOST_TEST((test(" a a", char_ > char_, space))); + BOOST_TEST((test(" x i", char_('x') > char_('i'), space))); + BOOST_TEST((!test(" x i", char_('x') > char_('o'), space))); + } + catch (expectation_failure<char const*> const& x) + { + std::cout << "expected: " << x.which(); + std::cout << " got: \"" << x.where() << '"' << std::endl; + } + } + + { + try + { + BOOST_TEST((test("bar", expect[lit("foo")]))); + } + catch (expectation_failure<char const*> const& x) + { + std::cout << "expected: " << x.which(); + std::cout << " got: \"" << x.where() << '"' << std::endl; + } + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/extract_int.cpp b/src/boost/libs/spirit/test/x3/extract_int.cpp new file mode 100644 index 00000000..f7b97cde --- /dev/null +++ b/src/boost/libs/spirit/test/x3/extract_int.cpp @@ -0,0 +1,162 @@ +/*============================================================================= + Copyright (c) 2018 Nikita Kniazev + + 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 <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3/support/numeric_utils/extract_int.hpp> +#include <cmath> // for std::pow +#include <cstdio> +#include <iosfwd> +#include <limits> + +#ifdef _MSC_VER +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +template <int Min, int Max> +struct custom_int +{ + custom_int() = default; + constexpr custom_int(int value) : value_{value} {} + + custom_int operator+(custom_int x) const { return value_ + x.value_; } + custom_int operator-(custom_int x) const { return value_ - x.value_; } + custom_int operator*(custom_int x) const { return value_ * x.value_; } + custom_int operator/(custom_int x) const { return value_ / x.value_; } + + custom_int& operator+=(custom_int x) { value_ += x.value_; return *this; } + custom_int& operator-=(custom_int x) { value_ -= x.value_; return *this; } + custom_int& operator*=(custom_int x) { value_ *= x.value_; return *this; } + custom_int& operator/=(custom_int x) { value_ /= x.value_; return *this; } + custom_int& operator++() { ++value_; return *this; } + custom_int& operator--() { --value_; return *this; } + custom_int operator++(int) { return value_++; } + custom_int operator--(int) { return value_--; } + + custom_int operator+() { return +value_; } + custom_int operator-() { return -value_; } + + bool operator< (custom_int x) const { return value_ < x.value_; } + bool operator> (custom_int x) const { return value_ > x.value_; } + bool operator<=(custom_int x) const { return value_ <= x.value_; } + bool operator>=(custom_int x) const { return value_ >= x.value_; } + bool operator==(custom_int x) const { return value_ == x.value_; } + bool operator!=(custom_int x) const { return value_ != x.value_; } + + template <typename Char, typename Traits> + friend std::basic_ostream<Char, Traits>& + operator<<(std::basic_ostream<Char, Traits>& os, custom_int x) { + return os << x.value_; + } + + static constexpr int max = Max; + static constexpr int min = Min; + +private: + int value_; +}; + +namespace utils { + +template <int Min, int Max> struct digits; +template <> struct digits<-9, 9> { static constexpr int r2 = 3, r10 = 1; }; +template <> struct digits<-10, 10> { static constexpr int r2 = 3, r10 = 1; }; +template <> struct digits<-15, 15> { static constexpr int r2 = 3, r10 = 1; }; + +} + +namespace std { + +template <int Min, int Max> +class numeric_limits<custom_int<Min, Max>> : public numeric_limits<int> +{ +public: + static constexpr custom_int<Min, Max> max() noexcept { return Max; } + static constexpr custom_int<Min, Max> min() noexcept { return Min; } + static constexpr custom_int<Min, Max> lowest() noexcept { return min(); } + static_assert(numeric_limits<int>::radix == 2, "hardcoded for digits of radix 2"); + static constexpr int digits = utils::digits<Min, Max>::r2; + static constexpr int digits10 = utils::digits<Min, Max>::r10; +}; + +} + +namespace x3 = boost::spirit::x3; + +template <typename T, int Base, int MaxDigits> +void test_overflow_handling(char const* begin, char const* end, int i) +{ + // Check that parser fails on overflow + static_assert(std::numeric_limits<T>::is_bounded, "tests prerequest"); + BOOST_ASSERT_MSG(MaxDigits == -1 || static_cast<int>(std::pow(float(Base), MaxDigits)) > T::max, + "test prerequest"); + int initial = Base - i % Base; // just a 'random' non-equal to i number + T x { initial }; + char const* it = begin; + bool r = x3::extract_int<T, Base, 1, MaxDigits>::call(it, end, x); + if (T::min <= i && i <= T::max) { + BOOST_TEST(r); + BOOST_TEST(it == end); + BOOST_TEST_EQ(x, i); + } + else + if (MaxDigits == -1) // TODO: Looks like a regression. See #430 + { + BOOST_TEST(!r); + BOOST_TEST(it == begin); + } +} + +template <typename T, int Base> +void test_unparsed_digits_are_not_consumed(char const* it, char const* end, int i) +{ + // Check that unparsed digits are not consumed + static_assert(T::min <= -Base+1, "test prerequest"); + static_assert(T::max >= Base-1, "test prerequest"); + bool has_sign = *it == '+' || *it == '-'; + auto len = end - it; + int initial = Base - i % Base; // just a 'random' non-equal to i number + T x { initial }; + bool r = x3::extract_int<T, Base, 1, 1>::call(it, end, x); + BOOST_TEST(r); + if (-Base < i && i < Base) { + BOOST_TEST(it == end); + BOOST_TEST_EQ(x, i); + } + else { + BOOST_TEST_EQ(end - it, len - 1 - has_sign); + BOOST_TEST_EQ(x, i / Base); + } +} + +template <typename T, int Base> +void run_tests(char const* begin, char const* end, int i) +{ + // Check that parser fails on overflow + test_overflow_handling<T, Base, -1>(begin, end, i); + // Check that MaxDigits > digits10 behave like MaxDigits=-1 + test_overflow_handling<T, Base, 2>(begin, end, i); + // Check that unparsed digits are not consumed + test_unparsed_digits_are_not_consumed<T, Base>(begin, end, i); +} + +int main() +{ + for (int i = -30; i <= 30; ++i) { + char s[4]; + std::snprintf(s, 4, "%d", i); + auto begin = &s[0], end = begin + std::strlen(begin); + + // log(Base, abs(MinOrMax) + 1) == digits + run_tests<custom_int<-9, 9>, 10>(begin, end, i); + // (MinOrMax % Base) == 0 + run_tests<custom_int<-10, 10>, 10>(begin, end, i); + // (MinOrMax % Base) != 0 + run_tests<custom_int<-15, 15>, 10>(begin, end, i); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/fusion_map.cpp b/src/boost/libs/spirit/test/x3/fusion_map.cpp new file mode 100644 index 00000000..719b5e30 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/fusion_map.cpp @@ -0,0 +1,138 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) + =============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/include/at_key.hpp> +#include <boost/fusion/include/make_map.hpp> +#include <boost/fusion/adapted/struct.hpp> + +#include <string> +#include <iostream> +#include "test.hpp" + +struct AdaptedStruct { + std::string key1; + std::string key2; +}; + +class key1_attr {}; +class key2_attr {}; + +BOOST_FUSION_ADAPT_ASSOC_STRUCT( + AdaptedStruct, + (std::string, key1, class key1_attr) + (std::string, key2, class key2_attr) + ) + +template <class Parser, class Attribute> +bool test_attr(const std::string in,Parser const& p, Attribute& attr) { + auto it = in.begin(); + return boost::spirit::x3::parse(it,in.end(), p, attr); +} + +int +main() +{ + using spirit_test::test; + using boost::spirit::x3::lit; + using boost::spirit::x3::attr; + using boost::spirit::x3::char_; + using boost::spirit::x3::eps; + namespace fusion = boost::fusion; + + { // parsing sequence directly into fusion map + + auto const key1 = lit("key1") >> attr(key1_attr()); + auto const kv1 = key1 >> lit("=") >> +char_; + + { + auto attr_ = fusion::make_map<key1_attr>(std::string()); + BOOST_TEST(test_attr("key1=ABC", kv1, attr_)); + BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "ABC"); + } + { + AdaptedStruct attr_; + BOOST_TEST(test_attr("key1=ABC", kv1, attr_)); + BOOST_TEST(attr_.key1 == "ABC"); + BOOST_TEST(attr_.key2 == ""); + } + } + { // case when parser handling fusion assoc sequence + // is on one side of another sequence + auto const key1 = lit("key1") >> attr(key1_attr()); + auto const kv1 = key1 >> lit("=") >> +~char_(';'); + + AdaptedStruct attr_; + BOOST_TEST(test_attr("key1=ABC", eps >> (kv1 % ';') , attr_)); + BOOST_TEST(attr_.key1 == "ABC"); + BOOST_TEST(attr_.key2 == ""); + } + { // parsing repeated sequence directly into fusion map (overwrite) + auto const key1 = lit("key1") >> attr(key1_attr()); + auto const kv1 = key1 >> lit("=") >> +~char_(';'); + + { + auto attr_ = fusion::make_map<key1_attr>(std::string()); + BOOST_TEST(test_attr("key1=ABC;key1=XYZ", kv1 % ';', attr_)); + BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "XYZ"); + } + { + AdaptedStruct attr_; + BOOST_TEST(test_attr("key1=ABC;key1=XYZ", kv1 % ';', attr_)); + BOOST_TEST(attr_.key1 == "XYZ"); + } + } + + { // parsing repeated sequence directly into fusion map (append) + + /* NOT IMPLEMENTED + auto const key1 = lit("key1") >> attr(key1_attr()); + auto const kv1 = key1 >> lit("=") >> +char_; + auto attr_ = fusion::make_map<key1_attr>(std::vector<std::string>()); + + BOOST_TEST(test_attr("key1=ABC;key1=XYZ", kv1 % ";", attr_)); + BOOST_TEST(fusion::at_key<key1_attr>(attr_) == {"ABC","XYZ"}); + */ + } + + { // alternative over key-value pairs + + auto const key1 = lit("key1") >> attr(key1_attr()); + auto const key2 = lit("key2") >> attr(key2_attr()); + auto const kv1 = key1 >> lit("=") >> +~char_(';'); + auto const kv2 = key2 >> lit("=") >> +~char_(';'); + + auto attr_ = fusion::make_map<key1_attr, key2_attr>(std::string(),std::string()); + BOOST_TEST(test_attr("key2=XYZ;key1=ABC", (kv1|kv2) % ';', attr_)); + BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "ABC"); + BOOST_TEST(fusion::at_key<key2_attr>(attr_) == "XYZ"); + } + + { // parsing sequence where key is a variant + + namespace x3 = boost::spirit::x3; + auto key1 = lit("key1") >> attr(key1_attr()); + auto key2 = lit("key2") >> attr(key2_attr()); + auto keys = key1 | key2; + auto pair = keys >> lit("=") >> +~char_(';'); + + { + auto attr_ = fusion::make_map<key1_attr,key2_attr>(std::string(),std::string()); + BOOST_TEST(test_attr("key1=ABC;key2=XYZ", pair % ';', attr_)); + BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "ABC"); + BOOST_TEST(fusion::at_key<key2_attr>(attr_) == "XYZ"); + } + { + AdaptedStruct attr_; + BOOST_TEST(test_attr("key1=ABC;key2=XYZ", pair % ';', attr_)); + BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "ABC"); + BOOST_TEST(fusion::at_key<key2_attr>(attr_) == "XYZ"); + } + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/grammar.cpp b/src/boost/libs/spirit/test/x3/grammar.cpp new file mode 100644 index 00000000..519e15cc --- /dev/null +++ b/src/boost/libs/spirit/test/x3/grammar.cpp @@ -0,0 +1,6 @@ +#include "grammar.hpp" + +auto const grammar_def = x3::int_; + +BOOST_SPIRIT_DEFINE(grammar) +BOOST_SPIRIT_INSTANTIATE(grammar_type, char const*, x3::unused_type) diff --git a/src/boost/libs/spirit/test/x3/grammar.hpp b/src/boost/libs/spirit/test/x3/grammar.hpp new file mode 100644 index 00000000..14b9402a --- /dev/null +++ b/src/boost/libs/spirit/test/x3/grammar.hpp @@ -0,0 +1,7 @@ +#include <boost/spirit/home/x3.hpp> + +namespace x3 = boost::spirit::x3; + +x3::rule<struct grammar_r, int> const grammar; +using grammar_type = decltype(grammar); +BOOST_SPIRIT_DECLARE(grammar_type) diff --git a/src/boost/libs/spirit/test/x3/grammar_linker.cpp b/src/boost/libs/spirit/test/x3/grammar_linker.cpp new file mode 100644 index 00000000..00a6fcf1 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/grammar_linker.cpp @@ -0,0 +1,24 @@ +/*============================================================================= + Copyright (c) 2019 Nikita Kniazev + Copyright (c) 2019 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) +=============================================================================*/ +#include "grammar.hpp" +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + char const* s = "123", * e = s + std::strlen(s); +#if 1 + auto r = parse(s, e, grammar); +#else + int i = 0; + auto r = parse(s, e, grammar, i); +#endif + + BOOST_TEST(r); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/test/x3/int.hpp b/src/boost/libs/spirit/test/x3/int.hpp new file mode 100644 index 00000000..21c92504 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/int.hpp @@ -0,0 +1,61 @@ +/*============================================================================= + Copyright (c) 2001-2012 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2011 Bryce Lelbach + + 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) +=============================================================================*/ +#if !defined(BOOST_SPIRIT_TEST_X3_INT_HPP) +#define BOOST_SPIRIT_TEST_X3_INT_HPP + +#include <climits> +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3/numeric/int.hpp> +#include "test.hpp" + +/////////////////////////////////////////////////////////////////////////////// +// +// *** BEWARE PLATFORM DEPENDENT!!! *** +// *** The following assumes 32 bit or 64 bit integers and 64 bit long longs. +// *** Modify these constant strings when appropriate. +// +/////////////////////////////////////////////////////////////////////////////// + + static_assert(sizeof(long long) == 8, "unexpected long long size"); + +#if INT_MAX != LLONG_MAX + static_assert(sizeof(int) == 4, "unexpected int size"); + char const* max_int = "2147483647"; + char const* int_overflow = "2147483648"; + char const* min_int = "-2147483648"; + char const* int_underflow = "-2147483649"; +#else + static_assert(sizeof(int) == 8, "unexpected int size"); + char const* max_int = "9223372036854775807"; + char const* int_overflow = "9223372036854775808"; + char const* min_int = "-9223372036854775808"; + char const* int_underflow = "-9223372036854775809"; +#endif + + char const* max_long_long = "9223372036854775807"; + char const* long_long_overflow = "9223372036854775808"; + char const* min_long_long = "-9223372036854775808"; + char const* long_long_underflow = "-9223372036854775809"; + +/////////////////////////////////////////////////////////////////////////////// +// A custom int type +struct custom_int +{ + int n; + custom_int() : n(0) {} + explicit custom_int(int n_) : n(n_) {} + custom_int& operator=(int n_) { n = n_; return *this; } + friend bool operator==(custom_int a, custom_int b) { return a.n == b.n; } + friend bool operator==(custom_int a, int b) { return a.n == b; } + friend custom_int operator*(custom_int a, custom_int b) { return custom_int(a.n * b.n); } + friend custom_int operator+(custom_int a, custom_int b) { return custom_int(a.n + b.n); } + friend custom_int operator-(custom_int a, custom_int b) { return custom_int(a.n - b.n); } +}; + +#endif diff --git a/src/boost/libs/spirit/test/x3/int1.cpp b/src/boost/libs/spirit/test/x3/int1.cpp new file mode 100644 index 00000000..cf42d511 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/int1.cpp @@ -0,0 +1,186 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2011 Bryce Lelbach + + 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 "int.hpp" +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/include/vector.hpp> +#include <boost/fusion/include/at.hpp> + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + + /////////////////////////////////////////////////////////////////////////// + // signed integer tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::int_; + int i; + + BOOST_TEST(test("123456", int_)); + BOOST_TEST(test_attr("123456", int_, i)); + BOOST_TEST(i == 123456); + + BOOST_TEST(test("+123456", int_)); + BOOST_TEST(test_attr("+123456", int_, i)); + BOOST_TEST(i == 123456); + + BOOST_TEST(test("-123456", int_)); + BOOST_TEST(test_attr("-123456", int_, i)); + BOOST_TEST(i == -123456); + + BOOST_TEST(test(max_int, int_)); + BOOST_TEST(test_attr(max_int, int_, i)); + BOOST_TEST(i == INT_MAX); + + BOOST_TEST(test(min_int, int_)); + BOOST_TEST(test_attr(min_int, int_, i)); + BOOST_TEST(i == INT_MIN); + + BOOST_TEST(!test(int_overflow, int_)); + BOOST_TEST(!test_attr(int_overflow, int_, i)); + BOOST_TEST(!test(int_underflow, int_)); + BOOST_TEST(!test_attr(int_underflow, int_, i)); + + BOOST_TEST(!test("-", int_)); + BOOST_TEST(!test_attr("-", int_, i)); + + BOOST_TEST(!test("+", int_)); + BOOST_TEST(!test_attr("+", int_, i)); + + // Bug report from Steve Nutt + BOOST_TEST(!test_attr("5368709120", int_, i)); + + // with leading zeros + BOOST_TEST(test("0000000000123456", int_)); + BOOST_TEST(test_attr("0000000000123456", int_, i)); + BOOST_TEST(i == 123456); + } + + /////////////////////////////////////////////////////////////////////////// + // long long tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::long_long; + boost::long_long_type ll; + + BOOST_TEST(test("1234567890123456789", long_long)); + BOOST_TEST(test_attr("1234567890123456789", long_long, ll)); + BOOST_TEST(ll == 1234567890123456789LL); + + BOOST_TEST(test("-1234567890123456789", long_long)); + BOOST_TEST(test_attr("-1234567890123456789", long_long, ll)); + BOOST_TEST(ll == -1234567890123456789LL); + + BOOST_TEST(test(max_long_long, long_long)); + BOOST_TEST(test_attr(max_long_long, long_long, ll)); + BOOST_TEST(ll == LLONG_MAX); + + BOOST_TEST(test(min_long_long, long_long)); + BOOST_TEST(test_attr(min_long_long, long_long, ll)); + BOOST_TEST(ll == LLONG_MIN); + + BOOST_TEST(!test(long_long_overflow, long_long)); + BOOST_TEST(!test_attr(long_long_overflow, long_long, ll)); + BOOST_TEST(!test(long_long_underflow, long_long)); + BOOST_TEST(!test_attr(long_long_underflow, long_long, ll)); + } + + /////////////////////////////////////////////////////////////////////////// + // short_ and long_ tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::short_; + using boost::spirit::x3::long_; + int i; + + BOOST_TEST(test("12345", short_)); + BOOST_TEST(test_attr("12345", short_, i)); + BOOST_TEST(i == 12345); + + BOOST_TEST(test("1234567890", long_)); + BOOST_TEST(test_attr("1234567890", long_, i)); + BOOST_TEST(i == 1234567890); + } + + /////////////////////////////////////////////////////////////////////////// + // Check overflow is parse error + /////////////////////////////////////////////////////////////////////////// + { + boost::spirit::x3::int_parser<boost::int8_t> int8_; + char c; + + BOOST_TEST(!test_attr("999", int8_, c)); + + int i; + using boost::spirit::x3::short_; + BOOST_TEST(!test_attr("32769", short_, i, false)); + BOOST_TEST(!test_attr("41234", short_, i, false)); + } + + /////////////////////////////////////////////////////////////////////////// + // int_parser<unused_type> tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::int_parser; + using boost::spirit::x3::unused_type; + int_parser<unused_type> any_int; + + BOOST_TEST(test("123456", any_int)); + BOOST_TEST(test("-123456", any_int)); + BOOST_TEST(test("-1234567890123456789", any_int)); + } + + /////////////////////////////////////////////////////////////////////////// + // action tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::_attr; + using boost::spirit::x3::ascii::space; + using boost::spirit::x3::int_; + int n = 0, m = 0; + + auto f = [&](auto& ctx){ n = _attr(ctx); }; + + BOOST_TEST(test("123", int_[f])); + BOOST_TEST(n == 123); + BOOST_TEST(test_attr("789", int_[f], m)); + BOOST_TEST(n == 789 && m == 789); + BOOST_TEST(test(" 456", int_[f], space)); + BOOST_TEST(n == 456); + } + + /////////////////////////////////////////////////////////////////////////// + // custom int tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::int_; + using boost::spirit::x3::int_parser; + custom_int i; + + BOOST_TEST(test_attr("-123456", int_, i)); + int_parser<custom_int, 10, 1, 2> int2; + BOOST_TEST(test_attr("-12", int2, i)); + } + + /////////////////////////////////////////////////////////////////////////// + // single-element fusion vector tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::int_; + using boost::spirit::x3::int_parser; + boost::fusion::vector<int> i; + + BOOST_TEST(test_attr("-123456", int_, i)); + BOOST_TEST(boost::fusion::at_c<0>(i) == -123456); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/iterator_check.cpp b/src/boost/libs/spirit/test/x3/iterator_check.cpp new file mode 100644 index 00000000..70a8a176 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/iterator_check.cpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2001-2017 Joel de Guzman + Copyright (c) 2017 think-cell GmbH + + 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 <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/range/adaptor/transformed.hpp> + +#include <iostream> +#include <string> +#include <functional> + +int main() +{ + using boost::adaptors::transform; + using boost::spirit::x3::raw; + using boost::spirit::x3::eps; + using boost::spirit::x3::eoi; + using boost::spirit::x3::upper; + using boost::spirit::x3::repeat; + using boost::spirit::x3::parse; + + std::string input = "abcde"; + std::function<char(char)> func = [](char c) { + return c < 'a' || 'z' < c ? c : static_cast<char>(c - 'a' + 'A'); + }; + auto const rng = transform(input, func); + + { + std::string str; + BOOST_TEST((parse(boost::begin(rng), boost::end(rng), +upper >> eoi, str))); + BOOST_TEST(("ABCDE"==str)); + } + + { + boost::iterator_range<decltype(boost::begin(rng))> str; + BOOST_TEST((parse(boost::begin(rng), boost::end(rng), raw[+upper >> eoi], str))); + BOOST_TEST((boost::equal(std::string("ABCDE"), str))); + } + + { + BOOST_TEST((parse(boost::begin(rng), boost::end(rng), (repeat(6)[upper] | repeat(5)[upper]) >> eoi))); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/kleene.cpp b/src/boost/libs/spirit/test/x3/kleene.cpp new file mode 100644 index 00000000..67f59d28 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/kleene.cpp @@ -0,0 +1,126 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <string> +#include <vector> + +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <string> +#include <iostream> +#include "test.hpp" +#include "utils.hpp" + +struct x_attr +{ +}; + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <> + struct container_value<x_attr> + { + typedef char type; // value type of container + }; + + template <> + struct push_back_container<x_attr> + { + static bool call(x_attr& /*c*/, char /*val*/) + { + // push back value type into container + return true; + } + }; +}}}} + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + using boost::spirit::x3::char_; + using boost::spirit::x3::alpha; + using boost::spirit::x3::upper; + using boost::spirit::x3::space; + using boost::spirit::x3::digit; + using boost::spirit::x3::int_; + using boost::spirit::x3::lexeme; + + { + BOOST_TEST(test("aaaaaaaa", *char_)); + BOOST_TEST(test("a", *char_)); + BOOST_TEST(test("", *char_)); + BOOST_TEST(test("aaaaaaaa", *alpha)); + BOOST_TEST(!test("aaaaaaaa", *upper)); + } + + { + BOOST_TEST(test(" a a aaa aa", *char_, space)); + BOOST_TEST(test("12345 678 9", *digit, space)); + } + + { + std::string s; + BOOST_TEST(test_attr("bbbb", *char_, s) && 4 == s.size() && s == "bbbb"); + + s.clear(); + BOOST_TEST(test_attr("b b b b ", *char_, s, space) && s == "bbbb"); + } + + { + std::vector<int> v; + BOOST_TEST(test_attr("123 456 789 10", *int_, v, space) && 4 == v.size() && + v[0] == 123 && v[1] == 456 && v[2] == 789 && v[3] == 10); + } + + { + std::vector<std::string> v; + BOOST_TEST(test_attr("a b c d", *lexeme[+alpha], v, space) && 4 == v.size() && + v[0] == "a" && v[1] == "b" && v[2] == "c" && v[3] == "d"); + } + + { + std::vector<int> v; + BOOST_TEST(test_attr("123 456 789", *int_, v, space) && 3 == v.size() && + v[0] == 123 && v[1] == 456 && v[2] == 789); + } + + { // actions + using boost::spirit::x3::_attr; + + std::string v; + auto f = [&](auto& ctx){ v = _attr(ctx); }; + + BOOST_TEST(test("bbbb", (*char_)[f]) && 4 == v.size() && + v[0] == 'b' && v[1] == 'b' && v[2] == 'b' && v[3] == 'b'); + } + + { // more actions + using boost::spirit::x3::_attr; + + std::vector<int> v; + auto f = [&](auto& ctx){ v = _attr(ctx); }; + + BOOST_TEST(test("123 456 789", (*int_)[f], space) && 3 == v.size() && + v[0] == 123 && v[1] == 456 && v[2] == 789); + } + + { // attribute customization + + x_attr x; + test_attr("abcde", *char_, x); + } + + { // test move only types + std::vector<move_only> v; + BOOST_TEST(test_attr("sss", *synth_move_only, v)); + BOOST_TEST_EQ(v.size(), 3); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/lexeme.cpp b/src/boost/libs/spirit/test/x3/lexeme.cpp new file mode 100644 index 00000000..f8962e52 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/lexeme.cpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + using boost::spirit::x3::ascii::space; + using boost::spirit::x3::ascii::space_type; + using boost::spirit::x3::ascii::digit; + using boost::spirit::x3::lexeme; + using boost::spirit::x3::rule; + + { + BOOST_TEST((test(" 1 2 3 4 5", +digit, space))); + BOOST_TEST((!test(" 1 2 3 4 5", lexeme[+digit], space))); + BOOST_TEST((test(" 12345", lexeme[+digit], space))); + BOOST_TEST((test(" 12345 ", lexeme[+digit], space, false))); + + // lexeme collapsing + BOOST_TEST((!test(" 1 2 3 4 5", lexeme[lexeme[+digit]], space))); + BOOST_TEST((test(" 12345", lexeme[lexeme[+digit]], space))); + BOOST_TEST((test(" 12345 ", lexeme[lexeme[+digit]], space, false))); + + auto r = +digit; + auto rr = lexeme[r]; + + BOOST_TEST((!test(" 1 2 3 4 5", rr, space))); + BOOST_TEST((test(" 12345", rr, space))); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/list.cpp b/src/boost/libs/spirit/test/x3/list.cpp new file mode 100644 index 00000000..ff41de0e --- /dev/null +++ b/src/boost/libs/spirit/test/x3/list.cpp @@ -0,0 +1,109 @@ +/*============================================================================= + Copyright (c) 2001-2013 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) +=============================================================================*/ +#include <string> +#include <vector> +#include <set> +#include <map> + +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <string> +#include <iostream> +#include "test.hpp" +#include "utils.hpp" + +using namespace spirit_test; + +int +main() +{ + using namespace boost::spirit::x3::ascii; + + { + BOOST_TEST(test("a,b,c,d,e,f,g,h", char_ % ',')); + BOOST_TEST(test("a,b,c,d,e,f,g,h,", char_ % ',', false)); + } + + { + BOOST_TEST(test("a, b, c, d, e, f, g, h", char_ % ',', space)); + BOOST_TEST(test("a, b, c, d, e, f, g, h,", char_ % ',', space, false)); + } + + { + std::string s; + BOOST_TEST(test_attr("a,b,c,d,e,f,g,h", char_ % ',', s)); + BOOST_TEST(s == "abcdefgh"); + + BOOST_TEST(!test("a,b,c,d,e,f,g,h,", char_ % ',')); + } + + { + std::string s; + BOOST_TEST(test_attr("ab,cd,ef,gh", (char_ >> char_) % ',', s)); + BOOST_TEST(s == "abcdefgh"); + + BOOST_TEST(!test("ab,cd,ef,gh,", (char_ >> char_) % ',')); + BOOST_TEST(!test("ab,cd,ef,g", (char_ >> char_) % ',')); + + s.clear(); + BOOST_TEST(test_attr("ab,cd,efg", (char_ >> char_) % ',' >> char_, s)); + BOOST_TEST(s == "abcdefg"); + } + + { + using boost::spirit::x3::int_; + + std::vector<int> v; + BOOST_TEST(test_attr("1,2", int_ % ',', v)); + BOOST_TEST(2 == v.size() && 1 == v[0] && 2 == v[1]); + } + + { + using boost::spirit::x3::int_; + + std::vector<int> v; + BOOST_TEST(test_attr("(1,2)", '(' >> int_ % ',' >> ')', v)); + BOOST_TEST(2 == v.size() && 1 == v[0] && 2 == v[1]); + } + + { + std::vector<std::string> v; + BOOST_TEST(test_attr("a,b,c,d", +alpha % ',', v)); + BOOST_TEST(4 == v.size() && "a" == v[0] && "b" == v[1] + && "c" == v[2] && "d" == v[3]); + } + + { + std::vector<boost::optional<char> > v; + BOOST_TEST(test_attr("#a,#", ('#' >> -alpha) % ',', v)); + BOOST_TEST(2 == v.size() && + !!v[0] && 'a' == boost::get<char>(v[0]) && !v[1]); + + std::vector<char> v2; + BOOST_TEST(test_attr("#a,#", ('#' >> -alpha) % ',', v2)); + BOOST_TEST(1 == v2.size() && 'a' == v2[0]); + } + + { // actions + using boost::spirit::x3::_attr; + + std::string s; + auto f = [&](auto& ctx){ s = std::string(_attr(ctx).begin(), _attr(ctx).end()); }; + + BOOST_TEST(test("a,b,c,d,e,f,g,h", (char_ % ',')[f])); + BOOST_TEST(s == "abcdefgh"); + } + + { // test move only types + std::vector<move_only> v; + BOOST_TEST(test_attr("s.s.s.s", synth_move_only % '.', v)); + BOOST_TEST_EQ(v.size(), 4); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/lit.cpp b/src/boost/libs/spirit/test/x3/lit.cpp new file mode 100644 index 00000000..2a9abc98 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/lit.cpp @@ -0,0 +1,53 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <string> + +#include "test.hpp" + +int +main() +{ + using spirit_test::test_attr; + using boost::spirit::x3::lit; + using boost::spirit::x3::char_; + + { + std::string attr; + auto p = char_ >> lit("\n"); + BOOST_TEST(test_attr("A\n", p, attr)); + BOOST_TEST(attr == "A"); + } + + { + using namespace boost::spirit::x3::ascii; + std::string attr; + auto p = char_ >> lit("\n"); + BOOST_TEST(test_attr("A\n", p, attr)); + BOOST_TEST(attr == "A"); + } + + { + using namespace boost::spirit::x3::iso8859_1; + std::string attr; + auto p = char_ >> lit("\n"); + BOOST_TEST(test_attr("É\n", p, attr)); + BOOST_TEST(attr == "É"); + } + + { + using namespace boost::spirit::x3::standard_wide; + std::wstring attr; + auto p = char_ >> lit("\n"); + BOOST_TEST(test_attr(l"É\n", p, attr)); + BOOST_TEST(attr == "A"); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/lit1.cpp b/src/boost/libs/spirit/test/x3/lit1.cpp new file mode 100644 index 00000000..7eefba6c --- /dev/null +++ b/src/boost/libs/spirit/test/x3/lit1.cpp @@ -0,0 +1,85 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + http://spirit.sourceforge.net/ + + 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 <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/include/vector.hpp> + +#include <string> +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + using boost::spirit::x3::string; + + { + BOOST_TEST((test("kimpo", "kimpo"))); + BOOST_TEST((test("kimpo", string("kimpo")))); + + BOOST_TEST((test("x", string("x")))); + BOOST_TEST((test(L"x", string(L"x")))); + + std::basic_string<char> s("kimpo"); + std::basic_string<wchar_t> ws(L"kimpo"); + BOOST_TEST((test("kimpo", s))); + BOOST_TEST((test(L"kimpo", ws))); + BOOST_TEST((test("kimpo", string(s)))); + BOOST_TEST((test(L"kimpo", string(ws)))); + } + + { + BOOST_TEST((test(L"kimpo", L"kimpo"))); + BOOST_TEST((test(L"kimpo", string(L"kimpo")))); + BOOST_TEST((test(L"x", string(L"x")))); + } + + { + std::basic_string<char> s("kimpo"); + BOOST_TEST((test("kimpo", string(s)))); + + std::basic_string<wchar_t> ws(L"kimpo"); + BOOST_TEST((test(L"kimpo", string(ws)))); + } + + { + using namespace boost::spirit::x3::ascii; + BOOST_TEST((test(" kimpo", string("kimpo"), space))); + BOOST_TEST((test(L" kimpo", string(L"kimpo"), space))); + BOOST_TEST((test(" x", string("x"), space))); + } + + { + using namespace boost::spirit::x3::ascii; + BOOST_TEST((test(" kimpo", string("kimpo"), space))); + BOOST_TEST((test(L" kimpo", string(L"kimpo"), space))); + BOOST_TEST((test(" x", string("x"), space))); + } + + { + using namespace boost::spirit::x3::ascii; + std::string s; + BOOST_TEST((test_attr("kimpo", string("kimpo"), s))); + BOOST_TEST(s == "kimpo"); + s.clear(); + BOOST_TEST((test_attr(L"kimpo", string(L"kimpo"), s))); + BOOST_TEST(s == "kimpo"); + s.clear(); + BOOST_TEST((test_attr("x", string("x"), s))); + BOOST_TEST(s == "x"); + } + + { // single-element fusion vector tests + boost::fusion::vector<std::string> s; + BOOST_TEST(test_attr("kimpo", string("kimpo"), s)); + BOOST_TEST(boost::fusion::at_c<0>(s) == "kimpo"); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/lit2.cpp b/src/boost/libs/spirit/test/x3/lit2.cpp new file mode 100644 index 00000000..947837f9 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/lit2.cpp @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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 <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + using boost::spirit::x3::lit; + + { + BOOST_TEST((test("kimpo", lit("kimpo")))); + + std::basic_string<char> s("kimpo"); + std::basic_string<wchar_t> ws(L"kimpo"); + BOOST_TEST((test("kimpo", lit(s)))); + BOOST_TEST((test(L"kimpo", lit(ws)))); + } + + { + std::basic_string<char> s("kimpo"); + BOOST_TEST((test("kimpo", lit(s)))); + + std::basic_string<wchar_t> ws(L"kimpo"); + BOOST_TEST((test(L"kimpo", lit(ws)))); + } + + { + using namespace boost::spirit::x3::ascii; + BOOST_TEST((test(" kimpo", lit("kimpo"), space))); + BOOST_TEST((test(L" kimpo", lit(L"kimpo"), space))); + } + + { + using namespace boost::spirit::x3::iso8859_1; + BOOST_TEST((test(" kimpo", lit("kimpo"), space))); + BOOST_TEST((test(L" kimpo", lit(L"kimpo"), space))); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/matches.cpp b/src/boost/libs/spirit/test/x3/matches.cpp new file mode 100644 index 00000000..58923b72 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/matches.cpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + Copyright (c) 2001-2010 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 <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + using boost::spirit::x3::matches; + using boost::spirit::x3::char_; + + { + BOOST_TEST(test("x", matches[char_])); + bool result = false; + BOOST_TEST(test_attr("x", matches[char_], result) && result); + } + + { + BOOST_TEST(!test("y", matches[char_('x')])); + BOOST_TEST(!test("y", matches['x'])); + bool result = true; + BOOST_TEST(test_attr("y", matches[char_('x')], result, false) && !result); + result = true; + BOOST_TEST(test_attr("y", matches['x'], result, false) && !result); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/no_case.cpp b/src/boost/libs/spirit/test/x3/no_case.cpp new file mode 100644 index 00000000..cbf6c9dd --- /dev/null +++ b/src/boost/libs/spirit/test/x3/no_case.cpp @@ -0,0 +1,148 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + http://spirit.sourceforge.net/ + + 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 <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + using boost::spirit::x3::no_case; + + { + using namespace boost::spirit::x3::ascii; + BOOST_TEST(test("x", no_case[char_])); + BOOST_TEST(test("X", no_case[char_('x')])); + BOOST_TEST(test("X", no_case[char_('X')])); + BOOST_TEST(test("x", no_case[char_('X')])); + BOOST_TEST(test("x", no_case[char_('x')])); + BOOST_TEST(!test("z", no_case[char_('X')])); + BOOST_TEST(!test("z", no_case[char_('x')])); + BOOST_TEST(test("x", no_case[char_('a', 'z')])); + BOOST_TEST(test("X", no_case[char_('a', 'z')])); + BOOST_TEST(!test("a", no_case[char_('b', 'z')])); + BOOST_TEST(!test("z", no_case[char_('a', 'y')])); + } + { + using namespace boost::spirit::x3::ascii; + BOOST_TEST(test("X", no_case['x'])); + BOOST_TEST(test("X", no_case['X'])); + BOOST_TEST(test("x", no_case['X'])); + BOOST_TEST(test("x", no_case['x'])); + BOOST_TEST(!test("z", no_case['X'])); + BOOST_TEST(!test("z", no_case['x'])); + } + + { + using namespace boost::spirit::x3::iso8859_1; + BOOST_TEST(test("X", no_case[char_("a-z")])); + BOOST_TEST(!test("1", no_case[char_("a-z")])); + } + + { // test extended ASCII characters + using namespace boost::spirit::x3::iso8859_1; + BOOST_TEST(test("\xC1", no_case[char_('\xE1')])); + + BOOST_TEST(test("\xC9", no_case[char_("\xE5-\xEF")])); + BOOST_TEST(!test("\xFF", no_case[char_("\xE5-\xEF")])); + + BOOST_TEST(test("\xC1\xE1", no_case[lit("\xE1\xC1")])); + BOOST_TEST(test("\xE1\xE1", no_case[no_case[lit("\xE1\xC1")]])); + } + + { + using namespace boost::spirit::x3::ascii; + BOOST_TEST(test("Bochi Bochi", no_case[lit("bochi bochi")])); + BOOST_TEST(test("BOCHI BOCHI", no_case[lit("bochi bochi")])); + BOOST_TEST(!test("Vavoo", no_case[lit("bochi bochi")])); + } + + { + // should work! + using namespace boost::spirit::x3::ascii; + BOOST_TEST(test("x", no_case[no_case[char_]])); + BOOST_TEST(test("x", no_case[no_case[char_('x')]])); + BOOST_TEST(test("yabadabadoo", no_case[no_case[lit("Yabadabadoo")]])); + } + + { + using namespace boost::spirit::x3::ascii; + BOOST_TEST(test("X", no_case[alnum])); + BOOST_TEST(test("6", no_case[alnum])); + BOOST_TEST(!test(":", no_case[alnum])); + + BOOST_TEST(test("X", no_case[lower])); + BOOST_TEST(test("x", no_case[lower])); + BOOST_TEST(test("X", no_case[upper])); + BOOST_TEST(test("x", no_case[upper])); + BOOST_TEST(!test(":", no_case[lower])); + BOOST_TEST(!test(":", no_case[upper])); + } + + { + using namespace boost::spirit::x3::iso8859_1; + BOOST_TEST(test("X", no_case[alnum])); + BOOST_TEST(test("6", no_case[alnum])); + BOOST_TEST(!test(":", no_case[alnum])); + + BOOST_TEST(test("X", no_case[lower])); + BOOST_TEST(test("x", no_case[lower])); + BOOST_TEST(test("X", no_case[upper])); + BOOST_TEST(test("x", no_case[upper])); + BOOST_TEST(!test(":", no_case[lower])); + BOOST_TEST(!test(":", no_case[upper])); + } + + { + using namespace boost::spirit::x3::standard; + BOOST_TEST(test("X", no_case[alnum])); + BOOST_TEST(test("6", no_case[alnum])); + BOOST_TEST(!test(":", no_case[alnum])); + + BOOST_TEST(test("X", no_case[lower])); + BOOST_TEST(test("x", no_case[lower])); + BOOST_TEST(test("X", no_case[upper])); + BOOST_TEST(test("x", no_case[upper])); + BOOST_TEST(!test(":", no_case[lower])); + BOOST_TEST(!test(":", no_case[upper])); + } + + { + // chsets + namespace standard = boost::spirit::x3::standard; + namespace standard_wide = boost::spirit::x3::standard_wide; + + BOOST_TEST(test("x", no_case[standard::char_("a-z")])); + BOOST_TEST(test("X", no_case[standard::char_("a-z")])); + BOOST_TEST(test(L"X", no_case[standard_wide::char_(L"a-z")])); + BOOST_TEST(test(L"X", no_case[standard_wide::char_(L"X")])); + } + + { + using namespace boost::spirit::x3::standard; + std::string s("bochi bochi"); + BOOST_TEST(test("Bochi Bochi", no_case[lit(s.c_str())])); + BOOST_TEST(test("Bochi Bochi", no_case[lit(s)])); + BOOST_TEST(test("Bochi Bochi", no_case[s.c_str()])); + BOOST_TEST(test("Bochi Bochi", no_case[s])); + } + + { + { + using namespace boost::spirit::x3::standard; + BOOST_TEST(!test("ą", no_case['a'])); + } + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/no_skip.cpp b/src/boost/libs/spirit/test/x3/no_skip.cpp new file mode 100644 index 00000000..b64a4a6e --- /dev/null +++ b/src/boost/libs/spirit/test/x3/no_skip.cpp @@ -0,0 +1,50 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + Copyright (c) 2013 Agustin Berge + + 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 <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + using boost::spirit::x3::ascii::space; + using boost::spirit::x3::ascii::space_type; + using boost::spirit::x3::ascii::char_; + using boost::spirit::x3::lexeme; + using boost::spirit::x3::no_skip; + + // without skipping no_skip is equivalent to lexeme + { + std::string str; + BOOST_TEST((test_attr("' abc '", '\'' >> no_skip[+~char_('\'')] >> '\'', str))); + BOOST_TEST(str == " abc "); + } + { + std::string str; + BOOST_TEST((test_attr("' abc '", '\'' >> lexeme[+~char_('\'')] >> '\'', str))); + BOOST_TEST(str == " abc "); + } + + // with skipping, no_skip allows to match a leading skipper + { + std::string str; + BOOST_TEST((test_attr("' abc '", '\'' >> no_skip[+~char_('\'')] >> '\'', str, space))); + BOOST_TEST(str == " abc "); + } + { + std::string str; + BOOST_TEST((test_attr("' abc '", '\'' >> lexeme[+~char_('\'')] >> '\'', str, space))); + BOOST_TEST(str == "abc "); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/not_predicate.cpp b/src/boost/libs/spirit/test/x3/not_predicate.cpp new file mode 100644 index 00000000..d5b962a4 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/not_predicate.cpp @@ -0,0 +1,26 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + using boost::spirit::x3::int_; + + { + BOOST_TEST((!test("1234", !int_))); + BOOST_TEST((test("abcd", !int_, false))); + BOOST_TEST((!test("abcd", !!int_, false))); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/omit.cpp b/src/boost/libs/spirit/test/x3/omit.cpp new file mode 100644 index 00000000..f89a4851 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/omit.cpp @@ -0,0 +1,114 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#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 <string> +#include <iostream> +#include "test.hpp" + +int +main() +{ + using namespace boost::spirit::x3::ascii; + using boost::spirit::x3::omit; + using boost::spirit::x3::unused_type; + using boost::spirit::x3::unused; + using boost::spirit::x3::int_; + + using boost::fusion::vector; + using boost::fusion::at_c; + + using spirit_test::test; + using spirit_test::test_attr; + + { + BOOST_TEST(test("a", omit['a'])); + } + + { + // omit[] means we don't receive the attribute + char attr; + BOOST_TEST((test_attr("abc", omit[char_] >> omit['b'] >> char_, attr))); + BOOST_TEST((attr == 'c')); + } + + { + // If all elements except 1 is omitted, the attribute is + // a single-element sequence. For this case alone, we allow + // naked attributes (unwrapped in a fusion sequence). + char attr; + BOOST_TEST((test_attr("abc", omit[char_] >> 'b' >> char_, attr))); + BOOST_TEST((attr == 'c')); + } + + { + // omit[] means we don't receive the attribute + vector<> attr; + BOOST_TEST((test_attr("abc", omit[char_] >> omit['b'] >> omit[char_], attr))); + } + + { + // omit[] means we don't receive the attribute + // this test is merely a compile test, because using a unused as the + // explicit attribute doesn't make any sense + unused_type attr; + BOOST_TEST((test_attr("abc", omit[char_ >> 'b' >> char_], attr))); + } + + { + // omit[] means we don't receive the attribute, if all elements of a + // sequence have unused attributes, the whole sequence has an unused + // attribute as well + vector<char, char> attr; + BOOST_TEST((test_attr("abcde", + char_ >> (omit[char_] >> omit['c'] >> omit[char_]) >> char_, attr))); + BOOST_TEST((at_c<0>(attr) == 'a')); + BOOST_TEST((at_c<1>(attr) == 'e')); + } + + { + // "hello" has an unused_type. unused attrubutes are not part of the sequence + vector<char, char> attr; + BOOST_TEST((test_attr("a hello c", char_ >> "hello" >> char_, attr, space))); + BOOST_TEST((at_c<0>(attr) == 'a')); + BOOST_TEST((at_c<1>(attr) == 'c')); + } + + { + // if only one node in a sequence is left (all the others are omitted), + // then we need "naked" attributes (not wraped in a tuple) + int attr; + BOOST_TEST((test_attr("a 123 c", omit['a'] >> int_ >> omit['c'], attr, space))); + BOOST_TEST((attr == 123)); + } + + { + // unused means we don't care about the attribute + BOOST_TEST((test_attr("abc", char_ >> 'b' >> char_, unused))); + } + + { // test action with omitted attribute + char c = 0; + auto f = [&](auto& ctx){ c = _attr(ctx); }; + + BOOST_TEST(test("x123\"a string\"", (char_ >> omit[int_] >> "\"a string\"")[f])); + BOOST_TEST(c == 'x'); + } + + { // test action with omitted attribute + int n = 0; + auto f = [&](auto& ctx){ n = _attr(ctx); }; + + BOOST_TEST(test("x 123 \"a string\"", (omit[char_] >> int_ >> "\"a string\"")[f], space)); + BOOST_TEST(n == 123); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/optional.cpp b/src/boost/libs/spirit/test/x3/optional.cpp new file mode 100644 index 00000000..cd7f6d32 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/optional.cpp @@ -0,0 +1,113 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/adapted/struct.hpp> +#include <boost/fusion/include/vector.hpp> + +#include <iostream> +#include "test.hpp" +#include "utils.hpp" + +struct adata +{ + int a; + boost::optional<int> b; +}; + +BOOST_FUSION_ADAPT_STRUCT(adata, + a, b +) + +struct test_attribute_type +{ + template <typename Context> + void operator()(Context& ctx) const + { + BOOST_TEST(typeid(decltype(_attr(ctx))).name() == typeid(boost::optional<int>).name()); + } +}; + +int +main() +{ + using boost::spirit::x3::traits::is_optional; + + static_assert(is_optional<boost::optional<int>>(), "is_optional problem"); + + using spirit_test::test; + using spirit_test::test_attr; + + using boost::spirit::x3::int_; + using boost::spirit::x3::omit; + using boost::spirit::x3::ascii::char_; + + { + BOOST_TEST((test("1234", -int_))); + BOOST_TEST((test("abcd", -int_, false))); + } + + { // test propagation of unused + using boost::fusion::at_c; + using boost::fusion::vector; + + vector<char, char> v; + BOOST_TEST((test_attr("a1234c", char_ >> -omit[int_] >> char_, v))); + BOOST_TEST((at_c<0>(v) == 'a')); + BOOST_TEST((at_c<1>(v) == 'c')); + + v = boost::fusion::vector<char, char>(); + BOOST_TEST((test_attr("a1234c", char_ >> omit[-int_] >> char_, v))); + BOOST_TEST((at_c<0>(v) == 'a')); + BOOST_TEST((at_c<1>(v) == 'c')); + + char ch; + BOOST_TEST((test_attr(",c", -(',' >> char_), ch))); + BOOST_TEST((ch == 'c')); + } + + { // test action + boost::optional<int> n = 0; + BOOST_TEST((test_attr("1234", (-int_)[test_attribute_type()], n))); + BOOST_TEST((n.get() == 1234)); + } + + { + std::string s; + BOOST_TEST((test_attr("abc", char_ >> -(char_ >> char_), s))); + BOOST_TEST(s == "abc"); + } + + { + boost::optional<int> n = 0; + auto f = [&](auto& ctx){ n = _attr(ctx); }; + + BOOST_TEST((test("1234", (-int_)[f]))); + BOOST_TEST(n.get() == 1234); + + n = boost::optional<int>(); + BOOST_TEST((test("abcd", (-int_)[f], false))); + BOOST_TEST(!n); + } + + { + std::vector<adata> v; + BOOST_TEST((test_attr("a 1 2 a 2", *('a' >> int_ >> -int_), v + , char_(' ')))); + BOOST_TEST(2 == v.size() && + 1 == v[0].a && v[0].b && 2 == *(v[0].b) && + 2 == v[1].a && !v[1].b); + } + + { // test move only types + boost::optional<move_only> o; + BOOST_TEST(test_attr("s", -synth_move_only, o)); + BOOST_TEST(o); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/optional_ast_node.cpp b/src/boost/libs/spirit/test/x3/optional_ast_node.cpp new file mode 100644 index 00000000..036d6de4 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/optional_ast_node.cpp @@ -0,0 +1,66 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) + + Duzy Chan: + This test addresses the usage of boost::optional<foo> as an ast node. +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/adapted/struct.hpp> +#include <boost/fusion/include/vector.hpp> + +#include <iostream> +#include "test.hpp" +#include "utils.hpp" + +struct twoints +{ + int a; + int b; +}; + +struct adata +{ + twoints a; + boost::optional<twoints> b; + twoints c; +}; + +BOOST_FUSION_ADAPT_STRUCT(twoints, a, b) +BOOST_FUSION_ADAPT_STRUCT(adata, a, b, c) + +int +main() +{ + { + // Duzy Chan: This case addresses the usage of boost::optional<foo> + // as an ast node. Which should actually test the ability of + // boost::spirit::x3::traits::move_to to handle with optional source + // value. + boost::spirit::x3::rule<class twoints, adata> top = "top"; + boost::spirit::x3::rule<class twoints, boost::optional<twoints>> + twoints = "twoints"; + + using boost::spirit::x3::int_; + auto const top_def = twoints >> ',' >> -twoints >> ',' >> twoints; + auto const twoints_def = int_ >> int_; + + BOOST_SPIRIT_DEFINE(top, twoints); + + twoints a, b; + BOOST_TEST((test_attr("1 2,3 4,5 6", top, a))); + BOOST_TEST((a.a.a == 1 && a.a.b == 2)); + BOOST_TEST((a.b && a.b->a == 3 && a.b->b == 4)); + BOOST_TEST((a.c.a == 5 && a.c.b == 6)); + + BOOST_TEST((test_attr("1 2,,5 6", top), b)); + BOOST_TEST((b.a.a == 1 && b.a.b == 2)); + BOOST_TEST((!a.b)); + BOOST_TEST((b.c.a == 5 && b.c.b == 6)); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/plus.cpp b/src/boost/libs/spirit/test/x3/plus.cpp new file mode 100644 index 00000000..7e27c84b --- /dev/null +++ b/src/boost/libs/spirit/test/x3/plus.cpp @@ -0,0 +1,140 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <string> +#include <vector> + +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/include/vector.hpp> + +#include <string> +#include <iostream> +#include "test.hpp" +#include "utils.hpp" + +struct x_attr +{ +}; + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + template <> + struct container_value<x_attr> + { + typedef char type; // value type of container + }; + + template <> + struct push_back_container<x_attr> + { + static bool call(x_attr& /*c*/, char /*val*/) + { + // push back value type into container + return true; + } + }; +}}}} + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + using boost::spirit::x3::char_; + using boost::spirit::x3::alpha; + using boost::spirit::x3::upper; + using boost::spirit::x3::space; + using boost::spirit::x3::digit; + //~ using boost::spirit::x3::no_case; + using boost::spirit::x3::int_; + using boost::spirit::x3::omit; + using boost::spirit::x3::lit; + //~ using boost::spirit::x3::_1; + using boost::spirit::x3::lexeme; + + { + BOOST_TEST(test("aaaaaaaa", +char_)); + BOOST_TEST(test("a", +char_)); + BOOST_TEST(!test("", +char_)); + BOOST_TEST(test("aaaaaaaa", +alpha)); + BOOST_TEST(!test("aaaaaaaa", +upper)); + } + + { + BOOST_TEST(test(" a a aaa aa", +char_, space)); + BOOST_TEST(test("12345 678 9 ", +digit, space)); + } + + //~ { + //~ BOOST_TEST(test("aBcdeFGH", no_case[+char_])); + //~ BOOST_TEST(test("a B cde FGH ", no_case[+char_], space)); + //~ } + + { + std::vector<int> v; + BOOST_TEST(test_attr("123 456 789 10", +int_, v, space) && 4 == v.size() && + v[0] == 123 && v[1] == 456 && v[2] == 789 && v[3] == 10); + } + + { + std::vector<std::string> v; + BOOST_TEST(test_attr("a b c d", +lexeme[+alpha], v, space) && 4 == v.size() && + v[0] == "a" && v[1] == "b" && v[2] == "c" && v[3] == "d"); + } + + { + BOOST_TEST(test("Kim Kim Kim", +lit("Kim"), space)); + } + + // $$$ Fixme $$$ + /*{ + // The following 2 tests show that omit does not inhibit explicit attributes + + std::string s; + BOOST_TEST(test_attr("bbbb", omit[+char_('b')], s) && s == "bbbb"); + + s.clear(); + BOOST_TEST(test_attr("b b b b ", omit[+char_('b')], s, space) && s == "bbbb"); + }*/ + + { // actions + std::string v; + auto f = [&](auto& ctx){ v = _attr(ctx); }; + + BOOST_TEST(test("bbbb", (+char_)[f]) && 4 == v.size() && + v[0] == 'b' && v[1] == 'b' && v[2] == 'b' && v[3] == 'b'); + } + + { // more actions + std::vector<int> v; + auto f = [&](auto& ctx){ v = _attr(ctx); }; + + BOOST_TEST(test("1 2 3", (+int_)[f], space) && 3 == v.size() && + v[0] == 1 && v[1] == 2 && v[2] == 3); + } + + { // attribute customization + + x_attr x; + test_attr("abcde", +char_, x); + } + + // single-element fusion vector tests + { + boost::fusion::vector<std::string> fs; + BOOST_TEST((test_attr("12345", +char_, fs))); // ok + BOOST_TEST(boost::fusion::at_c<0>(fs) == "12345"); + } + + { // test move only types + std::vector<move_only> v; + BOOST_TEST(test_attr("sss", +synth_move_only, v)); + BOOST_TEST_EQ(v.size(), 3); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/raw.cpp b/src/boost/libs/spirit/test/x3/raw.cpp new file mode 100644 index 00000000..78f025dd --- /dev/null +++ b/src/boost/libs/spirit/test/x3/raw.cpp @@ -0,0 +1,97 @@ +/*============================================================================= + 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/include/std_pair.hpp> + +#include <iostream> +#include <string> +#include "test.hpp" + +int main() +{ + using spirit_test::test; + using spirit_test::test_attr; + using namespace boost::spirit::x3::ascii; + using boost::spirit::x3::raw; + using boost::spirit::x3::eps; + using boost::spirit::x3::lit; + using boost::spirit::x3::_attr; + using boost::spirit::x3::parse; + using boost::spirit::x3::int_; + using boost::spirit::x3::char_; + + { + boost::iterator_range<char const*> range; + std::string str; + BOOST_TEST((test_attr("spirit_test_123", raw[alpha >> *(alnum | '_')], range))); + BOOST_TEST((std::string(range.begin(), range.end()) == "spirit_test_123")); + BOOST_TEST((test_attr(" spirit", raw[*alpha], range, space))); + BOOST_TEST((range.size() == 6)); + } + + { + std::string str; + BOOST_TEST((test_attr("spirit_test_123", raw[alpha >> *(alnum | '_')], str))); + BOOST_TEST((str == "spirit_test_123")); + } + + { + boost::iterator_range<char const*> range; + BOOST_TEST((test("x", raw[alpha]))); + BOOST_TEST((test_attr("x", raw[alpha], range))); + } + + { + boost::iterator_range<char const*> range; + BOOST_TEST((test("x", raw[alpha][ ([&](auto& ctx){ range = _attr(ctx); }) ]))); + BOOST_TEST(range.size() == 1 && *range.begin() == 'x'); + } + + { + boost::iterator_range<char const*> range; + BOOST_TEST((test("x123x", lit('x') >> raw[+digit] >> lit('x')))); + BOOST_TEST((test_attr("x123x", lit('x') >> raw[+digit] >> lit('x'), range))); + BOOST_TEST((std::string(range.begin(), range.end()) == "123")); + } + + { + using range = boost::iterator_range<std::string::iterator>; + boost::variant<int, range> attr; + + std::string str("test"); + parse(str.begin(), str.end(), (int_ | raw[*char_]), attr); + + auto rng = boost::get<range>(attr); + BOOST_TEST(std::string(rng.begin(), rng.end()) == "test"); + } + + { + std::vector<boost::iterator_range<std::string::iterator>> attr; + std::string str("123abcd"); + parse(str.begin(), str.end() + , (raw[int_] >> raw[*char_]) + , attr + ); + BOOST_TEST(attr.size() == 2); + BOOST_TEST(std::string(attr[0].begin(), attr[0].end()) == "123"); + BOOST_TEST(std::string(attr[1].begin(), attr[1].end()) == "abcd"); + } + + { + std::pair<int, boost::iterator_range<std::string::iterator>> attr; + std::string str("123abcd"); + parse(str.begin(), str.end() + , (int_ >> raw[*char_]) + , attr + ); + BOOST_TEST(attr.first == 123); + BOOST_TEST(std::string(attr.second.begin(), attr.second.end()) == "abcd"); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/real.hpp b/src/boost/libs/spirit/test/x3/real.hpp new file mode 100644 index 00000000..7a680f73 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/real.hpp @@ -0,0 +1,122 @@ +/*============================================================================= + Copyright (c) 2001-2010 Joel de Guzman + Copyright (c) 2001-2010 Hartmut Kaiser + + Use, modification and distribution is subject to 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) +=============================================================================*/ +#if !defined(BOOST_SPIRIT_TEST_X3_REAL_HPP) +#define BOOST_SPIRIT_TEST_X3_REAL_HPP + +#include <climits> +#include <boost/math/concepts/real_concept.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3/char.hpp> +#include <boost/spirit/home/x3/numeric.hpp> +#include <boost/spirit/home/x3/operator.hpp> +#include <boost/math/special_functions/fpclassify.hpp> +#include <boost/math/special_functions/sign.hpp> + +#include "test.hpp" + +/////////////////////////////////////////////////////////////////////////////// +// These policies can be used to parse thousand separated +// numbers with at most 2 decimal digits after the decimal +// point. e.g. 123,456,789.01 +/////////////////////////////////////////////////////////////////////////////// +template <typename T> +struct ts_real_policies : boost::spirit::x3::ureal_policies<T> +{ + // 2 decimal places Max + template <typename Iterator, typename Attribute> + static bool + parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr) + { + namespace x3 = boost::spirit::x3; + return boost::spirit::x3::extract_uint<T, 10, 1, 2, true>::call(first, last, attr); + } + + // No exponent + template <typename Iterator> + static bool + parse_exp(Iterator&, Iterator const&) + { + return false; + } + + // No exponent + template <typename Iterator, typename Attribute> + static bool + parse_exp_n(Iterator&, Iterator const&, Attribute&) + { + return false; + } + + // Thousands separated numbers + template <typename Iterator, typename Accumulator> + static bool + parse_n(Iterator& first, Iterator const& last, Accumulator& result) + { + using boost::spirit::x3::uint_parser; + namespace x3 = boost::spirit::x3; + + uint_parser<unsigned, 10, 1, 3> uint3; + uint_parser<unsigned, 10, 3, 3> uint3_3; + + if (parse(first, last, uint3, result)) + { + Accumulator n; + Iterator iter = first; + + while (x3::parse(iter, last, ',') && x3::parse(iter, last, uint3_3, n)) + { + result = result * 1000 + n; + first = iter; + } + + return true; + } + return false; + } +}; + +template <typename T> +struct no_trailing_dot_policy : boost::spirit::x3::real_policies<T> +{ + static bool const allow_trailing_dot = false; +}; + +template <typename T> +struct no_leading_dot_policy : boost::spirit::x3::real_policies<T> +{ + static bool const allow_leading_dot = false; +}; + +template <typename T, typename T2> +bool +compare(T n, T2 expected) +{ + T const eps = std::pow(10.0, -std::numeric_limits<T>::digits10); + T delta = n - expected; + return (delta >= -eps) && (delta <= eps); +} + +/////////////////////////////////////////////////////////////////////////////// +// A custom real type +struct custom_real +{ + double n; + custom_real() : n(0) {} + custom_real(double n_) : n(n_) {} + friend bool operator==(custom_real a, custom_real b) + { return a.n == b.n; } + friend custom_real operator*(custom_real a, custom_real b) + { return custom_real(a.n * b.n); } + friend custom_real operator+(custom_real a, custom_real b) + { return custom_real(a.n + b.n); } + friend custom_real operator-(custom_real a, custom_real b) + { return custom_real(a.n - b.n); } +}; + +#endif diff --git a/src/boost/libs/spirit/test/x3/real1.cpp b/src/boost/libs/spirit/test/x3/real1.cpp new file mode 100644 index 00000000..f550a606 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/real1.cpp @@ -0,0 +1,119 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2011 Bryce Lelbach + + Use, modification and distribution is subject to 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 "real.hpp" + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + + /////////////////////////////////////////////////////////////////////////// + // thousand separated numbers + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::uint_parser; + using boost::spirit::x3::parse; + + uint_parser<unsigned, 10, 1, 3> uint3; + uint_parser<unsigned, 10, 3, 3> uint3_3; + + #define r (uint3 >> *(',' >> uint3_3)) + + BOOST_TEST(test("1,234,567,890", r)); + BOOST_TEST(test("12,345,678,900", r)); + BOOST_TEST(test("123,456,789,000", r)); + BOOST_TEST(!test("1000,234,567,890", r)); + BOOST_TEST(!test("1,234,56,890", r)); + BOOST_TEST(!test("1,66", r)); + } + + /////////////////////////////////////////////////////////////////////////// + // unsigned real number tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::real_parser; + using boost::spirit::x3::parse; + using boost::spirit::x3::ureal_policies; + + real_parser<double, ureal_policies<double> > udouble; + double d; + + BOOST_TEST(test("1234", udouble)); + BOOST_TEST(test_attr("1234", udouble, d) && compare(d, 1234)); + + BOOST_TEST(test("1.2e3", udouble)); + BOOST_TEST(test_attr("1.2e3", udouble, d) && compare(d, 1.2e3)); + + BOOST_TEST(test("1.2e-3", udouble)); + BOOST_TEST(test_attr("1.2e-3", udouble, d) && compare(d, 1.2e-3)); + + BOOST_TEST(test("1.e2", udouble)); + BOOST_TEST(test_attr("1.e2", udouble, d) && compare(d, 1.e2)); + + BOOST_TEST(test("1.", udouble)); + BOOST_TEST(test_attr("1.", udouble, d) && compare(d, 1.)); + + BOOST_TEST(test(".2e3", udouble)); + BOOST_TEST(test_attr(".2e3", udouble, d) && compare(d, .2e3)); + + BOOST_TEST(test("2e3", udouble)); + BOOST_TEST(test_attr("2e3", udouble, d) && compare(d, 2e3)); + + BOOST_TEST(test("2", udouble)); + BOOST_TEST(test_attr("2", udouble, d) && compare(d, 2)); + + using boost::math::fpclassify; + BOOST_TEST(test("inf", udouble)); + BOOST_TEST(test("infinity", udouble)); + BOOST_TEST(test("INF", udouble)); + BOOST_TEST(test("INFINITY", udouble)); + + BOOST_TEST(test_attr("inf", udouble, d) + && FP_INFINITE == fpclassify(d)); + BOOST_TEST(test_attr("INF", udouble, d) + && FP_INFINITE == fpclassify(d)); + BOOST_TEST(test_attr("infinity", udouble, d) + && FP_INFINITE == fpclassify(d)); + BOOST_TEST(test_attr("INFINITY", udouble, d) + && FP_INFINITE == fpclassify(d)); + + BOOST_TEST(test("nan", udouble)); + BOOST_TEST(test_attr("nan", udouble, d) + && FP_NAN == fpclassify(d)); + BOOST_TEST(test("NAN", udouble)); + BOOST_TEST(test_attr("NAN", udouble, d) + && FP_NAN == fpclassify(d)); + BOOST_TEST(test("nan(...)", udouble)); + BOOST_TEST(test_attr("nan(...)", udouble, d) + && FP_NAN == fpclassify(d)); + BOOST_TEST(test("NAN(...)", udouble)); + BOOST_TEST(test_attr("NAN(...)", udouble, d) + && FP_NAN == fpclassify(d)); + + BOOST_TEST(!test("e3", udouble)); + BOOST_TEST(!test_attr("e3", udouble, d)); + + BOOST_TEST(!test("-1.2e3", udouble)); + BOOST_TEST(!test_attr("-1.2e3", udouble, d)); + + BOOST_TEST(!test("+1.2e3", udouble)); + BOOST_TEST(!test_attr("+1.2e3", udouble, d)); + + BOOST_TEST(!test("1.2e", udouble)); + BOOST_TEST(!test_attr("1.2e", udouble, d)); + + BOOST_TEST(!test("-.3", udouble)); + BOOST_TEST(!test_attr("-.3", udouble, d)); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/real2.cpp b/src/boost/libs/spirit/test/x3/real2.cpp new file mode 100644 index 00000000..dc003f0d --- /dev/null +++ b/src/boost/libs/spirit/test/x3/real2.cpp @@ -0,0 +1,132 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2011 Bryce Lelbach + + Use, modification and distribution is subject to 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 "real.hpp" + +template <typename T, typename P> +void basic_real_parser_test(P parser) +{ + using spirit_test::test; + using spirit_test::test_attr; + + T attr; + + BOOST_TEST(test("-1234", parser)); + BOOST_TEST(test_attr("-1234", parser, attr) && compare(attr, T(-1234l))); + + BOOST_TEST(test("-1.2e3", parser)); + BOOST_TEST(test_attr("-1.2e3", parser, attr) && compare(attr, T(-1.2e3l))); + + BOOST_TEST(test("+1.2e3", parser)); + BOOST_TEST(test_attr("+1.2e3", parser, attr) && compare(attr, T(1.2e3l))); + + BOOST_TEST(test("-0.1", parser)); + BOOST_TEST(test_attr("-0.1", parser, attr) && compare(attr, T(-0.1l))); + + BOOST_TEST(test("-1.2e-3", parser)); + BOOST_TEST(test_attr("-1.2e-3", parser, attr) && compare(attr, T(-1.2e-3l))); + + BOOST_TEST(test("-1.e2", parser)); + BOOST_TEST(test_attr("-1.e2", parser, attr) && compare(attr, T(-1.e2l))); + + BOOST_TEST(test("-.2e3", parser)); + BOOST_TEST(test_attr("-.2e3", parser, attr) && compare(attr, T(-.2e3l))); + + BOOST_TEST(test("-2e3", parser)); + BOOST_TEST(test_attr("-2e3", parser, attr) && compare(attr, T(-2e3l))); + + BOOST_TEST(!test("-e3", parser)); + BOOST_TEST(!test_attr("-e3", parser, attr)); + + BOOST_TEST(!test("-1.2e", parser)); + BOOST_TEST(!test_attr("-1.2e", parser, attr)); +} + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + /////////////////////////////////////////////////////////////////////////// + // signed real number tests + /////////////////////////////////////////////////////////////////////////// + { + basic_real_parser_test<float>(boost::spirit::x3::float_); + basic_real_parser_test<double>(boost::spirit::x3::double_); + basic_real_parser_test<long double>(boost::spirit::x3::long_double); + } + + { + using boost::spirit::x3::double_; + double d; + +#if defined(BOOST_SPIRIT_TEST_REAL_PRECISION) + BOOST_TEST(test_attr("-5.7222349715140557e+307", double_, d)); + BOOST_TEST(d == -5.7222349715140557e+307); // exact! + + BOOST_TEST(test_attr("2.0332938517515416e-308", double_, d)); + BOOST_TEST(d == 2.0332938517515416e-308); // exact! + + BOOST_TEST(test_attr("20332938517515416e291", double_, d)); + BOOST_TEST(d == 20332938517515416e291); // exact! + + BOOST_TEST(test_attr("2.0332938517515416e307", double_, d)); + BOOST_TEST(d == 2.0332938517515416e307); // exact! +#endif + + using boost::math::fpclassify; + using boost::spirit::x3::signbit; // Boost version is broken + + BOOST_TEST(test("-inf", double_)); + BOOST_TEST(test("-infinity", double_)); + BOOST_TEST(test_attr("-inf", double_, d) && + FP_INFINITE == fpclassify(d) && signbit(d)); + BOOST_TEST(test_attr("-infinity", double_, d) && + FP_INFINITE == fpclassify(d) && signbit(d)); + BOOST_TEST(test("-INF", double_)); + BOOST_TEST(test("-INFINITY", double_)); + BOOST_TEST(test_attr("-INF", double_, d) && + FP_INFINITE == fpclassify(d) && signbit(d)); + BOOST_TEST(test_attr("-INFINITY", double_, d) && + FP_INFINITE == fpclassify(d) && signbit(d)); + + BOOST_TEST(test("-nan", double_)); + BOOST_TEST(test_attr("-nan", double_, d) && + FP_NAN == fpclassify(d) && signbit(d)); + BOOST_TEST(test("-NAN", double_)); + BOOST_TEST(test_attr("-NAN", double_, d) && + FP_NAN == fpclassify(d) && signbit(d)); + + BOOST_TEST(test("-nan(...)", double_)); + BOOST_TEST(test_attr("-nan(...)", double_, d) && + FP_NAN == fpclassify(d) && signbit(d)); + BOOST_TEST(test("-NAN(...)", double_)); + BOOST_TEST(test_attr("-NAN(...)", double_, d) && + FP_NAN == fpclassify(d) && signbit(d)); + + BOOST_TEST(!test("1e999", double_)); + BOOST_TEST(!test("1e-999", double_)); + BOOST_TEST(test_attr("2.1111111e-303", double_, d) && + compare(d, 2.1111111e-303)); + BOOST_TEST(!test_attr("1.1234e", double_, d) && compare(d, 1.1234)); + + // https://svn.boost.org/trac10/ticket/11608 + BOOST_TEST(test_attr("1267650600228229401496703205376", double_, d) && + compare(d, 1.2676506002282291E+30)); // Note Qi has better precision + + BOOST_TEST(test_attr("12676506.00228229401496703205376", double_, d) && + compare(d, 1.2676506002282292E7)); // Note Qi has better precision + + BOOST_TEST(test_attr("12676506.00228229401496703205376E6", double_, d) && + compare(d, 1.2676506002282291016E13)); // Note Qi has better precision + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/real3.cpp b/src/boost/libs/spirit/test/x3/real3.cpp new file mode 100644 index 00000000..09e11ad9 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/real3.cpp @@ -0,0 +1,85 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + Copyright (c) 2001-2010 Hartmut Kaiser + + Use, modification and distribution is subject to 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 "real.hpp" + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + + /////////////////////////////////////////////////////////////////////////// + // strict real number tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::real_parser; + using boost::spirit::x3::parse; + using boost::spirit::x3::strict_ureal_policies; + using boost::spirit::x3::strict_real_policies; + + real_parser<double, strict_ureal_policies<double> > strict_udouble; + real_parser<double, strict_real_policies<double> > strict_double; + double d; + + BOOST_TEST(!test("1234", strict_udouble)); + BOOST_TEST(!test_attr("1234", strict_udouble, d)); + + BOOST_TEST(test("1.2", strict_udouble)); + BOOST_TEST(test_attr("1.2", strict_udouble, d) && compare(d, 1.2)); + + BOOST_TEST(!test("-1234", strict_double)); + BOOST_TEST(!test_attr("-1234", strict_double, d)); + + BOOST_TEST(test("123.", strict_double)); + BOOST_TEST(test_attr("123.", strict_double, d) && compare(d, 123)); + + BOOST_TEST(test("3.E6", strict_double)); + BOOST_TEST(test_attr("3.E6", strict_double, d) && compare(d, 3e6)); + + real_parser<double, no_trailing_dot_policy<double> > notrdot_real; + real_parser<double, no_leading_dot_policy<double> > nolddot_real; + + BOOST_TEST(!test("1234.", notrdot_real)); // Bad trailing dot + BOOST_TEST(!test(".1234", nolddot_real)); // Bad leading dot + } + + /////////////////////////////////////////////////////////////////////////// + // Special thousands separated numbers + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::real_parser; + using boost::spirit::x3::parse; + real_parser<double, ts_real_policies<double> > ts_real; + double d; + + BOOST_TEST(test("123.01", ts_real)); + BOOST_TEST(test_attr("123.01", ts_real, d) + && compare(d, 123.01)); + + BOOST_TEST(test("123,456,789.01", ts_real)); + BOOST_TEST(test_attr("123,456,789.01", ts_real, d) + && compare(d, 123456789.01)); + + BOOST_TEST(test("12,345,678.90", ts_real)); + BOOST_TEST(test_attr("12,345,678.90", ts_real, d) + && compare(d, 12345678.90)); + + BOOST_TEST(test("1,234,567.89", ts_real)); + BOOST_TEST(test_attr("1,234,567.89", ts_real, d) + && compare(d, 1234567.89)); + + BOOST_TEST(!test("1234,567,890", ts_real)); + BOOST_TEST(!test("1,234,5678,9", ts_real)); + BOOST_TEST(!test("1,234,567.89e6", ts_real)); + BOOST_TEST(!test("1,66", ts_real)); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/real4.cpp b/src/boost/libs/spirit/test/x3/real4.cpp new file mode 100644 index 00000000..0b668c75 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/real4.cpp @@ -0,0 +1,73 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2011 Bryce Lelbach + + Use, modification and distribution is subject to 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 "real.hpp" + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + + /////////////////////////////////////////////////////////////////////////// + // Custom data type + /////////////////////////////////////////////////////////////////////////// + { + using boost::math::concepts::real_concept; + using boost::spirit::x3::real_parser; + using boost::spirit::x3::real_policies; + using boost::spirit::x3::parse; + + real_parser<real_concept, real_policies<real_concept> > custom_real; + real_concept d; + + BOOST_TEST(test("-1234", custom_real)); + BOOST_TEST(test_attr("-1234", custom_real, d) && compare(d, -1234)); + + BOOST_TEST(test("-1.2e3", custom_real)); + BOOST_TEST(test_attr("-1.2e3", custom_real, d) && compare(d, -1.2e3)); + + BOOST_TEST(test("+1.2e3", custom_real)); + BOOST_TEST(test_attr("+1.2e3", custom_real, d) && compare(d, 1.2e3)); + + BOOST_TEST(test("-0.1", custom_real)); + BOOST_TEST(test_attr("-0.1", custom_real, d) && compare(d, -0.1)); + + BOOST_TEST(test("-1.2e-3", custom_real)); + BOOST_TEST(test_attr("-1.2e-3", custom_real, d) && compare(d, -1.2e-3)); + + BOOST_TEST(test("-1.e2", custom_real)); + BOOST_TEST(test_attr("-1.e2", custom_real, d) && compare(d, -1.e2)); + + BOOST_TEST(test("-.2e3", custom_real)); + BOOST_TEST(test_attr("-.2e3", custom_real, d) && compare(d, -.2e3)); + + BOOST_TEST(test("-2e3", custom_real)); + BOOST_TEST(test_attr("-2e3", custom_real, d) && compare(d, -2e3)); + + BOOST_TEST(!test("-e3", custom_real)); + BOOST_TEST(!test_attr("-e3", custom_real, d)); + + BOOST_TEST(!test("-1.2e", custom_real)); + BOOST_TEST(!test_attr("-1.2e", custom_real, d)); + } + + /////////////////////////////////////////////////////////////////////////// + // custom real tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::double_; + custom_real n; + + BOOST_TEST(test_attr("-123456e6", double_, n)); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/repeat.cpp b/src/boost/libs/spirit/test/x3/repeat.cpp new file mode 100644 index 00000000..99c080fe --- /dev/null +++ b/src/boost/libs/spirit/test/x3/repeat.cpp @@ -0,0 +1,152 @@ +/*============================================================================= + Copyright (c) 2001-2011 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) +=============================================================================*/ +#include <string> +#include <vector> + +#include <boost/detail/lightweight_test.hpp> +#include <boost/utility/enable_if.hpp> + +#include <boost/spirit/home/x3.hpp> +#include <string> +#include <iostream> +#include "test.hpp" +#include "utils.hpp" + +int +main() +{ + using spirit_test::test_attr; + using spirit_test::test; + + using namespace boost::spirit::x3::ascii; + using boost::spirit::x3::repeat; + using boost::spirit::x3::inf; + using boost::spirit::x3::omit; + using boost::spirit::x3::int_; + using boost::spirit::x3::lexeme; + using boost::spirit::x3::char_; + { + BOOST_TEST(test("aaaaaaaa", repeat[char_])); // kleene synonym + BOOST_TEST(test("aaaaaaaa", repeat(8)[char_])); + BOOST_TEST(!test("aa", repeat(3)[char_])); + BOOST_TEST(test("aaa", repeat(3, 5)[char_])); + BOOST_TEST(test("aaaaa", repeat(3, 5)[char_])); + BOOST_TEST(!test("aaaaaa", repeat(3, 5)[char_])); + BOOST_TEST(!test("aa", repeat(3, 5)[char_])); + + BOOST_TEST(test("aaa", repeat(3, inf)[char_])); + BOOST_TEST(test("aaaaa", repeat(3, inf)[char_])); + BOOST_TEST(test("aaaaaa", repeat(3, inf)[char_])); + BOOST_TEST(!test("aa", repeat(3, inf)[char_])); + } + { + std::string s; + BOOST_TEST(test_attr("aaaaaaaa", repeat[char_ >> char_], s)); // kleene synonym + BOOST_TEST(s == "aaaaaaaa"); + + s.clear(); + BOOST_TEST(test_attr("aaaaaaaa", repeat(4)[char_ >> char_], s)); + BOOST_TEST(s == "aaaaaaaa"); + + BOOST_TEST(!test("aa", repeat(3)[char_ >> char_])); + BOOST_TEST(!test("a", repeat(1)[char_ >> char_])); + + s.clear(); + BOOST_TEST(test_attr("aa", repeat(1, 3)[char_ >> char_], s)); + BOOST_TEST(s == "aa"); + + s.clear(); + BOOST_TEST(test_attr("aaaaaa", repeat(1, 3)[char_ >> char_], s)); + BOOST_TEST(s == "aaaaaa"); + + BOOST_TEST(!test("aaaaaaa", repeat(1, 3)[char_ >> char_])); + BOOST_TEST(!test("a", repeat(1, 3)[char_ >> char_])); + + s.clear(); + BOOST_TEST(test_attr("aaaa", repeat(2, inf)[char_ >> char_], s)); + BOOST_TEST(s == "aaaa"); + + s.clear(); + BOOST_TEST(test_attr("aaaaaa", repeat(2, inf)[char_ >> char_], s)); + BOOST_TEST(s == "aaaaaa"); + + BOOST_TEST(!test("aa", repeat(2, inf)[char_ >> char_])); + } + + { // from classic spirit tests + BOOST_TEST(test("", repeat(0, inf)['x'])); + + // repeat exact 8 + #define rep8 repeat(8)[alpha] >> 'X' + BOOST_TEST(!test("abcdefgX", rep8, false)); + BOOST_TEST(test("abcdefghX", rep8)); + BOOST_TEST(!test("abcdefghiX", rep8, false)); + BOOST_TEST(!test("abcdefgX", rep8, false)); + BOOST_TEST(!test("aX", rep8, false)); + + // repeat 2 to 8 + #define rep28 repeat(2, 8)[alpha] >> '*' + BOOST_TEST(test("abcdefg*", rep28)); + BOOST_TEST(test("abcdefgh*", rep28)); + BOOST_TEST(!test("abcdefghi*", rep28, false)); + BOOST_TEST(!test("a*", rep28, false)); + + // repeat 2 or more + #define rep2_ repeat(2, inf)[alpha] >> '+' + BOOST_TEST(test("abcdefg+", rep2_)); + BOOST_TEST(test("abcdefgh+", rep2_)); + BOOST_TEST(test("abcdefghi+", rep2_)); + BOOST_TEST(test("abcdefg+", rep2_)); + BOOST_TEST(!test("a+", rep2_, false)); + + // repeat 0 + #define rep0 repeat(0)[alpha] >> '/' + BOOST_TEST(test("/", rep0)); + BOOST_TEST(!test("a/", rep0, false)); + + // repeat 0 or 1 + #define rep01 repeat(0, 1)[alpha >> digit] >> '?' + BOOST_TEST(!test("abcdefg?", rep01, false)); + BOOST_TEST(!test("a?", rep01, false)); + BOOST_TEST(!test("1?", rep01, false)); + BOOST_TEST(!test("11?", rep01, false)); + BOOST_TEST(!test("aa?", rep01, false)); + BOOST_TEST(test("?", rep01)); + BOOST_TEST(test("a1?", rep01)); + } + + { + BOOST_TEST(test(" a a aaa aa", repeat(7)[char_], space)); + BOOST_TEST(test("12345 678 9", repeat(9)[digit], space)); + } + + { + std::vector<std::string> v; + BOOST_TEST(test_attr("a b c d", repeat(4)[lexeme[+alpha]], v, space) && 4 == v.size() && + v[0] == "a" && v[1] == "b" && v[2] == "c" && v[3] == "d"); + } + { + BOOST_TEST(test("1 2 3", int_ >> repeat(2)[int_], space)); + BOOST_TEST(!test("1 2", int_ >> repeat(2)[int_], space)); + } + + { + std::vector<char> v; + BOOST_TEST(test_attr("1 2 3", int_ >> repeat(2)[int_], v, space)); + BOOST_TEST(v.size() == 3 && v[0] == 1 && v[1] == 2 && v[2] == 3); + + BOOST_TEST(!test("1 2", int_ >> repeat(2)[int_], space)); + } + + { // test move only types + std::vector<move_only> v; + BOOST_TEST(test_attr("sss", repeat(3)[synth_move_only], v)); + BOOST_TEST_EQ(v.size(), 3); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/rule1.cpp b/src/boost/libs/spirit/test/x3/rule1.cpp new file mode 100644 index 00000000..09941dec --- /dev/null +++ b/src/boost/libs/spirit/test/x3/rule1.cpp @@ -0,0 +1,129 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ + +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <string> +#include <cstring> +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test_attr; + using spirit_test::test; + + using namespace boost::spirit::x3::ascii; + using boost::spirit::x3::rule; + using boost::spirit::x3::lit; + using boost::spirit::x3::int_; + using boost::spirit::x3::unused_type; + using boost::spirit::x3::phrase_parse; + using boost::spirit::x3::skip_flag; + using boost::spirit::x3::traits::has_attribute; + + // check attribute advertising + static_assert( has_attribute<rule<class r, int>, /*Context=*/unused_type>::value, ""); + static_assert(!has_attribute<rule<class r >, /*Context=*/unused_type>::value, ""); + static_assert( has_attribute<decltype(rule<class r, int>{} = int_), /*Context=*/unused_type>::value, ""); + static_assert(!has_attribute<decltype(rule<class r >{} = int_), /*Context=*/unused_type>::value, ""); + + + { // basic tests + + auto a = lit('a'); + auto b = lit('b'); + auto c = lit('c'); + rule<class r> r; + + { + auto start = + r = *(a | b | c); + + BOOST_TEST(test("abcabcacb", start)); + } + + { + auto start = + r = (a | b) >> (r | b); + + BOOST_TEST(test("aaaabababaaabbb", start)); + BOOST_TEST(test("aaaabababaaabba", start, false)); + + // ignore the skipper! + BOOST_TEST(test("aaaabababaaabba", start, space, false)); + } + } + + { // basic tests w/ skipper + + auto a = lit('a'); + auto b = lit('b'); + auto c = lit('c'); + rule<class r> r; + + { + auto start = + r = *(a | b | c); + + BOOST_TEST(test(" a b c a b c a c b ", start, space)); + } + + { + auto start = + r = (a | b) >> (r | b); + + BOOST_TEST(test(" a a a a b a b a b a a a b b b ", start, space)); + BOOST_TEST(test(" a a a a b a b a b a a a b b a ", start, space, false)); + } + } + + { // basic tests w/ skipper but no final post-skip + + auto a = rule<class a>() + = lit('a'); + + auto b = rule<class b>() + = lit('b'); + + auto c = rule<class c>() + = lit('c'); + + { + auto start = rule<class start>() = *(a | b) >> c; + + char const *s1 = " a b a a b b a c ... " + , *const e1 = s1 + std::strlen(s1); + BOOST_TEST(phrase_parse(s1, e1, start, space, skip_flag::dont_post_skip) + && s1 == e1 - 5); + + } + + { + rule<class start> start; + + auto p = + start = (a | b) >> (start | c); + { + char const *s1 = " a a a a b a b a b a a a b b b c " + , *const e1 = s1 + std::strlen(s1); + BOOST_TEST(phrase_parse(s1, e1, p, space, skip_flag::post_skip) + && s1 == e1); + } + { + char const *s1 = " a a a a b a b a b a a a b b b c " + , *const e1 = s1 + std::strlen(s1); + BOOST_TEST(phrase_parse(s1, e1, p, space, skip_flag::dont_post_skip) + && s1 == e1 - 1); + } + } + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/rule2.cpp b/src/boost/libs/spirit/test/x3/rule2.cpp new file mode 100644 index 00000000..fd6c07fa --- /dev/null +++ b/src/boost/libs/spirit/test/x3/rule2.cpp @@ -0,0 +1,108 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ + +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <string> +#include <cstring> +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test_attr; + using spirit_test::test; + + using namespace boost::spirit::x3::ascii; + using boost::spirit::x3::rule; + using boost::spirit::x3::lit; + using boost::spirit::x3::unused_type; + using boost::spirit::x3::_attr; + + { // context tests + + char ch; + auto a = rule<class a, char>() = alpha; + + // this semantic action requires the context + auto f = [&](auto& ctx){ ch = _attr(ctx); }; + BOOST_TEST(test("x", a[f])); + BOOST_TEST(ch == 'x'); + + // this semantic action requires the (unused) context + auto f2 = [&](auto&){ ch = 'y'; }; + BOOST_TEST(test("x", a[f2])); + BOOST_TEST(ch == 'y'); + + // the semantic action may optionally not have any arguments at all + auto f3 = [&]{ ch = 'z'; }; + BOOST_TEST(test("x", a[f3])); + BOOST_TEST(ch == 'z'); + + BOOST_TEST(test_attr("z", a, ch)); // attribute is given. + BOOST_TEST(ch == 'z'); + } + + { // auto rules tests + + char ch = '\0'; + auto a = rule<class a, char>() = alpha; + auto f = [&](auto& ctx){ ch = _attr(ctx); }; + + BOOST_TEST(test("x", a[f])); + BOOST_TEST(ch == 'x'); + ch = '\0'; + BOOST_TEST(test_attr("z", a, ch)); // attribute is given. + BOOST_TEST(ch == 'z'); + + ch = '\0'; + BOOST_TEST(test("x", a[f])); + BOOST_TEST(ch == 'x'); + ch = '\0'; + BOOST_TEST(test_attr("z", a, ch)); // attribute is given. + BOOST_TEST(ch == 'z'); + } + + { // auto rules tests: allow stl containers as attributes to + // sequences (in cases where attributes of the elements + // are convertible to the value_type of the container or if + // the element itself is an stl container with value_type + // that is convertible to the value_type of the attribute). + + std::string s; + auto f = [&](auto& ctx){ s = _attr(ctx); }; + + { + auto r = rule<class r, std::string>() + = char_ >> *(',' >> char_) + ; + + BOOST_TEST(test("a,b,c,d,e,f", r[f])); + BOOST_TEST(s == "abcdef"); + } + + { + auto r = rule<class r, std::string>() + = char_ >> *(',' >> char_); + s.clear(); + BOOST_TEST(test("a,b,c,d,e,f", r[f])); + BOOST_TEST(s == "abcdef"); + } + + { + auto r = rule<class r, std::string>() + = char_ >> char_ >> char_ >> char_ >> char_ >> char_; + s.clear(); + BOOST_TEST(test("abcdef", r[f])); + BOOST_TEST(s == "abcdef"); + } + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/rule3.cpp b/src/boost/libs/spirit/test/x3/rule3.cpp new file mode 100644 index 00000000..420146c0 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/rule3.cpp @@ -0,0 +1,109 @@ +/*============================================================================= + Copyright (c) 2001-2012 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) +=============================================================================*/ + +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/include/std_pair.hpp> + +#include <string> +#include <cstring> +#include <iostream> +#include "test.hpp" + +using boost::spirit::x3::_val; + +struct f +{ + template <typename Context> + void operator()(Context const& ctx) const + { + _val(ctx) += _attr(ctx); + } +}; + + +struct stationary : boost::noncopyable +{ + explicit stationary(int i) : val{i} {} + stationary& operator=(int i) { val = i; return *this; } + + int val; +}; + + +namespace check_stationary { + +boost::spirit::x3::rule<class a_r, stationary> const a; +boost::spirit::x3::rule<class b_r, stationary> const b; + +auto const a_def = '{' >> boost::spirit::x3::int_ >> '}'; +auto const b_def = a; + +BOOST_SPIRIT_DEFINE(a, b) + +} + + +int main() +{ + using spirit_test::test_attr; + using spirit_test::test; + + using namespace boost::spirit::x3::ascii; + using boost::spirit::x3::rule; + using boost::spirit::x3::lit; + using boost::spirit::x3::eps; + using boost::spirit::x3::unused_type; + + + { // synth attribute value-init + + std::string s; + typedef rule<class r, std::string> rule_type; + + auto rdef = rule_type() + = alpha [f()] + ; + + BOOST_TEST(test_attr("abcdef", +rdef, s)); + BOOST_TEST(s == "abcdef"); + } + + { // synth attribute value-init + + std::string s; + typedef rule<class r, std::string> rule_type; + + auto rdef = rule_type() = + alpha / + [](auto& ctx) + { + _val(ctx) += _attr(ctx); + } + ; + + BOOST_TEST(test_attr("abcdef", +rdef, s)); + BOOST_TEST(s == "abcdef"); + } + + { + auto r = rule<class r, int>{} = eps[([] (auto& ctx) { + using boost::spirit::x3::_val; + static_assert(std::is_same<std::decay_t<decltype(_val(ctx))>, unused_type>::value, + "Attribute must not be synthesized"); + })]; + BOOST_TEST(test("", r)); + } + + { // ensure no unneded synthesization, copying and moving occured + stationary st { 0 }; + BOOST_TEST(test_attr("{42}", check_stationary::b, st)); + BOOST_TEST_EQ(st.val, 42); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/rule4.cpp b/src/boost/libs/spirit/test/x3/rule4.cpp new file mode 100644 index 00000000..3e3a647d --- /dev/null +++ b/src/boost/libs/spirit/test/x3/rule4.cpp @@ -0,0 +1,164 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ + +#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 <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&) + { + 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::rule; + using boost::spirit::x3::int_; + using boost::spirit::x3::lit; + + { // 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); + } + + { // show that ra %= rb works as expected with semantic actions + rule<class a, int> ra; + rule<class b, int> rb; + int attr; + + auto f = [](auto&){}; + auto ra_def = (ra %= int_[f]); + BOOST_TEST(test_attr("123", ra_def, attr)); + BOOST_TEST(attr == 123); + + auto ra_def2 = (rb = (ra %= int_[f])); + BOOST_TEST(test_attr("123", ra_def2, attr)); + BOOST_TEST(attr == 123); + } + + + { // std::string as container attribute with auto rules + + std::string attr; + + // 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); + } + + { + 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); + } + + { // 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(); +} diff --git a/src/boost/libs/spirit/test/x3/rule_separate_tu.cpp b/src/boost/libs/spirit/test/x3/rule_separate_tu.cpp new file mode 100644 index 00000000..c3fcb29e --- /dev/null +++ b/src/boost/libs/spirit/test/x3/rule_separate_tu.cpp @@ -0,0 +1,71 @@ +/*============================================================================= + Copyright (c) 2019 Nikita Kniazev + + Use, modification and distribution is subject to 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 "rule_separate_tu_grammar.hpp" + +#include <boost/core/lightweight_test.hpp> + +#include "test.hpp" + +namespace sem_act { + +namespace x3 = boost::spirit::x3; + +auto nop = [](auto const&){}; + +x3::rule<class used_attr1_r, int> used_attr1; +auto const used_attr1_def = used_attr::grammar[nop]; +BOOST_SPIRIT_DEFINE(used_attr1); + +x3::rule<class used_attr2_r, int> used_attr2; +auto const used_attr2_def = unused_attr::grammar[nop]; +BOOST_SPIRIT_DEFINE(used_attr2); + +x3::rule<class unused_attr1_r> unused_attr1; +auto const unused_attr1_def = used_attr::grammar[nop]; +BOOST_SPIRIT_DEFINE(unused_attr1); + +x3::rule<class unused_attr2_r> unused_attr2; +auto const unused_attr2_def = unused_attr::grammar[nop]; +BOOST_SPIRIT_DEFINE(unused_attr2); + +} + +int main() +{ + using spirit_test::test; + using spirit_test::test_attr; + + { + BOOST_TEST(test("*", unused_attr::skipper)); + BOOST_TEST(test("#", unused_attr::skipper2)); + BOOST_TEST(test("==", unused_attr::grammar)); + BOOST_TEST(test("*=*=", unused_attr::grammar, unused_attr::skipper)); + BOOST_TEST(test("#=#=", unused_attr::grammar, unused_attr::skipper2)); + } + + { + long i; + static_assert(!std::is_same<decltype(i), used_attr::grammar_type::attribute_type>::value, + "ensure we have instantiated the rule with a different attribute type"); + BOOST_TEST(test_attr("123", used_attr::grammar, i)); + BOOST_TEST_EQ(i, 123); + BOOST_TEST(test_attr(" 42", used_attr::grammar, i, used_attr::skipper)); + BOOST_TEST_EQ(i, 42); + } + + { + long i; + BOOST_TEST(test_attr("123", sem_act::used_attr1, i)); + BOOST_TEST(test_attr("===", sem_act::used_attr2, i)); + BOOST_TEST(test("123", sem_act::unused_attr1)); + BOOST_TEST(test("===", sem_act::unused_attr2)); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/rule_separate_tu_grammar.cpp b/src/boost/libs/spirit/test/x3/rule_separate_tu_grammar.cpp new file mode 100644 index 00000000..cf29fd75 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/rule_separate_tu_grammar.cpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2019 Nikita Kniazev + + Use, modification and distribution is subject to 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 "rule_separate_tu_grammar.hpp" + +#include <boost/spirit/home/x3.hpp> + +namespace unused_attr { + +const auto skipper_def = x3::lit('*'); +BOOST_SPIRIT_DEFINE(skipper) +BOOST_SPIRIT_INSTANTIATE(skipper_type, char const*, x3::unused_type) + +const auto skipper2_def = x3::lit('#'); +BOOST_SPIRIT_DEFINE(skipper2) +BOOST_SPIRIT_INSTANTIATE(skipper2_type, char const*, x3::unused_type) + +const auto grammar_def = *x3::lit('='); +BOOST_SPIRIT_DEFINE(grammar) +BOOST_SPIRIT_INSTANTIATE(grammar_type, char const*, x3::unused_type) +BOOST_SPIRIT_INSTANTIATE(grammar_type, char const*, x3::phrase_parse_context<skipper_type>::type) +BOOST_SPIRIT_INSTANTIATE(grammar_type, char const*, x3::phrase_parse_context<skipper2_type>::type) + +} + +namespace used_attr { + +const auto skipper_def = x3::space; +BOOST_SPIRIT_DEFINE(skipper) +BOOST_SPIRIT_INSTANTIATE(skipper_type, char const*, x3::unused_type) + +const auto grammar_def = x3::int_; +BOOST_SPIRIT_DEFINE(grammar) +BOOST_SPIRIT_INSTANTIATE(grammar_type, char const*, x3::unused_type) +BOOST_SPIRIT_INSTANTIATE(grammar_type, char const*, x3::phrase_parse_context<skipper_type>::type) + +} diff --git a/src/boost/libs/spirit/test/x3/rule_separate_tu_grammar.hpp b/src/boost/libs/spirit/test/x3/rule_separate_tu_grammar.hpp new file mode 100644 index 00000000..7187a36a --- /dev/null +++ b/src/boost/libs/spirit/test/x3/rule_separate_tu_grammar.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2019 Nikita Kniazev + + Use, modification and distribution is subject to 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 <boost/spirit/home/x3.hpp> + +// Check that `BOOST_SPIRIT_INSTANTIATE` instantiates `parse_rule` with proper +// types when a rule has no attribute. + +namespace unused_attr { + +namespace x3 = boost::spirit::x3; + +// skipper must has no attribute, checks `parse` and `skip_over` +using skipper_type = x3::rule<class skipper_r>; +const skipper_type skipper; +BOOST_SPIRIT_DECLARE(skipper_type) + +// the `unused_type const` must have the same effect as no attribute +using skipper2_type = x3::rule<class skipper2_r, x3::unused_type const>; +const skipper2_type skipper2; +BOOST_SPIRIT_DECLARE(skipper2_type) + +// grammar must has no attribute, checks `parse` and `phrase_parse` +using grammar_type = x3::rule<class grammar_r>; +const grammar_type grammar; +BOOST_SPIRIT_DECLARE(grammar_type) + +} + +// Check instantiation when rule has an attribute. + +namespace used_attr { + +namespace x3 = boost::spirit::x3; + +using skipper_type = x3::rule<class skipper_r>; +const skipper_type skipper; +BOOST_SPIRIT_DECLARE(skipper_type) + +using grammar_type = x3::rule<class grammar_r, int>; +const grammar_type grammar; +BOOST_SPIRIT_DECLARE(grammar_type) + +} diff --git a/src/boost/libs/spirit/test/x3/seek.cpp b/src/boost/libs/spirit/test/x3/seek.cpp new file mode 100644 index 00000000..2986a55e --- /dev/null +++ b/src/boost/libs/spirit/test/x3/seek.cpp @@ -0,0 +1,95 @@ +/*////////////////////////////////////////////////////////////////////////////// + Copyright (c) 2011 Jamboree + Copyright (c) 2014 Lee Clagett + + 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 <vector> + +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3/auxiliary/eoi.hpp> +#include <boost/spirit/home/x3/core.hpp> +#include <boost/spirit/home/x3/char.hpp> +#include <boost/spirit/home/x3/string.hpp> +#include <boost/spirit/home/x3/numeric.hpp> +#include <boost/spirit/home/x3/operator/plus.hpp> +#include <boost/spirit/home/x3/operator/sequence.hpp> + +#include <boost/spirit/home/x3/directive/seek.hpp> + +#include "test.hpp" + + +/////////////////////////////////////////////////////////////////////////////// +int main() +{ + using namespace spirit_test; + namespace x3 = boost::spirit::x3; + + // test eoi + { + BOOST_TEST(test("", x3::seek[x3::eoi])); + BOOST_TEST(test(" ", x3::seek[x3::eoi], x3::space)); + BOOST_TEST(test("a", x3::seek[x3::eoi])); + BOOST_TEST(test(" a", x3::seek[x3::eoi], x3::space)); + } + + // test literal finding + { + int i = 0; + + BOOST_TEST( + test_attr("!@#$%^&*KEY:123", x3::seek["KEY:"] >> x3::int_, i) + && i == 123 + ); + } + // test sequence finding + { + int i = 0; + + BOOST_TEST( + test_attr("!@#$%^&* KEY : 123", x3::seek[x3::lit("KEY") >> ':'] >> x3::int_, i, x3::space) + && i == 123 + ); + } + + // test attr finding + { + std::vector<int> v; + + BOOST_TEST( // expect partial match + test_attr("a06b78c3d", +x3::seek[x3::int_], v, false) + && v.size() == 3 && v[0] == 6 && v[1] == 78 && v[2] == 3 + ); + } + + // test action + { + + bool b = false; + auto const action = [&b]() { b = true; }; + + BOOST_TEST( // expect partial match + test("abcdefg", x3::seek["def"][action], false) + && b + ); + } + + // test container + { + std::vector<int> v; + + BOOST_TEST( + test_attr("abcInt:100Int:95Int:44", x3::seek[+("Int:" >> x3::int_)], v) + && v.size() == 3 && v[0] == 100 && v[1] == 95 && v[2] == 44 + ); + } + + // test failure rollback + { + BOOST_TEST(test_failure("abcdefg", x3::seek[x3::int_])); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/sequence.cpp b/src/boost/libs/spirit/test/x3/sequence.cpp new file mode 100644 index 00000000..f6559078 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/sequence.cpp @@ -0,0 +1,503 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/include/vector.hpp> +#include <boost/fusion/include/deque.hpp> +#include <boost/fusion/include/at.hpp> +#include <boost/fusion/include/comparison.hpp> + +#include <string> +#include <iostream> +#include "test.hpp" +#include "utils.hpp" + +int +main() +{ + using boost::spirit::x3::unused_type; + + using boost::spirit::x3::char_; + using boost::spirit::x3::space; + using boost::spirit::x3::string; + using boost::spirit::x3::attr; + using boost::spirit::x3::omit; + using boost::spirit::x3::lit; + using boost::spirit::x3::unused; + using boost::spirit::x3::int_; + using boost::spirit::x3::float_; + using boost::spirit::x3::no_case; + using boost::spirit::x3::rule; + using boost::spirit::x3::alnum; + + using boost::spirit::x3::traits::attribute_of; + + using boost::fusion::vector; + using boost::fusion::deque; + using boost::fusion::at_c; + + using spirit_test::test; + using spirit_test::test_attr; + + { + BOOST_TEST((test("aa", char_ >> char_))); + BOOST_TEST((test("aa", char_ >> 'a'))); + BOOST_TEST((test("aaa", char_ >> char_ >> char_('a')))); + BOOST_TEST((test("xi", char_('x') >> char_('i')))); + BOOST_TEST((!test("xi", char_('x') >> char_('o')))); + BOOST_TEST((test("xin", char_('x') >> char_('i') >> char_('n')))); + } + +#ifdef BOOST_SPIRIT_COMPILE_ERROR_CHECK + { + // Compile check only + struct x {}; + char_ >> x(); // this should give a reasonable error message + } +#endif + + { + BOOST_TEST((test(" a a", char_ >> char_, space))); + BOOST_TEST((test(" x i", char_('x') >> char_('i'), space))); + BOOST_TEST((!test(" x i", char_('x') >> char_('o'), space))); + } + + + { + BOOST_TEST((test(" Hello, World", lit("Hello") >> ',' >> "World", space))); + } + + + { + vector<char, char> attr; + BOOST_TEST((test_attr("ab", char_ >> char_, attr))); + BOOST_TEST((at_c<0>(attr) == 'a')); + BOOST_TEST((at_c<1>(attr) == 'b')); + } + +#ifdef BOOST_SPIRIT_COMPILE_ERROR_CHECK + { + // Compile check only + vector<char, char> attr; + + // error: attr does not have enough elements + test_attr("abc", char_ >> char_ >> char_, attr); + } +#endif + + { + vector<char, char, char> attr; + BOOST_TEST((test_attr(" a\n b\n c", char_ >> char_ >> char_, attr, space))); + BOOST_TEST((at_c<0>(attr) == 'a')); + BOOST_TEST((at_c<1>(attr) == 'b')); + BOOST_TEST((at_c<2>(attr) == 'c')); + } + + { + // 'b' has an unused_type. unused attributes are not part of the sequence + vector<char, char> attr; + BOOST_TEST((test_attr("abc", char_ >> 'b' >> char_, attr))); + BOOST_TEST((at_c<0>(attr) == 'a')); + BOOST_TEST((at_c<1>(attr) == 'c')); + } + + { + // 'b' has an unused_type. unused attributes are not part of the sequence + vector<char, char> attr; + BOOST_TEST((test_attr("acb", char_ >> char_ >> 'b', attr))); + BOOST_TEST((at_c<0>(attr) == 'a')); + BOOST_TEST((at_c<1>(attr) == 'c')); + } + + { + // "hello" has an unused_type. unused attributes are not part of the sequence + vector<char, char> attr; + BOOST_TEST((test_attr("a hello c", char_ >> "hello" >> char_, attr, space))); + BOOST_TEST((at_c<0>(attr) == 'a')); + BOOST_TEST((at_c<1>(attr) == 'c')); + } + + { + // a single element + char attr; + BOOST_TEST((test_attr("ab", char_ >> 'b', attr))); + BOOST_TEST((attr == 'a')); + } + + { + // a single element fusion sequence + vector<char> attr; + BOOST_TEST((test_attr("ab", char_ >> 'b', attr))); + BOOST_TEST((at_c<0>(attr) == 'a')); + } + + { + // make sure single element tuples get passed through if the rhs + // has a single element tuple as its attribute. Edit JDG 2014: + // actually he issue here is that if the rhs in this case a rule + // (r), it should get it (i.e. the sequence parser should not + // unwrap it). It's odd that the RHS (r) does not really have a + // single element tuple (it's a deque<char, int>), so the original + // comment is not accurate. + + typedef deque<char, int> attr_type; + attr_type fv; + + auto r = rule<class r, attr_type>() + = char_ >> ',' >> int_; + + BOOST_TEST((test_attr("test:x,1", "test:" >> r, fv) && + fv == attr_type('x', 1))); + } + + { + // make sure single element tuples get passed through if the rhs + // has a single element tuple as its attribute. This is a correction + // of the test above. + + typedef deque<int> attr_type; + attr_type fv; + + auto r = rule<class r, attr_type>() + = int_; + + BOOST_TEST((test_attr("test:1", "test:" >> r, fv) && + fv == attr_type(1))); + } + + { + // unused means we don't care about the attribute + BOOST_TEST((test_attr("abc", char_ >> 'b' >> char_, unused))); + } + + { + BOOST_TEST((test("aA", no_case[char_('a') >> 'a']))); + BOOST_TEST((test("BEGIN END", no_case[lit("begin") >> "end"], space))); + BOOST_TEST((!test("BEGIN END", no_case[lit("begin") >> "nend"], space))); + } + + { // check attribute is passed through unary to another sequence + using boost::spirit::x3::eps; + std::string s; + BOOST_TEST(test_attr("ab", eps >> no_case[char_ >> char_], s)); + BOOST_TEST("ab" == s); + s.clear(); + BOOST_TEST(test_attr("ab", no_case[char_ >> char_] >> eps, s)); + BOOST_TEST("ab" == s); + s.clear(); + BOOST_TEST(test_attr("abc", char_ >> no_case[char_ >> char_], s)); + BOOST_TEST("abc" == s); + s.clear(); + BOOST_TEST(test_attr("abc", no_case[char_ >> char_] >> char_, s)); + BOOST_TEST("abc" == s); + } + + { +#ifdef SPIRIT_NO_COMPILE_CHECK + char_ >> char_ = char_ >> char_; // disallow this! +#endif + } + + { // alternative forms of attributes. Allow sequences to take in + // stl containers. + + std::vector<char> v; + BOOST_TEST(test_attr("abc", char_ >> char_ >> char_, v)); + BOOST_TEST(v.size() == 3); + BOOST_TEST(v[0] == 'a'); + BOOST_TEST(v[1] == 'b'); + BOOST_TEST(v[2] == 'c'); + } + + { // alternative forms of attributes. Allow sequences to take in + // stl containers. + + std::vector<char> v; + BOOST_TEST(test_attr("a,b,c", char_ >> *(',' >> char_), v)); + BOOST_TEST(v.size() == 3); + BOOST_TEST(v[0] == 'a'); + BOOST_TEST(v[1] == 'b'); + BOOST_TEST(v[2] == 'c'); + } + + { // alternative forms of attributes. Allow sequences to take in + // stl containers. + + std::vector<char> v; + BOOST_TEST(test_attr("abc", char_ >> *char_, v)); + BOOST_TEST(v.size() == 3); + BOOST_TEST(v[0] == 'a'); + BOOST_TEST(v[1] == 'b'); + BOOST_TEST(v[2] == 'c'); + } + + { // alternative forms of attributes. Allow sequences to take in + // stl containers. + //~ using boost::spirit::x3::hold; + + std::vector<char> v; + BOOST_TEST(test_attr("abc", char_ >> *(char_ >> char_), v)); + BOOST_TEST(v.size() == 3); + BOOST_TEST(v[0] == 'a'); + BOOST_TEST(v[1] == 'b'); + BOOST_TEST(v[2] == 'c'); + + v.clear(); + BOOST_TEST(!test_attr("abcd", char_ >> *(char_ >> char_), v)); + + // $$$ hold not yet implementd $$$ + //~ v.clear(); + //~ BOOST_TEST(test_attr("abcdef", char_ >> *hold[char_ >> char_] >> char_, v)); + //~ BOOST_TEST(v.size() == 6); + //~ BOOST_TEST(v[0] == 'a'); + //~ BOOST_TEST(v[1] == 'b'); + //~ BOOST_TEST(v[2] == 'c'); + //~ BOOST_TEST(v[3] == 'd'); + //~ BOOST_TEST(v[4] == 'e'); + //~ BOOST_TEST(v[5] == 'f'); + + v.clear(); + BOOST_TEST(test_attr("abc", char_ >> +(char_ >> char_), v)); + BOOST_TEST(v.size() == 3); + BOOST_TEST(v[0] == 'a'); + BOOST_TEST(v[1] == 'b'); + BOOST_TEST(v[2] == 'c'); + } + + { // alternative forms of attributes. Allow sequences to take in + // stl containers. + + std::vector<char> v; + BOOST_TEST(test_attr("abc", char_ >> -(+char_), v)); + BOOST_TEST(v.size() == 3); + BOOST_TEST(v[0] == 'a'); + BOOST_TEST(v[1] == 'b'); + BOOST_TEST(v[2] == 'c'); + } + + { // alternative forms of attributes. Allow sequences to take in + // stl containers. + + std::string s; + BOOST_TEST(test_attr("foobar", string("foo") >> string("bar"), s)); + BOOST_TEST(s == "foobar"); + + s.clear(); + + // $$$ hold not yet implemented $$$ + //~ using boost::spirit::x3::hold; + + //~ rule<char const*, std::string()> word = +char_("abc"); + //~ BOOST_TEST(test_attr("ab.bc.ca", *hold[word >> string(".")] >> word, s)); + //~ BOOST_TEST(s == "ab.bc.ca"); + } + + // Make sure get_sequence_types works for sequences of sequences. + { + std::vector<char> v; + BOOST_TEST(test_attr(" a b", (' ' >> char_) >> (' ' >> char_), v)); + BOOST_TEST(v.size() == 2); + BOOST_TEST(v[0] == 'a'); + BOOST_TEST(v[1] == 'b'); + } + + // alternative forms of attributes. Allow sequences to take in + // stl containers of stl containers. + { + std::vector<std::string> v; + BOOST_TEST(test_attr("abc1,abc2", + *~char_(',') >> *(',' >> *~char_(',')), v)); + BOOST_TEST(v.size() == 2 && v[0] == "abc1" && v[1] == "abc2"); + } + + { + std::vector<std::string> v; + + auto e = rule<class e, std::string>() + = *~char_(','); + + auto l = rule<class l, std::vector<std::string>>() + = e >> *(',' >> e); + + BOOST_TEST(test_attr("abc1,abc2,abc3", l, v)); + BOOST_TEST(v.size() == 3); + BOOST_TEST(v[0] == "abc1"); + BOOST_TEST(v[1] == "abc2"); + BOOST_TEST(v[2] == "abc3"); + } + + // do the same with a plain string object + { + std::string s; + BOOST_TEST(test_attr("abc1,abc2", + *~char_(',') >> *(',' >> *~char_(',')), s)); + BOOST_TEST(s == "abc1abc2"); + } + + { + std::string s; + auto e = rule<class e, std::string>() + = *~char_(','); + + auto l = rule<class l, std::string>() + = e >> *(',' >> e); + + BOOST_TEST(test_attr("abc1,abc2,abc3", l, s)); + BOOST_TEST(s == "abc1abc2abc3"); + } + + { + std::vector<char> v; + BOOST_TEST(test_attr("ab", char_ >> -char_, v)); + BOOST_TEST(v.size() == 2 && v[0] == 'a' && v[1] == 'b'); + + v.clear(); + BOOST_TEST(test_attr("a", char_ >> -char_, v)); + BOOST_TEST(v.size() == 1 && v[0] == 'a'); + + // $$$ should this be allowed? I don't think so... $$$ + //~ v.clear(); + //~ BOOST_TEST(test_attr("a", char_, v)); + //~ BOOST_TEST(v.size() == 1 && v[0] == 'a'); + } + + { + std::vector<boost::optional<char>> v; + BOOST_TEST(test_attr("ab", char_ >> -char_, v)); + BOOST_TEST(v.size() == 2 && v[0] == 'a' && v[1] == 'b'); + + v.clear(); + BOOST_TEST(test_attr("a", char_ >> -char_, v)); + BOOST_TEST(v.size() == 2 && v[0] == 'a' && !v[1]); + + // $$$ should this be allowed? I don't think so... $$$ + //~ v.clear(); + //~ BOOST_TEST(test_attr("a", char_, v)); + //~ BOOST_TEST(v.size() == 1 && v[0] == 'a'); + } + + // test from spirit mailing list + // "Optional operator causes string attribute concatenation" + { + typedef vector<char, char, int> attr_type; + attr_type attr; + + auto node = alnum >> -('[' >> alnum >> '=' >> int_ >> ']'); + + BOOST_TEST(test_attr("x[y=123]", node, attr)); + BOOST_TEST(attr == attr_type('x', 'y', 123)); + } + + // test from spirit mailing list (variation of above) + // "Optional operator causes string attribute concatenation" + { + typedef vector<std::string, std::string, int> attr_type; + attr_type attr; + + auto node = +alnum >> -('[' >> +alnum >> '=' >> int_ >> ']'); + + BOOST_TEST(test_attr("xxx[yyy=123]", node, attr)); + BOOST_TEST(attr == attr_type("xxx", "yyy", 123)); + } + + // test from spirit mailing list + // "Error with container within sequence" + { + typedef vector<std::string> attr_type; + attr_type attr; + + auto r = *alnum; + + BOOST_TEST(test_attr("abcdef", r, attr)); + BOOST_TEST(at_c<0>(attr) == "abcdef"); + } + + // test from spirit mailing list (variation of above) + // "Error with container within sequence" + { + typedef vector<std::vector<int>> attr_type; + attr_type attr; + + auto r = *int_; + + BOOST_TEST(test_attr("123 456", r, attr, space)); + BOOST_TEST(at_c<0>(attr).size() == 2); + BOOST_TEST(at_c<0>(attr)[0] == 123); + BOOST_TEST(at_c<0>(attr)[1] == 456); + } + + { + using Attr = boost::variant<int, float>; + Attr attr; + auto const term = rule<class term, Attr>("term") = int_ | float_; + auto const expr = rule<class expr, Attr>("expr") = term | ('(' > term > ')'); + BOOST_TEST((test_attr("(1)", expr, attr, space))); + } + + // test that failing sequence leaves attribute consistent + { + std::string attr; + //no need to use omit[], but lit() is buggy ATM + BOOST_TEST(test_attr("A\nB\nC", *(char_ >> omit[lit("\n")]), attr, false)); + BOOST_TEST(attr == "AB"); + } + + // test that sequence with only one parser producing attribute + // makes it unwrapped + { + BOOST_TEST((boost::is_same< + typename attribute_of<decltype(lit("abc") >> attr(long())), unused_type>::type, + long>() )); + } + + { // test action + using boost::fusion::at_c; + + char c = 0; + int n = 0; + auto f = [&](auto& ctx) + { + c = at_c<0>(_attr(ctx)); + n = at_c<1>(_attr(ctx)); + }; + + BOOST_TEST(test("x123\"a string\"", (char_ >> int_ >> "\"a string\"")[f])); + BOOST_TEST(c == 'x'); + BOOST_TEST(n == 123); + } + + { // test action + char c = 0; + int n = 0; + auto f = [&](auto& ctx) + { + c = at_c<0>(_attr(ctx)); + n = at_c<1>(_attr(ctx)); + }; + + BOOST_TEST(test("x 123 \"a string\"", (char_ >> int_ >> "\"a string\"")[f], space)); + BOOST_TEST(c == 'x'); + BOOST_TEST(n == 123); + } + + { +#ifdef SPIRIT_NO_COMPILE_CHECK + char const* const s = ""; + int i; + parse(s, s, int_ >> int_, i); +#endif + } + + { // test move only types + using boost::spirit::x3::eps; + std::vector<move_only> v; + BOOST_TEST(test_attr("ssszs", *synth_move_only >> 'z' >> synth_move_only, v)); + BOOST_TEST_EQ(v.size(), 4); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/skip.cpp b/src/boost/libs/spirit/test/x3/skip.cpp new file mode 100644 index 00000000..3a201408 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/skip.cpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + Copyright (c) 2013 Agustin Berge + + 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 <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + using boost::spirit::x3::ascii::space; + using boost::spirit::x3::ascii::space_type; + using boost::spirit::x3::ascii::char_; + using boost::spirit::x3::ascii::alpha; + using boost::spirit::x3::lexeme; + using boost::spirit::x3::skip; + using boost::spirit::x3::lit; + + { + BOOST_TEST((test("a b c d", skip(space)[*char_]))); + } + + { // test attribute + std::string s; + BOOST_TEST((test_attr("a b c d", skip(space)[*char_], s))); + BOOST_TEST(s == "abcd"); + } + + { // reskip + BOOST_TEST((test("ab c d", lexeme[lit('a') >> 'b' >> skip[lit('c') >> 'd']], space))); + BOOST_TEST((test("abcd", lexeme[lit('a') >> 'b' >> skip[lit('c') >> 'd']], space))); + BOOST_TEST(!(test("a bcd", lexeme[lit('a') >> 'b' >> skip[lit('c') >> 'd']], space))); + + BOOST_TEST((test("ab c d", lexeme[lexeme[lit('a') >> 'b' >> skip[lit('c') >> 'd']]], space))); + BOOST_TEST((test("abcd", lexeme[lexeme[lit('a') >> 'b' >> skip[lit('c') >> 'd']]], space))); + BOOST_TEST(!(test("a bcd", lexeme[lexeme[lit('a') >> 'b' >> skip[lit('c') >> 'd']]], space))); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/symbols1.cpp b/src/boost/libs/spirit/test/x3/symbols1.cpp new file mode 100644 index 00000000..38771e45 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/symbols1.cpp @@ -0,0 +1,187 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <iostream> +#include "test.hpp" + +// Custom string type with a C-style string conversion. +struct custom_string_c +{ + custom_string_c(char c) { str[0] = c; str[1] = '\0'; } + + operator char*() { return str; } + operator char const*() const { return str; } + +private: + char str[2]; +}; + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + using boost::spirit::x3::symbols; + using boost::spirit::x3::no_case; + + { // basics + symbols<int> sym; + + sym.add + ("Joel") + ("Ruby") + ("Tenji") + ("Tutit") + ("Kim") + ("Joey") + ("Joeyboy") + ; + + BOOST_TEST((test("Joel", sym))); + BOOST_TEST((test("Ruby", sym))); + BOOST_TEST((test("Tenji", sym))); + BOOST_TEST((test("Tutit", sym))); + BOOST_TEST((test("Kim", sym))); + BOOST_TEST((test("Joey", sym))); + BOOST_TEST((test("Joeyboy", sym))); + BOOST_TEST((!test("XXX", sym))); + + // test copy + symbols<int> sym2; + sym2 = sym; + BOOST_TEST((test("Joel", sym2))); + BOOST_TEST((test("Ruby", sym2))); + BOOST_TEST((test("Tenji", sym2))); + BOOST_TEST((test("Tutit", sym2))); + BOOST_TEST((test("Kim", sym2))); + BOOST_TEST((test("Joey", sym2))); + BOOST_TEST((!test("XXX", sym2))); + + // make sure it plays well with other parsers + BOOST_TEST((test("Joelyo", sym >> "yo"))); + + sym.remove + ("Joel") + ("Ruby") + ; + + BOOST_TEST((!test("Joel", sym))); + BOOST_TEST((!test("Ruby", sym))); + } + + { // comma syntax + symbols<int> sym; + sym += "Joel", "Ruby", "Tenji", "Tutit", "Kim", "Joey"; + + BOOST_TEST((test("Joel", sym))); + BOOST_TEST((test("Ruby", sym))); + BOOST_TEST((test("Tenji", sym))); + BOOST_TEST((test("Tutit", sym))); + BOOST_TEST((test("Kim", sym))); + BOOST_TEST((test("Joey", sym))); + BOOST_TEST((!test("XXX", sym))); + + sym -= "Joel", "Ruby"; + + BOOST_TEST((!test("Joel", sym))); + BOOST_TEST((!test("Ruby", sym))); + } + + { // no-case handling + using namespace boost::spirit::x3::ascii; + + symbols<int> sym; + // NOTE: make sure all entries are in lower-case!!! + sym = "joel", "ruby", "tenji", "tutit", "kim", "joey"; + + BOOST_TEST((test("joel", no_case[sym]))); + BOOST_TEST((test("ruby", no_case[sym]))); + BOOST_TEST((test("tenji", no_case[sym]))); + BOOST_TEST((test("tutit", no_case[sym]))); + BOOST_TEST((test("kim", no_case[sym]))); + BOOST_TEST((test("joey", no_case[sym]))); + + BOOST_TEST((test("JOEL", no_case[sym]))); + BOOST_TEST((test("RUBY", no_case[sym]))); + BOOST_TEST((test("TENJI", no_case[sym]))); + BOOST_TEST((test("TUTIT", no_case[sym]))); + BOOST_TEST((test("KIM", no_case[sym]))); + BOOST_TEST((test("JOEY", no_case[sym]))); + + // make sure it plays well with other parsers + BOOST_TEST((test("Joelyo", no_case[sym] >> "yo"))); + } + + { // attributes + symbols<int> sym; + + sym.add + ("Joel", 1) + ("Ruby", 2) + ("Tenji", 3) + ("Tutit", 4) + ("Kim", 5) + ("Joey", 6) + ; + + int i; + BOOST_TEST((test_attr("Joel", sym, i))); + BOOST_TEST(i == 1); + BOOST_TEST((test_attr("Ruby", sym, i))); + BOOST_TEST(i == 2); + BOOST_TEST((test_attr("Tenji", sym, i))); + BOOST_TEST(i == 3); + BOOST_TEST((test_attr("Tutit", sym, i))); + BOOST_TEST(i == 4); + BOOST_TEST((test_attr("Kim", sym, i))); + BOOST_TEST(i == 5); + BOOST_TEST((test_attr("Joey", sym, i))); + BOOST_TEST(i == 6); + BOOST_TEST((!test_attr("XXX", sym, i))); + + // double add: + + sym.add("Joel", 265); + BOOST_TEST((test_attr("Joel", sym, i))); + BOOST_TEST(i == 1); + } + + { // actions + using boost::spirit::x3::_attr; + + symbols<int> sym; + sym.add + ("Joel", 1) + ("Ruby", 2) + ("Tenji", 3) + ("Tutit", 4) + ("Kim", 5) + ("Joey", 6) + ; + + int i; + auto f = [&](auto& ctx){ i = _attr(ctx); }; + + BOOST_TEST((test("Joel", sym[f]))); + BOOST_TEST(i == 1); + BOOST_TEST((test("Ruby", sym[f]))); + BOOST_TEST(i == 2); + BOOST_TEST((test("Tenji", sym[f]))); + BOOST_TEST(i == 3); + BOOST_TEST((test("Tutit", sym[f]))); + BOOST_TEST(i == 4); + BOOST_TEST((test("Kim", sym[f]))); + BOOST_TEST(i == 5); + BOOST_TEST((test("Joey", sym[f]))); + BOOST_TEST(i == 6); + BOOST_TEST((!test("XXX", sym[f]))); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/symbols2.cpp b/src/boost/libs/spirit/test/x3/symbols2.cpp new file mode 100644 index 00000000..f401dc14 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/symbols2.cpp @@ -0,0 +1,202 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <iostream> +#include "test.hpp" + +// Custom string type with a C-style string conversion. +struct custom_string_c +{ + custom_string_c(char c) { str[0] = c; str[1] = '\0'; } + + operator char*() { return str; } + operator char const*() const { return str; } + +private: + char str[2]; +}; + +std::string get_str(char const* str) +{ + return std::string(str); +} + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + using boost::spirit::x3::symbols; + using boost::spirit::x3::rule; + + { // construction from symbol array + char const* syms[] = {"Joel","Ruby","Tenji","Tutit","Kim","Joey"}; + symbols<int> sym(syms); + + BOOST_TEST((test("Joel", sym))); + BOOST_TEST((test("Ruby", sym))); + BOOST_TEST((test("Tenji", sym))); + BOOST_TEST((test("Tutit", sym))); + BOOST_TEST((test("Kim", sym))); + BOOST_TEST((test("Joey", sym))); + BOOST_TEST((!test("XXX", sym))); + } + + { // construction from 2 arrays + + char const* syms[] = {"Joel","Ruby","Tenji","Tutit","Kim","Joey"}; + int data[] = {1,2,3,4,5,6}; + symbols<int> sym(syms, data); + + int i; + BOOST_TEST((test_attr("Joel", sym, i))); + BOOST_TEST(i == 1); + BOOST_TEST((test_attr("Ruby", sym, i))); + BOOST_TEST(i == 2); + BOOST_TEST((test_attr("Tenji", sym, i))); + BOOST_TEST(i == 3); + BOOST_TEST((test_attr("Tutit", sym, i))); + BOOST_TEST(i == 4); + BOOST_TEST((test_attr("Kim", sym, i))); + BOOST_TEST(i == 5); + BOOST_TEST((test_attr("Joey", sym, i))); + BOOST_TEST(i == 6); + BOOST_TEST((!test_attr("XXX", sym, i))); + } + + { // allow std::string and other string types + symbols<> sym; + + // const and non-const std::string + std::string a("abc"); + std::string const b("def"); + sym += a; + sym += b; + BOOST_TEST((test("abc", sym))); + BOOST_TEST((test("def", sym))); + sym = a; + BOOST_TEST((test("abc", sym))); + BOOST_TEST((!test("def", sym))); + + // non-const C-style string + char arr[2]; arr[0] = 'a'; arr[1] = '\0'; + sym = arr; + BOOST_TEST((test("a", sym))); + BOOST_TEST((!test("b", sym))); + + // const and non-const custom string type + custom_string_c c('x'); + custom_string_c const cc('y'); + sym = c, cc; + BOOST_TEST((test("x", sym))); + BOOST_TEST((test("y", sym))); + BOOST_TEST((!test("z", sym))); + } + + { // find + + symbols<int> sym; + sym.add("a", 1)("b", 2); + + BOOST_TEST(!sym.find("c")); + + BOOST_TEST(sym.find("a") && *sym.find("a") == 1); + BOOST_TEST(sym.find("b") && *sym.find("b") == 2); + + BOOST_TEST(sym.at("a") == 1); + BOOST_TEST(sym.at("b") == 2); + BOOST_TEST(sym.at("c") == 0); + + BOOST_TEST(sym.find("a") && *sym.find("a") == 1); + BOOST_TEST(sym.find("b") && *sym.find("b") == 2); + BOOST_TEST(sym.find("c") && *sym.find("c") == 0); + + symbols<int> const_sym(sym); + + BOOST_TEST(const_sym.find("a") && *const_sym.find("a") == 1); + BOOST_TEST(const_sym.find("b") && *const_sym.find("b") == 2); + BOOST_TEST(const_sym.find("c") && *const_sym.find("c") == 0); + BOOST_TEST(!const_sym.find("d")); + + char const *str1 = "all"; + char const *first = str1, *last = str1 + 3; + BOOST_TEST(*sym.prefix_find(first, last) == 1 && first == str1 + 1); + + char const *str2 = "dart"; + first = str2; last = str2 + 4; + BOOST_TEST(!sym.prefix_find(first, last) && first == str2); + } + + { // name + symbols <int> sym,sym2; + sym.name("test"); + BOOST_TEST(sym.name()=="test"); + sym2 = sym; + BOOST_TEST(sym2.name()=="test"); + + symbols <int> sym3(sym); + BOOST_TEST(sym3.name()=="test"); + } + + { // Substrings + + symbols<int> sym; + BOOST_TEST(sym.at("foo") == 0); + sym.at("foo") = 1; + BOOST_TEST(sym.at("foo") == 1); + BOOST_TEST(sym.at("fool") == 0); + sym.at("fool") = 2; + BOOST_TEST(sym.find("foo") && *sym.find("foo") == 1); + BOOST_TEST(sym.find("fool") && *sym.find("fool") == 2); + BOOST_TEST(!sym.find("foolish")); + BOOST_TEST(!sym.find("foot")); + BOOST_TEST(!sym.find("afoot")); + + char const *str, *first, *last; + str = "foolish"; first = str; last = str + 7; + BOOST_TEST(*sym.prefix_find(first, last) == 2 && first == str + 4); + + first = str; last = str + 4; + BOOST_TEST(*sym.prefix_find(first, last) == 2 && first == str + 4); + + str = "food"; first = str; last = str + 4; + BOOST_TEST(*sym.prefix_find(first, last) == 1 && first == str + 3); + + first = str; last = str + 3; + BOOST_TEST(*sym.prefix_find(first, last) == 1 && first == str + 3); + + first = str; last = str + 2; + BOOST_TEST(!sym.prefix_find(first, last) && first == str); + } + + { + // remove bug + + std::string s; + symbols<double> vars; + + vars.add("l1", 12.0); + vars.add("l2", 0.0); + vars.remove("l2"); + vars.find("l1"); + double* d = vars.find("l1"); + BOOST_TEST(d != 0); + } + + { // test for proto problem with rvalue references (10-11-2011) + symbols<int> sym; + sym += get_str("Joel"); + sym += get_str("Ruby"); + + BOOST_TEST((test("Joel", sym))); + BOOST_TEST((test("Ruby", sym))); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/symbols3.cpp b/src/boost/libs/spirit/test/x3/symbols3.cpp new file mode 100644 index 00000000..d732ca3d --- /dev/null +++ b/src/boost/libs/spirit/test/x3/symbols3.cpp @@ -0,0 +1,86 @@ +/*============================================================================= + Copyright (c) 2013 Carl Barron + Copyright (c) 2015 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) +=============================================================================*/ + +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/fusion/include/at.hpp> +#include <boost/fusion/include/vector.hpp> +#include <boost/fusion/include/adapt_struct.hpp> +#include <boost/mpl/int.hpp> +#include <boost/optional.hpp> + +#include <iostream> +#include <numeric> +#include <vector> +#include "test.hpp" + +struct roman +{ + boost::optional<int> a; + boost::optional<int> b; + boost::optional<int> c; +}; + +BOOST_FUSION_ADAPT_STRUCT(roman, + a, b, c +) + +int eval(roman const & c) +{ + return c.a.get_value_or(0) + c.b.get_value_or(0) + c.c.get_value_or(0); +} + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + using boost::spirit::x3::symbols; + + { // construction from initializer-list + symbols<int> const ones = + { + {"I", 1}, {"II", 2}, {"III", 3}, {"IV", 4}, + {"V", 5}, {"VI", 6}, {"VII", 7}, {"VIII", 8}, + {"IX", 9} + }; + symbols<int> const tens = + { + {"X", 10}, {"XX", 20}, {"XXX", 30}, {"XL", 40}, + {"L", 50}, {"LX", 60}, {"LXX", 70}, {"LXXX", 80}, + {"XC", 90} + }; + symbols<int> const hundreds + { + {"C", 100}, {"CC", 200}, {"CCC", 300}, {"CD", 400}, + {"D", 500}, {"DC", 600}, {"DCC", 700}, {"DCCC", 800}, + {"CM", 900} + }; + + auto number = -hundreds >> -tens >> -ones; + + roman r; + BOOST_TEST((test_attr("CDXLII", number, r))); + BOOST_TEST(eval(r) == 442); + } + + { // construction from initializer-list without attribute + symbols<> foo = {"a1", "a2", "a3"}; + + BOOST_TEST((test("a3", foo))); + } + + { // assignment from initializer-list + symbols<> foo; + foo = {"a1", "a2", "a3"}; + + BOOST_TEST((test("a3", foo))); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/test.hpp b/src/boost/libs/spirit/test/x3/test.hpp new file mode 100644 index 00000000..af1c22ee --- /dev/null +++ b/src/boost/libs/spirit/test/x3/test.hpp @@ -0,0 +1,125 @@ +/*============================================================================= + Copyright (c) 2001-2013 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) +=============================================================================*/ +#if !defined(BOOST_SPIRIT_TEST_FEBRUARY_01_2007_0605PM) +#define BOOST_SPIRIT_TEST_FEBRUARY_01_2007_0605PM + +#include <boost/spirit/home/x3/core/parse.hpp> +#include <boost/utility/string_view.hpp> +#include <iostream> + +namespace spirit_test +{ + template <typename Char, typename Parser> + bool test(Char const* in, Parser const& p, bool full_match = true) + { + Char const* last = in; + while (*last) + last++; + return boost::spirit::x3::parse(in, last, p) + && (!full_match || (in == last)); + } + + template <typename Char, typename Parser> + bool test(boost::basic_string_view<Char, std::char_traits<Char>> in, + Parser const& p, bool full_match = true) + { + auto const last = in.end(); + auto pos = in.begin(); + + return boost::spirit::x3::parse(pos, last, p) && (!full_match || (pos == last)); + } + + template <typename Char, typename Parser, typename Skipper> + bool test(Char const* in, Parser const& p + , Skipper const& s, bool full_match = true) + { + Char const* last = in; + while (*last) + last++; + return boost::spirit::x3::phrase_parse(in, last, p, s) + && (!full_match || (in == last)); + } + + template <typename Char, typename Parser> + bool test_failure(Char const* in, Parser const& p) + { + Char const * const start = in; + Char const* last = in; + while (*last) + last++; + + return !boost::spirit::x3::parse(in, last, p) && (in == start); + } + + template <typename Char, typename Parser> + bool test_failure(boost::basic_string_view<Char, std::char_traits<Char>> const in, + Parser const& p) + { + auto pos = in.begin(); + return !boost::spirit::x3::parse(pos, in.end(), p) && (pos == in.begin()); + } + + template <typename Char, typename Parser, typename Attr> + bool test_attr(Char const* in, Parser const& p + , Attr& attr, bool full_match = true) + { + Char const* last = in; + while (*last) + last++; + return boost::spirit::x3::parse(in, last, p, attr) + && (!full_match || (in == last)); + } + + template <typename Char, typename Parser, typename Attr, typename Skipper> + bool test_attr(Char const* in, Parser const& p + , Attr& attr, Skipper const& s, bool full_match = true) + { + Char const* last = in; + while (*last) + last++; + return boost::spirit::x3::phrase_parse(in, last, p, s, attr) + && (!full_match || (in == last)); + } + + template <typename Char, typename Parser> + bool binary_test(Char const* in, std::size_t size, Parser const& p, + bool full_match = true) + { + Char const* last = in + size; + return boost::spirit::x3::parse(in, last, p) + && (!full_match || (in == last)); + } + + template <typename Char, typename Parser, typename Skipper> + bool binary_test(Char const* in, std::size_t size, Parser const& p, + Skipper const& s, bool full_match = true) + { + Char const* last = in + size; + return boost::spirit::x3::phrase_parse(in, last, p, s) + && (!full_match || (in == last)); + } + + template <typename Char, typename Parser, typename Attr> + bool binary_test_attr(Char const* in, std::size_t size, Parser const& p, + Attr& attr, bool full_match = true) + { + Char const* last = in + size; + return boost::spirit::x3::parse(in, last, p, attr) + && (!full_match || (in == last)); + } + + template <typename Char, typename Parser, typename Attr, typename Skipper> + bool binary_test_attr(Char const* in, std::size_t size, Parser const& p, + Attr& attr, Skipper const& s, bool full_match = true) + { + Char const* last = in + size; + return boost::spirit::x3::phrase_parse(in, last, p, s, attr) + && (!full_match || (in == last)); + } +} + +#endif diff --git a/src/boost/libs/spirit/test/x3/to_utf8.cpp b/src/boost/libs/spirit/test/x3/to_utf8.cpp new file mode 100644 index 00000000..9974e8b2 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/to_utf8.cpp @@ -0,0 +1,28 @@ +/*============================================================================= + Copyright (c) 2018 Nikita Kniazev + + 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 <boost/core/lightweight_test.hpp> +#include <boost/spirit/home/x3/support/utility/utf8.hpp> + +int main() +{ + using boost::spirit::x3::to_utf8; + + // Assume wchar_t is 16-bit on Windows and 32-bit on Unix +#if defined(_WIN32) || defined(__CYGWIN__) + BOOST_TEST_CSTR_EQ("\xEF\xBF\xA1", to_utf8(L'\uFFE1').c_str()); +#else + BOOST_TEST_CSTR_EQ("\xF0\x9F\xA7\x90", to_utf8(L'\U0001F9D0').c_str()); +#endif + + BOOST_TEST_CSTR_EQ("\xF0\x9F\xA7\x90\xF0\x9F\xA7\xA0", + to_utf8(L"\U0001F9D0\U0001F9E0").c_str()); + + BOOST_TEST_CSTR_EQ("\xF0\x9F\xA7\x90\xF0\x9F\xA7\xA0", + to_utf8(std::wstring(L"\U0001F9D0\U0001F9E0")).c_str()); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/tst.cpp b/src/boost/libs/spirit/test/x3/tst.cpp new file mode 100644 index 00000000..abe19a59 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/tst.cpp @@ -0,0 +1,337 @@ +/*============================================================================= + Copyright (c) 2001-2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3/string/tst.hpp> +#include <boost/spirit/home/x3/string/tst_map.hpp> +#include <boost/spirit/home/x3/support/no_case.hpp> +#include <boost/spirit/home/support/char_encoding/standard.hpp> +#include <boost/spirit/home/support/char_encoding/standard_wide.hpp> +#include <string> +#include <cctype> +#include <iostream> + +namespace +{ + template <typename TST, typename Char> + void add(TST& tst, Char const* s, int data) + { + Char const* last = s; + while (*last) + last++; + tst.add(s, last, data); + } + + template <typename TST, typename Char> + void remove(TST& tst, Char const* s) + { + Char const* last = s; + while (*last) + last++; + tst.remove(s, last); + } + + template <typename TST, typename Char, typename CaseCompare> + void docheck(TST const& tst, CaseCompare const& comp, Char const* s, bool expected, int N = 0, int val = -1) + { + Char const* first = s; + Char const* last = s; + while (*last) + last++; + int* r = tst.find(s, last,comp); + BOOST_TEST((r != 0) == expected); + if (r != 0) + BOOST_TEST((s-first) == N); + if (r) + BOOST_TEST(*r == val); + } + + struct printer + { + template <typename String, typename Data> + void operator()(String const& s, Data const& data) + { + std::cout << " " << s << ": " << data << std::endl; + } + }; + + template <typename TST> + void print(TST const& tst) + { + std::cout << '[' << std::endl; + tst.for_each(printer()); + std::cout << ']' << std::endl; + } + +} + +boost::spirit::x3::case_compare<boost::spirit::char_encoding::standard> ncomp; +boost::spirit::x3::case_compare<boost::spirit::char_encoding::standard_wide> wcomp; +boost::spirit::x3::no_case_compare<boost::spirit::char_encoding::standard> nc_ncomp; +boost::spirit::x3::no_case_compare<boost::spirit::char_encoding::standard_wide> nc_wcomp; + +template <typename Lookup, typename WideLookup> +void tests() +{ + { // basic tests + Lookup lookup; + + docheck(lookup, ncomp, "not-yet-there", false); + docheck(lookup, ncomp, "", false); + + add(lookup, "apple", 123); + docheck(lookup, ncomp, "apple", true, 5, 123); // full match + docheck(lookup, ncomp, "banana", false); // no-match + docheck(lookup, ncomp, "applexxx", true, 5, 123); // partial match + + add(lookup, "applepie", 456); + docheck(lookup, ncomp, "applepie", true, 8, 456); // full match + docheck(lookup, ncomp, "banana", false); // no-match + docheck(lookup, ncomp, "applepiexxx", true, 8, 456); // partial match + docheck(lookup, ncomp, "apple", true, 5, 123); // full match + docheck(lookup, ncomp, "applexxx", true, 5, 123); // partial match + } + + { // variation of above + Lookup lookup; + + add(lookup, "applepie", 456); + add(lookup, "apple", 123); + + docheck(lookup, ncomp, "applepie", true, 8, 456); // full match + docheck(lookup, ncomp, "banana", false); // no-match + docheck(lookup, ncomp, "applepiexxx", true, 8, 456); // partial match + docheck(lookup, ncomp, "apple", true, 5, 123); // full match + docheck(lookup, ncomp, "applexxx", true, 5, 123); // partial match + } + { // variation of above + Lookup lookup; + + add(lookup, "applepie", 456); + add(lookup, "apple", 123); + + docheck(lookup, ncomp, "applepie", true, 8, 456); // full match + docheck(lookup, ncomp, "banana", false); // no-match + docheck(lookup, ncomp, "applepiexxx", true, 8, 456); // partial match + docheck(lookup, ncomp, "apple", true, 5, 123); // full match + docheck(lookup, ncomp, "applexxx", true, 5, 123); // partial match + } + + { // narrow char tests + Lookup lookup; + add(lookup, "pineapple", 1); + add(lookup, "orange", 2); + add(lookup, "banana", 3); + add(lookup, "applepie", 4); + add(lookup, "apple", 5); + + docheck(lookup, ncomp, "pineapple", true, 9, 1); + docheck(lookup, ncomp, "orange", true, 6, 2); + docheck(lookup, ncomp, "banana", true, 6, 3); + docheck(lookup, ncomp, "apple", true, 5, 5); + docheck(lookup, ncomp, "pizza", false); + docheck(lookup, ncomp, "steak", false); + docheck(lookup, ncomp, "applepie", true, 8, 4); + docheck(lookup, ncomp, "bananarama", true, 6, 3); + docheck(lookup, ncomp, "applet", true, 5, 5); + docheck(lookup, ncomp, "applepi", true, 5, 5); + docheck(lookup, ncomp, "appl", false); + + docheck(lookup, ncomp, "pineapplez", true, 9, 1); + docheck(lookup, ncomp, "orangez", true, 6, 2); + docheck(lookup, ncomp, "bananaz", true, 6, 3); + docheck(lookup, ncomp, "applez", true, 5, 5); + docheck(lookup, ncomp, "pizzaz", false); + docheck(lookup, ncomp, "steakz", false); + docheck(lookup, ncomp, "applepiez", true, 8, 4); + docheck(lookup, ncomp, "bananaramaz", true, 6, 3); + docheck(lookup, ncomp, "appletz", true, 5, 5); + docheck(lookup, ncomp, "applepix", true, 5, 5); + } + + { // wide char tests + WideLookup lookup; + add(lookup, L"pineapple", 1); + add(lookup, L"orange", 2); + add(lookup, L"banana", 3); + add(lookup, L"applepie", 4); + add(lookup, L"apple", 5); + + docheck(lookup, wcomp, L"pineapple", true, 9, 1); + docheck(lookup, wcomp, L"orange", true, 6, 2); + docheck(lookup, wcomp, L"banana", true, 6, 3); + docheck(lookup, wcomp, L"apple", true, 5, 5); + docheck(lookup, wcomp, L"pizza", false); + docheck(lookup, wcomp, L"steak", false); + docheck(lookup, wcomp, L"applepie", true, 8, 4); + docheck(lookup, wcomp, L"bananarama", true, 6, 3); + docheck(lookup, wcomp, L"applet", true, 5, 5); + docheck(lookup, wcomp, L"applepi", true, 5, 5); + docheck(lookup, wcomp, L"appl", false); + + docheck(lookup, wcomp, L"pineapplez", true, 9, 1); + docheck(lookup, wcomp, L"orangez", true, 6, 2); + docheck(lookup, wcomp, L"bananaz", true, 6, 3); + docheck(lookup, wcomp, L"applez", true, 5, 5); + docheck(lookup, wcomp, L"pizzaz", false); + docheck(lookup, wcomp, L"steakz", false); + docheck(lookup, wcomp, L"applepiez", true, 8, 4); + docheck(lookup, wcomp, L"bananaramaz", true, 6, 3); + docheck(lookup, wcomp, L"appletz", true, 5, 5); + docheck(lookup, wcomp, L"applepix", true, 5, 5); + } + + { // test remove + Lookup lookup; + add(lookup, "pineapple", 1); + add(lookup, "orange", 2); + add(lookup, "banana", 3); + add(lookup, "applepie", 4); + add(lookup, "apple", 5); + + docheck(lookup, ncomp, "pineapple", true, 9, 1); + docheck(lookup, ncomp, "orange", true, 6, 2); + docheck(lookup, ncomp, "banana", true, 6, 3); + docheck(lookup, ncomp, "apple", true, 5, 5); + docheck(lookup, ncomp, "applepie", true, 8, 4); + docheck(lookup, ncomp, "bananarama", true, 6, 3); + docheck(lookup, ncomp, "applet", true, 5, 5); + docheck(lookup, ncomp, "applepi", true, 5, 5); + docheck(lookup, ncomp, "appl", false); + + remove(lookup, "banana"); + docheck(lookup, ncomp, "pineapple", true, 9, 1); + docheck(lookup, ncomp, "orange", true, 6, 2); + docheck(lookup, ncomp, "banana", false); + docheck(lookup, ncomp, "apple", true, 5, 5); + docheck(lookup, ncomp, "applepie", true, 8, 4); + docheck(lookup, ncomp, "bananarama", false); + docheck(lookup, ncomp, "applet", true, 5, 5); + docheck(lookup, ncomp, "applepi", true, 5, 5); + docheck(lookup, ncomp, "appl", false); + + remove(lookup, "apple"); + docheck(lookup, ncomp, "pineapple", true, 9, 1); + docheck(lookup, ncomp, "orange", true, 6, 2); + docheck(lookup, ncomp, "apple", false); + docheck(lookup, ncomp, "applepie", true, 8, 4); + docheck(lookup, ncomp, "applet", false); + docheck(lookup, ncomp, "applepi", false); + docheck(lookup, ncomp, "appl", false); + + remove(lookup, "orange"); + docheck(lookup, ncomp, "pineapple", true, 9, 1); + docheck(lookup, ncomp, "orange", false); + docheck(lookup, ncomp, "applepie", true, 8, 4); + + remove(lookup, "pineapple"); + docheck(lookup, ncomp, "pineapple", false); + docheck(lookup, ncomp, "orange", false); + docheck(lookup, ncomp, "applepie", true, 8, 4); + + remove(lookup, "applepie"); + docheck(lookup, ncomp, "applepie", false); + } + + { // copy/assign/clear test + Lookup lookupa; + add(lookupa, "pineapple", 1); + add(lookupa, "orange", 2); + add(lookupa, "banana", 3); + add(lookupa, "applepie", 4); + add(lookupa, "apple", 5); + + Lookup lookupb(lookupa); // copy ctor + docheck(lookupb, ncomp, "pineapple", true, 9, 1); + docheck(lookupb, ncomp, "orange", true, 6, 2); + docheck(lookupb, ncomp, "banana", true, 6, 3); + docheck(lookupb, ncomp, "apple", true, 5, 5); + docheck(lookupb, ncomp, "pizza", false); + docheck(lookupb, ncomp, "steak", false); + docheck(lookupb, ncomp, "applepie", true, 8, 4); + docheck(lookupb, ncomp, "bananarama", true, 6, 3); + docheck(lookupb, ncomp, "applet", true, 5, 5); + docheck(lookupb, ncomp, "applepi", true, 5, 5); + docheck(lookupb, ncomp, "appl", false); + + lookupb.clear(); // clear + docheck(lookupb, ncomp, "pineapple", false); + docheck(lookupb, ncomp, "orange", false); + docheck(lookupb, ncomp, "banana", false); + docheck(lookupb, ncomp, "apple", false); + docheck(lookupb, ncomp, "applepie", false); + docheck(lookupb, ncomp, "bananarama", false); + docheck(lookupb, ncomp, "applet", false); + docheck(lookupb, ncomp, "applepi", false); + docheck(lookupb, ncomp, "appl", false); + + lookupb = lookupa; // assign + docheck(lookupb, ncomp, "pineapple", true, 9, 1); + docheck(lookupb, ncomp, "orange", true, 6, 2); + docheck(lookupb, ncomp, "banana", true, 6, 3); + docheck(lookupb, ncomp, "apple", true, 5, 5); + docheck(lookupb, ncomp, "pizza", false); + docheck(lookupb, ncomp, "steak", false); + docheck(lookupb, ncomp, "applepie", true, 8, 4); + docheck(lookupb, ncomp, "bananarama", true, 6, 3); + docheck(lookupb, ncomp, "applet", true, 5, 5); + docheck(lookupb, ncomp, "applepi", true, 5, 5); + docheck(lookupb, ncomp, "appl", false); + } + + { // test for_each + Lookup lookup; + add(lookup, "pineapple", 1); + add(lookup, "orange", 2); + add(lookup, "banana", 3); + add(lookup, "applepie", 4); + add(lookup, "apple", 5); + + print(lookup); + } + + { // case insensitive tests + Lookup lookup; + + // NOTE: make sure all entries are in lower-case!!! + add(lookup, "pineapple", 1); + add(lookup, "orange", 2); + add(lookup, "banana", 3); + add(lookup, "applepie", 4); + add(lookup, "apple", 5); + + docheck(lookup, nc_ncomp, "pineapple", true, 9, 1); + docheck(lookup, nc_ncomp, "orange", true, 6, 2); + docheck(lookup, nc_ncomp, "banana", true, 6, 3); + docheck(lookup, nc_ncomp, "apple", true, 5, 5); + docheck(lookup, nc_ncomp, "applepie", true, 8, 4); + + docheck(lookup, nc_ncomp, "PINEAPPLE", true, 9, 1); + docheck(lookup, nc_ncomp, "ORANGE", true, 6, 2); + docheck(lookup, nc_ncomp, "BANANA", true, 6, 3); + docheck(lookup, nc_ncomp, "APPLE", true, 5, 5); + docheck(lookup, nc_ncomp, "APPLEPIE", true, 8, 4); + + docheck(lookup, nc_ncomp, "pineApple", true, 9, 1); + docheck(lookup, nc_ncomp, "orangE", true, 6, 2); + docheck(lookup, nc_ncomp, "Banana", true, 6, 3); + docheck(lookup, nc_ncomp, "aPPLe", true, 5, 5); + docheck(lookup, nc_ncomp, "ApplePie", true, 8, 4); + + print(lookup); + } +} + +int main() +{ + using boost::spirit::x3::tst; + using boost::spirit::x3::tst_map; + + tests<tst<char, int>, tst<wchar_t, int> >(); +//~ tests<tst_map<char, int>, tst_map<wchar_t, int> >(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/uint.hpp b/src/boost/libs/spirit/test/x3/uint.hpp new file mode 100644 index 00000000..b7d4fb7d --- /dev/null +++ b/src/boost/libs/spirit/test/x3/uint.hpp @@ -0,0 +1,59 @@ +/*============================================================================= + Copyright (c) 2001-2012 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2011 Bryce Lelbach + + 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) +=============================================================================*/ +#if !defined(BOOST_SPIRIT_TEST_QI_UINT_HPP) +#define BOOST_SPIRIT_TEST_QI_UINT_HPP + +#include <climits> +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include "test.hpp" +#include <cstring> + +/////////////////////////////////////////////////////////////////////////////// +// +// *** BEWARE PLATFORM DEPENDENT!!! *** +// *** The following assumes 32 bit integers and 64 bit long longs. +// *** Modify these constant strings when appropriate. +// +/////////////////////////////////////////////////////////////////////////////// + + char const* max_unsigned = "4294967295"; + char const* unsigned_overflow = "4294967296"; + char const* max_int = "2147483647"; + char const* int_overflow = "2147483648"; + char const* min_int = "-2147483648"; + char const* int_underflow = "-2147483649"; + char const* max_binary = "11111111111111111111111111111111"; + char const* binary_overflow = "100000000000000000000000000000000"; + char const* max_octal = "37777777777"; + char const* octal_overflow = "100000000000"; + char const* max_hex = "FFFFFFFF"; + char const* hex_overflow = "100000000"; + +/////////////////////////////////////////////////////////////////////////////// +// A custom int type +struct custom_uint +{ + unsigned n; + custom_uint() : n(0) {} + explicit custom_uint(unsigned n_) : n(n_) {} + custom_uint& operator=(unsigned n_) { n = n_; return *this; } + friend bool operator==(custom_uint a, custom_uint b) + { return a.n == b.n; } + friend bool operator==(custom_uint a, unsigned b) + { return a.n == b; } + friend custom_uint operator*(custom_uint a, custom_uint b) + { return custom_uint(a.n * b.n); } + friend custom_uint operator+(custom_uint a, custom_uint b) + { return custom_uint(a.n + b.n); } +}; + +#endif + diff --git a/src/boost/libs/spirit/test/x3/uint1.cpp b/src/boost/libs/spirit/test/x3/uint1.cpp new file mode 100644 index 00000000..7778ef0b --- /dev/null +++ b/src/boost/libs/spirit/test/x3/uint1.cpp @@ -0,0 +1,211 @@ +/*============================================================================= + Copyright (c) 2001-2015 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2011 Bryce Lelbach + + 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 "uint.hpp" +#include <boost/spirit/home/x3.hpp> + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + /////////////////////////////////////////////////////////////////////////// + // unsigned tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::uint_; + unsigned u; + + BOOST_TEST(test("123456", uint_)); + BOOST_TEST(test_attr("123456", uint_, u)); + BOOST_TEST(u == 123456); + + BOOST_TEST(test(max_unsigned, uint_)); + BOOST_TEST(test_attr(max_unsigned, uint_, u)); + BOOST_TEST(u == UINT_MAX); + + BOOST_TEST(!test(unsigned_overflow, uint_)); + BOOST_TEST(!test_attr(unsigned_overflow, uint_, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // binary tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::bin; + unsigned u; + + BOOST_TEST(test("11111110", bin)); + BOOST_TEST(test_attr("11111110", bin, u)); + BOOST_TEST(u == 0xFE); + + BOOST_TEST(test(max_binary, bin)); + BOOST_TEST(test_attr(max_binary, bin, u)); + BOOST_TEST(u == UINT_MAX); + + BOOST_TEST(!test(binary_overflow, bin)); + BOOST_TEST(!test_attr(binary_overflow, bin, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // octal tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::oct; + unsigned u; + + BOOST_TEST(test("12545674515", oct)); + BOOST_TEST(test_attr("12545674515", oct, u)); + BOOST_TEST(u == 012545674515); + + BOOST_TEST(test(max_octal, oct)); + BOOST_TEST(test_attr(max_octal, oct, u)); + BOOST_TEST(u == UINT_MAX); + + BOOST_TEST(!test(octal_overflow, oct)); + BOOST_TEST(!test_attr(octal_overflow, oct, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // hex tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::hex; + unsigned u; + + BOOST_TEST(test("95BC8DF", hex)); + BOOST_TEST(test_attr("95BC8DF", hex, u)); + BOOST_TEST(u == 0x95BC8DF); + + BOOST_TEST(test("abcdef12", hex)); + BOOST_TEST(test_attr("abcdef12", hex, u)); + BOOST_TEST(u == 0xabcdef12); + + BOOST_TEST(test(max_hex, hex)); + BOOST_TEST(test_attr(max_hex, hex, u)); + BOOST_TEST(u == UINT_MAX); + + BOOST_TEST(!test(hex_overflow, hex)); + BOOST_TEST(!test_attr(hex_overflow, hex, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // limited fieldwidth + /////////////////////////////////////////////////////////////////////////// + { + unsigned u; + using boost::spirit::x3::uint_parser; + + uint_parser<unsigned, 10, 1, 3> uint3; + BOOST_TEST(test("123456", uint3, false)); + BOOST_TEST(test_attr("123456", uint3, u, false)); + BOOST_TEST(u == 123); + + uint_parser<unsigned, 10, 2, 4> uint4; + BOOST_TEST(test("123456", uint4, false)); + BOOST_TEST(test_attr("123456", uint4, u, false)); + BOOST_TEST(u == 1234); + + char const * first = "0000000"; + char const * last = first + std::strlen(first); + uint_parser<unsigned, 10, 4, 4> uint_exact4; + BOOST_TEST(boost::spirit::x3::parse(first, last, uint_exact4, u) + && first != last && (last-first == 3) && u == 0); + + first = "0001400"; + last = first + std::strlen(first); + BOOST_TEST(boost::spirit::x3::parse(first, last, uint_exact4, u) + && first != last && (last-first == 3) && u == 1); + + BOOST_TEST(!test("1", uint4)); + BOOST_TEST(!test_attr("1", uint4, u)); + BOOST_TEST(test_attr("014567", uint4, u, false) && u == 145); + } + + /////////////////////////////////////////////////////////////////////////// + // action tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::_attr; + using boost::spirit::x3::uint_; + using boost::spirit::x3::ascii::space; + int n; + + auto f = [&](auto& ctx){ n = _attr(ctx); }; + + BOOST_TEST(test("123", uint_[f])); + BOOST_TEST(n == 123); + BOOST_TEST(test(" 456", uint_[f], space)); + BOOST_TEST(n == 456); + } + + /////////////////////////////////////////////////////////////////////////// + // Check overflow is parse error + /////////////////////////////////////////////////////////////////////////// + { + boost::spirit::x3::uint_parser<boost::uint8_t> uint8_; + boost::uint8_t u8; + + BOOST_TEST(!test_attr("999", uint8_, u8)); + BOOST_TEST(!test_attr("256", uint8_, u8)); + BOOST_TEST(test_attr("255", uint8_, u8)); + + boost::spirit::x3::uint_parser<boost::uint16_t> uint16_; + boost::uint16_t u16; + + BOOST_TEST(!test_attr("99999", uint16_, u16)); + BOOST_TEST(!test_attr("65536", uint16_, u16)); + BOOST_TEST(test_attr("65535", uint16_, u16)); + + boost::spirit::x3::uint_parser<boost::uint32_t> uint32_; + boost::uint32_t u32; + + BOOST_TEST(!test_attr("9999999999", uint32_, u32)); + BOOST_TEST(!test_attr("4294967296", uint32_, u32)); + BOOST_TEST(test_attr("4294967295", uint32_, u32)); + + boost::spirit::x3::uint_parser<boost::int8_t> u_int8_; + + BOOST_TEST(!test_attr("999", u_int8_, u8)); + BOOST_TEST(!test_attr("-1", u_int8_, u8)); + BOOST_TEST(!test_attr("128", u_int8_, u8)); + BOOST_TEST(test_attr("127", u_int8_, u8)); + BOOST_TEST(test_attr("0", u_int8_, u8)); + + boost::spirit::x3::uint_parser<boost::int16_t> u_int16_; + + BOOST_TEST(!test_attr("99999", u_int16_, u16)); + BOOST_TEST(!test_attr("-1", u_int16_, u16)); + BOOST_TEST(!test_attr("32768", u_int16_, u16)); + BOOST_TEST(test_attr("32767", u_int16_, u16)); + BOOST_TEST(test_attr("0", u_int16_, u16)); + + boost::spirit::x3::uint_parser<boost::int32_t> u_int32_; + + BOOST_TEST(!test_attr("9999999999", u_int32_, u32)); + BOOST_TEST(!test_attr("-1", u_int32_, u32)); + BOOST_TEST(!test_attr("2147483648", u_int32_, u32)); + BOOST_TEST(test_attr("2147483647", u_int32_, u32)); + BOOST_TEST(test_attr("0", u_int32_, u32)); + } + + /////////////////////////////////////////////////////////////////////////// + // custom uint tests + /////////////////////////////////////////////////////////////////////////// + { + using boost::spirit::x3::uint_; + using boost::spirit::x3::uint_parser; + custom_uint u; + + BOOST_TEST(test_attr("123456", uint_, u)); + uint_parser<custom_uint, 10, 1, 2> uint2; + BOOST_TEST(test_attr("12", uint2, u)); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/uint_radix.cpp b/src/boost/libs/spirit/test/x3/uint_radix.cpp new file mode 100644 index 00000000..4ae4fb0f --- /dev/null +++ b/src/boost/libs/spirit/test/x3/uint_radix.cpp @@ -0,0 +1,740 @@ +/*============================================================================= + Copyright (c) 2011 Jan Frederick Eick + + 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 <boost/config/warning_disable.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> + +#include <climits> +#include <cstring> +#include "test.hpp" + +#include "uint_radix.hpp" + +int +main() +{ + using spirit_test::test; + using spirit_test::test_attr; + + using boost::spirit::x3::uint_parser; + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 3) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 3, 1, -1> base3_parser; + + BOOST_TEST(test("210112221200", base3_parser)); + BOOST_TEST(test_attr("210112221200", base3_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("1231", base3_parser)); + BOOST_TEST(!test_attr("1231", base3_parser, u)); + + BOOST_TEST(test(max_unsigned_base3, base3_parser)); + BOOST_TEST(test_attr(max_unsigned_base3, base3_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base3, base3_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base3, base3_parser, u)); + BOOST_TEST(!test(digit_overflow_base3, base3_parser)); + BOOST_TEST(!test_attr(digit_overflow_base3, base3_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 4) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + + uint_parser<unsigned int, 4, 1, -1> base4_parser; + + BOOST_TEST(test("1213210302", base4_parser)); + BOOST_TEST(test_attr("1213210302", base4_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("1234", base4_parser)); + BOOST_TEST(!test_attr("1234", base4_parser, u)); + + BOOST_TEST(test(max_unsigned_base4, base4_parser)); + BOOST_TEST(test_attr(max_unsigned_base4, base4_parser, u)); + BOOST_TEST(!test(digit_overflow_base4, base4_parser)); + BOOST_TEST(!test_attr(digit_overflow_base4, base4_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 5) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + + uint_parser<unsigned int, 5, 1, -1> base5_parser; + + BOOST_TEST(test("102033432", base5_parser)); + BOOST_TEST(test_attr("102033432", base5_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("2345", base5_parser)); + BOOST_TEST(!test_attr("2345", base5_parser, u)); + + BOOST_TEST(test(max_unsigned_base5, base5_parser)); + BOOST_TEST(test_attr(max_unsigned_base5, base5_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base5, base5_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base5, base5_parser, u)); + BOOST_TEST(!test(digit_overflow_base5, base5_parser)); + BOOST_TEST(!test_attr(digit_overflow_base5, base5_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 6) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + + uint_parser<unsigned int, 6, 1, -1> base6_parser; + + BOOST_TEST(test("13032030", base6_parser)); + BOOST_TEST(test_attr("13032030", base6_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("3456", base6_parser)); + BOOST_TEST(!test_attr("3456", base6_parser, u)); + + BOOST_TEST(test(max_unsigned_base6, base6_parser)); + BOOST_TEST(test_attr(max_unsigned_base6, base6_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base6, base6_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base6, base6_parser, u)); + BOOST_TEST(!test(digit_overflow_base6, base6_parser)); + BOOST_TEST(!test_attr(digit_overflow_base6, base6_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 7) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + + uint_parser<unsigned int, 7, 1, -1> base7_parser; + + BOOST_TEST(test("3414600", base7_parser)); + BOOST_TEST(test_attr("3414600", base7_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("4567", base7_parser)); + BOOST_TEST(!test_attr("4567", base7_parser, u)); + + BOOST_TEST(test(max_unsigned_base7, base7_parser)); + BOOST_TEST(test_attr(max_unsigned_base7, base7_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base7, base7_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base7, base7_parser, u)); + BOOST_TEST(!test(digit_overflow_base7, base7_parser)); + BOOST_TEST(!test_attr(digit_overflow_base7, base7_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 9) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + + uint_parser<unsigned int, 9, 1, -1> base9_parser; + + BOOST_TEST(test("715850", base9_parser)); + BOOST_TEST(test_attr("715850", base9_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("6789", base9_parser)); + BOOST_TEST(!test_attr("6789", base9_parser, u)); + + BOOST_TEST(test(max_unsigned_base9, base9_parser)); + BOOST_TEST(test_attr(max_unsigned_base9, base9_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base9, base9_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base9, base9_parser, u)); + BOOST_TEST(!test(digit_overflow_base9, base9_parser)); + BOOST_TEST(!test_attr(digit_overflow_base9, base9_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 11) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + + uint_parser<unsigned int, 11, 1, -1> base11_parser; + + BOOST_TEST(test("26a815", base11_parser)); + BOOST_TEST(test_attr("26a815", base11_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("90ab", base11_parser)); + BOOST_TEST(!test_attr("90AB", base11_parser, u)); + + BOOST_TEST(test(max_unsigned_base11, base11_parser)); + BOOST_TEST(test_attr(max_unsigned_base11, base11_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base11, base11_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base11, base11_parser, u)); + BOOST_TEST(!test(digit_overflow_base11, base11_parser)); + BOOST_TEST(!test_attr(digit_overflow_base11, base11_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 12) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 12, 1, -1> base12_parser; + + BOOST_TEST(test("185616", base12_parser)); + BOOST_TEST(test_attr("185616", base12_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("9abc", base12_parser)); + BOOST_TEST(!test_attr("9ABC", base12_parser, u)); + + BOOST_TEST(test(max_unsigned_base12, base12_parser)); + BOOST_TEST(test_attr(max_unsigned_base12, base12_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base12, base12_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base12, base12_parser, u)); + BOOST_TEST(!test(digit_overflow_base12, base12_parser)); + BOOST_TEST(!test_attr(digit_overflow_base12, base12_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 13) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 13, 1, -1> base13_parser; + + BOOST_TEST(test("11b140", base13_parser)); + BOOST_TEST(test_attr("11b140", base13_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("abcd", base13_parser)); + BOOST_TEST(!test_attr("ABCD", base13_parser, u)); + + BOOST_TEST(test(max_unsigned_base13, base13_parser)); + BOOST_TEST(test_attr(max_unsigned_base13, base13_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base13, base13_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base13, base13_parser, u)); + BOOST_TEST(!test(digit_overflow_base13, base13_parser)); + BOOST_TEST(!test_attr(digit_overflow_base13, base13_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 14) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 14, 1, -1> base14_parser; + + BOOST_TEST(test("b0870", base14_parser)); + BOOST_TEST(test_attr("b0870", base14_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("bcde", base14_parser)); + BOOST_TEST(!test_attr("BCDE", base14_parser, u)); + + BOOST_TEST(test(max_unsigned_base14, base14_parser)); + BOOST_TEST(test_attr(max_unsigned_base14, base14_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base14, base14_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base14, base14_parser, u)); + BOOST_TEST(!test(digit_overflow_base14, base14_parser)); + BOOST_TEST(!test_attr(digit_overflow_base14, base14_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 15) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 15, 1, -1> base15_parser; + + BOOST_TEST(test("85a7c", base15_parser)); + BOOST_TEST(test_attr("85a7c", base15_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("cdef", base15_parser)); + BOOST_TEST(!test_attr("CDEF", base15_parser, u)); + + BOOST_TEST(test(max_unsigned_base15, base15_parser)); + BOOST_TEST(test_attr(max_unsigned_base15, base15_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base15, base15_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base15, base15_parser, u)); + BOOST_TEST(!test(digit_overflow_base15, base15_parser)); + BOOST_TEST(!test_attr(digit_overflow_base15, base15_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 17) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 17, 1, -1> base17_parser; + + BOOST_TEST(test("515g7", base17_parser)); + BOOST_TEST(test_attr("515g7", base17_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("efgh", base17_parser)); + BOOST_TEST(!test_attr("EFGH", base17_parser, u)); + + BOOST_TEST(test(max_unsigned_base17, base17_parser)); + BOOST_TEST(test_attr(max_unsigned_base17, base17_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base17, base17_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base17, base17_parser, u)); + BOOST_TEST(!test(digit_overflow_base17, base17_parser)); + BOOST_TEST(!test_attr(digit_overflow_base17, base17_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 18) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 18, 1, -1> base18_parser; + + BOOST_TEST(test("40d70", base18_parser)); + BOOST_TEST(test_attr("40d70", base18_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("fghi", base18_parser)); + BOOST_TEST(!test_attr("FGHI", base18_parser, u)); + + BOOST_TEST(test(max_unsigned_base18, base18_parser)); + BOOST_TEST(test_attr(max_unsigned_base18, base18_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base18, base18_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base18, base18_parser, u)); + BOOST_TEST(!test(digit_overflow_base18, base18_parser)); + BOOST_TEST(!test_attr(digit_overflow_base18, base18_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 19) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 19, 1, -1> base19_parser; + + BOOST_TEST(test("34g3a", base19_parser)); + BOOST_TEST(test_attr("34g3a", base19_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("ghij", base19_parser)); + BOOST_TEST(!test_attr("GHIJ", base19_parser, u)); + + BOOST_TEST(test(max_unsigned_base19, base19_parser)); + BOOST_TEST(test_attr(max_unsigned_base19, base19_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base19, base19_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base19, base19_parser, u)); + BOOST_TEST(!test(digit_overflow_base19, base19_parser)); + BOOST_TEST(!test_attr(digit_overflow_base19, base19_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 20) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 20, 1, -1> base20_parser; + + BOOST_TEST(test("2d0c2", base20_parser)); + BOOST_TEST(test_attr("2d0c2", base20_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("hijk", base20_parser)); + BOOST_TEST(!test_attr("HIJK", base20_parser, u)); + + BOOST_TEST(test(max_unsigned_base20, base20_parser)); + BOOST_TEST(test_attr(max_unsigned_base20, base20_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base20, base20_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base20, base20_parser, u)); + BOOST_TEST(!test(digit_overflow_base20, base20_parser)); + BOOST_TEST(!test_attr(digit_overflow_base20, base20_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 21) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 21, 1, -1> base21_parser; + + BOOST_TEST(test("23h00", base21_parser)); + BOOST_TEST(test_attr("23h00", base21_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("ijkl", base21_parser)); + BOOST_TEST(!test_attr("IJKL", base21_parser, u)); + + BOOST_TEST(test(max_unsigned_base21, base21_parser)); + BOOST_TEST(test_attr(max_unsigned_base21, base21_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base21, base21_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base21, base21_parser, u)); + BOOST_TEST(!test(digit_overflow_base21, base21_parser)); + BOOST_TEST(!test_attr(digit_overflow_base21, base21_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 22) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 22, 1, -1> base22_parser; + + BOOST_TEST(test("1hibg", base22_parser)); + BOOST_TEST(test_attr("1hibg", base22_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("jklm", base22_parser)); + BOOST_TEST(!test_attr("JKLM", base22_parser, u)); + + BOOST_TEST(test(max_unsigned_base22, base22_parser)); + BOOST_TEST(test_attr(max_unsigned_base22, base22_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base22, base22_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base22, base22_parser, u)); + BOOST_TEST(!test(digit_overflow_base22, base22_parser)); + BOOST_TEST(!test_attr(digit_overflow_base22, base22_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 23) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 23, 1, -1> base23_parser; + + BOOST_TEST(test("1bjm7", base23_parser)); + BOOST_TEST(test_attr("1bjm7", base23_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("klmn", base23_parser)); + BOOST_TEST(!test_attr("KLMN", base23_parser, u)); + + BOOST_TEST(test(max_unsigned_base23, base23_parser)); + BOOST_TEST(test_attr(max_unsigned_base23, base23_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base23, base23_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base23, base23_parser, u)); + BOOST_TEST(!test(digit_overflow_base23, base23_parser)); + BOOST_TEST(!test_attr(digit_overflow_base23, base23_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 24) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 24, 1, -1> base24_parser; + + BOOST_TEST(test("16gci", base24_parser)); + BOOST_TEST(test_attr("16gci", base24_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("lmno", base24_parser)); + BOOST_TEST(!test_attr("LMNO", base24_parser, u)); + + BOOST_TEST(test(max_unsigned_base24, base24_parser)); + BOOST_TEST(test_attr(max_unsigned_base24, base24_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base24, base24_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base24, base24_parser, u)); + BOOST_TEST(!test(digit_overflow_base24, base24_parser)); + BOOST_TEST(!test_attr(digit_overflow_base24, base24_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 25) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 25, 1, -1> base25_parser; + + BOOST_TEST(test("123jh", base25_parser)); + BOOST_TEST(test_attr("123jh", base25_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("mnop", base25_parser)); + BOOST_TEST(!test_attr("MNOP", base25_parser, u)); + + BOOST_TEST(test(max_unsigned_base25, base25_parser)); + BOOST_TEST(test_attr(max_unsigned_base25, base25_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base25, base25_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base25, base25_parser, u)); + BOOST_TEST(!test(digit_overflow_base25, base25_parser)); + BOOST_TEST(!test_attr(digit_overflow_base25, base25_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 26) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 26, 1, -1> base26_parser; + + BOOST_TEST(test("o3f0", base26_parser)); + BOOST_TEST(test_attr("o3f0", base26_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("nopq", base26_parser)); + BOOST_TEST(!test_attr("NOPQ", base26_parser, u)); + + BOOST_TEST(test(max_unsigned_base26, base26_parser)); + BOOST_TEST(test_attr(max_unsigned_base26, base26_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base26, base26_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base26, base26_parser, u)); + BOOST_TEST(!test(digit_overflow_base26, base26_parser)); + BOOST_TEST(!test_attr(digit_overflow_base26, base26_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 27) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 27, 1, -1> base27_parser; + + BOOST_TEST(test("lepi", base27_parser)); + BOOST_TEST(test_attr("lepi", base27_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("opqr", base27_parser)); + BOOST_TEST(!test_attr("OPQR", base27_parser, u)); + + BOOST_TEST(test(max_unsigned_base27, base27_parser)); + BOOST_TEST(test_attr(max_unsigned_base27, base27_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base27, base27_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base27, base27_parser, u)); + BOOST_TEST(!test(digit_overflow_base27, base27_parser)); + BOOST_TEST(!test_attr(digit_overflow_base27, base27_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 28) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 28, 1, -1> base28_parser; + + BOOST_TEST(test("j93e", base28_parser)); + BOOST_TEST(test_attr("j93e", base28_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("pqrs", base28_parser)); + BOOST_TEST(!test_attr("PQRS", base28_parser, u)); + + BOOST_TEST(test(max_unsigned_base28, base28_parser)); + BOOST_TEST(test_attr(max_unsigned_base28, base28_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base28, base28_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base28, base28_parser, u)); + BOOST_TEST(!test(digit_overflow_base28, base28_parser)); + BOOST_TEST(!test_attr(digit_overflow_base28, base28_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 29) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 29, 1, -1> base29_parser; + + BOOST_TEST(test("hbd1", base29_parser)); + BOOST_TEST(test_attr("hbd1", base29_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("qrst", base29_parser)); + BOOST_TEST(!test_attr("QRST", base29_parser, u)); + + BOOST_TEST(test(max_unsigned_base29, base29_parser)); + BOOST_TEST(test_attr(max_unsigned_base29, base29_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base29, base29_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base29, base29_parser, u)); + BOOST_TEST(!test(digit_overflow_base29, base29_parser)); + BOOST_TEST(!test_attr(digit_overflow_base29, base29_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 30) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 30, 1, -1> base30_parser; + + BOOST_TEST(test("flbc", base30_parser)); + BOOST_TEST(test_attr("flbc", base30_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("rstu", base30_parser)); + BOOST_TEST(!test_attr("RSTU", base30_parser, u)); + + BOOST_TEST(test(max_unsigned_base30, base30_parser)); + BOOST_TEST(test_attr(max_unsigned_base30, base30_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base30, base30_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base30, base30_parser, u)); + BOOST_TEST(!test(digit_overflow_base30, base30_parser)); + BOOST_TEST(!test_attr(digit_overflow_base30, base30_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 31) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 31, 1, -1> base31_parser; + + BOOST_TEST(test("e7e7", base31_parser)); + BOOST_TEST(test_attr("e7e7", base31_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("stuv", base31_parser)); + BOOST_TEST(!test_attr("STUV", base31_parser, u)); + + BOOST_TEST(test(max_unsigned_base31, base31_parser)); + BOOST_TEST(test_attr(max_unsigned_base31, base31_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base31, base31_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base31, base31_parser, u)); + BOOST_TEST(!test(digit_overflow_base31, base31_parser)); + BOOST_TEST(!test_attr(digit_overflow_base31, base31_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 32) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 32, 1, -1> base32_parser; + + BOOST_TEST(test("cu9i", base32_parser)); + BOOST_TEST(test_attr("cu9i", base32_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("tuvw", base32_parser)); + BOOST_TEST(!test_attr("TUVW", base32_parser, u)); + + BOOST_TEST(test(max_unsigned_base32, base32_parser)); + BOOST_TEST(test_attr(max_unsigned_base32, base32_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base32, base32_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base32, base32_parser, u)); + BOOST_TEST(!test(digit_overflow_base32, base32_parser)); + BOOST_TEST(!test_attr(digit_overflow_base32, base32_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 33) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 33, 1, -1> base33_parser; + + BOOST_TEST(test("bqir", base33_parser)); + BOOST_TEST(test_attr("bqir", base33_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("uvwx", base33_parser)); + BOOST_TEST(!test_attr("UVWX", base33_parser, u)); + + BOOST_TEST(test(max_unsigned_base33, base33_parser)); + BOOST_TEST(test_attr(max_unsigned_base33, base33_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base33, base33_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base33, base33_parser, u)); + BOOST_TEST(!test(digit_overflow_base33, base33_parser)); + BOOST_TEST(!test_attr(digit_overflow_base33, base33_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 34) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 34, 1, -1> base34_parser; + + BOOST_TEST(test("aqxo", base34_parser)); + BOOST_TEST(test_attr("aqxo", base34_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("vwxy", base34_parser)); + BOOST_TEST(!test_attr("VWXY", base34_parser, u)); + + BOOST_TEST(test(max_unsigned_base34, base34_parser)); + BOOST_TEST(test_attr(max_unsigned_base34, base34_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base34, base34_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base34, base34_parser, u)); + BOOST_TEST(!test(digit_overflow_base34, base34_parser)); + BOOST_TEST(!test_attr(digit_overflow_base34, base34_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 35) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 35, 1, -1> base35_parser; + + BOOST_TEST(test("9vb7", base35_parser)); + BOOST_TEST(test_attr("9vb7", base35_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(!test("wxyz", base35_parser)); + BOOST_TEST(!test_attr("WXYZ", base35_parser, u)); + + BOOST_TEST(test(max_unsigned_base35, base35_parser)); + BOOST_TEST(test_attr(max_unsigned_base35, base35_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base35, base35_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base35, base35_parser, u)); + BOOST_TEST(!test(digit_overflow_base35, base35_parser)); + BOOST_TEST(!test_attr(digit_overflow_base35, base35_parser, u)); + } + + /////////////////////////////////////////////////////////////////////////// + // arbitrary radix test (base 36) + /////////////////////////////////////////////////////////////////////////// + { + unsigned int u; + uint_parser<unsigned int, 36, 1, -1> base36_parser; + + BOOST_TEST(test("93ci", base36_parser)); + BOOST_TEST(test_attr("93ci", base36_parser, u)); + BOOST_TEST(424242 == u); + + BOOST_TEST(test(max_unsigned_base36, base36_parser)); + BOOST_TEST(test_attr(max_unsigned_base36, base36_parser, u)); + + BOOST_TEST(!test(unsigned_overflow_base36, base36_parser)); + BOOST_TEST(!test_attr(unsigned_overflow_base36, base36_parser, u)); + BOOST_TEST(!test(digit_overflow_base36, base36_parser)); + BOOST_TEST(!test_attr(digit_overflow_base36, base36_parser, u)); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/uint_radix.hpp b/src/boost/libs/spirit/test/x3/uint_radix.hpp new file mode 100644 index 00000000..07b5638f --- /dev/null +++ b/src/boost/libs/spirit/test/x3/uint_radix.hpp @@ -0,0 +1,142 @@ +/*============================================================================= + Copyright (c) 2011 Jan Frederick Eick + + 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) +=============================================================================*/ + +#if !defined(BOOST_SPIRIT_TEST_X3_UINT4_HPP) +#define BOOST_SPIRIT_TEST_X3_UINT4_HPP + +/////////////////////////////////////////////////////////////////////////////// +// +// *** BEWARE PLATFORM DEPENDENT!!! *** +// *** The following assumes 32 bit integers and 64 bit long longs. +// *** Modify these constant strings when appropriate. +// +/////////////////////////////////////////////////////////////////////////////// + +char const* max_unsigned_base3 = "102002022201221111210"; +char const* unsigned_overflow_base3 = "102002022201221111211"; +char const* digit_overflow_base3 = "1020020222012211112100"; + +char const* max_unsigned_base4 = "3333333333333333"; +char const* digit_overflow_base4 = "33333333333333330"; + +char const* max_unsigned_base5 = "32244002423140"; +char const* unsigned_overflow_base5 = "32244002423141"; +char const* digit_overflow_base5 = "322440024231400"; + +char const* max_unsigned_base6 = "1550104015503"; +char const* unsigned_overflow_base6 = "1550104015504"; +char const* digit_overflow_base6 = "15501040155030"; + +char const* max_unsigned_base7 = "211301422353"; +char const* unsigned_overflow_base7 = "211301422354"; +char const* digit_overflow_base7 = "2113014223530"; + +char const* max_unsigned_base9 = "12068657453"; +char const* unsigned_overflow_base9 = "12068657454"; +char const* digit_overflow_base9 = "120686574530"; + +char const* max_unsigned_base11 = "1904440553"; +char const* unsigned_overflow_base11 = "1904440554"; +char const* digit_overflow_base11 = "19044405530"; + +char const* max_unsigned_base12 = "9BA461593"; +char const* unsigned_overflow_base12 = "9BA461594"; +char const* digit_overflow_base12 = "9BA4615930"; + +char const* max_unsigned_base13 = "535A79888"; +char const* unsigned_overflow_base13 = "535A79889"; +char const* digit_overflow_base13 = "535A798880"; + +char const* max_unsigned_base14 = "2CA5B7463"; +char const* unsigned_overflow_base14 = "2CA5B7464"; +char const* digit_overflow_base14 = "2CA5B74630"; + +char const* max_unsigned_base15 = "1A20DCD80"; +char const* unsigned_overflow_base15 = "1A20DCD81"; +char const* digit_overflow_base15 = "1A20DCD800"; + +char const* max_unsigned_base17 = "A7FFDA90"; +char const* unsigned_overflow_base17 = "A7FFDA91"; +char const* digit_overflow_base17 = "A7FFDA900"; + +char const* max_unsigned_base18 = "704HE7G3"; +char const* unsigned_overflow_base18 = "704HE7G4"; +char const* digit_overflow_base18 = "704HE7G30"; + +char const* max_unsigned_base19 = "4F5AFF65"; +char const* unsigned_overflow_base19 = "4F5AFF66"; +char const* digit_overflow_base19 = "4F5AFF650"; + +char const* max_unsigned_base20 = "3723AI4F"; +char const* unsigned_overflow_base20 = "3723AI4G"; +char const* digit_overflow_base20 = "3723AI4G0"; + +char const* max_unsigned_base21 = "281D55I3"; +char const* unsigned_overflow_base21 = "281D55I4"; +char const* digit_overflow_base21 = "281D55I30"; + +char const* max_unsigned_base22 = "1FJ8B183"; +char const* unsigned_overflow_base22 = "1FJ8B184"; +char const* digit_overflow_base22 = "1FJ8B1830"; + +char const* max_unsigned_base23 = "1606K7IB"; +char const* unsigned_overflow_base23 = "1606K7IC"; +char const* digit_overflow_base23 = "1606K7IB0"; + +char const* max_unsigned_base24 = "MB994AF"; +char const* unsigned_overflow_base24 = "MB994AG"; +char const* digit_overflow_base24 = "MB994AF0"; + +char const* max_unsigned_base25 = "HEK2MGK"; +char const* unsigned_overflow_base25 = "HEK2MGL"; +char const* digit_overflow_base25 = "HEK2MGK0"; + +char const* max_unsigned_base26 = "DNCHBNL"; +char const* unsigned_overflow_base26 = "DNCHBNM"; +char const* digit_overflow_base26 = "DNCHBNL0"; + +char const* max_unsigned_base27 = "B28JPDL"; +char const* unsigned_overflow_base27 = "B28JPDM"; +char const* digit_overflow_base27 = "B28JPDL0"; + +char const* max_unsigned_base28 = "8PFGIH3"; +char const* unsigned_overflow_base28 = "8PFGIH4"; +char const* digit_overflow_base28 = "8PFGIH30"; + +char const* max_unsigned_base29 = "76BEIGF"; +char const* unsigned_overflow_base29 = "76BEIGH"; +char const* digit_overflow_base29 = "76BEIGF0"; + +char const* max_unsigned_base30 = "5QMCPQF"; +char const* unsigned_overflow_base30 = "5QMCPQG"; +char const* digit_overflow_base30 = "5QMCPQF0"; + +char const* max_unsigned_base31 = "4Q0JTO3"; +char const* unsigned_overflow_base31 = "4Q0JTO4"; +char const* digit_overflow_base31 = "4Q0JTO30"; + +char const* max_unsigned_base32 = "3VVVVVV"; +char const* unsigned_overflow_base32 = "3VVVVVW"; +char const* digit_overflow_base32 = "3VVVVVV0"; + +char const* max_unsigned_base33 = "3AOKQ93"; +char const* unsigned_overflow_base33 = "3AOKQ94"; +char const* digit_overflow_base33 = "3AOKQ930"; + +char const* max_unsigned_base34 = "2QHXJLH"; +char const* unsigned_overflow_base34 = "2QHXJLI"; +char const* digit_overflow_base34 = "2QHXJLH0"; + +char const* max_unsigned_base35 = "2BR45QA"; +char const* unsigned_overflow_base35 = "2BR45QB"; +char const* digit_overflow_base35 = "2BR45QA0"; + +char const* max_unsigned_base36 = "1Z141Z3"; +char const* unsigned_overflow_base36 = "1Z141Z4"; +char const* digit_overflow_base36 = "1Z141Z30"; + +#endif
\ No newline at end of file diff --git a/src/boost/libs/spirit/test/x3/unused_type.cpp b/src/boost/libs/spirit/test/x3/unused_type.cpp new file mode 100644 index 00000000..6a660590 --- /dev/null +++ b/src/boost/libs/spirit/test/x3/unused_type.cpp @@ -0,0 +1,34 @@ +/*============================================================================= + Copyright (c) 2019 Nikita Kniazev + + Use, modification and distribution is subject to 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 <boost/spirit/home/x3/support/unused.hpp> +#include <type_traits> + +void test_use(boost::spirit::x3::unused_type) {} + +int main() +{ + using boost::spirit::x3::unused; + using boost::spirit::x3::unused_type; + + static_assert(std::is_trivial<unused_type>::value, ""); + + unused_type unused_mut; + static_assert(std::is_same<decltype((unused)), unused_type const&>::value, ""); + static_assert(std::is_same<decltype((unused_mut)), unused_type&>::value, ""); + static_assert(std::is_same<decltype(unused = 123), unused_type const&>::value, ""); + static_assert(std::is_same<decltype(unused = unused), unused_type const&>::value, ""); + static_assert(std::is_same<decltype(unused = unused_mut), unused_type const&>::value, ""); + static_assert(std::is_same<decltype(unused_mut = 123), unused_type&>::value, ""); + static_assert(std::is_same<decltype(unused_mut = unused), unused_type&>::value, ""); + static_assert(std::is_same<decltype(unused_mut = unused_mut), unused_type&>::value, ""); + + test_use(0); + test_use(unused); + test_use(unused_mut); +} diff --git a/src/boost/libs/spirit/test/x3/utils.hpp b/src/boost/libs/spirit/test/x3/utils.hpp new file mode 100644 index 00000000..588f60de --- /dev/null +++ b/src/boost/libs/spirit/test/x3/utils.hpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2019 Nikita Kniazev + + Use, modification and distribution is subject to 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) +=============================================================================*/ +#if !defined(BOOST_SPIRIT_TEST_X3_UTILS_HPP) +#define BOOST_SPIRIT_TEST_X3_UTILS_HPP + +#include <boost/spirit/home/x3/core/parser.hpp> + +struct move_only +{ + move_only() = default; + move_only(move_only&&) = default; + move_only& operator=(move_only&&) = default; +}; + + +template <typename T> +struct synth_parser : boost::spirit::x3::parser<synth_parser<T>> +{ + typedef T attribute_type; + + static bool const has_attribute = true; + static bool const handles_container = false; + + template <typename Iterator, typename Context, + typename RuleContext, typename Attribute> + bool parse(Iterator& iter, Iterator const& last, Context const&, + RuleContext&, Attribute& attr) const + { + if (iter != last && *iter == 's') { + ++iter; + boost::spirit::x3::traits::move_to(attribute_type{}, attr); + return true; + } + return false; + } +}; + +template <typename T> +synth_parser<T> synth{}; + +synth_parser<move_only> const synth_move_only{}; + +#endif diff --git a/src/boost/libs/spirit/test/x3/with.cpp b/src/boost/libs/spirit/test/x3/with.cpp new file mode 100644 index 00000000..8160b80e --- /dev/null +++ b/src/boost/libs/spirit/test/x3/with.cpp @@ -0,0 +1,114 @@ +/*============================================================================= + Copyright (c) 2015 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include "test.hpp" + +namespace x3 = boost::spirit::x3; + +struct my_tag; + +struct my_rule_class +{ + template <typename Iterator, typename Exception, typename Context> + x3::error_handler_result + on_error(Iterator&, Iterator const&, Exception const&, Context const& context) + { + x3::get<my_tag>(context)++; + return x3::error_handler_result::fail; + } + + template <typename Iterator, typename Attribute, typename Context> + inline void + on_success(Iterator const&, Iterator const&, Attribute&, Context const& context) + { + x3::get<my_tag>(context)++; + } +}; + +int +main() +{ + using spirit_test::test_attr; + using spirit_test::test; + + using boost::spirit::x3::rule; + using boost::spirit::x3::int_; + using boost::spirit::x3::with; + + { // injecting data into the context in the grammar + + int val = 0; + auto r = rule<my_rule_class, char const*>() = + '(' > int_ > ',' > int_ > ')' + ; + + auto start = + with<my_tag>(std::ref(val)) [ r ] + ; + + BOOST_TEST(test("(123,456)", start)); + BOOST_TEST(!test("(abc,def)", start)); + BOOST_TEST(val == 2); + } + + { // injecting non-const lvalue into the context + int val = 0; + auto const r = int_[([](auto& ctx){ + x3::get<my_tag>(ctx) += x3::_attr(ctx); + })]; + BOOST_TEST(test("123,456", with<my_tag>(val)[r % ','])); + BOOST_TEST(579 == val); + } + + { // injecting rvalue into the context + auto const r1 = int_[([](auto& ctx){ + x3::get<my_tag>(ctx) += x3::_attr(ctx); + })]; + auto const r2 = rule<struct my_rvalue_rule_class, int>() = + x3::lit('(') >> (r1 % ',') >> x3::lit(')')[([](auto& ctx){ + x3::_val(ctx) = x3::get<my_tag>(ctx); + })]; + int attr = 0; + BOOST_TEST(test_attr("(1,2,3)", with<my_tag>(100)[r2], attr)); + BOOST_TEST(106 == attr); + } + + { // injecting const/non-const lvalue and rvalue into the context + struct functor { + int operator()(int& val) { + return val * 10; // non-const ref returns 10 * injected val + } + int operator()(int const& val) { + return val; // const ref returns injected val + } + }; + + auto f = [](auto& ctx){ + x3::_val(ctx) = x3::_attr(ctx) + functor()(x3::get<my_tag>(ctx)); + }; + auto const r = rule<struct my_rule_class2, int>() = int_[f]; + + int attr = 0; + int const cval = 10; + BOOST_TEST(test_attr("5", with<my_tag>(cval)[r], attr)); + BOOST_TEST(15 == attr); // x3::get returns const ref to cval + + attr = 0; + int val = 10; + BOOST_TEST(test_attr("5", with<my_tag>(val)[r], attr)); + BOOST_TEST(105 == attr); // x3::get returns ref to val + + attr = 0; + + BOOST_TEST(test_attr("5", with<my_tag>(10)[r], attr)); + // x3::get returns ref to member variable of with_directive + BOOST_TEST(105 == attr); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/test/x3/x3_variant.cpp b/src/boost/libs/spirit/test/x3/x3_variant.cpp new file mode 100644 index 00000000..5a3f510c --- /dev/null +++ b/src/boost/libs/spirit/test/x3/x3_variant.cpp @@ -0,0 +1,57 @@ +/*============================================================================= + Copyright (c) 2001-2016 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) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/home/x3.hpp> +#include <boost/spirit/home/x3/support/ast/variant.hpp> + +#include <string> +#include <iostream> +#include "test.hpp" + +namespace x3 = boost::spirit::x3; + +struct none {}; + +using variant = x3::variant< + none + , bool + , std::string + , int + , double + >; + +struct ast : variant +{ + using variant::variant; + using variant::operator=; + + ast(char const* s) + : variant(std::string{s}) + {} + + ast& operator=(char const* s) + { + variant::operator=(std::string{s}); + return *this; + } +}; + +int +main() +{ + { + ast v{123}; + BOOST_TEST(boost::get<int>(v) == 123); + + v = "test"; + BOOST_TEST(boost::get<std::string>(v) == "test"); + + v = true; + BOOST_TEST(boost::get<bool>(v) == true); + } + return boost::report_errors(); +} |