diff options
Diffstat (limited to 'src/boost/libs/spirit/classic/test')
97 files changed, 12815 insertions, 0 deletions
diff --git a/src/boost/libs/spirit/classic/test/Jamfile b/src/boost/libs/spirit/classic/test/Jamfile new file mode 100644 index 00000000..3ec2edcb --- /dev/null +++ b/src/boost/libs/spirit/classic/test/Jamfile @@ -0,0 +1,204 @@ +#============================================================================== +# Copyright (c) 2002 Joel de Guzman +# Copyright (c) 2003-2004 Martin Wille +# Copyright (c) 2019 Nikita Kniazev +# http://spirit.sourceforge.net/ +# +# 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) +#============================================================================== +# +# Spirit regression test boost-jam file +# Joel de Guzman [Sept 27, 2002] +# + +project spirit-classic + : requirements + <include>. + ; + +############################################################################### + +cpp-pch pch : pch.hpp : : : <include>. <toolset>msvc:<cxxflags>"/FIpch.hpp" ; +cpp-pch pch-dbg : pch.hpp : <define>BOOST_SPIRIT_DEBUG : + : <include>. <toolset>msvc:<cxxflags>"/FIpch.hpp" ; + +explicit pch pch-dbg ; + +############################################################################### + +rule spirit-run ( sources + : args * : input-files * : requirements * : name ? : default-build * ) +{ + name ?= $(sources[1]:D=:S=) ; + return + [ run $(sources) : $(args) : $(input-files) : $(requirements) + <pch>on-spirit:<source>pch : $(name) + : $(default-build) ] + [ run $(sources) : $(args) : $(input-files) : $(requirements) + <pch>on-spirit:<source>pch-dbg <define>BOOST_SPIRIT_DEBUG : $(name)_debug + : $(default-build) ] + ; +} + +############################################################ + +local opt = <toolset>vc-7.0:<optimization>speed + <toolset>vc-7.0:<inlining>on + <toolset>cw:<optimization>speed ; + +local opt-metrowerks = <toolset>cw:<optimization>speed ; + + +# VP, 2005/04/14: MT is not available with Como, but this is +# not handled yet. +local multi-threading = <library>/boost/thread//boost_thread + <threading>multi <define>BOOST_ALL_NO_LIB ; + + test-suite "spirit.classic.core.kernel" + : [ spirit-run match_tests.cpp ] + [ spirit-run post_skips.cpp ] + ; + + test-suite "spirit.classic.core.scanner" + : [ spirit-run scanner_tests.cpp ] + [ spirit-run scanner_value_type_tests.cpp : : : <pch>off ] + ; + + test-suite "spirit.classic.core.primitive" + : [ spirit-run primitives_tests.cpp ] + [ spirit-run char_strings_test.cpp ] + [ compile-fail char_strings_test_fail.cpp ] + [ spirit-run numerics_tests.cpp : : : $(opt) ] + [ spirit-run custom_real_parser.cpp ] + ; + + test-suite "spirit.classic.core.composite" + : [ spirit-run epsilon_tests.cpp ] + [ spirit-run negated_eps_p_test.cpp ] + [ spirit-run operators_tests.cpp ] + [ spirit-run directives_tests.cpp ] + [ spirit-run shortest_alternative_tests.cpp ] + ; + + test-suite "spirit.classic.core.non_terminal" + : [ spirit-run rule_tests.cpp : : : <pch>off ] + [ spirit-run owi_st_tests.cpp : : : <undef>BOOST_SPIRIT_THREADSAFE ] + [ spirit-run grammar_tests.cpp : : : <pch>off $(opt-metrowerks) ] + [ spirit-run grammar_multi_instance_tst.cpp : : : $(opt-metrowerks) ] + [ spirit-run subrule_tests.cpp ] + [ run owi_mt_tests.cpp : : : $(multi-threading) ] + [ run grammar_mt_tests.cpp : : : $(multi-threading) ] + [ spirit-run parser_context_test.cpp ] + ; + + # traverse_tests defines SPIRIT_DEBUG, don't run the tests twice + test-suite "spirit.classic.meta" + : [ spirit-run fundamental_tests.cpp ] + [ spirit-run parser_traits_tests.cpp ] + [ spirit-run traverse_tests.cpp : : : <pch>off <toolset>intel:<debug-symbols>off ] + ; + + test-suite "spirit.classic.attribute" + : [ spirit-run closure_tests.cpp : : : $(opt-metrowerks) ] + [ run bug_000008.cpp : : : $(multi-threading) ] + [ spirit-run parametric_tests.cpp ] + ; + + test-suite "spirit.classic.error_handling" + : [ spirit-run exception_tests.cpp ] + ; + + test-suite "spirit.classic.tree" + : [ spirit-run ast_calc_tests.cpp ] + [ spirit-run group_match_bug.cpp ] + [ spirit-run repeat_ast_tests.cpp ] + [ spirit-run tree_to_xml.cpp ] + [ compile mix_and_match_trees.cpp ] + ; + +# temporarily removed from the test suite. tree_tests are not finished, yet. +# [ spirit-run tree_tests.cpp ] + + test-suite "spirit.classic.dynamic" + : [ compile if_p_as_parser_tests.cpp ] + [ compile while_p_as_parser_tests.cpp ] + [ compile for_p_as_parser_tests.cpp ] + [ spirit-run if_tests.cpp ] + [ spirit-run if_p_int_as_condition_test.cpp ] + [ spirit-run for_tests.cpp ] + [ spirit-run while_tests.cpp ] + [ spirit-run lazy_tests.cpp ] + [ spirit-run switch_tests_eps_default.cpp : : : <pch>off ] + [ spirit-run switch_tests_general_def.cpp : : : <pch>off ] + [ spirit-run switch_tests_wo_default.cpp : : : <pch>off ] + [ spirit-run switch_tests_single.cpp : : : <pch>off ] + [ spirit-run switch_problem.cpp ] + [ spirit-run select_p_with_rule.cpp : : : <pch>off ] + ; + + test-suite "spirit.classic.utility.parsers" + : [ spirit-run chset_tests.cpp ] + [ spirit-run confix_tests.cpp ] + [ spirit-run loops_tests.cpp ] + [ spirit-run symbols_tests.cpp ] + [ spirit-run symbols_add_null.cpp : : : <pch>off ] + [ spirit-run symbols_find_null.cpp ] + [ spirit-run escape_char_parser_tests.cpp : : : $(opt) ] + [ spirit-run distinct_tests.cpp ] + [ spirit-run grammar_def_test.cpp ] + ; + + test-suite "spirit.classic.utility.support" + # This test doesn't actually use multiple threads + : [ spirit-run scoped_lock_tests.cpp : : : $(multi-threading) ] + [ compile threads_disabled_compile.cpp ] + ; + + test-suite "spirit.classic.iterator" + : [ spirit-run fixed_size_queue_tests.cpp ] + [ compile-fail fixed_size_queue_fail_tests.cpp ] + [ run file_iterator_tests.cpp : : : <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS ] + [ spirit-run multi_pass_tests.cpp : : : $(opt-metrowerks) ] + [ spirit-run sf_bug_720917.cpp : : : <pch>off $(opt-metrowerks) ] + [ spirit-run position_iterator_tests.cpp : : : $(opt-metrowerks) ] + [ compile multi_pass_compile_tests.cpp ] + ; + + test-suite "spirit.classic.small_bug_fixes" + : [ spirit-run bug_fixes.cpp ] + ; + + actor_test_sources = + action_tests + assign_test + assign_key_test + clear_test + decrement_test + erase_at_test + increment_test + insert_key_test + insert_at_test + push_back_test + push_front_test + swap_test + ; + + test-suite "spirit.classic.utility.actors" + : [ spirit-run actor/$(actor_test_sources).cpp ] + ; + + test-suite "spirit.classic.typeof-support" + : [ compile typeof_support/typeof_actor.cpp ] + [ compile typeof_support/typeof_attribute.cpp ] + [ compile typeof_support/typeof_core.cpp ] + [ compile typeof_support/typeof_debug.cpp ] + [ compile typeof_support/typeof_dynamic.cpp ] + [ compile typeof_support/typeof_error_handling.cpp ] + [ compile typeof_support/typeof_iterator.cpp ] + [ compile typeof_support/typeof_symbols.cpp ] + [ compile typeof_support/typeof_tree.cpp ] + [ compile typeof_support/typeof_utility.cpp ] + ; + + diff --git a/src/boost/libs/spirit/classic/test/actor/action_tests.cpp b/src/boost/libs/spirit/classic/test/actor/action_tests.cpp new file mode 100644 index 00000000..792ba8c0 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/action_tests.cpp @@ -0,0 +1,26 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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 "action_tests.hpp" + +int +main() +{ + assign_action_test(); + assign_key_action_test(); + clear_action_test(); + decrement_action_test(); + erase_action_test(); + increment_action_test(); + insert_key_action_test(); + push_front_action_test(); + push_back_action_test(); + swap_action_test(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/actor/action_tests.hpp b/src/boost/libs/spirit/classic/test/actor/action_tests.hpp new file mode 100644 index 00000000..a17499e1 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/action_tests.hpp @@ -0,0 +1,33 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ +#ifndef BOOST_SPIRIT_ACTOR_TEST_HPP +#define BOOST_SPIRIT_ACTOR_TEST_HPP +#include <boost/detail/lightweight_test.hpp> +#include "../impl/string_length.hpp" + +/////////////////////////////////////////////////////////////////////////////// +// Test suite for actors +/////////////////////////////////////////////////////////////////////////////// +void assign_action_test(); +void assign_key_action_test(); +void clear_action_test(); +void decrement_action_test(); +void erase_action_test(); +void increment_action_test(); +void insert_key_action_test(); +void insert_at_action_test(); +void push_back_action_test(); +void push_front_action_test(); +void swap_action_test(); + +#define BOOST_CHECK(t) BOOST_TEST((t)); +#define BOOST_CHECK_EQUAL(a, b) BOOST_TEST((a == b)); +#define BOOST_MESSAGE(m) std::cout << m << std::endl + +#endif diff --git a/src/boost/libs/spirit/classic/test/actor/assign_key_test.cpp b/src/boost/libs/spirit/classic/test/actor/assign_key_test.cpp new file mode 100644 index 00000000..f599b5e2 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/assign_key_test.cpp @@ -0,0 +1,116 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// Test suite for assign_key_actor +/////////////////////////////////////////////////////////////////////////////// + +#include "action_tests.hpp" +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_confix.hpp> +#include <boost/spirit/include/classic_lists.hpp> +#include <map> +#include <cstring> +#include <iostream> +#include <boost/spirit/include/classic_assign_key_actor.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> + +void assign_key_single_argument_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + const char* cp = "(one,0),(two,1),(three,2)"; + const char* cp_first = cp; + const char* cp_last = cp + test_impl::string_length(cp); + const char* cp_i[] = {"one","two","three"}; + int i; + typedef std::map<int,std::string> map_string_type; + map_string_type c; + map_string_type::const_iterator it_find; + std::string str; + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = list_p( + confix_p( + '(', + (*alpha_p)[ assign(str)] + >>ch_p(',') + >> int_p[ assign_key_a(c,str)] + , + ')' + ) + , + ch_p(',') + ).parse(scan); + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + BOOST_CHECK_EQUAL( c.size(), static_cast<map_string_type::size_type>(3)); + for (i=0;i<3;++i) + { + it_find = c.find(i); + BOOST_CHECK( it_find != c.end() ); + BOOST_CHECK_EQUAL( i,it_find->first); + BOOST_CHECK_EQUAL( cp_i[i],it_find->second); + } + +} + +void assign_key_two_arguments_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + const char* cp = "(0,one),(1,two),(2,three)"; + const char* cp_first = cp; + const char* cp_last = cp + test_impl::string_length(cp); + const char* cp_i[] = {"one","two","three"}; + int i; + typedef std::map<std::string, int> map_string_type; + map_string_type c; + map_string_type::const_iterator it_find; + std::string str; + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = list_p( + confix_p( + '(', + int_p[ assign_a(i)] + >>ch_p(',') + >> (*alpha_p)[ assign_key_a(c,i)] + , + ')' + ) + , + ch_p(',') + ).parse(scan); + + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + BOOST_CHECK_EQUAL( c.size(), static_cast<map_string_type::size_type>(3)); + + for (i=0;i<3;++i) + { + it_find = c.find(cp_i[i]); + BOOST_CHECK( it_find != c.end() ); + BOOST_CHECK_EQUAL( i,it_find->second); + BOOST_CHECK_EQUAL( cp_i[i],it_find->first); + } + scan.first = cp; + +} + +void assign_key_action_test() +{ + assign_key_single_argument_test(); + assign_key_two_arguments_test(); +} + diff --git a/src/boost/libs/spirit/classic/test/actor/assign_test.cpp b/src/boost/libs/spirit/classic/test/actor/assign_test.cpp new file mode 100644 index 00000000..e59fcc2c --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/assign_test.cpp @@ -0,0 +1,65 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// Test suite for assign_actor +/////////////////////////////////////////////////////////////////////////////// + +#include "action_tests.hpp" +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> + +void assign_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + const char* cp = "63"; + const char* cp_first = cp; + const char* cp_last = cp + test_impl::string_length(cp); + int h=127; + int hm=h; + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = int_p[ assign_a(hm)].parse(scan); + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + + h=63; + BOOST_CHECK_EQUAL( hm,h); +} + +void assign_test_ref() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + + const char* cp = "63"; + const char* cp_first = cp; + const char* cp_last = cp + test_impl::string_length(cp); + int h=127; + int hm=63; + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = int_p[ assign_a(h,hm)].parse(scan); + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + + BOOST_CHECK_EQUAL( hm,h); +} + +void assign_action_test() +{ + assign_test(); + assign_test_ref(); +} + diff --git a/src/boost/libs/spirit/classic/test/actor/clear_test.cpp b/src/boost/libs/spirit/classic/test/actor/clear_test.cpp new file mode 100644 index 00000000..b39d9114 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/clear_test.cpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// Test suite for clear_actor +/////////////////////////////////////////////////////////////////////////////// + +#include "action_tests.hpp" +#include <boost/spirit/include/classic_core.hpp> +#include <vector> +#include <boost/spirit/include/classic_clear_actor.hpp> + +void clear_action_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + BOOST_MESSAGE("clear_test"); + + const char* cp = "63"; + const char* cp_first = cp; + const char* cp_last = cp + test_impl::string_length(cp); + std::vector<int> c; + c.push_back(1); + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = int_p[ clear_a(c)].parse(scan); + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + BOOST_CHECK( c.empty() ); + scan.first = cp; + c.push_back(1); + + hit = str_p("63")[ clear_a(c)].parse(scan); + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + BOOST_CHECK( c.empty() ); +} + + diff --git a/src/boost/libs/spirit/classic/test/actor/decrement_test.cpp b/src/boost/libs/spirit/classic/test/actor/decrement_test.cpp new file mode 100644 index 00000000..728c838c --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/decrement_test.cpp @@ -0,0 +1,40 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// Test suite for increment_actor +/////////////////////////////////////////////////////////////////////////////// + +#include "action_tests.hpp" +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_decrement_actor.hpp> + +void decrement_action_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + BOOST_MESSAGE("decrement_test"); + + const char* cp = "63"; + const char* cp_first = cp; + const char* cp_last = cp + test_impl::string_length(cp); + int h=127; + int hm=h; + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = int_p[ decrement_a(hm)].parse(scan); + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + + --h; + BOOST_CHECK_EQUAL( hm,h); +} + diff --git a/src/boost/libs/spirit/classic/test/actor/erase_at_test.cpp b/src/boost/libs/spirit/classic/test/actor/erase_at_test.cpp new file mode 100644 index 00000000..9254b177 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/erase_at_test.cpp @@ -0,0 +1,54 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// Test suite for push_front_actor, pop_front_actor +/////////////////////////////////////////////////////////////////////////////// + +#include "action_tests.hpp" +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_erase_actor.hpp> +#include <map> + +void erase_action_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + const char* cp = "one,two,three"; + const char* cp_first = cp; + const char* cp_last = cp + test_impl::string_length(cp); + const char* cp_i[] = {"one","two","three"}; + typedef std::map<std::string, int> map_string_type; + map_string_type c; + map_string_type::const_iterator it_find; + + scanner<char const*> scan(cp_first, cp_last); + match<> hit; + + c["one"]=1; + c["two"]=2; + c["three"]=3; + c["four"]=4; + + hit = (*((+alpha_p)[ erase_a(c) ] >> !ch_p(','))).parse(scan); + + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + BOOST_CHECK_EQUAL( c.size(), static_cast<map_string_type::size_type>(1)); + for (int i=0;i<3;++i) + { + it_find = c.find(cp_i[i]); + BOOST_CHECK( it_find == c.end() ); + } + scan.first = cp; + +} + + + diff --git a/src/boost/libs/spirit/classic/test/actor/increment_test.cpp b/src/boost/libs/spirit/classic/test/actor/increment_test.cpp new file mode 100644 index 00000000..57f59970 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/increment_test.cpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// Test suite for increment_actor +/////////////////////////////////////////////////////////////////////////////// + +#include "action_tests.hpp" +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_increment_actor.hpp> + +void increment_action_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + BOOST_MESSAGE("increment_test"); + + const char* cp = "63"; + const char* cp_first = cp; + const char* cp_last = cp + test_impl::string_length(cp); + int h=127; + int hm=h; + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = int_p[ increment_a(hm)].parse(scan); + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + + ++h; + BOOST_CHECK_EQUAL( hm,h); +} + + + diff --git a/src/boost/libs/spirit/classic/test/actor/insert_at_test.cpp b/src/boost/libs/spirit/classic/test/actor/insert_at_test.cpp new file mode 100644 index 00000000..5ef6a102 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/insert_at_test.cpp @@ -0,0 +1,109 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// Test suite for insert_at_actor +/////////////////////////////////////////////////////////////////////////////// + +#include "action_tests.hpp" +#include <map> +#include <cstring> +#include <iostream> +#include <boost/spirit/include/classic_spirit.hpp> +#include <boost/spirit/include/classic_insert_at_actor.hpp> + +void insert_at_single_argument_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + const char* cp = "(one,0),(two,1),(three,2)"; + const char* cp_first = cp; + const char* cp_last = cp + std::strlen(cp); + const char* cp_i[] = {"one","two","three"}; + int i; + typedef std::map<std::string,int> map_string_type; + map_string_type c; + map_string_type::const_iterator it_find; + std::string str; + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = list_p( + confix_p( + '(', + (*alpha_p)[ assign(str)] + >>ch_p(',') + >> int_p[ insert_at_a(c,str)] + , + ')' + ) + , + ch_p(',') + ).parse(scan); + + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + BOOST_CHECK_EQUAL( c.size(), static_cast<map_string_type::size_type>(3)); + for (i=0;i<3;++i) + { + it_find = c.find(cp_i[i]); + BOOST_CHECK( it_find != c.end() ); + BOOST_CHECK_EQUAL( i,it_find->second); + BOOST_CHECK_EQUAL( cp_i[i],it_find->first); + } +} + +void insert_at_two_arguments_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + const char* cp = "(0,one),(1,two),(2,three)"; + const char* cp_first = cp; + const char* cp_last = cp + std::strlen(cp); + const char* cp_i[] = {"one","two","three"}; + int i; + typedef std::map<int,std::string> map_string_type; + map_string_type c; + map_string_type::const_iterator it_find; + std::string str; + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = list_p( + confix_p( + '(', + int_p[ assign(i)] + >>ch_p(',') + >> (*alpha_p)[ insert_at_a(c,i)] + , + ')' + ) + , + ch_p(',') + ).parse(scan); + + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + BOOST_CHECK_EQUAL( c.size(), static_cast<map_string_type::size_type>(3)); + for (i=0;i<3;++i) + { + it_find = c.find(i); + BOOST_CHECK( it_find != c.end() ); + BOOST_CHECK_EQUAL( i,it_find->first); + BOOST_CHECK_EQUAL( cp_i[i],it_find->second); + } +} + +void insert_at_action_test() +{ + insert_at_single_argument_test(); + insert_at_two_arguments_test(); +} + diff --git a/src/boost/libs/spirit/classic/test/actor/insert_key_test.cpp b/src/boost/libs/spirit/classic/test/actor/insert_key_test.cpp new file mode 100644 index 00000000..4f6eb0b5 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/insert_key_test.cpp @@ -0,0 +1,116 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// Test suite for insert_key_actor +/////////////////////////////////////////////////////////////////////////////// + +#include "action_tests.hpp" +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_confix.hpp> +#include <boost/spirit/include/classic_lists.hpp> +#include <map> +#include <cstring> +#include <iostream> +#include <boost/spirit/include/classic_insert_key_actor.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> + +void insert_key_single_argument_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + const char* cp = "(one,0),(two,1),(three,2)"; + const char* cp_first = cp; + const char* cp_last = cp + test_impl::string_length(cp); + const char* cp_i[] = {"one","two","three"}; + int i; + typedef std::map<int,std::string> map_string_type; + map_string_type c; + map_string_type::const_iterator it_find; + std::string str; + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = list_p( + confix_p( + '(', + (*alpha_p)[ assign_a(str)] + >>ch_p(',') + >> int_p[ insert_key_a(c,str)] + , + ')' + ) + , + ch_p(',') + ).parse(scan); + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + BOOST_CHECK_EQUAL( c.size(), static_cast<map_string_type::size_type>(3)); + for (i=0;i<3;++i) + { + it_find = c.find(i); + BOOST_CHECK( it_find != c.end() ); + BOOST_CHECK_EQUAL( i,it_find->first); + BOOST_CHECK_EQUAL( cp_i[i],it_find->second); + } + +} + +void insert_key_two_arguments_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + const char* cp = "(0,one),(1,two),(2,three)"; + const char* cp_first = cp; + const char* cp_last = cp + test_impl::string_length(cp); + const char* cp_i[] = {"one","two","three"}; + int i; + typedef std::map<std::string, int> map_string_type; + map_string_type c; + map_string_type::const_iterator it_find; + std::string str; + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = list_p( + confix_p( + '(', + int_p[ assign_a(i)] + >>ch_p(',') + >> (*alpha_p)[ insert_key_a(c,i)] + , + ')' + ) + , + ch_p(',') + ).parse(scan); + + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + BOOST_CHECK_EQUAL( c.size(), static_cast<map_string_type::size_type>(3)); + + for (i=0;i<3;++i) + { + it_find = c.find(cp_i[i]); + BOOST_CHECK( it_find != c.end() ); + BOOST_CHECK_EQUAL( i,it_find->second); + BOOST_CHECK_EQUAL( cp_i[i],it_find->first); + } + scan.first = cp; + +} + +void insert_key_action_test() +{ + insert_key_single_argument_test(); + insert_key_two_arguments_test(); +} + diff --git a/src/boost/libs/spirit/classic/test/actor/push_back_test.cpp b/src/boost/libs/spirit/classic/test/actor/push_back_test.cpp new file mode 100644 index 00000000..ee83c19a --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/push_back_test.cpp @@ -0,0 +1,56 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// Test suite for push_back_actor +/////////////////////////////////////////////////////////////////////////////// + +#include "action_tests.hpp" +#include <string> +#include <vector> +#include <deque> +#include <cstring> +#include <iostream> +#include <boost/spirit/include/classic_core.hpp> +#include <algorithm> +#include <boost/bind.hpp> +#include <boost/spirit/include/classic_push_back_actor.hpp> +#include <boost/spirit/include/classic_lists.hpp> + +template<typename ContainerT> +void push_back_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + const char* cp = "one,two,three"; + const char* cp_first = cp; + const char* cp_last = cp + test_impl::string_length(cp); + const char* cp_i[] = {"one","two","three"}; + int i; + ContainerT c; + typename ContainerT::const_iterator it; + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = list_p( (*alpha_p)[ push_back_a(c)] , ch_p(',') ).parse(scan); + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + BOOST_CHECK_EQUAL( c.size(), static_cast<typename ContainerT::size_type>(3)); + for (i=0, it = c.begin();i<3 && it != c.end();++i, ++it) + BOOST_CHECK_EQUAL( cp_i[i], *it); + scan.first = cp; +} + +void push_back_action_test() +{ + push_back_test< std::deque<std::string> >(); + push_back_test< std::vector<std::string> >(); +} + diff --git a/src/boost/libs/spirit/classic/test/actor/push_front_test.cpp b/src/boost/libs/spirit/classic/test/actor/push_front_test.cpp new file mode 100644 index 00000000..ac42708e --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/push_front_test.cpp @@ -0,0 +1,53 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// Test suite for push_front_actor +/////////////////////////////////////////////////////////////////////////////// + +#include "action_tests.hpp" +#include <string> +#include <vector> +#include <deque> +#include <cstring> +#include <iostream> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_push_front_actor.hpp> +#include <boost/spirit/include/classic_lists.hpp> + +template<typename ContainerT> +void push_front_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + const char* cp = "one,two,three"; + const char* cp_first = cp; + const char* cp_last = cp + test_impl::string_length(cp); + const char* cp_i[] = {"one","two","three"};; + int i; + ContainerT c; + typename ContainerT::const_iterator it; + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = list_p( (*alpha_p)[ push_front_a(c)] , ch_p(',') ).parse(scan); + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + BOOST_CHECK_EQUAL( c.size(), static_cast<typename ContainerT::size_type>(3)); + for (i=2, it = c.begin();i>=0 && it != c.end();--i, ++it) + BOOST_CHECK_EQUAL( cp_i[i], *it); + scan.first = cp; +} + +void push_front_action_test() +{ + push_front_test< std::deque<std::string> >(); +} + diff --git a/src/boost/libs/spirit/classic/test/actor/swap_test.cpp b/src/boost/libs/spirit/classic/test/actor/swap_test.cpp new file mode 100644 index 00000000..0ba203de --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/swap_test.cpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// Test suite for and_assign_actor +/////////////////////////////////////////////////////////////////////////////// + +#include "action_tests.hpp" +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_swap_actor.hpp> + +void swap_action_test() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + + const char* cp = "63"; + const char* cp_first = cp; + const char* cp_last = cp + test_impl::string_length(cp); + std::vector<int> v1,v2; + + v1.push_back(0); + v1.push_back(1); + + v2.push_back(2); + v2.push_back(3); + + scanner<char const*> scan( cp_first, cp_last ); + match<> hit; + + hit = int_p[ swap_a(v1,v2)].parse(scan); + BOOST_CHECK(hit); + BOOST_CHECK_EQUAL(scan.first, scan.last); + BOOST_CHECK(v1.size()==2); + BOOST_CHECK(v2.size()==2); + BOOST_CHECK_EQUAL(v2[0],0); + BOOST_CHECK_EQUAL(v2[1],1); + BOOST_CHECK_EQUAL(v1[0],2); + BOOST_CHECK_EQUAL(v1[1],3); +} + + diff --git a/src/boost/libs/spirit/classic/test/actor/unit_test.cpp b/src/boost/libs/spirit/classic/test/actor/unit_test.cpp new file mode 100644 index 00000000..f908155c --- /dev/null +++ b/src/boost/libs/spirit/classic/test/actor/unit_test.cpp @@ -0,0 +1,10 @@ +/*============================================================================= + Copyright (c) 2003 Jonathan de Halleux (dehalleux@pelikhan.com) + http://spirit.sourceforge.net/ + + 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/detail/lightweight_test.hpp> + diff --git a/src/boost/libs/spirit/classic/test/ast_calc_tests.cpp b/src/boost/libs/spirit/classic/test/ast_calc_tests.cpp new file mode 100644 index 00000000..a8b8be72 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/ast_calc_tests.cpp @@ -0,0 +1,279 @@ +/*============================================================================= + Copyright (c) 2001-2003 Daniel Nuffer + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ +// JDG 4-16-03 Modified from ast_calc.cpp as a test + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_ast.hpp> +#include <boost/spirit/include/classic_tree_to_xml.hpp> +#include <boost/detail/workaround.hpp> + +#include <iostream> +#include <stack> +#include <functional> +#include <string> +#include <boost/detail/lightweight_test.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +//////////////////////////////////////////////////////////////////////////// +// +// Our calculator grammar +// +//////////////////////////////////////////////////////////////////////////// +struct calculator : public grammar<calculator> +{ + static const int integerID = 1; + static const int factorID = 2; + static const int termID = 3; + static const int expressionID = 4; + + template <typename ScannerT> + struct definition + { + definition(calculator const& /*self*/) + { + // Start grammar definition + integer = leaf_node_d[real_p]; // we're not really using a real + // but just for compile checking + // the AST tree match code... + factor = integer + | inner_node_d[ch_p('(') >> expression >> ch_p(')')] + | (root_node_d[ch_p('-')] >> factor); + + term = factor >> + *( (root_node_d[ch_p('*')] >> factor) + | (root_node_d[ch_p('/')] >> factor) + ); + + expression = term >> + *( (root_node_d[ch_p('+')] >> term) + | (root_node_d[ch_p('-')] >> term) + ); + // End grammar definition + } + + rule<ScannerT, parser_context<>, parser_tag<expressionID> > expression; + rule<ScannerT, parser_context<>, parser_tag<termID> > term; + rule<ScannerT, parser_context<>, parser_tag<factorID> > factor; + rule<ScannerT, parser_context<>, parser_tag<integerID> > integer; + + rule<ScannerT, parser_context<>, parser_tag<expressionID> > const& + start() const { return expression; } + }; +}; + +//////////////////////////////////////////////////////////////////////////// +// +// Our calculator grammar, but with dynamically assigned rule ID's +// +//////////////////////////////////////////////////////////////////////////// +struct dyn_calculator : public grammar<dyn_calculator> +{ + static const int integerID = 1; + static const int factorID = 2; + static const int termID = 3; + static const int expressionID = 4; + + template <typename ScannerT> + struct definition + { + definition(dyn_calculator const& /*self*/) + { + expression.set_id(expressionID); + term.set_id(termID); + factor.set_id(factorID); + integer.set_id(integerID); + + // Start grammar definition + integer = leaf_node_d[real_p]; // we're not really using a real + // but just for compile checking + // the AST tree match code... + factor = integer + | inner_node_d[ch_p('(') >> expression >> ch_p(')')] + | (root_node_d[ch_p('-')] >> factor); + + term = factor >> + *( (root_node_d[ch_p('*')] >> factor) + | (root_node_d[ch_p('/')] >> factor) + ); + + expression = term >> + *( (root_node_d[ch_p('+')] >> term) + | (root_node_d[ch_p('-')] >> term) + ); + // End grammar definition + } + + rule<ScannerT, parser_context<>, dynamic_parser_tag> expression; + rule<ScannerT, parser_context<>, dynamic_parser_tag> term; + rule<ScannerT, parser_context<>, dynamic_parser_tag> factor; + rule<ScannerT, parser_context<>, dynamic_parser_tag> integer; + + rule<ScannerT, parser_context<>, dynamic_parser_tag> const& + start() const { return expression; } + }; +}; + +//////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +typedef char const* parser_iterator_t; +typedef tree_match<parser_iterator_t> parse_tree_match_t; +typedef parse_tree_match_t::tree_iterator iter_t; + +//////////////////////////////////////////////////////////////////////////// +long evaluate(parse_tree_match_t hit); +long eval_expression(iter_t const& i); + +long evaluate(tree_parse_info<> info) +{ + return eval_expression(info.trees.begin()); +} + +long eval_expression(iter_t const& i) +{ + switch (i->value.id().to_long()) + { + case calculator::integerID: + { + BOOST_TEST(i->children.size() == 0); + // extract integer (not always delimited by '\0') +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + // std::string(iter,iter) constructor has a bug in MWCW 8.3: + // in some situations, the null terminator won't be added + // and c_str() will return bogus data. Conservatively, I + // activate this workaround up to version 8.3. + std::vector<char> value(i->value.begin(), i->value.end()); + value.push_back('\0'); + return strtol(&value[0], 0, 10); +#else + string integer(i->value.begin(), i->value.end()); + return strtol(integer.c_str(), 0, 10); +#endif + } + + case calculator::factorID: + { + // factor can only be unary minus + BOOST_TEST(*i->value.begin() == '-'); + return - eval_expression(i->children.begin()); + } + + case calculator::termID: + { + if (*i->value.begin() == '*') + { + BOOST_TEST(i->children.size() == 2); + return eval_expression(i->children.begin()) * + eval_expression(i->children.begin()+1); + } + else if (*i->value.begin() == '/') + { + BOOST_TEST(i->children.size() == 2); + return eval_expression(i->children.begin()) / + eval_expression(i->children.begin()+1); + } + else + std::abort(); + } + + case calculator::expressionID: + { + if (*i->value.begin() == '+') + { + BOOST_TEST(i->children.size() == 2); + return eval_expression(i->children.begin()) + + eval_expression(i->children.begin()+1); + } + else if (*i->value.begin() == '-') + { + BOOST_TEST(i->children.size() == 2); + return eval_expression(i->children.begin()) - + eval_expression(i->children.begin()+1); + } + else + std::abort(); + } + + default: + std::abort(); // error + } + +#if defined(_MSC_VER) && (_MSC_VER < 1700) + return 0; +#endif +} + +//////////////////////////////////////////////////////////////////////////// +int +parse(char const* str) +{ + calculator calc; + tree_parse_info<> info = ast_parse(str, calc, space_p); + + if (info.full) + return evaluate(info); + else + return -1; +} + +int +parse_dyn(char const* str) +{ + dyn_calculator calc; + tree_parse_info<> info = ast_parse(str, calc, space_p); + + if (info.full) + return evaluate(info); + else + return -1; +} + +int +main() +{ +// test the calculator with statically assigned rule ID's + BOOST_TEST(parse("12345") == 12345); + BOOST_TEST(parse("-12345") == -12345); + BOOST_TEST(parse("1 + 2") == 1 + 2); + BOOST_TEST(parse("1 * 2") == 1 * 2); + BOOST_TEST(parse("1/2 + 3/4") == 1/2 + 3/4); + BOOST_TEST(parse("1 + 2 + 3 + 4") == 1 + 2 + 3 + 4); + BOOST_TEST(parse("1 * 2 * 3 * 4") == 1 * 2 * 3 * 4); + BOOST_TEST(parse("(1 + 2) * (3 + 4)") == (1 + 2) * (3 + 4)); + BOOST_TEST(parse("(-1 + 2) * (3 + -4)") == (-1 + 2) * (3 + -4)); + BOOST_TEST(parse("1 + ((6 * 200) - 20) / 6") == 1 + ((6 * 200) - 20) / 6); + BOOST_TEST(parse("(1 + (2 + (3 + (4 + 5))))") == (1 + (2 + (3 + (4 + 5))))); + BOOST_TEST(parse("1 + 2 + 3 + 4 + 5") == 1 + 2 + 3 + 4 + 5); + BOOST_TEST(parse("(12 * 22) + (36 + -4 + 5)") == (12 * 22) + (36 + -4 + 5)); + BOOST_TEST(parse("(12 * 22) / (5 - 10 + 15)") == (12 * 22) / (5 - 10 + 15)); + BOOST_TEST(parse("12 * 6 * 15 + 5 - 25") == 12 * 6 * 15 + 5 - 25); + +// test the calculator with dynamically assigned rule ID's + BOOST_TEST(parse_dyn("12345") == 12345); + BOOST_TEST(parse_dyn("-12345") == -12345); + BOOST_TEST(parse_dyn("1 + 2") == 1 + 2); + BOOST_TEST(parse_dyn("1 * 2") == 1 * 2); + BOOST_TEST(parse_dyn("1/2 + 3/4") == 1/2 + 3/4); + BOOST_TEST(parse_dyn("1 + 2 + 3 + 4") == 1 + 2 + 3 + 4); + BOOST_TEST(parse_dyn("1 * 2 * 3 * 4") == 1 * 2 * 3 * 4); + BOOST_TEST(parse_dyn("(1 + 2) * (3 + 4)") == (1 + 2) * (3 + 4)); + BOOST_TEST(parse_dyn("(-1 + 2) * (3 + -4)") == (-1 + 2) * (3 + -4)); + BOOST_TEST(parse_dyn("1 + ((6 * 200) - 20) / 6") == 1 + ((6 * 200) - 20) / 6); + BOOST_TEST(parse_dyn("(1 + (2 + (3 + (4 + 5))))") == (1 + (2 + (3 + (4 + 5))))); + BOOST_TEST(parse_dyn("1 + 2 + 3 + 4 + 5") == 1 + 2 + 3 + 4 + 5); + BOOST_TEST(parse_dyn("(12 * 22) + (36 + -4 + 5)") == (12 * 22) + (36 + -4 + 5)); + BOOST_TEST(parse_dyn("(12 * 22) / (5 - 10 + 15)") == (12 * 22) / (5 - 10 + 15)); + BOOST_TEST(parse_dyn("12 * 6 * 15 + 5 - 25") == 12 * 6 * 15 + 5 - 25); + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/spirit/classic/test/bug_000008.cpp b/src/boost/libs/spirit/classic/test/bug_000008.cpp new file mode 100644 index 00000000..0d52cb34 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/bug_000008.cpp @@ -0,0 +1,115 @@ +/*============================================================================= + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + + // see http://article.gmane.org/gmane.comp.parsers.spirit.general/4575 + // or https://sf.net/mailarchive/forum.php?thread_id=2692308&forum_id=1595 + // for a description of the bug being tested for by this program + // + // the problem should be solved with version 1.3 of phoenix/closures.hpp> + +#if defined(BOOST_SPIRIT_DEBUG) && defined(__GNUC__) && defined(__WIN32__) +// It seems that MinGW has some problems with threads and iostream ? +// This code crashes MinGW when BOOST_SPIRIT_DEBUG is defined. The reason +// is beyond me. Disable BOOST_SPIRIT_DEBUG for now. +#undef BOOST_SPIRIT_DEBUG +#endif + +#include <iostream> +#include <boost/config.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined(DONT_HAVE_BOOST) || !defined(BOOST_HAS_THREADS) || defined(BOOST_DISABLE_THREADS) +// we end here if we can't do multithreading +static void skipped() +{ + std::cout << "skipped\n"; +} + +int +main() +{ + skipped(); + return boost::report_errors(); +} + +#else +// the real MT stuff + +#undef BOOST_SPIRIT_THREADSAFE +#define BOOST_SPIRIT_THREADSAFE +#undef PHOENIX_THREADSAFE +#define PHOENIX_THREADSAFE + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_closure.hpp> +#include <boost/thread.hpp> + +static const int number_of_calls_to_parse_per_thread=20000; + +struct test_closure + : BOOST_SPIRIT_CLASSIC_NS::closure<test_closure, char const*> +{ + member1 b; +}; + +struct test_grammar + : BOOST_SPIRIT_CLASSIC_NS::grammar<test_grammar, test_closure::context_t> +{ + test_grammar() {} + + template <typename ScannerT> + struct definition + { + definition(test_grammar const &self) + { + using namespace phoenix; + rule = BOOST_SPIRIT_CLASSIC_NS::epsilon_p[self.b = arg1]; + } + + BOOST_SPIRIT_CLASSIC_NS::rule<ScannerT> const &start() const { return rule; } + + BOOST_SPIRIT_CLASSIC_NS::rule<ScannerT> rule; + }; +}; + +test_grammar const g; + +void +in_thread(void) +{ + char const text[]="foo"; + for(int i=0; i<number_of_calls_to_parse_per_thread; ++i) + { + BOOST_SPIRIT_CLASSIC_NS::parse(&text[0], text+sizeof(text), g); + } +} + +void +bug_000008() +{ + boost::thread t1(in_thread); + boost::thread t2(in_thread); + boost::thread t3(in_thread); + boost::thread t4(in_thread); + + t1.join(); + t2.join(); + t3.join(); + t4.join(); +} + +int +main() +{ + bug_000008(); + return boost::report_errors(); +} + +#endif + diff --git a/src/boost/libs/spirit/classic/test/bug_fixes.cpp b/src/boost/libs/spirit/classic/test/bug_fixes.cpp new file mode 100644 index 00000000..69490b8b --- /dev/null +++ b/src/boost/libs/spirit/classic/test/bug_fixes.cpp @@ -0,0 +1,365 @@ +/*============================================================================= + Copyright (c) 2003 Giovanni Bajo + Copyright (c) 2003 Joel de Guzman + Copyright (c) 2003 Vaclav Vesely + http://spirit.sourceforge.net/ + + 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/detail/lightweight_test.hpp> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> + +using namespace boost; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// bug_001 +// +// access_node_d[] and access_match_d[] iterator bug +// http://sf.net/mailarchive/forum.php?thread_id=1963157&forum_id=1595 +// http://sf.net/mailarchive/forum.php?thread_id=1966224&forum_id=1595 +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_ast.hpp> + +struct my_action +{ + template <typename TreeT, typename IterT> + void operator()(TreeT& /*t*/, IterT begin, IterT end) const + { + BOOST_TEST(*begin == '1'); + BOOST_TEST(*end == '2'); + } +}; + +void bug_001() +{ + const char* text = "123"; + + ast_parse(text, text+3, access_node_d[chlit<>('1')][my_action()]); + ast_parse(text, text+3, access_match_d[chlit<>('1')][my_action()]); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// bug_001 +// +// mismatch closure return type bug +// http://article.gmane.org/gmane.comp.parsers.spirit.general/3678 +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_attribute.hpp> +#include <string> + +typedef std::string member_type; + +struct my_closure: closure<my_closure, member_type> +{ + member1 val; +}; + +void bug_002() +{ + rule<scanner<char const*>, my_closure::context_t> my_rule = real_p; + BOOST_TEST(parse("1", my_rule).full); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// bug_003 +// +// impl::detach_clear bug +// http://sourceforge.net/mailarchive/forum.php?thread_id=2008510&forum_id=25901 +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_chset.hpp> + +void bug_003() +{ + chset<> set; + set = 'a'; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// bug_004 +// +// chset<>::operator~(range<>) bug +// operator&(chset<>, range<>) bug +// operator&(range<>, chset<>) bug +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/limits.hpp> +#include <boost/spirit/include/classic_chset.hpp> + +void bug_004() +{ + const char min = (std::numeric_limits<char>::min)(); + const char max = (std::numeric_limits<char>::max)(); + + { + chset<> set(~range<>(min, max)); + BOOST_TEST(set.test(min) == false); + BOOST_TEST(set.test(min) == false); + } + + { + chset<> set(chset<>(anychar_p) & range<>(min, max)); + BOOST_TEST(set.test(min) == true); + BOOST_TEST(set.test(min) == true); + } + + { + chset<> set(range<>(min, max) & chset<>(anychar_p)); + BOOST_TEST(set.test(min) == true); + BOOST_TEST(set.test(min) == true); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// bug_005 +// +// Most trailing space bug +// http://article.gmane.org/gmane.comp.parsers.spirit.general/4029 +// JDG: Oct 18, 2005. We shall revert to the previous behavior where +// Post skips are not allowed. The reason is that +// there is a valid use case where input is obtained +// from cin and multi_pass which results in an infinite +// loop while the post skipper waits for a whitespace. +// For examples like below, the grammar must explicitly +// include the post whitespace. One possible way is to +// place an end_p at the end of the grammar. The end_p +// will trigger the post-skip. +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> + +using namespace boost; +using namespace spirit; + +void bug_005() +{ + BOOST_TEST( + parse(" aaaaaaaaa ", *ch_p('a') >> end_p, space_p).full + ); + + BOOST_TEST( + parse(" aaaaaaaaa ", lexeme_d[*ch_p('a')] >> end_p, space_p).full + ); + +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) + // not sure why Code Warrior 9.5 does not recognize ch_p(' ') as the + // same as space_p (see above) when the inputs are spaces. The + // tests below are redundant anyway. +#else + + BOOST_TEST( + parse(" aaaaaaaaa ", *ch_p('a') >> end_p, ch_p(' ')).full + ); + + BOOST_TEST( + parse(" aaaaaaaaa ", lexeme_d[*ch_p('a')] >> end_p, ch_p(' ')).full + ); + +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +// +// bug_006 +// +// confix bug +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/limits.hpp> +#include <boost/spirit/include/classic_confix.hpp> + +void bug_006() +{ + BOOST_TEST(parse("#some comment", comment_p('#')).full); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// bug_007 +// +// handling of trailing whitespace bug (ast_parse/pt_parse related) +// JDG: Oct 18, 2005. We shall revert to the previous behavior where +// Post skips are not allowed. The reason is that +// there is a valid use case where input is obtained +// from cin and multi_pass which results in an infinite +// loop while the post skipper waits for a whitespace. +// For examples like below, the grammar must explicitly +// include the post whitespace. One possible way is to +// place an end_p at the end of the grammar. The end_p +// will trigger the post-skip. +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_ast.hpp> +#include <boost/spirit/include/classic_parse_tree.hpp> + +void bug_007() +{ + BOOST_TEST(parse("test ", str_p("test") >> end_p, space_p).full); + BOOST_TEST(pt_parse("test ", str_p("test") >> end_p, space_p).full); + BOOST_TEST(ast_parse("test ", str_p("test") >> end_p, space_p).full); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// sf_bug_718903 +// +// see https://sourceforge.net/tracker/index.php +// ?func=detail&aid=718903&group_id=28447&atid=393386 +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/cstdlib.hpp> +#include <boost/spirit/include/classic_chset.hpp> + +void sf_bug_718903() +{ + empty_match_parser<chset<char> > + e(epsilon_p(chset_p("abc"))); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// sf_bug_719322 +// range_run bug +// +// see http://sourceforge.net/tracker/index.php +// ?func=detail&aid=719322&group_id=28447&atid=393386 +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_basic_chset.hpp> + +void sf_bug_719322() +{ + basic_chset<int> s; + s.set(3, 3); + s.set(1, 5); + BOOST_TEST(s.test(5)); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// sf_bug_742038 +// +// see http://sf.net/tracker/ +// ?func=detail&atid=393386&aid=742038&group_id=28447 +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_position_iterator.hpp> +#include <boost/spirit/include/classic_file_iterator.hpp> +#include <string> +#include <fstream> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> +#include <stdio.h> + +template <typename IterT> +void test_assign(IterT b, IterT e) +{ + typedef scanner<IterT> scanner_t; + +#if (defined(__GNUC__) && defined(__MINGW32__)) \ + || (defined(__GNUC__) && (__GNUC_MINOR__ < 20)) + +// There's a bug in g++3.x on MinGW that makes basic_string assert +// when assigning from IterT [f, l) where IterT is a position_iterator. +// This issue is discussed here: +// +// http://gcc.gnu.org/ml/libstdc++/2002-03/msg00196.html +// +// Aparently, this bug is only present on MinGW. I'm clueless as +// to why this is so. Regressions on linux seem to be OK! :( +// +// With, g++3.1, assigning to basic_string from IterT [f, l) is a +// compile error (a g++3.1 bug). +// +// In both cases above, we use a vector instead of a string. + + typedef std::vector<char> store; +#else + typedef std::string store; +#endif + + store dst; + rule<scanner_t> r = (*alpha_p)[assign_a(dst)]; + + parse(b, e, r); + + store::iterator d = dst.begin(); + + while (b != e) + { + if (*d != *b) + BOOST_TEST(*d == *b); + ++b; + ++d; + } +} + +void sf_bug_742038() +{ + std::string src = "abcdef"; + const char* tmpfilename = "sf_bug_742038.tmp"; + + test_assign(src.begin(), src.end()); + + position_iterator<std::string::iterator> b(src.begin(), src.end(), ""); + position_iterator<std::string::iterator> e; + test_assign(b, e); + + { + std::fstream f(tmpfilename, std::ios::out); + f << src; + f.close(); + + file_iterator<> b1(tmpfilename); + file_iterator<> e1(b1.make_end()); + test_assign(b1, e1); + } + + std::remove(tmpfilename); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// bug_009 +// +// limit_d bug +// http://article.gmane.org/gmane.comp.parsers.spirit.devel/1891/ +// +/////////////////////////////////////////////////////////////////////////////// +void +bug_009() +{ + parse( + "test" + , limit_d(1U, 10U)[uint_p] | str_p("test")); +} + +int +main() +{ + bug_001(); + bug_002(); + bug_003(); + bug_004(); + bug_005(); + bug_006(); + bug_007(); + bug_009(); + + sf_bug_718903(); + sf_bug_719322(); + sf_bug_742038(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/char_strings_test.cpp b/src/boost/libs/spirit/classic/test/char_strings_test.cpp new file mode 100644 index 00000000..f2507a5f --- /dev/null +++ b/src/boost/libs/spirit/classic/test/char_strings_test.cpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2004 Joao Abecasis + http://spirit.sourceforge.net/ + + 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/include/classic_primitives.hpp> +#include <boost/spirit/include/classic_rule.hpp> + +#include <string> + +int main() +{ + using BOOST_SPIRIT_CLASSIC_NS::rule; + using BOOST_SPIRIT_CLASSIC_NS::str_p; + using BOOST_SPIRIT_CLASSIC_NS::ch_p; + + using std::string; + + string str = "abcd"; + + rule<> strings = str_p("abcd"); + strings = str_p('a'); + strings = str_p(str.begin(), str.end()); + + rule<> chars = ch_p('a'); + chars = ch_p("b"); +} + diff --git a/src/boost/libs/spirit/classic/test/char_strings_test_fail.cpp b/src/boost/libs/spirit/classic/test/char_strings_test_fail.cpp new file mode 100644 index 00000000..3bba0b56 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/char_strings_test_fail.cpp @@ -0,0 +1,19 @@ +/*============================================================================= + Copyright (c) 2004 Joao Abecasis + http://spirit.sourceforge.net/ + + 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/include/classic_primitives.hpp> +#include <boost/spirit/include/classic_rule.hpp> + +int main() +{ + using BOOST_SPIRIT_CLASSIC_NS::rule; + using BOOST_SPIRIT_CLASSIC_NS::ch_p; + + rule<> chars = ch_p("string"); +} diff --git a/src/boost/libs/spirit/classic/test/chset_tests.cpp b/src/boost/libs/spirit/classic/test/chset_tests.cpp new file mode 100644 index 00000000..8955b152 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/chset_tests.cpp @@ -0,0 +1,331 @@ +/*============================================================================= + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2001-2003 Daniel Nuffer + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "impl/sstream.hpp" + +#include <boost/spirit/include/classic_chset.hpp> + +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +namespace +{ + /////////////////////////////////////////////////////////////////////////// + // + // chset tests + // + /////////////////////////////////////////////////////////////////////////// + void + DrawRuler(sstream_t& out, char const* str) + { + out << std::endl << std::endl; + out << "\t_____________________________________________________________\n"; + out << "\t" << str << std::endl; + out << "\t"; + for (char i = '!'; i < '^'; i++) + out << i; + out << "\n"; + out << "\t_____________________________________________________________\n\n"; + } + + ////////////////////////////////// + template <typename CharT> + void + Draw(sstream_t& out, chset<CharT> a, char const* str) + { + out << "\t"; + + for (int i = '!'; i < '^'; i++) + if (a.test(CharT(i))) + out << '*'; + else + out << " "; + + out << "\t" << str << std::endl; + } + + ////////////////////////////////// + template <typename CharT> + void + chset_tests(sstream_t& out, CharT const* a_, CharT b1_, CharT b2_, CharT e1_) + { + chset<CharT> a(a_); + range<CharT> b_(b1_, b2_); + chset<CharT> b(b_); + chset<CharT> c(~a); // ~char_parser code must not interfere + // with chset + negated_char_parser<range<CharT> > d_(~b_); + chset<CharT> d(d_); + chlit<CharT> e_(e1_); + chset<CharT> e(e_); + negated_char_parser<chlit<CharT> > f_(e1_); + chset<CharT> f(f_); + + DrawRuler(out, "Initial"); + Draw(out, a, "a"); + Draw(out, b, "b"); + Draw(out, d, "d"); + Draw(out, e, "e"); + Draw(out, f, "f"); + + DrawRuler(out, "Inverse"); + Draw(out, ~a, "~a"); + Draw(out, c, "chset<>(~a)"); + Draw(out, ~~a, "~~a"); + Draw(out, ~b, "~b"); + + DrawRuler(out, "Union"); + Draw(out, a, "a"); + Draw(out, b, "b"); + Draw(out, d, "d"); + Draw(out, e, "e"); + Draw(out, f, "f"); + Draw(out, a | b, "a | b"); + Draw(out, a | b_, "a | b_"); + Draw(out, b_ | a, "b_ | a"); + Draw(out, a | anychar_p, "a | anychar_p"); + Draw(out, b | anychar_p, "b | anychar_p"); + Draw(out, a | d, "a | d"); + Draw(out, a | d_, "a | d_"); + Draw(out, d_ | a, "d_ | a"); + Draw(out, a | e_, "a | e_"); + Draw(out, e_ | b, "e_ | b"); + Draw(out, a | f_, "a | f_"); + Draw(out, f_ | b, "f_ | b"); + + DrawRuler(out, "Intersection"); + Draw(out, a, "a"); + Draw(out, b, "b"); + Draw(out, d, "d"); + Draw(out, e, "e"); + Draw(out, f, "f"); + Draw(out, a & b, "a & b"); + Draw(out, a & b_, "a & b_"); + Draw(out, b_ & a, "b_ & a"); + Draw(out, a & d, "a & d"); + Draw(out, a & d_, "a & d_"); + Draw(out, d_ & a, "d_ & a"); + Draw(out, a & e_, "a & e_"); + Draw(out, e_ & b, "e_ & b"); + Draw(out, a & f_, "a & f_"); + Draw(out, f_ & b, "f_ & b"); + Draw(out, a & anychar_p, "a & anychar_p"); + Draw(out, b & anychar_p, "b & anychar_p"); + + DrawRuler(out, "Difference"); + Draw(out, a, "a"); + Draw(out, b, "b"); + Draw(out, d, "d"); + Draw(out, e, "e"); + Draw(out, f, "f"); + Draw(out, a - b, "a - b"); + Draw(out, b - a, "b - a"); + Draw(out, a - b_, "a - b_"); + Draw(out, b_ - a, "b_ - a"); + Draw(out, a - d, "a - d"); + Draw(out, d - a, "d - a"); + Draw(out, a - d_, "a - d_"); + Draw(out, d_ - a, "d_ - a"); + Draw(out, a - e_, "a - e_"); + Draw(out, e_ - b, "e_ - b"); + Draw(out, a - f_, "a - f_"); + Draw(out, f_ - b, "f_ - b"); + Draw(out, a - anychar_p, "a - anychar_p"); + Draw(out, anychar_p - a, "anychar_p - a"); + Draw(out, b - anychar_p, "b - anychar_p"); + Draw(out, anychar_p - b, "anychar_p - b"); + + DrawRuler(out, "Xor"); + Draw(out, a, "a"); + Draw(out, b, "b"); + Draw(out, d, "d"); + Draw(out, e, "e"); + Draw(out, f, "f"); + Draw(out, a ^ b, "a ^ b"); + Draw(out, a ^ b_, "a ^ b_"); + Draw(out, b_ ^ a, "b_ ^ a"); + Draw(out, a ^ d, "a ^ d"); + Draw(out, a ^ d_, "a ^ d_"); + Draw(out, d_ ^ a, "d_ ^ a"); + Draw(out, a ^ e_, "a ^ e_"); + Draw(out, e_ ^ b, "e_ ^ b"); + Draw(out, a ^ f_, "a ^ f_"); + Draw(out, f_ ^ b, "f_ ^ b"); + Draw(out, a ^ nothing_p, "a ^ nothing_p"); + Draw(out, a ^ anychar_p, "a ^ anychar_p"); + Draw(out, b ^ nothing_p, "b ^ nothing_p"); + Draw(out, b ^ anychar_p, "b ^ anychar_p"); + } + + char const* expected_output = + "\n\n" + "\t_____________________________________________________________\n" + "\tInitial\n" + "\t!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]\n" + "\t_____________________________________________________________\n" + "\n" + "\t ********** ************************** \ta\n" + "\t ********************** \tb\n" + "\t******************** *******************\td\n" + "\t * \te\n" + "\t***************** *******************************************\tf\n" + "\n" + "\n" + "\t_____________________________________________________________\n" + "\tInverse\n" + "\t!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]\n" + "\t_____________________________________________________________\n" + "\n" + "\t*************** ******* ***\t~a\n" + "\t*************** ******* ***\tchset<>(~a)\n" + "\t ********** ************************** \t~~a\n" + "\t******************** *******************\t~b\n" + "\n" + "\n" + "\t_____________________________________________________________\n" + "\tUnion\n" + "\t!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]\n" + "\t_____________________________________________________________\n" + "\n" + "\t ********** ************************** \ta\n" + "\t ********************** \tb\n" + "\t******************** *******************\td\n" + "\t * \te\n" + "\t***************** *******************************************\tf\n" + "\t ******************************************* \ta | b\n" + "\t ******************************************* \ta | b_\n" + "\t ******************************************* \tb_ | a\n" + "\t*************************************************************\ta | anychar_p\n" + "\t*************************************************************\tb | anychar_p\n" + "\t************************* *****************************\ta | d\n" + "\t************************* *****************************\ta | d_\n" + "\t************************* *****************************\td_ | a\n" + "\t ********** ************************** \ta | e_\n" + "\t * ********************** \te_ | b\n" + "\t*************************************************************\ta | f_\n" + "\t***************** *******************************************\tf_ | b\n" + "\n" + "\n" + "\t_____________________________________________________________\n" + "\tIntersection\n" + "\t!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]\n" + "\t_____________________________________________________________\n" + "\n" + "\t ********** ************************** \ta\n" + "\t ********************** \tb\n" + "\t******************** *******************\td\n" + "\t * \te\n" + "\t***************** *******************************************\tf\n" + "\t ***** ********** \ta & b\n" + "\t ***** ********** \ta & b_\n" + "\t ***** ********** \tb_ & a\n" + "\t ***** **************** \ta & d\n" + "\t ***** **************** \ta & d_\n" + "\t ***** **************** \td_ & a\n" + "\t * \ta & e_\n" + "\t \te_ & b\n" + "\t ** ******* ************************** \ta & f_\n" + "\t ********************** \tf_ & b\n" + "\t ********** ************************** \ta & anychar_p\n" + "\t ********************** \tb & anychar_p\n" + "\n" + "\n" + "\t_____________________________________________________________\n" + "\tDifference\n" + "\t!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]\n" + "\t_____________________________________________________________\n" + "\n" + "\t ********** ************************** \ta\n" + "\t ********************** \tb\n" + "\t******************** *******************\td\n" + "\t * \te\n" + "\t***************** *******************************************\tf\n" + "\t ***** **************** \ta - b\n" + "\t ******* \tb - a\n" + "\t ***** **************** \ta - b_\n" + "\t ******* \tb_ - a\n" + "\t ***** ********** \ta - d\n" + "\t*************** ***\td - a\n" + "\t ***** ********** \ta - d_\n" + "\t*************** ***\td_ - a\n" + "\t ** ******* ************************** \ta - e_\n" + "\t * \te_ - b\n" + "\t * \ta - f_\n" + "\t***************** ** *******************\tf_ - b\n" + "\t \ta - anychar_p\n" + "\t*************** ******* ***\tanychar_p - a\n" + "\t \tb - anychar_p\n" + "\t******************** *******************\tanychar_p - b\n" + "\n" + "\n" + "\t_____________________________________________________________\n" + "\tXor\n" + "\t!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]\n" + "\t_____________________________________________________________\n" + "\n" + "\t ********** ************************** \ta\n" + "\t ********************** \tb\n" + "\t******************** *******************\td\n" + "\t * \te\n" + "\t***************** *******************************************\tf\n" + "\t ***** ******* **************** \ta ^ b\n" + "\t ***** ******* **************** \ta ^ b_\n" + "\t ***** ******* **************** \tb_ ^ a\n" + "\t*************** ***** ********** ***\ta ^ d\n" + "\t*************** ***** ********** ***\ta ^ d_\n" + "\t*************** ***** ********** ***\td_ ^ a\n" + "\t ** ******* ************************** \ta ^ e_\n" + "\t * ********************** \te_ ^ b\n" + "\t*************** * ******* ***\ta ^ f_\n" + "\t***************** ** *******************\tf_ ^ b\n" + "\t ********** ************************** \ta ^ nothing_p\n" + "\t*************** ******* ***\ta ^ anychar_p\n" + "\t ********************** \tb ^ nothing_p\n" + "\t******************** *******************\tb ^ anychar_p\n" + ; + + void chset_tests() + { + sstream_t tout, aout, bout; + + tout << expected_output; + + chset_tests(aout, "0-9A-Z", '5', 'J', '2'); + chset_tests(bout, L"0-9A-Z", L'5', L'J', L'2'); + +#define narrow_chset_works (getstring(aout) == getstring(tout)) +#define wide_chset_works (getstring(bout) == getstring(tout)) + + if (!narrow_chset_works || !wide_chset_works) + { + std::cout << "EXPECTED:\n" << + getstring(tout); + std::cout << "GOT:\n" << + getstring(aout); + std::cout << "AND:\n" << + getstring(bout); + } + + BOOST_TEST(narrow_chset_works); + BOOST_TEST(wide_chset_works); + } + +} // namespace + +int +main() +{ + chset_tests(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/closure_tests.cpp b/src/boost/libs/spirit/classic/test/closure_tests.cpp new file mode 100644 index 00000000..f05d7210 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/closure_tests.cpp @@ -0,0 +1,157 @@ +/*============================================================================= + Copyright (c) 2001-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> + + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_closure.hpp> +#include <boost/spirit/include/classic_parametric.hpp> +#include <boost/spirit/include/phoenix1_binders.hpp> +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +/////////////////////////////////////////////////////////////////////////////// +// +// Closure tests +// +/////////////////////////////////////////////////////////////////////////////// +struct my_closure1 : BOOST_SPIRIT_CLASSIC_NS::closure<my_closure1, double> +{ + member1 val; +}; + +struct my_closure2 : BOOST_SPIRIT_CLASSIC_NS::closure<my_closure2, char> +{ + member1 ch; +}; + +struct my_closure3 : BOOST_SPIRIT_CLASSIC_NS::closure<my_closure3, char> +{ + member1 ch; +}; + +struct X { int a; int b; }; + +#if defined(BOOST_SPIRIT_DEBUG) +// If debugging is switched on, all closure members should have a +// corresponding output streaming operator +std::ostream & +operator<< (std::ostream& o, X const &x) +{ + o << "X(" << x.a << ", " << x.b << ")"; + return o; +} +#endif // defined(BOOST_SPIRIT_DEBUG) + +struct my_closure4 : BOOST_SPIRIT_CLASSIC_NS::closure<my_closure4, X> +{ + member1 x; +}; + +// MWCW8.3 needs the default constructor here or it won't compile. +// It should not be needed. +struct Y { Y() {} Y(int) {} }; + +#if defined(BOOST_SPIRIT_DEBUG) +// If debugging is switched on, all closure members should have a +// corresponding output streaming operator +std::ostream & +operator<< (std::ostream& o, Y const &/*x*/) +{ + o << "Y"; + return o; +} +#endif // defined(BOOST_SPIRIT_DEBUG) + +struct my_closure5 : BOOST_SPIRIT_CLASSIC_NS::closure<my_closure5, int, Y> +{ + member1 y; +}; + +struct my_closure6 : BOOST_SPIRIT_CLASSIC_NS::closure<my_closure6, int, int, int> +{ + member1 x; + member2 y; + member3 z; +}; + +void +closure_tests() +{ + rule<phrase_scanner_t, my_closure1::context_t> num_list; + double n; + + num_list = + ( + real_p[num_list.val = arg1] >> *(',' >> real_p[num_list.val += arg1]) + ) + [var(n) = num_list.val]; + + parse_info<char const*> pi; + pi = parse("123, 456, 789", num_list, space_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(n == 123 + 456 + 789); + + rule<scanner<>, my_closure2::context_t> rev; + rev = anychar_p[rev.ch = arg1] >> !rev >> f_ch_p(rev.ch); + + pi = parse("xyzzyx", rev); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("xyzczyx", rev); + BOOST_TEST(!pi.hit); + + subrule<0, my_closure3::context_t> rev2; + pi = parse("atoyyota", + rev2 = anychar_p[rev2.ch = arg1] >> !rev2 >> f_ch_p(rev2.ch) + ); + + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("whatdahell", + rev2 = anychar_p[rev2.ch = arg1] >> !rev2 >> f_ch_p(rev2.ch) + ); + BOOST_TEST(!pi.hit); + + rule<phrase_scanner_t, my_closure4::context_t> complex_p; + complex_p = + int_p[bind(&X::a)(complex_p.x) = arg1] + >> ',' + >> int_p[bind(&X::b)(complex_p.x) = arg1] + ; + + X x; + pi = parse("123, 456", complex_p[var(x) = arg1], space_p); + BOOST_TEST(pi.hit); + BOOST_TEST(x.a == 123); + BOOST_TEST(x.b == 456); + + rule<scanner<>, my_closure5::context_t> init1; // compile check only + rule<> r1 = init1(3, 3); // member2 is constructed from int + + rule<scanner<>, my_closure6::context_t> init2; // compile check only + rule<> r2 = init2(3); // member2 and member3 are default constructed +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Main +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + closure_tests(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/confix_tests.cpp b/src/boost/libs/spirit/classic/test/confix_tests.cpp new file mode 100644 index 00000000..f1466a82 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/confix_tests.cpp @@ -0,0 +1,60 @@ +/*============================================================================= + Copyright (c) 2003 2003 Vaclav Vesely + http://spirit.sourceforge.net/ + + 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/include/classic_core.hpp> +#include <boost/spirit/include/classic_confix.hpp> +#include <boost/detail/lightweight_test.hpp> + +using namespace boost; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +typedef + scanner<char const*, scanner_policies<skipper_iteration_policy<> > > + scanner_t; + +typedef + rule<scanner_t> + rule_t; + +void comment_nest_p_test() +{ + rule_t r = comment_nest_p('{', '}'); + + { + parse_info<> info = parse("{a{b}c{d}e}", r, space_p); + BOOST_TEST(info.full); + } + + { + parse_info<> info = parse("{a{b}c{d}e}x", r, space_p); + BOOST_TEST(info.hit); + BOOST_TEST(info.length == 11); + } + + { + char const* str = "x{a{b}c{d}e}"; + parse_info<> info = parse(str, r, space_p); + BOOST_TEST(!info.hit); + BOOST_TEST(info.stop == str); + } + + { + char const* str = "{a{b}c{d}e"; + parse_info<> info = parse(str, r, space_p); + BOOST_TEST(!info.hit); + BOOST_TEST(info.stop == (str + 10)); + } +} + +int +main() +{ + comment_nest_p_test(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/custom_real_parser.cpp b/src/boost/libs/spirit/classic/test/custom_real_parser.cpp new file mode 100644 index 00000000..9971a69c --- /dev/null +++ b/src/boost/libs/spirit/classic/test/custom_real_parser.cpp @@ -0,0 +1,33 @@ +/*============================================================================= + Copyright (c) 2007 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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/detail/lightweight_test.hpp> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_actor.hpp> +#include <boost/math/concepts/real_concept.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; +using boost::math::concepts::real_concept; + +int main() +{ + real_parser<real_concept> const rr_p; + bool started = false; + real_concept a, b; + + parse_info<> pi = parse("range 0 1", + str_p("range")[assign_a(started, false)] + && rr_p[assign_a(a)] + && rr_p[assign_a(b)], + space_p); + + BOOST_TEST(pi.full && a == 0.0 && b == 1.0); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/directives_tests.cpp b/src/boost/libs/spirit/classic/test/directives_tests.cpp new file mode 100644 index 00000000..e45b9d7f --- /dev/null +++ b/src/boost/libs/spirit/classic/test/directives_tests.cpp @@ -0,0 +1,189 @@ +/*============================================================================= + Copyright (c) 2001-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> +#include <string> + + +#include "impl/string_length.hpp" +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Directives tests +// +/////////////////////////////////////////////////////////////////////////////// +void +directives_test1() +{ + char const* cpx = "H e l l o"; + char const* cpx_first = cpx; + char const* cpx_last = cpx + test_impl::string_length(cpx); + + match<> hit; + typedef skipper_iteration_policy<iteration_policy> iter_policy; + scanner<char const*, scanner_policies<iter_policy> > + scanx(cpx_first, cpx_last); + + hit = str_p("Hello").parse(scanx); + BOOST_TEST(!hit); + scanx.first = cpx; + + hit = chseq_p("Hello").parse(scanx); + BOOST_TEST(!!hit); + scanx.first = cpx; + + char const* cp = "Hello \n\tWorld"; + char const* cp_first = cp; + char const* cp_last = cp + test_impl::string_length(cp); + + scanner<char const*, scanner_policies<iter_policy> > + scan(cp_first, cp_last); + + hit = (+(alpha_p | punct_p)).parse(scan); + BOOST_TEST(!!hit); + BOOST_TEST(scan.first == scan.last); + scan.first = cp; + + hit = (+(lexeme_d[+(alpha_p | '\'')])).parse(scan); + BOOST_TEST(!!hit); + BOOST_TEST(scan.first == scan.last); + scan.first = cp; + + hit = (+(lexeme_d[lexeme_d[+anychar_p]])).parse(scan); + BOOST_TEST(!!hit); + BOOST_TEST(scan.first == scan.last); + scan.first = cp; + + hit = (str_p("Hello") >> "World").parse(scan); + BOOST_TEST(!!hit); + BOOST_TEST(scan.first == scan.last); + scan.first = cp; + + hit = as_lower_d[str_p("hello") >> "world"].parse(scan); + BOOST_TEST(!!hit); + BOOST_TEST(scan.first == scan.last); + scan.first = cp; + + hit = (+(as_lower_d[as_lower_d[+lower_p | '\'']])).parse(scan); + BOOST_TEST(!!hit); + BOOST_TEST(scan.first == scan.last); + scan.first = cp; + + char const* cpy = "123.456"; + char const* cpy_first = cpy; + char const* cpy_last = cpy + test_impl::string_length(cpy); + + scanner<> scany(cpy_first, cpy_last); + hit = longest_d[(+digit_p >> '.' >> +digit_p) | (+digit_p)].parse(scany); + BOOST_TEST(!!hit); + BOOST_TEST(scany.first == scany.last); + scany.first = cpy; + + hit = shortest_d[(+digit_p >> '.' >> +digit_p) | (+digit_p)].parse(scany); + BOOST_TEST(!!hit); + BOOST_TEST(scany.first != scany.last); + scany.first = cpy; + + char const* cpz = "razamanaz"; + char const* cpz_first = cpz; + char const* cpz_last = cpz + test_impl::string_length(cpz); + + scanner<> scanz(cpz_first, cpz_last); + hit = longest_d[str_p("raza") | "razaman" | "razamanaz"].parse(scanz); + BOOST_TEST(!!hit); + BOOST_TEST(scanz.first == scanz.last); + scanz.first = cpz; + + hit = shortest_d[str_p("raza") | "razaman" | "razamanaz"].parse(scanz); + BOOST_TEST(!!hit); + BOOST_TEST(scanz.first == cpz+4); + scanz.first = cpz; + +// bounds_d + + parse_info<> pr = parse("123", limit_d(0, 60)[int_p]); + BOOST_TEST(!pr.hit); + + pr = parse("-2", limit_d(0, 60)[int_p]); + BOOST_TEST(!pr.hit); + + pr = parse("60", limit_d(0, 60)[int_p]); + BOOST_TEST(pr.hit); + + pr = parse("0", limit_d(0, 60)[int_p]); + BOOST_TEST(pr.hit); + + pr = parse("-2", min_limit_d(0)[int_p]); + BOOST_TEST(!pr.hit); + + pr = parse("-2", min_limit_d(-5)[int_p]); + BOOST_TEST(pr.hit); + + pr = parse("101", max_limit_d(100)[int_p]); + BOOST_TEST(!pr.hit); + + pr = parse("100", max_limit_d(100)[int_p]); + BOOST_TEST(pr.hit); +} + +struct identifier : public grammar<identifier> +{ + template <typename ScannerT> + struct definition + { + definition(identifier const& /*self*/) + { + rr = +(alpha_p | '_'); + r = lexeme_d[rr]; + } + + rule<typename lexeme_scanner<ScannerT>::type> rr; + rule<ScannerT> r; + + rule<ScannerT> const& + start() const { return r; } + }; +}; + +void +directives_test2() +{ + // Test that lexeme_d does not skip trailing spaces + + std::string str1, str2; + identifier ident; + + parse("rock_n_roll never_dies ", + + ident[assign_a(str1)] >> ident[assign_a(str2)], space_p + ); + + std::cout << '*' << str1 << ',' << str2 << '*' << std::endl; + + + BOOST_TEST(str1 == "rock_n_roll"); + BOOST_TEST(str2 == "never_dies"); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Main +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + directives_test1(); + directives_test2(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/distinct_tests.cpp b/src/boost/libs/spirit/classic/test/distinct_tests.cpp new file mode 100644 index 00000000..0ef66b0a --- /dev/null +++ b/src/boost/libs/spirit/classic/test/distinct_tests.cpp @@ -0,0 +1,248 @@ +/*============================================================================= + Copyright (c) 2003 Vaclav Vesely + http://spirit.sourceforge.net/ + + 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/include/classic_core.hpp> +#include <boost/spirit/include/classic_distinct.hpp> +#include <boost/detail/lightweight_test.hpp> + +using namespace boost; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +typedef + scanner<char const*, scanner_policies<skipper_iteration_policy<> > > + scanner_t; + +typedef + rule<scanner_t> + rule_t; + +void distinct_parser_test() +{ + // distinct_parser() + { + distinct_parser<> distinct_p; + + // operator()(CharT const* str) const + rule_t r = distinct_p("keyword") >> !ch_p('-') >> int_p; + BOOST_TEST(parse("keyword123", r, space_p).full); + } + + // distinct_parser(CharT const* letters) + { + distinct_parser<> distinct_p("0-9a-zA-Z_"); + + // operator()(CharT const* str) const + rule_t r = distinct_p("keyword") >> !ch_p('-') >> int_p; + BOOST_TEST(parse("keyword 123", r, space_p).full); + BOOST_TEST(parse("keyword-123", r, space_p).full); + BOOST_TEST(!parse("keyword123", r, space_p).hit); + } + + // distinct_parser(parser<TailT> const & tail_) + { + distinct_parser< + char, + alternative< + alnum_parser, + sequence< + chlit<>, + negated_char_parser<chlit<> > + > + > + > + distinct_p(alnum_p | ('-' >> ~ch_p('-'))); + + // operator()(CharT const* str) const + rule_t r = distinct_p("keyword") >> !str_p("--") >> int_p; + BOOST_TEST(parse("keyword 123", r, space_p).full); + BOOST_TEST(parse("keyword--123", r, space_p).full); + BOOST_TEST(!parse("keyword-123", r, space_p).hit); + } +} + +void distinct_directive_test() +{ + // distinct_directive() + { + distinct_directive<> distinct_d; + + // operator[](CharT const* str) const + { + rule_t r = distinct_d["keyword"] >> !ch_p('-') >> int_p; + BOOST_TEST(parse("keyword123", r, space_p).full); + } + + // operator[](parser<ParserT> const &subject) const + { + rule_t r = distinct_d[str_p("keyword")] >> !ch_p('-') >> int_p; + BOOST_TEST(parse("keyword123", r, space_p).full); + } + } + + // distinct_directive(CharT const* letters) + { + distinct_directive<> distinct_d("0-9a-zA-Z_"); + + // operator[](CharT const* str) const + { + rule_t r = distinct_d["keyword"] >> !ch_p('-') >> int_p; + BOOST_TEST(parse("keyword 123", r, space_p).full); + BOOST_TEST(parse("keyword-123", r, space_p).full); + BOOST_TEST(!parse("keyword123", r, space_p).hit); + } + + // operator[](parser<ParserT> const &subject) const + { + rule_t r = distinct_d[str_p("keyword")] >> !ch_p('-') >> int_p; + BOOST_TEST(parse("keyword 123", r, space_p).full); + BOOST_TEST(parse("keyword-123", r, space_p).full); + BOOST_TEST(!parse("keyword123", r, space_p).hit); + } + } + + // distinct_directive(parser<TailT> const & tail_) + { + distinct_directive< + char, + alternative< + alnum_parser, + sequence< + chlit<>, + negated_char_parser<chlit<> > + > + > + > + distinct_d(alnum_p | ('-' >> ~ch_p('-'))); + + // operator[](CharT const* str) const + { + rule_t r = distinct_d["keyword"] >> !str_p("--") >> int_p; + BOOST_TEST(parse("keyword 123", r, space_p).full); + BOOST_TEST(parse("keyword--123", r, space_p).full); + BOOST_TEST(!parse("keyword-123", r, space_p).hit); + } + + // operator[](parser<ParserT> const &subject) const + { + rule_t r = distinct_d[str_p("keyword")] >> !str_p("--") >> int_p; + BOOST_TEST(parse("keyword 123", r, space_p).full); + BOOST_TEST(parse("keyword--123", r, space_p).full); + BOOST_TEST(!parse("keyword-123", r, space_p).hit); + } + } +} + +void dynamic_distinct_parser_test() +{ + // dynamic_distinct_parser() + { + dynamic_distinct_parser<scanner_t> distinct_p; + + // operator()(CharT const* str) const + rule_t r = distinct_p("keyword") >> !ch_p('-') >> int_p; + BOOST_TEST(parse("keyword123", r, space_p).full); + } + + // dynamic_distinct_parser(CharT const* letters) + { + dynamic_distinct_parser<scanner_t> distinct_p("0-9a-zA-Z_"); + + // operator()(CharT const* str) const + rule_t r = distinct_p("keyword") >> !ch_p('-') >> int_p; + BOOST_TEST(parse("keyword 123", r, space_p).full); + BOOST_TEST(parse("keyword-123", r, space_p).full); + BOOST_TEST(!parse("keyword123", r, space_p).hit); + } + + // dynamic_distinct_parser(parser<TailT> const & tail_) + { + dynamic_distinct_parser<scanner_t> + distinct_p(alnum_p | ('-' >> ~ch_p('-'))); + + // operator()(CharT const* str) const + rule_t r = distinct_p("keyword") >> !str_p("--") >> int_p; + BOOST_TEST(parse("keyword 123", r, space_p).full); + BOOST_TEST(parse("keyword--123", r, space_p).full); + BOOST_TEST(!parse("keyword-123", r, space_p).hit); + } +} + +void dynamic_distinct_directive_test() +{ + // dynamic_distinct_directive() + { + dynamic_distinct_directive<scanner_t> distinct_d; + + // operator[](CharT const* str) const + { + rule_t r = distinct_d["keyword"] >> !ch_p('-') >> int_p; + BOOST_TEST(parse("keyword123", r, space_p).full); + } + + // operator[](parser<ParserT> const &subject) const + { + rule_t r = distinct_d[str_p("keyword")] >> !ch_p('-') >> int_p; + BOOST_TEST(parse("keyword123", r, space_p).full); + } + } + + // dynamic_distinct_directive(CharT const* letters) + { + dynamic_distinct_directive<scanner_t> distinct_d("0-9a-zA-Z_"); + + // operator[](CharT const* str) const + { + rule_t r = distinct_d["keyword"] >> !ch_p('-') >> int_p; + BOOST_TEST(parse("keyword 123", r, space_p).full); + BOOST_TEST(parse("keyword-123", r, space_p).full); + BOOST_TEST(!parse("keyword123", r, space_p).hit); + } + + // operator[](parser<ParserT> const &subject) const + { + rule_t r = distinct_d[str_p("keyword")] >> !ch_p('-') >> int_p; + BOOST_TEST(parse("keyword 123", r, space_p).full); + BOOST_TEST(parse("keyword-123", r, space_p).full); + BOOST_TEST(!parse("keyword123", r, space_p).hit); + } + } + + // dynamic_distinct_directive(parser<TailT> const & tail_) + { + dynamic_distinct_directive<scanner_t> + distinct_d(alnum_p | ('-' >> ~ch_p('-'))); + + // operator[](CharT const* str) const + { + rule_t r = distinct_d["keyword"] >> !str_p("--") >> int_p; + BOOST_TEST(parse("keyword 123", r, space_p).full); + BOOST_TEST(parse("keyword--123", r, space_p).full); + BOOST_TEST(!parse("keyword-123", r, space_p).hit); + } + + // operator[](parser<ParserT> const &subject) const + { + rule_t r = distinct_d[str_p("keyword")] >> !str_p("--") >> int_p; + BOOST_TEST(parse("keyword 123", r, space_p).full); + BOOST_TEST(parse("keyword--123", r, space_p).full); + BOOST_TEST(!parse("keyword-123", r, space_p).hit); + } + } +} + +int +main() +{ + distinct_parser_test(); + distinct_directive_test(); + dynamic_distinct_parser_test(); + dynamic_distinct_directive_test(); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/epsilon_tests.cpp b/src/boost/libs/spirit/classic/test/epsilon_tests.cpp new file mode 100644 index 00000000..15aa632b --- /dev/null +++ b/src/boost/libs/spirit/classic/test/epsilon_tests.cpp @@ -0,0 +1,136 @@ +/*============================================================================= + Copyright (c) 2002-2003 Martin Wille + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <cstring> +#include <boost/detail/lightweight_test.hpp> + +// This test program only includes the epsilon.hpp header from Spirit +#include <boost/spirit/include/classic_epsilon.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "impl/var.hpp" +#include "impl/string_length.hpp" + +using namespace test; +static BOOST_SPIRIT_CLASSIC_NS::parse_info<char const *> pi; + +//////////////////////////////////////////////// +// These macros are used with BOOST_TEST +#define matches (pi.hit) +#define full_match (pi.hit && pi.full) +#define partial_match (pi.hit && !pi.full) +#define no_match (!pi.hit && !pi.full) +#define zero_length_match (pi.length == 0) +#define stop_equals_start (pi.stop == s) + +template<typename ParserT> +static void +parse(char const *s, ParserT const &p, bool match) +{ + + pi = BOOST_SPIRIT_CLASSIC_NS::parse(s, s + test_impl::string_length(s), p); + if (match) + { + BOOST_TEST(matches); + BOOST_TEST(zero_length_match); + BOOST_TEST(stop_equals_start); + } + else + { + BOOST_TEST(no_match); + } +} + +static char const empty[] = ""; +static char const not_empty[] = "asdfgh"; + +//////////////////////////////////////////////// +// Test wether epsilon_p/eps_p work as +// primitive parsers +static void +epsilon_as_primitive() +{ + // This test case also is a compile time check wether + // both eps_p and epsilon_p are present. + + parse(empty, BOOST_SPIRIT_CLASSIC_NS::epsilon_p, true); + BOOST_TEST(full_match); + parse(not_empty, BOOST_SPIRIT_CLASSIC_NS::epsilon_p, true); + BOOST_TEST(partial_match); + + parse(empty, BOOST_SPIRIT_CLASSIC_NS::eps_p, true); + BOOST_TEST(full_match); + parse(not_empty, BOOST_SPIRIT_CLASSIC_NS::eps_p, true); + BOOST_TEST(partial_match); +} + +//////////////////////////////////////////////// +// Test wether epsilon_p/eps_p work correctly as +// a parser generator for creating parsers from +// functors +static void +epsilon_as_parser_generator_for_functors() +{ + bool flag = false; + parse(empty, BOOST_SPIRIT_CLASSIC_NS::epsilon_p(var(flag)), flag); + BOOST_TEST(no_match); + + flag = true; + parse(empty, BOOST_SPIRIT_CLASSIC_NS::epsilon_p(var(flag)), flag); + BOOST_TEST(full_match); +} + +//////////////////////////////////////////////// +// Test wether epsilon_p/eps_p work correctly as +// a parser generator for creating parsers from +// other parsers +static void +epsilon_as_parser_generator_for_parsers() +{ + // This test case uses a parser created by epsilon_p + // as body-parser for another invokation of epsilon_p + + bool flag = false; + parse(empty, BOOST_SPIRIT_CLASSIC_NS::epsilon_p( + BOOST_SPIRIT_CLASSIC_NS::epsilon_p(var(flag))), flag); + BOOST_TEST(no_match); + + flag = true; + parse(empty, BOOST_SPIRIT_CLASSIC_NS::epsilon_p( + BOOST_SPIRIT_CLASSIC_NS::epsilon_p(var(flag))), flag); + BOOST_TEST(full_match); +} + +//////////////////////////////////////////////// +// Test wether epsilon_p/eps_p support negation +static void +negation_operator_for_epsilon() +{ + bool flag = false; + parse(empty, ~BOOST_SPIRIT_CLASSIC_NS::epsilon_p(var(flag)), !flag); + BOOST_TEST(full_match); + parse(empty, ~~BOOST_SPIRIT_CLASSIC_NS::epsilon_p(var(flag)), flag); + BOOST_TEST(no_match); + + flag = true; + parse(empty, ~BOOST_SPIRIT_CLASSIC_NS::epsilon_p(var(flag)), !flag); + BOOST_TEST(no_match); + parse(empty, ~~BOOST_SPIRIT_CLASSIC_NS::epsilon_p(var(flag)), flag); + BOOST_TEST(full_match); +} + +int +main() +{ + epsilon_as_primitive(); + epsilon_as_parser_generator_for_functors(); + epsilon_as_parser_generator_for_parsers(); + negation_operator_for_epsilon(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/escape_char_parser_tests.cpp b/src/boost/libs/spirit/classic/test/escape_char_parser_tests.cpp new file mode 100644 index 00000000..e719d6be --- /dev/null +++ b/src/boost/libs/spirit/classic/test/escape_char_parser_tests.cpp @@ -0,0 +1,194 @@ +/*============================================================================= + Copyright (c) 2001-2003 Daniel Nuffer + Copyright (c) 2001-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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/include/classic_core.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> +#include <boost/spirit/include/classic_escape_char.hpp> + +#include <iostream> +#include <boost/core/ignore_unused.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cstdio> // for sprintf + +#if !defined(BOOST_NO_CWCHAR) && !defined(BOOST_NO_SWPRINTF) +# include <cwchar> // for swprintf +#endif + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + char c; + + // testing good C escapes + BOOST_TEST(parse("a", c_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == 'a'); + BOOST_TEST(parse("\\b", c_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\b'); + BOOST_TEST(parse("\\t", c_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\t'); + BOOST_TEST(parse("\\n", c_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\n'); + BOOST_TEST(parse("\\f", c_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\f'); + BOOST_TEST(parse("\\r", c_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\r'); + BOOST_TEST(parse("\\\"", c_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\"'); + BOOST_TEST(parse("\\'", c_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\''); + BOOST_TEST(parse("\\\\", c_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\\'); + BOOST_TEST(parse("\\120", c_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\120'); + BOOST_TEST(parse("\\x2e", c_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\x2e'); + + // test bad C escapes + BOOST_TEST(!parse("\\z", c_escape_ch_p[assign_a(c)]).hit); + + // testing good lex escapes + BOOST_TEST(parse("a", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == 'a'); + BOOST_TEST(parse("\\b", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\b'); + BOOST_TEST(parse("\\t", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\t'); + BOOST_TEST(parse("\\n", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\n'); + BOOST_TEST(parse("\\f", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\f'); + BOOST_TEST(parse("\\r", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\r'); + BOOST_TEST(parse("\\\"", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\"'); + BOOST_TEST(parse("\\'", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\''); + BOOST_TEST(parse("\\\\", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\\'); + BOOST_TEST(parse("\\120", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\120'); + BOOST_TEST(parse("\\x2e", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\x2e'); + BOOST_TEST(parse("\\z", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == 'z'); + BOOST_TEST(parse("\\a", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == 'a'); + + // test bad lex escapes + BOOST_TEST(!parse("\\xz", lex_escape_ch_p[assign_a(c)]).hit); + + // test out of range octal escape + BOOST_TEST(!parse("\\777", lex_escape_ch_p[assign_a(c)]).hit); + +#if CHAR_MAX == 127 + BOOST_TEST(!parse("\\200", lex_escape_ch_p[assign_a(c)]).hit); + + BOOST_TEST(parse("\\177", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\177'); +#elif CHAR_MAX == 255 + BOOST_TEST(!parse("\\400", lex_escape_ch_p[assign_a(c)]).hit); + + BOOST_TEST(parse("\\377", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\377'); +#endif + + // test out of range hex escape + BOOST_TEST(!parse("\\xFFF", lex_escape_ch_p[assign_a(c)]).hit); + +#if CHAR_MAX == 127 + BOOST_TEST(!parse("\\X80", lex_escape_ch_p[assign_a(c)]).hit); + + BOOST_TEST(parse("\\X7F", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\x7f'); +#elif CHAR_MAX == 255 + BOOST_TEST(!parse("\\X100", lex_escape_ch_p[assign_a(c)]).hit); + + BOOST_TEST(parse("\\XFf", lex_escape_ch_p[assign_a(c)]).full); + BOOST_TEST(c == '\xff'); +#endif + +#ifndef BOOST_NO_CWCHAR + + // test wide chars + typedef escape_char_parser<lex_escapes, wchar_t> wlep_t; + wlep_t wlep = wlep_t(); + + typedef escape_char_parser<c_escapes, wchar_t> wcep_t; + wcep_t wcep = wcep_t(); + + //wchar_t const* wstr = L"a\\b\\t\\n\\f\\r\\\"\\'\\\\\\120\\x2e"; + //wchar_t const* wend(wstr + wcslen(wstr)); + + wchar_t wc; + BOOST_TEST(parse(L"a", wcep[assign_a(wc)]).hit); + BOOST_TEST(wc == L'a'); + BOOST_TEST(parse(L"\\b", wcep[assign_a(wc)]).full); + BOOST_TEST(wc == L'\b'); + BOOST_TEST(parse(L"\\t", wcep[assign_a(wc)]).full); + BOOST_TEST(wc == L'\t'); + BOOST_TEST(parse(L"\\n", wcep[assign_a(wc)]).full); + BOOST_TEST(wc == L'\n'); + BOOST_TEST(parse(L"\\f", wcep[assign_a(wc)]).full); + BOOST_TEST(wc == L'\f'); + BOOST_TEST(parse(L"\\r", wcep[assign_a(wc)]).full); + BOOST_TEST(wc == L'\r'); + BOOST_TEST(parse(L"\\\"", wcep[assign_a(wc)]).full); + BOOST_TEST(wc == L'\"'); + BOOST_TEST(parse(L"\\'", wcep[assign_a(wc)]).full); + BOOST_TEST(wc == L'\''); + BOOST_TEST(parse(L"\\\\", wcep[assign_a(wc)]).full); + BOOST_TEST(wc == L'\\'); + BOOST_TEST(parse(L"\\120", wcep[assign_a(wc)]).full); + BOOST_TEST(wc == L'\120'); + BOOST_TEST(parse(L"\\x2e", wcep[assign_a(wc)]).full); + BOOST_TEST(wc == L'\x2e'); + + // test bad wc escapes + BOOST_TEST(!parse(L"\\z", wcep[assign_a(wc)]).hit); + +#if !defined(BOOST_NO_SWPRINTF) + // test out of range octal escape + size_t const octmax_size = 16; + wchar_t octmax[octmax_size]; + + swprintf(octmax, octmax_size, + L"\\%lo", (unsigned long)(std::numeric_limits<wchar_t>::max)()); + BOOST_TEST(parse(octmax, wlep[assign_a(wc)]).full); + //BOOST_TEST(lex_escape_ch_p[assign_a(wc)].parse(str, end)); + BOOST_TEST(wc == (std::numeric_limits<wchar_t>::max)()); + + swprintf(octmax, octmax_size, + L"\\%lo", (unsigned long)(std::numeric_limits<wchar_t>::max)() + 1); + BOOST_TEST(!parse(octmax, wlep[assign_a(wc)]).hit); + + // test out of range hex escape + size_t const hexmax_size = 16; + wchar_t hexmax[hexmax_size]; + + swprintf(hexmax, hexmax_size, + L"\\x%lx", (unsigned long)(std::numeric_limits<wchar_t>::max)()); + BOOST_TEST(parse(hexmax, wlep[assign_a(wc)]).full); + BOOST_TEST(wc == (std::numeric_limits<wchar_t>::max)()); + + swprintf(hexmax, hexmax_size, + L"\\x%lx", (unsigned long)(std::numeric_limits<wchar_t>::max)() + 1); + BOOST_TEST(!parse(hexmax, wlep[assign_a(wc)]).hit); +#else + boost::ignore_unused(wlep); +#endif // !defined(BOOST_NO_SWPRINTF) + +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/exception_tests.cpp b/src/boost/libs/spirit/classic/test/exception_tests.cpp new file mode 100644 index 00000000..092f8fee --- /dev/null +++ b/src/boost/libs/spirit/classic/test/exception_tests.cpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + 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/include/classic_core.hpp> +#include <boost/spirit/include/classic_exceptions.hpp> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +struct handler +{ + template <typename ScannerT, typename ErrorT> + error_status<> + operator()(ScannerT const& /*scan*/, ErrorT const& /*error*/) const + { + cout << "exception caught...Test concluded successfully" << endl; + return error_status<>(error_status<>::fail); + } +}; + +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tExceptions Test...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + + assertion<int> expect(0); + guard<int> my_guard; + + bool r = + parse("abcx", + my_guard(ch_p('a') >> 'b' >> 'c' >> expect( ch_p('d') )) + [ + handler() + ] + ).full; + + BOOST_TEST(!r); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/file_iterator_tests.cpp b/src/boost/libs/spirit/classic/test/file_iterator_tests.cpp new file mode 100644 index 00000000..ec5d3678 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/file_iterator_tests.cpp @@ -0,0 +1,186 @@ +/*============================================================================= + Copyright (c) 2003 Giovanni Bajo + http://spirit.sourceforge.net/ + + 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/detail/lightweight_test.hpp> +#include <cstdio> +#include <iostream> +#include <boost/concept_check.hpp> +#include <boost/spirit/include/classic_file_iterator.hpp> + +// This checks for a namespace related problem in VC8 +// The problem can be avoided by not using "using namespace std;" in the +// Spirit headers +namespace vc8_bug_1 { struct plus {}; } +namespace vc8_bug_2 { using namespace vc8_bug_1; struct test : plus {}; } + + +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +namespace { + +static const char* TMP_FILE = "file_iter.tmp"; + +bool CreateTempFile(void) +{ + FILE* f = fopen(TMP_FILE, "wb"); + + if (!f) + return false; + + for (int i=0;i<256;i++) + { + unsigned char ci = (unsigned char)i; + + if (fwrite(&ci,1,1,f) == 0) + { + fclose(f); + return false; + } + } + + fclose(f); + return true; +} + +template <typename ITER> +void RunTest(void) +{ + // Check constructor opening a file + ITER a(TMP_FILE); + BOOST_TEST(!!a); + + // Assert dereference (twice: derefence + // must not move the iterator) + BOOST_TEST(*a == 0); + BOOST_TEST(*a == 0); + + // Check random access + BOOST_TEST(a[123] == 123); + + // Check copy constructor and operator== + ITER c(a); + BOOST_TEST(c == a); + BOOST_TEST(!(c != a)); + + // Check assignment operator + ITER d; d = a; + BOOST_TEST(d == a); + BOOST_TEST(!(d != a)); + + // Check make_end() + ITER b(a.make_end()); + BOOST_TEST(!!b); + BOOST_TEST(a != b); + BOOST_TEST(a+256 == b); + BOOST_TEST(a == b-256); + + // Check copy constructor on non-trivial position + BOOST_TEST(*ITER(a+67) == 67); + + // Check increment + ++a; ++a; a++; a++; + BOOST_TEST(*a == 4); + BOOST_TEST(a == c+4); + + // Check decrement + --a; --a; a--; a--; + BOOST_TEST(*a == 0); + BOOST_TEST(a == c); + + // Check end iterator increment/decrement + --b; b--; + BOOST_TEST(*b == 254); + BOOST_TEST(a+254 == b); + ++b; b++; + BOOST_TEST(a+256 == b); + + // Check order + a += 128; + BOOST_TEST(c < a); + BOOST_TEST(a < b); + BOOST_TEST(a > c); + BOOST_TEST(b > a); + + // Check assignment + a = b; + BOOST_TEST(a == b); + a = c; + BOOST_TEST(a == c); + + // Check weak order + BOOST_TEST(a <= c); + BOOST_TEST(a >= c); + BOOST_TEST(a <= b); + BOOST_TEST(!(a >= b)); + + // Check increment through end + a += 255; + BOOST_TEST(a != b); + ++a; + BOOST_TEST(a == b); + ++a; + BOOST_TEST(a != b); +} + +/////////////////////////////////////////////////////////////////////////////// +} + +typedef unsigned char character_t; +typedef file_iterator<character_t, + fileiter_impl::std_file_iterator<character_t> > iter; +BOOST_CLASS_REQUIRE(iter, boost, RandomAccessIteratorConcept); + +#ifdef BOOST_SPIRIT_FILEITERATOR_WINDOWS + typedef file_iterator<character_t, + fileiter_impl::mmap_file_iterator<character_t> > iterwin; + BOOST_CLASS_REQUIRE(iterwin, boost, RandomAccessIteratorConcept); +#endif +#ifdef BOOST_SPIRIT_FILEITERATOR_POSIX + typedef file_iterator<character_t, + fileiter_impl::mmap_file_iterator<character_t> > iterposix; + BOOST_CLASS_REQUIRE(iterposix, boost, RandomAccessIteratorConcept); +#endif + +int main(void) +{ + if (!CreateTempFile()) + { + cerr << "ERROR: Cannot create temporary file file_iter.tmp" << endl; + return 2; + } + + cerr << "Testing standard iterator" << endl; + RunTest<iter>(); + +#ifdef BOOST_SPIRIT_FILEITERATOR_WINDOWS + cerr << "Testing Windows iterator" << endl; + RunTest<iterwin>(); +#endif + +#ifdef BOOST_SPIRIT_FILEITERATOR_POSIX + cerr << "Testing POSIX iterator" << endl; + RunTest<iterposix>(); +#endif + + // Check if the file handles were closed correctly + BOOST_TEST(remove(TMP_FILE) == 0); + + return boost::report_errors(); +} + +#ifdef BOOST_NO_EXCEPTIONS + +namespace boost { + void throw_exception(std::exception const& e) + { + BOOST_EROR("throw_exception"); + } +} + +#endif diff --git a/src/boost/libs/spirit/classic/test/fixed_size_queue_fail_tests.cpp b/src/boost/libs/spirit/classic/test/fixed_size_queue_fail_tests.cpp new file mode 100644 index 00000000..aab7d61a --- /dev/null +++ b/src/boost/libs/spirit/classic/test/fixed_size_queue_fail_tests.cpp @@ -0,0 +1,64 @@ +/*============================================================================= + Copyright (c) 2001-2003 Daniel Nuffer + Copyright (c) 2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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/include/classic_fixed_size_queue.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/concept_check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> + +typedef BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue<int, 5> queue_t; +typedef queue_t::iterator iter_t; +typedef queue_t::const_iterator const_iter_t; +BOOST_CLASS_REQUIRE(const_iter_t, boost, RandomAccessIteratorConcept); + +// Right now, the iterator is not a full compliant MutableRandomAccessIterator +// because operator[] does not return a reference. This seems a problem in +// boost::iterator_adaptors. Anyway, this feature is not used in multi_pass +// iterator, and this class is not really meant for public use yet. +BOOST_CLASS_REQUIRE(iter_t, boost, RandomAccessIteratorConcept); + +int main(int, char**) +{ + // Iterators are random access. + BOOST_MPL_ASSERT(( boost::is_same< + iter_t::iterator_category, + std::random_access_iterator_tag > )); + BOOST_MPL_ASSERT(( boost::is_same< + const_iter_t::iterator_category, + std::random_access_iterator_tag > )); + + queue_t q; + const queue_t& cq = q; + + iter_t b = q.begin(); + const_iter_t c = cq.begin(); + +// MSVC7.1 and EDG aren't able to compile this code for the new iterator +// adaptors + +// The problem here is, that the old fixed_size_queue code wasn't a complete +// and 'clean' iterator implementation, some of the required iterator concepts +// were missing. It was never meant to be exposed outside the multi_pass. So I +// haven't added any features while porting. The #ifdef'ed tests expose the +// code weaknesses ((un-)fortunately only on conformant compilers, with a quite +// good STL implementation). The simplest way to solve this issue was to switch +// of the tests for these compilers then. + +// Check comparisons and interoperations (we are comparing +// const and non-const iterators) + + (void) c == b; + (void) c+4 > b; + (void) c < b+4; + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/fixed_size_queue_tests.cpp b/src/boost/libs/spirit/classic/test/fixed_size_queue_tests.cpp new file mode 100644 index 00000000..e9077a73 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/fixed_size_queue_tests.cpp @@ -0,0 +1,137 @@ +/*============================================================================= + Copyright (c) 2001-2003 Daniel Nuffer + Copyright (c) 2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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/include/classic_fixed_size_queue.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/concept_check.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> + +typedef BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue<int, 5> queue_t; +typedef queue_t::iterator iter_t; +typedef queue_t::const_iterator const_iter_t; +BOOST_CLASS_REQUIRE(const_iter_t, boost, RandomAccessIteratorConcept); + +// Right now, the iterator is not a full compliant MutableRandomAccessIterator +// because operator[] does not return a reference. This seems a problem in +// boost::iterator_adaptors. Anyway, this feature is not used in multi_pass +// iterator, and this class is not really meant for public use yet. +BOOST_CLASS_REQUIRE(iter_t, boost, RandomAccessIteratorConcept); + +int main(int, char**) +{ + queue_t q; + const queue_t& cq = q; + + q.push_back(1); + q.push_back(2); + q.push_back(3); + q.push_back(4); + BOOST_TEST(q.front() == 1); + q.pop_front(); + BOOST_TEST(q.front() == 2); + q.pop_front(); + BOOST_TEST(q.front() == 3); + q.pop_front(); + BOOST_TEST(q.front() == 4); + q.pop_front(); + q.push_back(5); + q.push_back(6); + q.push_back(7); + q.push_back(8); + BOOST_TEST(q.front() == 5); + q.pop_front(); + BOOST_TEST(q.front() == 6); + q.pop_front(); + BOOST_TEST(q.front() == 7); + q.pop_front(); + BOOST_TEST(q.front() == 8); + q.pop_front(); + + q.push_front(5); + q.push_front(4); + q.push_front(3); + q.push_front(2); + q.push_front(1); + + // NOTE: Iterator tests are not exhaustive and they are not meant to be so. + + // Check iterator + iter_t b = q.begin(); + BOOST_TEST(*b++ == 1); + BOOST_TEST(*b++ == 2); + BOOST_TEST(*b++ == 3); + BOOST_TEST(*b++ == 4); + BOOST_TEST(*b++ == 5); + BOOST_TEST(b == q.end()); + BOOST_TEST(*--b == 5); + BOOST_TEST(*--b == 4); + BOOST_TEST(*--b == 3); + BOOST_TEST(*--b == 2); + BOOST_TEST(*--b == 1); + BOOST_TEST(b == q.begin()); + + // Check const_iterator + const_iter_t c = cq.begin(); + BOOST_TEST(*c++ == 1); + BOOST_TEST(*c++ == 2); + BOOST_TEST(*c++ == 3); + BOOST_TEST(*c++ == 4); + BOOST_TEST(*c++ == 5); + BOOST_TEST(c == cq.end()); + BOOST_TEST(*--c == 5); + BOOST_TEST(*--c == 4); + BOOST_TEST(*--c == 3); + BOOST_TEST(*--c == 2); + BOOST_TEST(*--c == 1); + BOOST_TEST(c == cq.begin()); + +#if 0 + +// Conforming compilers aren't able to compile this code for the new iterator +// adaptors. + +// The problem here is, that the old fixed_size_queue code wasn't a complete +// and 'clean' iterator implementation, some of the required iterator concepts +// were missing. It was never meant to be exposed outside the multi_pass. So I +// haven't added any features while porting. The #ifdef'ed tests expose the +// code weaknesses ((un-)fortunately only on conformant compilers, with a quite +// good STL implementation). The simplest way to solve this issue was to switch +// of the tests for these compilers then. + +// $$$ This is isolated in fixed_size_queue_fail_tests.cpp [JDG 11-5-2003] $$$ + + // Iterators are random access. + BOOST_MPL_ASSERT(( boost::is_same< + iter_t::iterator_category, + std::random_access_iterator_tag > )); + BOOST_MPL_ASSERT(( boost::is_same< + const_iter_t::iterator_category, + std::random_access_iterator_tag > )); + + // Check comparisons and interoperations (we are comparing + // const and non-const iterators) + BOOST_TEST(c == b); + BOOST_TEST(c+4 > b); + BOOST_TEST(c < b+4); + +#endif + + // Check that you can actually modify the queue with an iterator + *b = 123; + BOOST_TEST(*c == 123); + + // Check random access + BOOST_TEST(*((c+4)-4) == 123); + BOOST_TEST(*((c-4)+4) == 123); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/for_p_as_parser_tests.cpp b/src/boost/libs/spirit/classic/test/for_p_as_parser_tests.cpp new file mode 100644 index 00000000..5d87f8de --- /dev/null +++ b/src/boost/libs/spirit/classic/test/for_p_as_parser_tests.cpp @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + 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/include/classic_core.hpp> +#include <boost/spirit/include/classic_for.hpp> + +extern bool fun(); + +struct ftor +{ + bool operator ()() const; +}; + +extern void init_fun(); + +struct init_ftor +{ + void operator()() const; +}; + +extern void step_fun(); + +struct step_ftor +{ + void operator()() const; +}; + +extern bool cmp_fun(); + +struct cmp_ftor +{ + bool operator()() const; +}; + +int +main() +{ + ////////////////////////////////// + // compile time check wether as_parser<> works for for_p + + ::BOOST_SPIRIT_CLASSIC_NS::rule<> r; + + r = BOOST_SPIRIT_CLASSIC_NS::for_p(&init_fun, &cmp_fun, &step_fun)['-']; + r = BOOST_SPIRIT_CLASSIC_NS::for_p(init_ftor(), cmp_ftor(), step_ftor())["-"]; + + r = BOOST_SPIRIT_CLASSIC_NS::for_p(init_ftor(), r, step_ftor())[r]; +} diff --git a/src/boost/libs/spirit/classic/test/for_tests.cpp b/src/boost/libs/spirit/classic/test/for_tests.cpp new file mode 100644 index 00000000..5c20fe46 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/for_tests.cpp @@ -0,0 +1,192 @@ +/*============================================================================= + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ +// vi:ts=4:sw=4:et +// Tests for spirit::for_p +// [13-Jan-2003] +//////////////////////////////////////////////////////////////////////////////// +#include <iostream> +#include <cstring> +#include <string> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> +#include <boost/spirit/include/classic_for.hpp> +#include <boost/ref.hpp> +#include "impl/string_length.hpp" + +namespace local +{ + template <typename T> + struct var_wrapper + : public ::boost::reference_wrapper<T> + { + typedef ::boost::reference_wrapper<T> parent; + + explicit inline var_wrapper(T& t) : parent(t) {} + + inline T& operator()() const { return parent::get(); } + }; + + template <typename T> + inline var_wrapper<T> + var(T& t) + { + return var_wrapper<T>(t); + } +} + +namespace +{ + template <typename T> + class add_actor + { + public: + explicit add_actor(T &ref_) : ref(ref_) {} + + template <typename T2> + void operator()(T2 const &val) const + { ref += val; } + + private: + T& ref; + }; + + template <typename T> + inline add_actor<T> const + add(T& ref) + { + return add_actor<T>(ref); + } +} + +typedef ::BOOST_SPIRIT_CLASSIC_NS::rule<> rule_t; + +unsigned int test_count = 0; +unsigned int error_count = 0; + +unsigned int iterations_performed; +unsigned int iterations_desired; +std::string input_matched; + +//static const unsigned int kError = 999; +static const bool good = true; +static const bool bad = false; + +rule_t for_rule; +rule_t for_rule2; + +void +test_for +( + char const *s, + bool succeed, + rule_t const &r, + unsigned int iterations_expected +) +{ + using namespace std; + + ++test_count; + + iterations_performed = 0; + + ::BOOST_SPIRIT_CLASSIC_NS::parse_info<> m = ::BOOST_SPIRIT_CLASSIC_NS::parse(s, s + test_impl::string_length(s), r); + + bool result = (succeed==m.full)?good:bad; + + if (m.full && (m.length != test_impl::string_length(s))) + result = bad; + + result &= iterations_expected == iterations_performed; + + if (result==good) + cout << "PASSED"; + else + { + ++error_count; + cout << "FAILED"; + } + + cout << ": \"" << s << "\" ==> "; + if (!m.full) + cout << "<error>"; + else + cout << '"' << input_matched << '"'; + + cout << " " << iterations_performed << " of " + << iterations_desired << " iterations\n"; +} + +namespace +{ + void zero() { iterations_performed = 0; } + + struct inc + { + inline void operator()() const { ++iterations_performed; } + }; + struct cmp + { + inline bool operator()() const + { + return iterations_performed<iterations_desired; + } + }; +} + +int +main() +{ + using namespace std; + + using BOOST_SPIRIT_CLASSIC_NS::uint_p; + using BOOST_SPIRIT_CLASSIC_NS::for_p; + using BOOST_SPIRIT_CLASSIC_NS::assign_a; + +#if qDebug + SPIRIT_DEBUG_RULE(for_rule); + SPIRIT_DEBUG_RULE(for_rule2); +#endif + + for_rule + = uint_p[assign_a(iterations_desired)] >> ':' + >> for_p(&zero, cmp(), inc())["xy"] + [assign_a(input_matched)] + ; + + for_rule2 + = for_p(&zero, '.', inc())["xy"] + [assign_a(input_matched)] + ; + + cout << "/////////////////////////////////////////////////////////\n"; + cout << "\n"; + cout << " for_p test\n"; + cout << "\n"; + cout << "/////////////////////////////////////////////////////////\n"; + cout << "\n"; + + test_for("3:xyxyxy", true, for_rule, 3); + test_for("3:", false, for_rule, 0); + test_for("3:xyxy", false, for_rule, 2); + test_for("3:xyxyxyxy", false, for_rule, 3); + + test_for(".xy.xy.xy", true, for_rule2, 3); + test_for(".xy.xy.xy.", false, for_rule2, 3); + + std::cout << "\n "; + if (error_count==0) + cout << "All " << test_count << " for_p-tests passed.\n" + << "Test concluded successfully\n"; + else + cout << error_count << " of " << test_count << " for_p-tests failed\n" + << "Test failed\n"; + + return error_count!=0; +} + diff --git a/src/boost/libs/spirit/classic/test/fundamental_tests.cpp b/src/boost/libs/spirit/classic/test/fundamental_tests.cpp new file mode 100644 index 00000000..978d243a --- /dev/null +++ b/src/boost/libs/spirit/classic/test/fundamental_tests.cpp @@ -0,0 +1,94 @@ +/*============================================================================= + Copyright (c) 2001-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// Fundamental meta sublayer tests +// +/////////////////////////////////////////////////////////////////////////////// + +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include <boost/static_assert.hpp> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_meta.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +typedef ref_value_actor<char, assign_action> assign_actor; + +/////////////////////////////////////////////////////////////////////////////// +// +// node_count_tests +// +/////////////////////////////////////////////////////////////////////////////// +void +node_count_tests() +{ +// simple types + typedef chlit<char> plain_t; + typedef optional<chlit<char> > optional_t; + typedef action<chlit<char>, assign_actor> action_t; + typedef sequence<chlit<char>, anychar_parser> sequence_t; + + BOOST_STATIC_ASSERT(1 == node_count<plain_t>::value); + BOOST_STATIC_ASSERT(2 == node_count<optional_t>::value); + BOOST_STATIC_ASSERT(2 == node_count<action_t>::value); + BOOST_STATIC_ASSERT(3 == node_count<sequence_t>::value); + +// more elaborate types + typedef sequence<sequence<plain_t, action_t>, plain_t> sequence2_t; + typedef sequence<plain_t, sequence<action_t, plain_t> > sequence3_t; + + BOOST_STATIC_ASSERT(6 == node_count<sequence2_t>::value); + BOOST_STATIC_ASSERT(6 == node_count<sequence3_t>::value); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// leaf_count_tests +// +/////////////////////////////////////////////////////////////////////////////// +void +leaf_count_tests() +{ +// simple types + typedef chlit<char> plain_t; + typedef optional<chlit<char> > optional_t; + typedef action<chlit<char>, assign_actor> action_t; + typedef sequence<chlit<char>, anychar_parser> sequence_t; + + BOOST_STATIC_ASSERT(1 == leaf_count<plain_t>::value); + BOOST_STATIC_ASSERT(1 == leaf_count<optional_t>::value); + BOOST_STATIC_ASSERT(1 == leaf_count<action_t>::value); + BOOST_STATIC_ASSERT(2 == leaf_count<sequence_t>::value); + +// more elaborate types + typedef sequence<sequence<plain_t, action_t>, plain_t> sequence2_t; + typedef sequence<plain_t, sequence<action_t, plain_t> > sequence3_t; + + BOOST_STATIC_ASSERT(3 == leaf_count<sequence2_t>::value); + BOOST_STATIC_ASSERT(3 == leaf_count<sequence3_t>::value); +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Main +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + node_count_tests(); + leaf_count_tests(); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/grammar_def_test.cpp b/src/boost/libs/spirit/classic/test/grammar_def_test.cpp new file mode 100644 index 00000000..20022f53 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/grammar_def_test.cpp @@ -0,0 +1,85 @@ +// +// Copyright (c) 2005 Joao Abecasis +// +// 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/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_attribute.hpp> +#include <boost/spirit/include/classic_grammar_def.hpp> + +struct my_grammar1 + : BOOST_SPIRIT_CLASSIC_NS::grammar<my_grammar1> +{ + template <typename Scanner> + struct definition + : BOOST_SPIRIT_CLASSIC_NS::grammar_def< + BOOST_SPIRIT_CLASSIC_NS::rule<Scanner>, + BOOST_SPIRIT_CLASSIC_NS::same + > + { + definition(my_grammar1 const &) + { + BOOST_SPIRIT_DEBUG_NODE(start_rule1); + BOOST_SPIRIT_DEBUG_NODE(start_rule2); + + start_rule1 = BOOST_SPIRIT_CLASSIC_NS::str_p("int"); + start_rule2 = BOOST_SPIRIT_CLASSIC_NS::int_p; + + this->start_parsers(start_rule1, start_rule2); + } + + BOOST_SPIRIT_CLASSIC_NS::rule<Scanner> + start_rule1, + start_rule2; + }; +}; + +struct my_closure : BOOST_SPIRIT_CLASSIC_NS::closure<my_closure, int> +{ + member1 value; +}; + +struct my_grammar2 + : BOOST_SPIRIT_CLASSIC_NS::grammar<my_grammar2, my_closure::context_t> +{ + template <typename Scanner> + struct definition + : BOOST_SPIRIT_CLASSIC_NS::grammar_def< + BOOST_SPIRIT_CLASSIC_NS::rule<Scanner>, + BOOST_SPIRIT_CLASSIC_NS::same + > + { + definition(my_grammar2 const &) + { + BOOST_SPIRIT_DEBUG_NODE(start_rule1); + BOOST_SPIRIT_DEBUG_NODE(start_rule2); + + start_rule1 = BOOST_SPIRIT_CLASSIC_NS::str_p("int"); + start_rule2 = BOOST_SPIRIT_CLASSIC_NS::int_p; + + this->start_parsers(start_rule1, start_rule2); + } + + BOOST_SPIRIT_CLASSIC_NS::rule<Scanner> + start_rule1, + start_rule2; + }; +}; + +int main() +{ + my_grammar1 g1; + my_grammar2 g2; + + BOOST_SPIRIT_DEBUG_NODE(g1); + BOOST_SPIRIT_DEBUG_NODE(g2); + + parse( + "int 5", + g1.use_parser<0>() >> g2.use_parser<1>(), + BOOST_SPIRIT_CLASSIC_NS::space_p + ); +} diff --git a/src/boost/libs/spirit/classic/test/grammar_mt_tests.cpp b/src/boost/libs/spirit/classic/test/grammar_mt_tests.cpp new file mode 100644 index 00000000..59ea69e9 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/grammar_mt_tests.cpp @@ -0,0 +1,318 @@ +/*============================================================================= + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/config.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined(DONT_HAVE_BOOST) || !defined(BOOST_HAS_THREADS) || defined(BOOST_DISABLE_THREADS) +// we end here if we can't do multithreading +static void skipped() +{ + std::cout << "skipped\n"; +} + +int +main() +{ + skipped(); + return 0; +} + +#else +// the real MT stuff + +#undef BOOST_SPIRIT_THREADSAFE +#define BOOST_SPIRIT_THREADSAFE + +#include <boost/thread/thread.hpp> +#include <boost/spirit/include/classic_grammar.hpp> +#include <boost/spirit/include/classic_rule.hpp> +#include <boost/spirit/include/classic_epsilon.hpp> +#include <boost/thread/xtime.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/lock_types.hpp> +#include <boost/ref.hpp> + +static boost::mutex simple_mutex; +static int simple_definition_count = 0; + +struct simple : public BOOST_SPIRIT_CLASSIC_NS::grammar<simple> +{ + template <typename ScannerT> + struct definition + { + definition(simple const& /*self*/) + { + top = BOOST_SPIRIT_CLASSIC_NS::epsilon_p; + boost::unique_lock<boost::mutex> lock(simple_mutex); + simple_definition_count++; + } + + BOOST_SPIRIT_CLASSIC_NS::rule<ScannerT> top; + BOOST_SPIRIT_CLASSIC_NS::rule<ScannerT> const &start() const { return top; } + }; +}; + +struct count_guard +{ + count_guard(int &c) : counter(c) {} + ~count_guard() { counter = 0; } +private: + int &counter; +}; + +static void +milli_sleep(unsigned long milliseconds) +{ + static long const nanoseconds_per_second = 1000L*1000L*1000L; + boost::xtime xt; + boost::xtime_get(&xt, boost::TIME_UTC_); + xt.nsec+=1000*1000*milliseconds; + while (xt.nsec > nanoseconds_per_second) + { + xt.nsec -= nanoseconds_per_second; + xt.sec++; + } + + boost::thread::sleep(xt); +} + +static void +nap() +{ + // this function is called by various threads to ensure + // that thread lifetime actually overlap + milli_sleep(300); +} + +template <typename GrammarT> +static void +make_definition(GrammarT &g) +{ + char const *text="blah"; + BOOST_SPIRIT_CLASSIC_NS::scanner<> s(text, text+4); + + g.parse(s); +} + +template <typename GrammarT> +static void +make_definition3(GrammarT &g) +{ + char const *text="blah"; + BOOST_SPIRIT_CLASSIC_NS::scanner<> s(text, text+4); + + g.parse(s); + nap(); + g.parse(s); + g.parse(s); +} +//////////////////////////////////////////////////////////////////////////////// +#define exactly_one_instance_created simple_definition_count == 1 +#define exactly_two_instances_created simple_definition_count == 2 +#define exactly_four_instances_created simple_definition_count == 4 +#define exactly_eight_instances_created simple_definition_count == 8 + +//////////////////////////////////////////////////////////////////////////////// +static void +multiple_attempts_to_instantiate_a_definition_from_a_single_thread() +{ + // checks wether exactly one definition per grammar + // object is created + + count_guard guard(simple_definition_count); + + simple simple1_p; + simple simple2_p; + + make_definition(simple1_p); + make_definition(simple1_p); + make_definition(simple1_p); + + BOOST_TEST(exactly_one_instance_created); + + make_definition(simple2_p); + make_definition(simple2_p); + make_definition(simple2_p); + + BOOST_TEST(exactly_two_instances_created); +} + +//////////////////////////////////////////////////////////////////////////////// +struct single_grammar_object_task +{ + void operator()() const + { + make_definition3(simple1_p); + }; + + simple simple1_p; +}; +//////////////////////////////////////////////////////////////////////////////// +template <typename T> +class callable_reference_wrapper + : public boost::reference_wrapper<T> +{ +public: + explicit callable_reference_wrapper(T& t) + : boost::reference_wrapper<T>(t) + {} + inline void operator()() { this->get().operator()(); } +}; + +template <typename T> +callable_reference_wrapper<T> +callable_ref(T &t) +{ + return callable_reference_wrapper<T>(t); +} +//////////////////////////////////////////////////////////////////////////////// +static void +single_local_grammar_object_multiple_threads() +{ + // check wether independent definition objects are + // created + count_guard guard(simple_definition_count); + single_grammar_object_task task1, task2, task3, task4; + + boost::thread t1(callable_ref(task1)); + boost::thread t2(callable_ref(task2)); + boost::thread t3(callable_ref(task3)); + boost::thread t4(callable_ref(task4)); + + t1.join(); + t2.join(); + t3.join(); + t4.join(); + + BOOST_TEST(exactly_four_instances_created); +} + +//////////////////////////////////////////////////////////////////////////////// +struct two_grammar_objects_task +{ + void operator()() const + { + make_definition3(simple1_p); + make_definition3(simple2_p); + }; + + simple simple1_p; + simple simple2_p; +}; + +static void +multiple_local_grammar_objects_multiple_threads() +{ + // check wether exactly one definition per thread + // and per grammar object is created + count_guard guard(simple_definition_count); + two_grammar_objects_task task1, task2, task3, task4; + + boost::thread t1(callable_ref(task1)); + boost::thread t2(callable_ref(task2)); + boost::thread t3(callable_ref(task3)); + boost::thread t4(callable_ref(task4)); + + t1.join(); + t2.join(); + t3.join(); + t4.join(); + + BOOST_TEST(exactly_eight_instances_created); +} + +//////////////////////////////////////////////////////////////////////////////// +static simple global_simple1_p; + +struct single_global_grammar_object_task +{ + void operator()() const + { + make_definition3(global_simple1_p); + }; +}; + +static void +single_global_grammar_object_multiple_threads() +{ + // check wether exactly one definition per thread is + // created + count_guard guard(simple_definition_count); + single_global_grammar_object_task task1, task2, task3, task4; + + boost::thread t1(callable_ref(task1)); + boost::thread t2(callable_ref(task2)); + boost::thread t3(callable_ref(task3)); + boost::thread t4(callable_ref(task4)); + + t1.join(); + t2.join(); + t3.join(); + t4.join(); + + BOOST_TEST(exactly_four_instances_created); +} + +//////////////////////////////////////////////////////////////////////////////// +static simple global_simple2_p; +static simple global_simple3_p; + +struct multiple_global_grammar_objects_task +{ + void operator()() const + { + make_definition3(global_simple2_p); + make_definition3(global_simple3_p); + }; +}; + +static void +multiple_global_grammar_objects_multiple_threads() +{ + // check wether exactly one definition per thread + // and per grammar object is created + count_guard guard(simple_definition_count); + multiple_global_grammar_objects_task task1, task2, task3, task4; + + boost::thread t1(callable_ref(task1)); + boost::thread t2(callable_ref(task2)); + boost::thread t3(callable_ref(task3)); + boost::thread t4(callable_ref(task4)); + + t1.join(); + t2.join(); + t3.join(); + t4.join(); + + BOOST_TEST(exactly_eight_instances_created); +} +//////////////////////////////////////////////////////////////////////////////// +int +main() +{ + multiple_attempts_to_instantiate_a_definition_from_a_single_thread(); + single_local_grammar_object_multiple_threads(); + multiple_local_grammar_objects_multiple_threads(); + single_global_grammar_object_multiple_threads(); + multiple_global_grammar_objects_multiple_threads(); + + return boost::report_errors(); +} + +//////////////////////////////////////////////////////////////////////////////// + +static BOOST_SPIRIT_CLASSIC_NS::parse_info<char const *> pi; + +//////////////////////////////////////////////// +// These macros are used with BOOST_TEST + + + +#endif // MT mode diff --git a/src/boost/libs/spirit/classic/test/grammar_multi_instance_tst.cpp b/src/boost/libs/spirit/classic/test/grammar_multi_instance_tst.cpp new file mode 100644 index 00000000..9ce05342 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/grammar_multi_instance_tst.cpp @@ -0,0 +1,50 @@ +/*============================================================================= + Copyright (c) 2004 Joel de Guzman + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/include/classic_core.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace std; + +int g_count = 0; + +struct g : public grammar<g> +{ + template <typename ScannerT> + struct definition + { + definition(g const& /*self*/) + { + g_count++; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; +}; + +void +grammar_tests() +{ + g my_g; + parse("", my_g); +} + +int +main() +{ + grammar_tests(); + grammar_tests(); + grammar_tests(); + BOOST_TEST(g_count == 3); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/grammar_tests.cpp b/src/boost/libs/spirit/classic/test/grammar_tests.cpp new file mode 100644 index 00000000..fb78ba33 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/grammar_tests.cpp @@ -0,0 +1,157 @@ +/*============================================================================= + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> + + +//#define BOOST_SPIRIT_DEBUG +#define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_grammar_def.hpp> +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// This feature is disabled on non compliant compilers (e.g. Borland 5.5.1 +// VC6 and VC7) +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && \ + !BOOST_WORKAROUND(__BORLANDC__, <= 0x551) && \ + !BOOST_WORKAROUND(__GNUC__, < 3) +# define BOOST_SPIRIT_USE_GRAMMARDEF +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Grammar tests +// +/////////////////////////////////////////////////////////////////////////////// +struct num_list : public grammar<num_list> +{ + enum { + default_rule = 0, + num_rule = 1 + }; + + template <typename ScannerT> + struct definition +#if defined(BOOST_SPIRIT_USE_GRAMMARDEF) + : public grammar_def<rule<ScannerT>, same> +#endif + { + definition(num_list const& /*self*/) + { + num = int_p; + r = num >> *(',' >> num); + +#if defined(BOOST_SPIRIT_USE_GRAMMARDEF) + this->start_parsers(r, num); +#endif + BOOST_SPIRIT_DEBUG_RULE(num); + BOOST_SPIRIT_DEBUG_RULE(r); + } + + rule<ScannerT> r, num; + +#if !defined(BOOST_SPIRIT_USE_GRAMMARDEF) + rule<ScannerT> const& start() const { return r; } +#endif + }; +}; + +struct num_list_ex : public grammar<num_list_ex> +{ + enum { + default_rule = 0, + num_rule = 1, + integer_rule = 2 + }; + + template <typename ScannerT> + struct definition +#if defined(BOOST_SPIRIT_USE_GRAMMARDEF) + : public grammar_def<rule<ScannerT>, same, int_parser<int, 10, 1, -1> > +#endif + { + definition(num_list_ex const& /*self*/) + { + num = integer; + r = num >> *(',' >> num); + +#if defined(BOOST_SPIRIT_USE_GRAMMARDEF) + this->start_parsers(r, num, integer); +#endif + BOOST_SPIRIT_DEBUG_RULE(num); + BOOST_SPIRIT_DEBUG_RULE(r); + } + + rule<ScannerT> r, num; + int_parser<int, 10, 1, -1> integer; + +#if !defined(BOOST_SPIRIT_USE_GRAMMARDEF) + rule<ScannerT> const& start() const { return r; } +#endif + }; +}; + +void +grammar_tests() +{ + num_list nlist; + BOOST_SPIRIT_DEBUG_GRAMMAR(nlist); + + parse_info<char const*> pi; + pi = parse("123, 456, 789", nlist, space_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + +#if defined(BOOST_SPIRIT_USE_GRAMMARDEF) + num_list_ex nlistex; + BOOST_SPIRIT_DEBUG_GRAMMAR(nlistex); + + pi = parse("123, 456, 789", nlist.use_parser<num_list::default_rule>(), + space_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("123", nlist.use_parser<num_list::num_rule>(), space_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("123, 456, 789", nlistex, space_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("123, 456, 789", + nlistex.use_parser<num_list_ex::default_rule>(), space_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("123", nlistex.use_parser<num_list_ex::num_rule>(), space_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("123", nlistex.use_parser<num_list_ex::integer_rule>(), + space_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); +#endif // defined(BOOST_SPIRIT_USE_GRAMMARDEF) +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Main +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + grammar_tests(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/group_match_bug.cpp b/src/boost/libs/spirit/classic/test/group_match_bug.cpp new file mode 100644 index 00000000..acc13a98 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/group_match_bug.cpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2004 Joao Abecasis + http://spirit.sourceforge.net/ + + 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/include/classic_core.hpp> + +#include <boost/spirit/include/classic_closure.hpp> + +#include <boost/spirit/include/classic_ast.hpp> +#include <boost/spirit/include/classic_parse_tree.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +struct test_closure : public closure<test_closure, int> +{ + member1 value; +}; + +struct test_grammar : public grammar<test_grammar> +{ + template <typename ScannerT> + struct definition + { + definition(const test_grammar&) + { + } + + rule<ScannerT, test_closure::context_t> const & start() const + { + return first; + } + + rule<ScannerT, test_closure::context_t> first; + }; +}; + +int main() +{ + parse("abcd", test_grammar()); + pt_parse("abcd", test_grammar()); + ast_parse("abcd", test_grammar()); +} + + diff --git a/src/boost/libs/spirit/classic/test/if_p_as_parser_tests.cpp b/src/boost/libs/spirit/classic/test/if_p_as_parser_tests.cpp new file mode 100644 index 00000000..5b20aa2e --- /dev/null +++ b/src/boost/libs/spirit/classic/test/if_p_as_parser_tests.cpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + 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/include/classic_core.hpp> +#include <boost/spirit/include/classic_if.hpp> + +extern bool fun(); + +struct ftor +{ + bool operator()() const; +}; + +int +main() +{ + ////////////////////////////////// + // compile time check wether as_parser<> works for if_p + + ::BOOST_SPIRIT_CLASSIC_NS::rule<> r; + + r = ::BOOST_SPIRIT_CLASSIC_NS::if_p('-')['-']; + r = ::BOOST_SPIRIT_CLASSIC_NS::if_p("-")["-"]; + r = ::BOOST_SPIRIT_CLASSIC_NS::if_p('-')['-'].else_p['-']; + r = ::BOOST_SPIRIT_CLASSIC_NS::if_p("-")["-"].else_p["-"]; + + r = ::BOOST_SPIRIT_CLASSIC_NS::if_p(&fun)["foo"]; + r = ::BOOST_SPIRIT_CLASSIC_NS::if_p(ftor())["foo"]; + r = ::BOOST_SPIRIT_CLASSIC_NS::if_p(&fun)["foo"].else_p["bar"]; + r = ::BOOST_SPIRIT_CLASSIC_NS::if_p(ftor())["foo"].else_p["bar"]; + + r = ::BOOST_SPIRIT_CLASSIC_NS::if_p(r)[r]; + r = ::BOOST_SPIRIT_CLASSIC_NS::if_p(r)[r].else_p[r]; +} diff --git a/src/boost/libs/spirit/classic/test/if_p_int_as_condition_test.cpp b/src/boost/libs/spirit/classic/test/if_p_int_as_condition_test.cpp new file mode 100644 index 00000000..c14058d7 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/if_p_int_as_condition_test.cpp @@ -0,0 +1,87 @@ +/*============================================================================= + Copyright (c) 2004 Martin Wille + http://spirit.sourceforge.net/ + + 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/include/classic_core.hpp> +#include <boost/spirit/include/classic_dynamic.hpp> +#include <boost/spirit/include/classic_ast.hpp> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; +int the_var_to_be_tested = 0; + +namespace local +{ + template <typename T> + struct var_wrapper : public ::boost::reference_wrapper<T> + { + typedef ::boost::reference_wrapper<T> parent; + + explicit inline var_wrapper(T& t) : parent(t) {} + + inline T& operator()() const { return parent::get(); } + }; + + template <typename T> + inline var_wrapper<T> + var(T& t) + { + return var_wrapper<T>(t); + } +} + +struct test_grammar : public grammar <test_grammar> +{ + template <typename ScannerT> + + struct definition + { + rule <ScannerT, parser_tag <0> > test; + + definition(const test_grammar& /*self*/) + { + test + = if_p(local::var(the_var_to_be_tested)) + [ + real_p + ]; + + } + const rule <ScannerT, parser_tag<0> >& start() const {return test;} + }; +}; + +int main() +{ + test_grammar gram; + tree_parse_info <const char*> result; + + //predictably fails + the_var_to_be_tested = 0; + result = ast_parse("1.50", gram, space_p); + std::cout << "Testing if_p against: " << the_var_to_be_tested << std::endl; + std::cout << "success: " << result.full << std::endl; + BOOST_TEST(!result.full); + + //predicatably succeeds + the_var_to_be_tested = 1; + result = ast_parse("1.50", gram, space_p); + std::cout << "Testing if_p against: " << the_var_to_be_tested << std::endl; + std::cout << "success: " << result.full << std::endl; + BOOST_TEST(result.full); + + //should succeed + the_var_to_be_tested = 2; + result = ast_parse("1.50", gram, space_p); + std::cout << "Testing if_p against: " << the_var_to_be_tested << std::endl; + std::cout << "success: " << result.full << std::endl; + BOOST_TEST(result.full); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/if_tests.cpp b/src/boost/libs/spirit/classic/test/if_tests.cpp new file mode 100644 index 00000000..bfbc9d5f --- /dev/null +++ b/src/boost/libs/spirit/classic/test/if_tests.cpp @@ -0,0 +1,250 @@ +/*============================================================================= + Copyright (c) 2004 Stefan Slapeta + Copyright (c) 2002-2003 Martin Wille + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ +// vi:ts=4:sw=4:et +// Tests for BOOST_SPIRIT_CLASSIC_NS::if_p +// [28-Dec-2002] +//////////////////////////////////////////////////////////////////////////////// +#include <iostream> +#include <cstring> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_if.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> +#include <boost/ref.hpp> +#include "impl/string_length.hpp" + +namespace local +{ + template <typename T> + struct var_wrapper + : public ::boost::reference_wrapper<T> + { + typedef ::boost::reference_wrapper<T> parent; + + explicit inline var_wrapper(T& t) : parent(t) {} + + inline T& operator()() const { return parent::get(); } + }; + + template <typename T> + inline var_wrapper<T> + var(T& t) + { + return var_wrapper<T>(t); + } +} + +typedef ::BOOST_SPIRIT_CLASSIC_NS::rule<> rule_t; +typedef ::BOOST_SPIRIT_CLASSIC_NS::rule<BOOST_SPIRIT_CLASSIC_NS::no_actions_scanner<>::type > + no_actions_rule_t; + +unsigned int test_count = 0; +unsigned int error_count = 0; + +unsigned int number_result; +static const unsigned int kError = 999; +static const bool good = true; +static const bool bad = false; + +rule_t hex_prefix; +no_actions_rule_t oct_prefix; +rule_t hex_rule, oct_rule, dec_rule; + +rule_t auto_number_rule; +rule_t hex_or_dec_number_rule; + +void +test_number(char const *s, unsigned int wanted, rule_t const &r) +{ + using namespace std; + + ++test_count; + + number_result = wanted-1; + ::BOOST_SPIRIT_CLASSIC_NS::parse_info<> m = ::BOOST_SPIRIT_CLASSIC_NS::parse(s, s + test_impl::string_length(s), r); + + bool result = wanted == kError?(m.full?bad:good): (number_result==wanted); + + if (m.full && (m.length != test_impl::string_length(s))) + result = bad; + + + if (result==good) + cout << "PASSED"; + else + { + ++error_count; + cout << "FAILED"; + } + + cout << ": \"" << s << "\" ==> "; + if (number_result==wanted-1) + cout << "<error>"; + else + cout << number_result; + + cout << "\n"; +} + +void +test_enclosed_fail() +{ + using namespace std; + + using ::BOOST_SPIRIT_CLASSIC_NS::if_p; + using ::BOOST_SPIRIT_CLASSIC_NS::str_p; + using ::BOOST_SPIRIT_CLASSIC_NS::nothing_p; + + cout << "\nfail enclosed parser:\n"; + + const char *p = "abc"; + + ::BOOST_SPIRIT_CLASSIC_NS::strlit<const char*> success_p = str_p(p); + ::BOOST_SPIRIT_CLASSIC_NS::strlit<const char*> fail_p = str_p("xxx"); + + ::BOOST_SPIRIT_CLASSIC_NS::rule<> r = if_p(success_p)[nothing_p]; + + ::BOOST_SPIRIT_CLASSIC_NS::parse_info<> m = ::BOOST_SPIRIT_CLASSIC_NS::parse(p, r); + + if (m.full) { + cout << "FAILED: if --> match" << endl; + ++error_count; + } else { + cout << "PASSED: if --> no_match" << endl; + } + + r = if_p(fail_p)[success_p].else_p[nothing_p]; + + m = ::BOOST_SPIRIT_CLASSIC_NS::parse(p, r); + + if (m.full) { + cout << "FAILED: else --> match" << endl; + ++error_count; + } else { + cout << "PASSED: else --> no_match" << endl; + } +} + +int +main() +{ + using namespace std; + using ::BOOST_SPIRIT_CLASSIC_NS::if_p; + using ::BOOST_SPIRIT_CLASSIC_NS::uint_p; + using ::BOOST_SPIRIT_CLASSIC_NS::oct_p; + using ::BOOST_SPIRIT_CLASSIC_NS::hex_p; + using ::BOOST_SPIRIT_CLASSIC_NS::str_p; + using ::BOOST_SPIRIT_CLASSIC_NS::ch_p; + using ::BOOST_SPIRIT_CLASSIC_NS::assign_a; + + cout << "/////////////////////////////////////////////////////////\n"; + cout << "\n"; + cout << " if_p test\n"; + cout << "\n"; + cout << "/////////////////////////////////////////////////////////\n"; + cout << "\n"; + + bool as_hex; + +#if qDebug + BOOST_SPIRIT_DEBUG_RULE(hex_prefix); + BOOST_SPIRIT_DEBUG_RULE(hex_rule); + BOOST_SPIRIT_DEBUG_RULE(oct_prefix); + BOOST_SPIRIT_DEBUG_RULE(oct_rule); + BOOST_SPIRIT_DEBUG_RULE(dec_rule); + BOOST_SPIRIT_DEBUG_RULE(auto_number_rule); + BOOST_SPIRIT_DEBUG_RULE(hex_or_dec_number_rule); +#endif + + hex_prefix = str_p("0x"); + oct_prefix = ch_p('0'); + + hex_rule = hex_p[assign_a(number_result)]; + oct_rule = oct_p[assign_a(number_result)]; + dec_rule = uint_p[assign_a(number_result)]; + + auto_number_rule = + if_p(hex_prefix) + [hex_rule] + .else_p + [ + if_p(::BOOST_SPIRIT_CLASSIC_NS::eps_p(oct_prefix)) + [oct_rule] + .else_p + [dec_rule] + ]; + + hex_or_dec_number_rule = + if_p(local::var(as_hex))[hex_prefix>>hex_rule].else_p[dec_rule]; + + cout << "auto:\n"; + test_number("", kError, auto_number_rule); + test_number("0", 0, auto_number_rule); + test_number("1", 1, auto_number_rule); + test_number("00", 0, auto_number_rule); + test_number("0x", kError, auto_number_rule); + test_number("0x0", 0, auto_number_rule); + test_number("0755", 493, auto_number_rule); + test_number("0x100", 256, auto_number_rule); + + cout << "\ndecimal:\n"; + as_hex = false; + test_number("", kError, hex_or_dec_number_rule); + test_number("100", 100, hex_or_dec_number_rule); + test_number("0x100", kError, hex_or_dec_number_rule); + test_number("0xff", kError, hex_or_dec_number_rule); + + cout << "\nhexadecimal:\n"; + as_hex = true; + test_number("", kError, hex_or_dec_number_rule); + test_number("0x100", 256, hex_or_dec_number_rule); + test_number("0xff", 255, hex_or_dec_number_rule); + + ////////////////////////////////// + // tests for if_p without else-parser + cout << "\nno-else:\n"; + rule_t r = if_p(::BOOST_SPIRIT_CLASSIC_NS::eps_p('0'))[oct_rule]; + + test_number("0", 0, r); + + ++test_count; + ::BOOST_SPIRIT_CLASSIC_NS::parse_info<> m = ::BOOST_SPIRIT_CLASSIC_NS::parse("", r); + if (!m.hit || !m.full || m.length!=0) + { + std::cout << "FAILED: \"\" ==> <error>\n"; + ++error_count; + } + else + std::cout << "PASSED: \"\" ==> <empty match>\n"; + + ++test_count; + m = ::BOOST_SPIRIT_CLASSIC_NS::parse("junk", r); + if (!m.hit || m.full || m.length!=0) + { + std::cout << "FAILED: \"junk\" ==> <error>\n"; + ++error_count; + } + else + std::cout << "PASSED: \"junk\" ==> <empty match>\n"; + + test_enclosed_fail(); + + + ////////////////////////////////// + // report results + std::cout << "\n "; + if (error_count==0) + cout << "All " << test_count << " if_p-tests passed.\n" + << "Test concluded successfully\n"; + else + cout << error_count << " of " << test_count << " if_p-tests failed\n" + << "Test failed\n"; + + return error_count!=0; +} diff --git a/src/boost/libs/spirit/classic/test/impl/sstream.hpp b/src/boost/libs/spirit/classic/test/impl/sstream.hpp new file mode 100644 index 00000000..bb94cb9c --- /dev/null +++ b/src/boost/libs/spirit/classic/test/impl/sstream.hpp @@ -0,0 +1,46 @@ +/*============================================================================= + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + 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/config.hpp> + +/////////////////////////////////////////////////////////////////////////// +// workaround for prestandard support of stringstreams +// +// * defines sstream_t for the string stream type +// * defines std::string getstring(sstream_t &); +// + +#ifdef BOOST_NO_STRINGSTREAM +# include <strstream> + typedef strstream sstream_t; + std::string + getstring(std::strstream& ss) + { + ss << ends; + std::string rval = ss.str(); + ss.freeze(false); + return rval; + } +#else +# include <sstream> + typedef std::stringstream sstream_t; + std::string + getstring(std::stringstream &ss) + { + return ss.str(); + } +#endif + +void use_getstring_to_avoid_compiler_warnings_about_unused_functions() +{ + sstream_t ss; + getstring(ss); + if(!ss) { // to be not recursive on all control paths + use_getstring_to_avoid_compiler_warnings_about_unused_functions(); + } +} diff --git a/src/boost/libs/spirit/classic/test/impl/string_length.hpp b/src/boost/libs/spirit/classic/test/impl/string_length.hpp new file mode 100644 index 00000000..f55c4bbf --- /dev/null +++ b/src/boost/libs/spirit/classic/test/impl/string_length.hpp @@ -0,0 +1,30 @@ +/*============================================================================= + Copyright (c) 2004 Joel de Guzman + http://spirit.sourceforge.net/ + + 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(SPIRIT_TEST_IMPL_STRING_LEN_HPP) +#define SPIRIT_TEST_IMPL_STRING_LEN_HPP + +// We use our own string_len function instead of std::strlen +// to avoid the namespace confusion on different compilers. Some +// have it in namespace std. Some have it in global namespace. +// Some have it in both. +namespace test_impl +{ + template <typename Char> + inline unsigned int + string_length(Char const* str) + { + unsigned int len = 0; + while (*str++) + ++len; + return len; + } +} + +#endif + diff --git a/src/boost/libs/spirit/classic/test/impl/var.hpp b/src/boost/libs/spirit/classic/test/impl/var.hpp new file mode 100644 index 00000000..d2019452 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/impl/var.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ +#ifndef BOOST_SPIRIT_TEST_IMPL_VAR_HPP +#define BOOST_SPIRIT_TEST_IMPL_VAR_HPP + +#include <boost/ref.hpp> + +namespace test +{ + template <typename T> + struct var_wrapper + : public ::boost::reference_wrapper<T> + { + typedef ::boost::reference_wrapper<T> parent; + + explicit inline var_wrapper(T& t) : parent(t) {} + + inline T& operator()() const { return parent::get(); } + }; + + template <typename T> + inline var_wrapper<T> + var(T& t) + { + return var_wrapper<T>(t); + } +} +#endif // BOOST_SPIRIT_TEST_IMPL_VAR_HPP diff --git a/src/boost/libs/spirit/classic/test/lazy_tests.cpp b/src/boost/libs/spirit/classic/test/lazy_tests.cpp new file mode 100644 index 00000000..47485c2f --- /dev/null +++ b/src/boost/libs/spirit/classic/test/lazy_tests.cpp @@ -0,0 +1,27 @@ +/*============================================================================= + Copyright (c) 2003 Vaclav Vesely + http://spirit.sourceforge.net/ + + 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/include/classic_core.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> +#include <boost/spirit/include/classic_lazy.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <boost/detail/lightweight_test.hpp> + +using namespace boost; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +int main() +{ + int result; + BOOST_TEST(parse("123", lazy_p(val(int_p))[assign_a(result)]).full); + BOOST_TEST((result == 123)); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/loops_tests.cpp b/src/boost/libs/spirit/classic/test/loops_tests.cpp new file mode 100644 index 00000000..2a97f311 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/loops_tests.cpp @@ -0,0 +1,118 @@ +/*============================================================================= + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_loops.hpp> +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Loops tests +// +/////////////////////////////////////////////////////////////////////////////// +void +loops_tests() +{ + parse_info<char const*> pi; + + pi = parse("\"Hello World\"", "\"" >> *(anychar_p - "\"") >> "\""); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 13); + BOOST_TEST(*pi.stop == 0); + + pi = parse("\"Hello World\"", "\"" >> repeat_p(0, more)[anychar_p - "\""] >> "\""); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 13); + BOOST_TEST(*pi.stop == 0); + + pi = parse("xx", +ch_p('x')); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 2); + BOOST_TEST(*pi.stop == 0); + + pi = parse("xx", repeat_p(1, more)[ch_p('x')]); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 2); + BOOST_TEST(*pi.stop == 0); + + pi = parse("", +ch_p('x')); + BOOST_TEST(!pi.hit); + + pi = parse("", repeat_p(1, more)[ch_p('x')]); + BOOST_TEST(!pi.hit); + + pi = parse("", *ch_p('x')); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 0); + BOOST_TEST(*pi.stop == 0); + + pi = parse("", repeat_p(0, more)[ch_p('x')]); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 0); + BOOST_TEST(*pi.stop == 0); + + // repeat exact 8 + rule<> rep8 = repeat_p(8)[alpha_p] >> 'X'; + BOOST_TEST(!parse("abcdefgX", rep8).hit); + BOOST_TEST(parse("abcdefghX", rep8).full); + BOOST_TEST(!parse("abcdefghiX", rep8).hit); + BOOST_TEST(!parse("abcdefgX", rep8).hit); + BOOST_TEST(!parse("aX", rep8).hit); + + // repeat 2 to 8 + rule<> rep28 = repeat_p(2, 8)[alpha_p] >> '*'; + BOOST_TEST(parse("abcdefg*", rep28).full); + BOOST_TEST(parse("abcdefgh*", rep28).full); + BOOST_TEST(!parse("abcdefghi*", rep28).hit); + BOOST_TEST(!parse("a*", rep28).hit); + + // repeat 2 or more + rule<> rep2_ = repeat_p(2, more)[alpha_p] >> '+'; + BOOST_TEST(parse("abcdefg+", rep2_).full); + BOOST_TEST(parse("abcdefgh+", rep2_).full); + BOOST_TEST(parse("abcdefghi+", rep2_).full); + BOOST_TEST(parse("abcdefg+", rep2_).full); + BOOST_TEST(!parse("a+", rep2_).hit); + + // repeat 0 + rule<> rep0 = repeat_p(0)[alpha_p] >> '/'; + BOOST_TEST(parse("/", rep0).full); + BOOST_TEST(!parse("a/", rep0).hit); + + // repeat 0 or 1 + rule<> rep01 = repeat_p(0, 1)[alpha_p >> digit_p] >> '?'; + BOOST_TEST(!parse("abcdefg?", rep01).hit); + BOOST_TEST(!parse("a?", rep01).hit); + BOOST_TEST(!parse("1?", rep01).hit); + BOOST_TEST(!parse("11?", rep01).hit); + BOOST_TEST(!parse("aa?", rep01).hit); + BOOST_TEST(parse("?", rep01).full); + BOOST_TEST(parse("a1?", rep01).full); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Main +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + loops_tests(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/match_tests.cpp b/src/boost/libs/spirit/classic/test/match_tests.cpp new file mode 100644 index 00000000..bc919bbe --- /dev/null +++ b/src/boost/libs/spirit/classic/test/match_tests.cpp @@ -0,0 +1,175 @@ +/*============================================================================= + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> +#include <string> + +using namespace std; + +#include <boost/spirit/include/classic_core.hpp> +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Match tests +// +/////////////////////////////////////////////////////////////////////////////// +struct X {}; +struct Y { Y(int) {} }; // not default constructible +struct Z { Z(double n):n(n){} double n; }; // implicitly convertible from double + +void +match_tests() +{ + match<> m0; + BOOST_TEST(!m0.has_valid_attribute()); + + match<int> m1(m0); + m1.value(123); + BOOST_TEST(m1.has_valid_attribute()); + BOOST_TEST(m1.value() == 123); + + match<double> m2(m1); + BOOST_TEST(m2.has_valid_attribute()); + BOOST_TEST(m1.value() == int(m2.value())); + m2.value(456); + + *&m0 = m0; // match<nil> = match<nil> + m0 = m1; // match<nil> = match<int> + m0 = m2; // match<nil> = match<double> + m1 = m0; // match<int> = match<nil> + BOOST_TEST(!m1); + BOOST_TEST(!m1.has_valid_attribute()); + + *&m1 = m1; // match<int> = match<int> + m1.value(int(m2.value())); + BOOST_TEST(m1.has_valid_attribute()); + BOOST_TEST(m1.value() == int(m2.value())); + + m2.value(123.456); + match<Z> mz(m2); // copy from match<double> + mz = m2; // assign from match<double> + BOOST_TEST(mz.value().n == 123.456); + + m1.value(123); + m2 = m0; + BOOST_TEST(!m2); + BOOST_TEST(!m2.has_valid_attribute()); + + m2 = m1; // match<double> = match<int> + BOOST_TEST(m2.has_valid_attribute()); + BOOST_TEST(m1.value() == int(m2.value())); + *&m2 = m2; // match<double> = match<double> + + cout << "sizeof(int) == " << sizeof(int) << '\n'; + cout << "sizeof(match<>) == " << sizeof(m0) << '\n'; + cout << "sizeof(match<int>) == " << sizeof(m1) << '\n'; + cout << "sizeof(match<double>) == " << sizeof(m2) << '\n'; + + match<int&> mr; + BOOST_TEST(!mr.has_valid_attribute()); + + match<int&> mrr(4); + BOOST_TEST(!mrr.has_valid_attribute()); + + int ri = 3; + match<int&> mr2(4, ri); + BOOST_TEST(mr2.has_valid_attribute()); + mr = mr2; + BOOST_TEST(mr.has_valid_attribute()); + + match<int&> mr3(mrr); + BOOST_TEST(!mr3.has_valid_attribute()); + mr2 = mr3; + BOOST_TEST(!mr2.has_valid_attribute()); + + match<X> mx; + m1 = mx; + m0 = mx; + BOOST_TEST(!mx.has_valid_attribute()); + BOOST_TEST(!m0.has_valid_attribute()); + BOOST_TEST(!m1.has_valid_attribute()); + + match<Y> my; + BOOST_TEST(!my.has_valid_attribute()); + + match<std::string> ms; + BOOST_TEST(!ms.has_valid_attribute()); + ms.value("Kimpo Ponchwayla"); + BOOST_TEST(ms.has_valid_attribute()); + BOOST_TEST(ms.value() == "Kimpo Ponchwayla"); + ms = match<>(); + BOOST_TEST(!ms.has_valid_attribute()); + + // let's try a match with a reference: + int i; + match<int&> mr4(4, i); + BOOST_TEST(mr4.has_valid_attribute()); + mr4.value(3); + BOOST_TEST(mr4.value() == 3); + BOOST_TEST(i == 3); + (void)i; + + int x = 456; + match<int&> mref(1, x); + BOOST_TEST(mref.value() == 456); + mref.value(123); + BOOST_TEST(mref.value() == 123); + x = mref.value(); + BOOST_TEST(x == 123); + mref.value() = 986; + BOOST_TEST(x == 986); + + std::string s("hello"); + match<int> mint(1, x); + BOOST_TEST(mint.value() == x); + match<std::string> mstr(1, s); + BOOST_TEST(mstr.value() == "hello"); + mstr = mint; + mint = mstr; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Match Policy tests +// +/////////////////////////////////////////////////////////////////////////////// +void +match_policy_tests() +{ + match<> m0; + match<int> m1; + match<double> m2; + match_policy mp; + + m0 = mp.no_match(); BOOST_TEST(!m0); + m1 = mp.no_match(); BOOST_TEST(!m1); + m0 = mp.empty_match(); BOOST_TEST(!!m0); + m2 = mp.empty_match(); BOOST_TEST(!!m2); + + m1 = mp.create_match(5, 100, 0, 0); + m2 = mp.create_match(5, 10.5, 0, 0); + + mp.concat_match(m1, m2); + BOOST_TEST(m1.length() == 10); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Main +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + match_tests(); + match_policy_tests(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/mix_and_match_trees.cpp b/src/boost/libs/spirit/classic/test/mix_and_match_trees.cpp new file mode 100644 index 00000000..f489e181 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/mix_and_match_trees.cpp @@ -0,0 +1,82 @@ +// +// Copyright (c) 2006 Joao Abecasis +// +// 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) +// + +//////////////////////////////////////////////////////////////////////////////// +// +// As reported by Jascha Wetzel, in +// http://article.gmane.org/gmane.comp.parsers.spirit.general/9013, the +// directives gen_ast_node_d and gen_pt_node_d were not working for lack of +// appropriate conversion constructors in the underlying tree match policies. +// +//////////////////////////////////////////////////////////////////////////////// + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_ast.hpp> +#include <boost/spirit/include/classic_parse_tree.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +struct my_grammar : grammar<my_grammar> +{ + template <class Scanner> + struct definition + { + typedef + scanner< + typename Scanner::iterator_t, + scanner_policies< + typename Scanner::iteration_policy_t, + ast_match_policy< + typename Scanner::match_policy_t::iterator_t, + typename Scanner::match_policy_t::factory_t + >, + typename Scanner::action_policy_t + > + > ast_scanner; + + typedef + scanner< + typename Scanner::iterator_t, + scanner_policies< + typename Scanner::iteration_policy_t, + pt_match_policy< + typename Scanner::match_policy_t::iterator_t, + typename Scanner::match_policy_t::factory_t + >, + typename Scanner::action_policy_t + > + > pt_scanner; + + typedef rule<ast_scanner> ast_rule; + typedef rule<pt_scanner> pt_rule; + typedef rule<Scanner> rule_; + + definition(my_grammar const & /* self */) + { + start_ = gen_ast_node_d[ ast_rule_ ]; + start_ = gen_pt_node_d[ pt_rule_ ]; + } + + rule_ const & start() const + { + return start_; + } + + rule_ start_; + ast_rule ast_rule_; + pt_rule pt_rule_; + }; +}; + +int main() +{ + const char * begin = NULL, * end = NULL; + + pt_parse(begin, end, my_grammar()); + ast_parse(begin, end, my_grammar()); +} diff --git a/src/boost/libs/spirit/classic/test/multi_pass_compile_tests.cpp b/src/boost/libs/spirit/classic/test/multi_pass_compile_tests.cpp new file mode 100644 index 00000000..eebab917 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/multi_pass_compile_tests.cpp @@ -0,0 +1,61 @@ +/*============================================================================= + Copyright (c) 2004 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +// This is a compile only test for verifying, whether the multi_pass<> +// iterator works ok with an input iterator, which returns a value_type and not +// a reference from its dereferencing operator. + +#include <cstdio> +#include <fstream> +#include <iterator> + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_multi_pass.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace std; + +int main () +{ + // create a sample file + { + ofstream out("./input_file.txt"); + out << 1.0 << "," << 2.0; + } + + int result = 0; + + // read in the values from the sample file + { + ifstream in("./input_file.txt"); // we get our input from this file + + typedef char char_t; + typedef multi_pass<istreambuf_iterator<char_t> > iterator_t; + + typedef skip_parser_iteration_policy<space_parser> it_policy_t; + typedef scanner_policies<it_policy_t> scan_policies_t; + typedef scanner<iterator_t, scan_policies_t> scanner_t; + + typedef rule<scanner_t> rule_t; + + it_policy_t iter_policy(space_p); + scan_policies_t policies(iter_policy); + iterator_t first(make_multi_pass(std::istreambuf_iterator<char_t>(in))); + scanner_t scan(first, make_multi_pass(std::istreambuf_iterator<char_t>()), + policies); + + rule_t n_list = real_p >> *(',' >> real_p); + match<> m = n_list.parse(scan); + + result = !m ? 1 : 0; + } + + std::remove("./input_file.txt"); + return result; +} diff --git a/src/boost/libs/spirit/classic/test/multi_pass_tests.cpp b/src/boost/libs/spirit/classic/test/multi_pass_tests.cpp new file mode 100644 index 00000000..2dcf2e56 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/multi_pass_tests.cpp @@ -0,0 +1,765 @@ +/*============================================================================= + Copyright (c) 2001-2003 Daniel Nuffer + http://spirit.sourceforge.net/ + + 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/include/classic_multi_pass.hpp> +#include <boost/scoped_ptr.hpp> +#include <iterator> +#include <string> +#include <boost/detail/lightweight_test.hpp> +#include "impl/sstream.hpp" + +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +sstream_t res; + +typedef multi_pass<istream_iterator<char> > default_multi_pass_t; + +typedef look_ahead<istream_iterator<char>, 6> fixed_multi_pass_t; + +typedef multi_pass< + istream_iterator<char>, + multi_pass_policies::input_iterator, + multi_pass_policies::first_owner, + multi_pass_policies::buf_id_check, + multi_pass_policies::std_deque +> first_owner_multi_pass_t; + + +// a functor to test out the functor_multi_pass +class my_functor +{ + public: + typedef char result_type; + my_functor() + : c('A') + {} + + char operator()() + { + if (c == 'M') + return eof; + else + return c++; + } + + static result_type eof; + private: + char c; +}; + +my_functor::result_type my_functor::eof = '\0'; + +typedef multi_pass< + my_functor, + multi_pass_policies::functor_input, + multi_pass_policies::first_owner, + multi_pass_policies::no_check, + multi_pass_policies::std_deque +> functor_multi_pass_t; + +void test_default_multi_pass() +{ + res << "-*= test_default_multi_pass =*-\n"; + istream_iterator<char> end; + boost::scoped_ptr<default_multi_pass_t> mpend(new default_multi_pass_t(end)); + + { + sstream_t ss; + ss << "test string"; + + istream_iterator<char> a(ss); + boost::scoped_ptr<default_multi_pass_t> mp1(new default_multi_pass_t(a)); + + while (*mp1 != *mpend) + { + res << *((*mp1)++); + } + + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> b(ss); + boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(b)); + boost::scoped_ptr<default_multi_pass_t> mp3(new default_multi_pass_t(b)); + *mp3 = *mp2; + + for (int i = 0; i < 4; ++i) + { + res << **mp2; + ++*mp2; + } + + mp3.reset(); + + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> a(ss); + boost::scoped_ptr<default_multi_pass_t> mp1(new default_multi_pass_t(a)); + boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(*mp1)); + + for (int i = 0; i < 4; ++i) + { + res << **mp1; + ++*mp1; + } + + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + while (*mp1 != *mpend) + { + res << **mp1; + ++*mp1; + } + + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> b(ss); + boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(b)); + boost::scoped_ptr<default_multi_pass_t> mp3(new default_multi_pass_t(b)); + *mp3 = *mp2; + + for (int i = 0; i < 4; ++i) + { + res << **mp2; + ++*mp2; + } + + mp3.reset(); + ++*mp2; + + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> a(ss); + boost::scoped_ptr<default_multi_pass_t> mp1(new default_multi_pass_t(a)); + boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(*mp1)); + + BOOST_TEST(*mp1 == *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp1 <= *mp2); + for (int i = 0; i < 4; ++i) + { + res << **mp1; + ++*mp1; + } + + BOOST_TEST(*mp1 != *mp2); + BOOST_TEST(*mp1 > *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp2 < *mp1); + BOOST_TEST(*mp2 <= *mp1); + while (*mp2 != *mp1) + { + res << **mp2; + ++*mp2; + } + + BOOST_TEST(*mp1 == *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp1 <= *mp2); + while (*mp1 != *mpend) + { + res << **mp1; + ++*mp1; + } + + BOOST_TEST(*mp1 != *mp2); + BOOST_TEST(*mp1 > *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp2 < *mp1); + BOOST_TEST(*mp2 <= *mp1); + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + BOOST_TEST(*mp1 == *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp1 <= *mp2); + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> a(ss); + boost::scoped_ptr<default_multi_pass_t> mp1(new default_multi_pass_t(a)); + boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(a)); + BOOST_TEST(*mp1 != *mp2); + ++*mp1; + BOOST_TEST(*mp1 != *mp2); + + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> b(ss); + boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(b)); + boost::scoped_ptr<default_multi_pass_t> mp3(new default_multi_pass_t(b)); + *mp3 = *mp2; + + for (int i = 0; i < 4; ++i) + { + res << **mp2; + ++*mp2; + } + + mp2->clear_queue(); + + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + try + { + res << **mp3; // this should throw illegal_backtracking + BOOST_TEST(0); + } + catch (const BOOST_SPIRIT_CLASSIC_NS::multi_pass_policies::illegal_backtracking& /*e*/) + { + } + res << endl; + } + + +} + +void test_fixed_multi_pass() +{ + res << "-*= test_fixed_multi_pass =*-\n"; + istream_iterator<char> end; + boost::scoped_ptr<fixed_multi_pass_t> mpend(new fixed_multi_pass_t(end)); + + { + sstream_t ss; + ss << "test string"; + + istream_iterator<char> a(ss); + boost::scoped_ptr<fixed_multi_pass_t> mp1(new fixed_multi_pass_t(a)); + + while (*mp1 != *mpend) + { + res << *((*mp1)++); + } + + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> b(ss); + boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(b)); + boost::scoped_ptr<fixed_multi_pass_t> mp3(new fixed_multi_pass_t(*mp2)); + + for (int i = 0; i < 4; ++i) + { + res << **mp2; + ++*mp2; + } + + mp3.reset(); + + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> a(ss); + boost::scoped_ptr<fixed_multi_pass_t> mp1(new fixed_multi_pass_t(a)); + boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(*mp1)); + + for (int i = 0; i < 4; ++i) + { + res << **mp1; + ++*mp1; + } + + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + while (*mp1 != *mpend) + { + res << **mp1; + ++*mp1; + } + + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> b(ss); + boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(b)); + boost::scoped_ptr<fixed_multi_pass_t> mp3(new fixed_multi_pass_t(*mp2)); + + for (int i = 0; i < 4; ++i) + { + res << **mp2; + ++*mp2; + } + + mp3.reset(); + ++*mp2; + + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> a(ss); + boost::scoped_ptr<fixed_multi_pass_t> mp1(new fixed_multi_pass_t(a)); + boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(*mp1)); + + BOOST_TEST(*mp1 == *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp1 <= *mp2); + for (int i = 0; i < 4; ++i) + { + res << **mp1; + ++*mp1; + } + + BOOST_TEST(*mp1 != *mp2); + BOOST_TEST(*mp1 > *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp2 < *mp1); + BOOST_TEST(*mp2 <= *mp1); + while (*mp2 != *mp1) + { + res << **mp2; + ++*mp2; + } + + BOOST_TEST(*mp1 == *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp1 <= *mp2); + while (*mp1 != *mpend) + { + res << **mp1; + ++*mp1; + } + + BOOST_TEST(*mp1 != *mp2); + BOOST_TEST(*mp1 > *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp2 < *mp1); + BOOST_TEST(*mp2 <= *mp1); + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + BOOST_TEST(*mp1 == *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp1 <= *mp2); + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> a(ss); + boost::scoped_ptr<fixed_multi_pass_t> mp1(new fixed_multi_pass_t(a)); + boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(a)); + BOOST_TEST(*mp1 != *mp2); + ++*mp1; + BOOST_TEST(*mp1 != *mp2); + + } + +} + +void test_first_owner_multi_pass() +{ + res << "-*= test_first_owner_multi_pass =*-\n"; + istream_iterator<char> end; + boost::scoped_ptr<first_owner_multi_pass_t> mpend(new first_owner_multi_pass_t(end)); + + { + sstream_t ss; + ss << "test string"; + + istream_iterator<char> a(ss); + boost::scoped_ptr<first_owner_multi_pass_t> mp1(new first_owner_multi_pass_t(a)); + + while (*mp1 != *mpend) + { + res << *((*mp1)++); + } + + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> b(ss); + boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(b)); + boost::scoped_ptr<first_owner_multi_pass_t> mp3(new first_owner_multi_pass_t(*mp2)); + + for (int i = 0; i < 4; ++i) + { + res << **mp2; + ++*mp2; + } + + mp3.reset(); + + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> a(ss); + boost::scoped_ptr<first_owner_multi_pass_t> mp1(new first_owner_multi_pass_t(a)); + boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(*mp1)); + + for (int i = 0; i < 4; ++i) + { + res << **mp1; + ++*mp1; + } + + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + while (*mp1 != *mpend) + { + res << **mp1; + ++*mp1; + } + + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> b(ss); + boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(b)); + boost::scoped_ptr<first_owner_multi_pass_t> mp3(new first_owner_multi_pass_t(*mp2)); + + for (int i = 0; i < 4; ++i) + { + res << **mp2; + ++*mp2; + } + + mp3.reset(); + ++*mp2; + + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> a(ss); + boost::scoped_ptr<first_owner_multi_pass_t> mp1(new first_owner_multi_pass_t(a)); + boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(*mp1)); + + BOOST_TEST(*mp1 == *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp1 <= *mp2); + for (int i = 0; i < 4; ++i) + { + res << **mp1; + ++*mp1; + } + + BOOST_TEST(*mp1 != *mp2); + BOOST_TEST(*mp1 > *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp2 < *mp1); + BOOST_TEST(*mp2 <= *mp1); + while (*mp2 != *mp1) + { + res << **mp2; + ++*mp2; + } + + BOOST_TEST(*mp1 == *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp1 <= *mp2); + while (*mp1 != *mpend) + { + res << **mp1; + ++*mp1; + } + + BOOST_TEST(*mp1 != *mp2); + BOOST_TEST(*mp1 > *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp2 < *mp1); + BOOST_TEST(*mp2 <= *mp1); + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + BOOST_TEST(*mp1 == *mp2); + BOOST_TEST(*mp1 >= *mp2); + BOOST_TEST(*mp1 <= *mp2); + res << endl; + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> a(ss); + boost::scoped_ptr<first_owner_multi_pass_t> mp1(new first_owner_multi_pass_t(a)); + boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(a)); + BOOST_TEST(*mp1 != *mp2); + ++*mp1; + BOOST_TEST(*mp1 != *mp2); + + } + + { + sstream_t ss; + ss << "test string"; + istream_iterator<char> b(ss); + boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(b)); + boost::scoped_ptr<first_owner_multi_pass_t> mp3(new first_owner_multi_pass_t(*mp2)); + + for (int i = 0; i < 4; ++i) + { + res << **mp2; + ++*mp2; + } + + mp2->clear_queue(); + + while (*mp2 != *mpend) + { + res << **mp2; + ++*mp2; + } + + try + { + res << **mp3; // this should throw illegal_backtracking + BOOST_TEST(0); + } + catch (const BOOST_SPIRIT_CLASSIC_NS::multi_pass_policies::illegal_backtracking& /*e*/) + { + } + res << endl; + } + +} + + +void test_functor_multi_pass() +{ + res << "-*= test_functor_multi_pass =*-\n"; + functor_multi_pass_t mpend; + + { + functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor()); + + while (mp1 != mpend) + { + res << *(mp1++); + } + + res << endl; + } + + { + functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor()); + functor_multi_pass_t mp2 = functor_multi_pass_t(mp1); + + for (int i = 0; i < 4; ++i) + { + res << *mp1; + ++mp1; + } + + while (mp2 != mpend) + { + res << *mp2; + ++mp2; + } + + while (mp1 != mpend) + { + res << *mp1; + ++mp1; + } + + res << endl; + } + + { + functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor()); + functor_multi_pass_t mp2 = functor_multi_pass_t(mp1); + + BOOST_TEST(mp1 == mp2); + BOOST_TEST(mp1 >= mp2); + BOOST_TEST(mp1 <= mp2); + for (int i = 0; i < 4; ++i) + { + res << *mp1; + ++mp1; + } + + BOOST_TEST(mp1 != mp2); + BOOST_TEST(mp1 > mp2); + BOOST_TEST(mp1 >= mp2); + BOOST_TEST(mp2 < mp1); + BOOST_TEST(mp2 <= mp1); + while (mp2 != mp1) + { + res << *mp2; + ++mp2; + } + + BOOST_TEST(mp1 == mp2); + BOOST_TEST(mp1 >= mp2); + BOOST_TEST(mp1 <= mp2); + while (mp1 != mpend) + { + res << *mp1; + ++mp1; + } + + BOOST_TEST(mp1 != mp2); + BOOST_TEST(mp1 > mp2); + BOOST_TEST(mp1 >= mp2); + BOOST_TEST(mp2 < mp1); + BOOST_TEST(mp2 <= mp1); + while (mp2 != mpend) + { + res << *mp2; + ++mp2; + } + + BOOST_TEST(mp1 == mp2); + BOOST_TEST(mp1 >= mp2); + BOOST_TEST(mp1 <= mp2); + res << endl; + } + + { + functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor()); + functor_multi_pass_t mp2 = functor_multi_pass_t(my_functor()); + BOOST_TEST(mp1 != mp2); + ++mp1; + BOOST_TEST(mp1 != mp2); + + } +} + +int main(int, char**) +{ + + test_default_multi_pass(); + test_fixed_multi_pass(); + test_first_owner_multi_pass(); + test_functor_multi_pass(); + + BOOST_TEST(getstring(res) == "-*= test_default_multi_pass =*-\n" + "teststring\n" + "teststring\n" + "testteststringstring\n" + "testtring\n" + "testteststringstring\n" + "teststring\n" + "-*= test_fixed_multi_pass =*-\n" + "teststring\n" + "teststring\n" + "testteststringstring\n" + "testtring\n" + "testteststringstring\n" + "-*= test_first_owner_multi_pass =*-\n" + "teststring\n" + "teststring\n" + "testteststringstring\n" + "testtring\n" + "testteststringstring\n" + "teststring\n" + "-*= test_functor_multi_pass =*-\n" + "ABCDEFGHIJKL\n" + "ABCDABCDEFGHIJKLEFGHIJKL\n" + "ABCDABCDEFGHIJKLEFGHIJKL\n"); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/negated_eps_p_test.cpp b/src/boost/libs/spirit/classic/test/negated_eps_p_test.cpp new file mode 100644 index 00000000..5dcf1e61 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/negated_eps_p_test.cpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2004 Joao Abecasis + Copyright (c) 2004 Joel de Guzman + http://spirit.sourceforge.net/ + + 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/include/classic_core.hpp> +#include <boost/spirit/include/classic_dynamic.hpp> +#include <boost/spirit/include/phoenix1.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include <string> + +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +int main() +{ + using std::cout; + using std::endl; + using std::string; + + bool f = false; + + rule<> start = + while_p(~eps_p(anychar_p[var(f) = true])) + [ + anychar_p + ]; + + parse("This goes to prove my point.", start); + BOOST_TEST(f == false); + return boost::report_errors(); +} + + diff --git a/src/boost/libs/spirit/classic/test/numerics_tests.cpp b/src/boost/libs/spirit/classic/test/numerics_tests.cpp new file mode 100644 index 00000000..69819eaa --- /dev/null +++ b/src/boost/libs/spirit/classic/test/numerics_tests.cpp @@ -0,0 +1,313 @@ +/*============================================================================= + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2001-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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/include/classic_core.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include <climits> + +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +template <typename T> +struct ts_real_parser_policies : public ureal_parser_policies<T> +{ + // 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 + + typedef uint_parser<int, 10, 1, 2> uint2_t; + typedef uint_parser<T, 10, 1, -1> uint_parser_t; + typedef int_parser<int, 10, 1, -1> int_parser_t; + + ////////////////////////////////// 2 decimal places Max + template <typename ScannerT> + static typename parser_result<uint2_t, ScannerT>::type + parse_frac_n(ScannerT& scan) + { return uint2_t().parse(scan); } + + ////////////////////////////////// No exponent + template <typename ScannerT> + static typename parser_result<chlit<>, ScannerT>::type + parse_exp(ScannerT& scan) + { return scan.no_match(); } + + ////////////////////////////////// No exponent + template <typename ScannerT> + static typename parser_result<int_parser_t, ScannerT>::type + parse_exp_n(ScannerT& scan) + { return scan.no_match(); } + + ////////////////////////////////// Thousands separated numbers + template <typename ScannerT> + static typename parser_result<uint_parser_t, ScannerT>::type + parse_n(ScannerT& scan) + { + typedef typename parser_result<uint_parser_t, ScannerT>::type RT; + static uint_parser<unsigned, 10, 1, 3> uint3_p; + static uint_parser<unsigned, 10, 3, 3> uint3_3_p; + + if (RT hit = uint3_p.parse(scan)) + { + T n; + typedef typename ScannerT::iterator_t iterator_t; + iterator_t save = scan.first; + while (match<> next = (',' >> uint3_3_p[assign_a(n)]).parse(scan)) + { + hit.value((hit.value() * 1000) + n); + scan.concat_match(hit, next); + save = scan.first; + } + scan.first = save; + return hit; + } + return scan.no_match(); + } +}; + +real_parser<double, ts_real_parser_policies<double> > const + ts_real_p = real_parser<double, ts_real_parser_policies<double> >(); + +template <typename T> +struct no_trailing_dot : public real_parser_policies<T> +{ + static const bool allow_trailing_dot = false; +}; + +real_parser<double, no_trailing_dot<double> > const + notrdot_real_p = real_parser<double, no_trailing_dot<double> >(); + +template <typename T> +struct no_leading_dot : public real_parser_policies<T> +{ + static const bool allow_leading_dot = false; +}; + +real_parser<double, no_leading_dot<double> > const + nolddot_real_p = real_parser<double, no_leading_dot<double> >(); + +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tNumeric tests...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + + // *** The following assumes 32 bit integers. Modify these constant + // *** strings when appropriate. BEWARE PLATFORM DEPENDENT! + + 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"; + +#ifdef BOOST_HAS_LONG_LONG + + char const* max_long_long = "9223372036854775807"; + char const* long_long_overflow = "9223372036854775808"; + char const* min_long_long = "-9223372036854775808"; + char const* long_long_underflow = "-9223372036854775809"; + +#endif + +// BEGIN TESTS... + + unsigned u; + +// unsigned integer + + parse("123456", uint_p[assign_a(u)]); + BOOST_TEST(u == 123456); + + parse(max_unsigned, uint_p[assign_a(u)]); + BOOST_TEST(u == UINT_MAX); + + BOOST_TEST(!parse(unsigned_overflow, uint_p).full); + +// signed integer + + int i; + + parse("123456", int_p[assign_a(i)]); + BOOST_TEST(i == 123456); + + parse("-123456", int_p[assign_a(i)]); + BOOST_TEST(i == -123456); + + parse(max_int, int_p[assign_a(i)]); + BOOST_TEST(i == INT_MAX); + + parse(min_int, int_p[assign_a(i)]); + BOOST_TEST(i == INT_MIN); + + BOOST_TEST(!parse(int_overflow, int_p).full); + BOOST_TEST(!parse(int_underflow, int_p).full); + + BOOST_TEST(!parse("-", int_p).hit); + +// binary + + parse("11111110", bin_p[assign_a(u)]); + BOOST_TEST(u == 0xFE); + + parse(max_binary, bin_p[assign_a(u)]); + BOOST_TEST(u == UINT_MAX); + + BOOST_TEST(!parse(binary_overflow, bin_p).full); + +// octal + + parse("12545674515", oct_p[assign_a(u)]); + BOOST_TEST(u == 012545674515); + + parse(max_octal, oct_p[assign_a(u)]); + BOOST_TEST(u == UINT_MAX); + + BOOST_TEST(!parse(octal_overflow, oct_p).full); + +// hex + + parse("95BC8DF", hex_p[assign_a(u)]); + BOOST_TEST(u == 0x95BC8DF); + + parse("abcdef12", hex_p[assign_a(u)]); + BOOST_TEST(u == 0xabcdef12); + + parse(max_hex, hex_p[assign_a(u)]); + BOOST_TEST(u == UINT_MAX); + + BOOST_TEST(!parse(hex_overflow, hex_p).full); + +// limited fieldwidth + + uint_parser<unsigned, 10, 1, 3> uint3_p; + parse("123456", uint3_p[assign_a(u)]); + BOOST_TEST(u == 123); + + uint_parser<unsigned, 10, 1, 4> uint4_p; + parse("123456", uint4_p[assign_a(u)]); + BOOST_TEST(u == 1234); + + uint_parser<unsigned, 10, 3, 3> uint3_3_p; + +// thousand separated numbers + +#define r (uint3_p >> *(',' >> uint3_3_p)) + + BOOST_TEST(parse("1,234,567,890", r).full); // OK + BOOST_TEST(parse("12,345,678,900", r).full); // OK + BOOST_TEST(parse("123,456,789,000", r).full); // OK + BOOST_TEST(!parse("1000,234,567,890", r).full); // Bad + BOOST_TEST(!parse("1,234,56,890", r).full); // Bad + BOOST_TEST(!parse("1,66", r).full); // Bad + +// long long + +#ifdef BOOST_HAS_LONG_LONG + +// Some compilers have long long, but don't define the +// LONG_LONG_MIN and LONG_LONG_MAX macros in limits.h. This +// assumes that long long is 64 bits. +#if !defined(LONG_LONG_MIN) && !defined(LONG_LONG_MAX) \ + && !defined(ULONG_LONG_MAX) +#define ULONG_LONG_MAX 0xffffffffffffffffLLU +#define LONG_LONG_MAX 0x7fffffffffffffffLL +#define LONG_LONG_MIN (-LONG_LONG_MAX - 1) +#endif + + ::boost::long_long_type ll; + int_parser< ::boost::long_long_type> long_long_p; + + parse("1234567890123456789", long_long_p[assign_a(ll)]); + BOOST_TEST(ll == 1234567890123456789LL); + + parse("-1234567890123456789", long_long_p[assign_a(ll)]); + BOOST_TEST(ll == -1234567890123456789LL); + + parse(max_long_long, long_long_p[assign_a(ll)]); + BOOST_TEST(ll == LONG_LONG_MAX); + + parse(min_long_long, long_long_p[assign_a(ll)]); + BOOST_TEST(ll == LONG_LONG_MIN); + +#if defined(__GNUG__) && (__GNUG__ == 3) && (__GNUC_MINOR__ < 3) \ + && !defined(__EDG__) + // gcc 3.2.3 crashes on parse(long_long_overflow, long_long_p) + // wrapping long_long_p into a rule avoids the crash + rule<> gcc_3_2_3_long_long_r = long_long_p; + BOOST_TEST(!parse(long_long_overflow, gcc_3_2_3_long_long_r).full); + BOOST_TEST(!parse(long_long_underflow, gcc_3_2_3_long_long_r).full); +#else + BOOST_TEST(!parse(long_long_overflow, long_long_p).full); + BOOST_TEST(!parse(long_long_underflow, long_long_p).full); +#endif + +#endif + +// real numbers + + double d; + + BOOST_TEST(parse("1234", ureal_p[assign_a(d)]).full && d == 1234); // Good. + BOOST_TEST(parse("1.2e3", ureal_p[assign_a(d)]).full && d == 1.2e3); // Good. + BOOST_TEST(parse("1.2e-3", ureal_p[assign_a(d)]).full && d == 1.2e-3); // Good. + BOOST_TEST(parse("1.e2", ureal_p[assign_a(d)]).full && d == 1.e2); // Good. + BOOST_TEST(parse(".2e3", ureal_p[assign_a(d)]).full && d == .2e3); // Good. + BOOST_TEST(parse("2e3", ureal_p[assign_a(d)]).full && d == 2e3); // Good. No fraction + BOOST_TEST(!parse("e3", ureal_p).full); // Bad! No number + BOOST_TEST(!parse("-1.2e3", ureal_p).full); // Bad! Negative number + BOOST_TEST(!parse("+1.2e3", ureal_p).full); // Bad! Positive sign + BOOST_TEST(!parse("1.2e", ureal_p).full); // Bad! No exponent + BOOST_TEST(!parse("-.3", ureal_p).full); // Bad! Negative + + BOOST_TEST(parse("-1234", real_p[assign_a(d)]).full && d == -1234); // Good. + BOOST_TEST(parse("-1.2e3", real_p[assign_a(d)]).full && d == -1.2e3); // Good. + BOOST_TEST(parse("+1.2e3", real_p[assign_a(d)]).full && d == 1.2e3); // Good. + BOOST_TEST(parse("-0.1", real_p[assign_a(d)]).full && d == -0.1); // Good. + BOOST_TEST(parse("-1.2e-3", real_p[assign_a(d)]).full && d == -1.2e-3); // Good. + BOOST_TEST(parse("-1.e2", real_p[assign_a(d)]).full && d == -1.e2); // Good. + BOOST_TEST(parse("-.2e3", real_p[assign_a(d)]).full && d == -.2e3); // Good. + BOOST_TEST(parse("-2e3", real_p[assign_a(d)]).full && d == -2e3); // Good. No fraction + BOOST_TEST(!parse("-e3", real_p).full); // Bad! No number + BOOST_TEST(!parse("-1.2e", real_p).full); // Bad! No exponent + + BOOST_TEST(!parse("1234", strict_ureal_p[assign_a(d)]).full); // Bad. Strict real + BOOST_TEST(parse("1.2", strict_ureal_p[assign_a(d)]).full && d == 1.2); // Good. + BOOST_TEST(!parse("-1234", strict_real_p[assign_a(d)]).full); // Bad. Strict real + BOOST_TEST(parse("123.", strict_real_p[assign_a(d)]).full && d == 123); // Good. + BOOST_TEST(parse("3.E6", strict_real_p[assign_a(d)]).full && d == 3e6); // Good. + + BOOST_TEST(!parse("1234.", notrdot_real_p[assign_a(d)]).full); // Bad trailing dot + BOOST_TEST(!parse(".1234", nolddot_real_p[assign_a(d)]).full); // Bad leading dot + +// Special thousands separated numbers + + BOOST_TEST(parse("123,456,789.01", ts_real_p[assign_a(d)]).full && d == 123456789.01); // Good. + BOOST_TEST(parse("12,345,678.90", ts_real_p[assign_a(d)]).full && d == 12345678.90); // Good. + BOOST_TEST(parse("1,234,567.89", ts_real_p[assign_a(d)]).full && d == 1234567.89); // Good. + BOOST_TEST(!parse("1234,567,890", ts_real_p).full); // Bad. + BOOST_TEST(!parse("1,234,5678,9", ts_real_p).full); // Bad. + BOOST_TEST(!parse("1,234,567.89e6", ts_real_p).full); // Bad. + BOOST_TEST(!parse("1,66", ts_real_p).full); // Bad. + +// END TESTS. + +///////////////////////////////////////////////////////////////// + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/operators_tests.cpp b/src/boost/libs/spirit/classic/test/operators_tests.cpp new file mode 100644 index 00000000..fd89e216 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/operators_tests.cpp @@ -0,0 +1,164 @@ +/*============================================================================= + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> + +using namespace std; + +#include <boost/spirit/include/classic_core.hpp> +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Operators tests +// +/////////////////////////////////////////////////////////////////////////////// +void +operators_tests() +{ + parse_info<char const*> pi; + + pi = parse("Hello World", str_p("Hello ") >> "World"); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 11); + BOOST_TEST(*pi.stop == 0); + + pi = parse("Banana", str_p("Banana") | "Pineapple"); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 6); + BOOST_TEST(*pi.stop == 0); + + pi = parse("Pineapple", str_p("Banana") | "Pineapple"); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 9); + BOOST_TEST(*pi.stop == 0); + + pi = parse("a.2 ", alpha_p || ('.' >> digit_p)); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 3); + + pi = parse("a ", alpha_p || ('.' >> digit_p)); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 1); + + pi = parse(".1 ", alpha_p || ('.' >> digit_p)); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 2); + + pi = parse("1.a ", alpha_p || ('.' >> digit_p)); + BOOST_TEST(!pi.hit); + + pi = parse("abcdefghij", +xdigit_p & +alpha_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 6); + + pi = parse("abcdefghij", +alpha_p & +xdigit_p); + BOOST_TEST(!pi.hit); + + pi = parse("abcdefghij", +digit_p & +alpha_p); + BOOST_TEST(!pi.hit); + + pi = parse("abcdefghij", +alpha_p & +digit_p); + BOOST_TEST(!pi.hit); + + // Test for bug reported by Yusaku Sugai here: + // http://article.gmane.org/gmane.comp.parsers.spirit.general/8544 + pi = parse( "foo", (anychar_p & anychar_p), ch_p(' ') ); + BOOST_TEST(pi.hit); + + pi = parse("F", xdigit_p - range_p('5','8')); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 1); + + pi = parse("0", xdigit_p - range_p('5','8')); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 1); + + pi = parse("4", xdigit_p - range_p('5','8')); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 1); + + pi = parse("9", xdigit_p - range_p('5','8')); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 1); + + pi = parse("5", xdigit_p - range_p('5','8')); + BOOST_TEST(!pi.hit); + + pi = parse("7", xdigit_p - range_p('5','8')); + BOOST_TEST(!pi.hit); + + pi = parse("x*/", anychar_p - "*/"); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 1); + + pi = parse("*/", anychar_p - "*/"); + BOOST_TEST(!pi.hit); + + pi = parse("switcher ", str_p("switcher") - "switch"); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 8); + + pi = parse("Z", alpha_p ^ xdigit_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 1); + + pi = parse("1", alpha_p ^ xdigit_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 1); + + pi = parse("B", alpha_p ^ xdigit_p); + BOOST_TEST(!pi.hit); + + pi = parse("B", !alpha_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 1); + + pi = parse("1", !alpha_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 0); + BOOST_TEST(*pi.stop == '1'); + + pi = parse("1234 5678 1234 5678", *(+digit_p >> *space_p)); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 19); + BOOST_TEST(*pi.stop == 0); + + pi = parse("abcdefghijklmnopqrstuvwxyz123", *alpha_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.length == 26); + + pi = parse("1234+5678*1234/5678", +digit_p % (ch_p('+') | '*' | '/')); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 19); + BOOST_TEST(*pi.stop == 0); + + pi = parse("1234+", +digit_p % '+'); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(pi.length == 4); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Main +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + operators_tests(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/owi_mt_tests.cpp b/src/boost/libs/spirit/classic/test/owi_mt_tests.cpp new file mode 100644 index 00000000..9490d092 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/owi_mt_tests.cpp @@ -0,0 +1,242 @@ +/*============================================================================= + Copyright (c) 2002-2004 Martin Wille + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +// std::lower_bound seems to perform awfully slow with _GLIBCXX_DEBUG enabled +#undef _GLIBCXX_DEBUG + +#include <iostream> +#include <boost/config.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if !defined(BOOST_HAS_THREADS) || defined(DONT_HAVE_BOOST) || defined(BOOST_DISABLE_THREADS) +static void skipped() +{ + std::cout << "skipped\n"; +} + +int +main() +{ + skipped(); + return 0; +} +#else + +//////////////////////////////////////////////////////////////////////////////// + +static const unsigned long initial_test_size = 5000UL; +#if defined(_DEBUG) && (BOOST_MSVC >= 1400) +static const unsigned long maximum_test_size = 10000UL; +#else +static const unsigned long maximum_test_size = 1000000UL; +#endif + +//////////////////////////////////////////////////////////////////////////////// + +#undef BOOST_SPIRIT_THREADSAFE +#define BOOST_SPIRIT_THREADSAFE + +#include <boost/thread/thread.hpp> +#include <boost/spirit/home/classic/core/non_terminal/impl/object_with_id.ipp> +#include <boost/ref.hpp> +#include <boost/thread/xtime.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/lock_types.hpp> +#include <vector> +#include <algorithm> +#include <boost/detail/lightweight_test.hpp> + +using BOOST_SPIRIT_CLASSIC_NS::impl::object_with_id; + +struct tag1 {}; +typedef object_with_id<tag1> class1; + +unsigned long test_size = initial_test_size; +boost::xtime start_time; + +template <typename ClassT> +struct test_task +{ + test_task() : v(), m(), progress(0) {} + + void operator ()() + { // create lots of objects + unsigned long i = 0; + + v.reserve(maximum_test_size); + do + { + for (; i<test_size; ++i) + v.push_back(new ClassT); + } + while ( i < increase_test_size(i) ); + } + + static unsigned long + increase_test_size(unsigned long size) + { + static boost::mutex m; + boost::unique_lock<boost::mutex> l(m); + + if (size<test_size || test_size == maximum_test_size) + return test_size; + + boost::xtime now; + boost::xtime_get(&now, boost::TIME_UTC_); + boost::xtime::xtime_sec_t seconds = now.sec - start_time.sec; + if (seconds < 4) + { + test_size *= 2; + if (test_size > maximum_test_size) + test_size = maximum_test_size; + } + + return test_size; + } + + std::vector<ClassT*> const &data() const + { + return v; + } + +private: + std::vector<ClassT*> v; + boost::mutex m; + unsigned int progress; +}; + +template <typename T> +class callable_reference_wrapper + : public boost::reference_wrapper<T> +{ +public: + explicit callable_reference_wrapper(T& t) + : boost::reference_wrapper<T>(t) + {} + inline void operator()() { this->get().operator()(); } +}; + +template <typename T> +callable_reference_wrapper<T> +callable_ref(T &t) +{ + return callable_reference_wrapper<T>(t); +} + +test_task<class1> test1; +test_task<class1> test2; +test_task<class1> test3; + + +template <typename ClassT> +void +check_ascending(test_task<ClassT> const &t) +{ + typedef typename std::vector<ClassT*>::const_iterator iter; + iter p(t.data().begin()); + iter const e(t.data().end()); + iter n(p); + + while (++n!=e) + { + if ((**n).get_object_id()<=(**p).get_object_id()) + { + using namespace std; + throw std::runtime_error("object ids out of order"); + } + p = n; + } +} + +struct less1 +{ + bool operator()(class1 const *p, class1 const *q) const + { + return p->get_object_id() < q->get_object_id(); + } +}; + +template <typename ClassT> +void +check_not_contained_in( + test_task<ClassT> const &candidate, + test_task<ClassT> const &in +) +{ + typedef typename std::vector<ClassT*>::const_iterator iter; + iter p(candidate.data().begin()); + iter const e(candidate.data().end()); + + while (p!=e) + { + iter found = std::lower_bound(in.data().begin(),in.data().end(),*p,less1()); + if (found!=in.data().end() && + (**found).get_object_id() == (**p).get_object_id()) + { + using namespace std; + throw std::runtime_error("object ids not unqiue"); + } + ++p; + } +} + +void concurrent_creation_of_objects() +{ + { + boost::xtime_get(&start_time, boost::TIME_UTC_); + boost::thread thread1(callable_ref(test1)); + boost::thread thread2(callable_ref(test2)); + boost::thread thread3(callable_ref(test3)); + + thread1.join(); + thread2.join(); + thread3.join(); + } +} + +void local_uniqueness() +{ + + + BOOST_TEST(test1.data().size()==test_size); + BOOST_TEST(test2.data().size()==test_size); + BOOST_TEST(test3.data().size()==test_size); +} + +void local_ordering_and_uniqueness() +{ + // now all objects should have unique ids, + // the ids must be ascending within each vector + // check for ascending ids + check_ascending(test1); + check_ascending(test2); + check_ascending(test3); +} + +void global_uniqueness() +{ + check_not_contained_in(test1,test3); + check_not_contained_in(test1,test2); + check_not_contained_in(test2,test1); + check_not_contained_in(test2,test3); + check_not_contained_in(test3,test2); + check_not_contained_in(test3,test1); +} + +int +main() +{ + concurrent_creation_of_objects(); + local_ordering_and_uniqueness(); + global_uniqueness(); + return boost::report_errors(); +} + +#endif // BOOST_HAS_THREADS + diff --git a/src/boost/libs/spirit/classic/test/owi_st_tests.cpp b/src/boost/libs/spirit/classic/test/owi_st_tests.cpp new file mode 100644 index 00000000..20c1ca09 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/owi_st_tests.cpp @@ -0,0 +1,88 @@ +/*============================================================================= + Copyright (c) 2002-2003 Martin Wille + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ +// vim:ts=4:sw=4:et + +#if defined(BOOST_BUILD_PCH_ENABLED) && defined(BOOST_SPIRIT_THREADSAFE) +# error BOOST_SPIRIT_THREADSAFE has to be undefined for this test +#endif +#undef BOOST_SPIRIT_THREADSAFE +#include <boost/spirit/home/classic/core/non_terminal/impl/object_with_id.ipp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> + +using BOOST_SPIRIT_CLASSIC_NS::impl::object_with_id; + +struct tag1 {}; +struct tag2 {}; + +typedef object_with_id<tag1> class1; +typedef object_with_id<tag2> class2; + +int +main() +{ + std::cout << "/////////////////////////////////////////////////////////\n"; + std::cout << "\n"; + std::cout << " object_with_id test (ST)\n"; + std::cout << "\n"; + std::cout << "/////////////////////////////////////////////////////////\n"; + std::cout << "\n"; + + class1 *c1o1 = new class1; + class1 *c1o2 = new class1; + class1 *c1o3 = new class1; + + // test wether the objects have consecutive numbers + BOOST_TEST(c1o1->get_object_id()==1); + BOOST_TEST(c1o2->get_object_id()==2); + BOOST_TEST(c1o3->get_object_id()==3); + + // test wether number recycling works + delete c1o3; + c1o3 = new class1; + BOOST_TEST(c1o3->get_object_id()==3); + + delete c1o2; + c1o2 = new class1; + BOOST_TEST(c1o2->get_object_id()==2); + + delete c1o2; + delete c1o3; + c1o2 = new class1; + c1o3 = new class1; + BOOST_TEST(c1o3->get_object_id()==3); + BOOST_TEST(c1o2->get_object_id()==2); + + // test whether objects of different classes are numbered independently + class2 *c2o1 = new class2; + class2 *c2o2 = new class2; + class2 *c2o3 = new class2; + BOOST_TEST(c2o1->get_object_id()==1); + BOOST_TEST(c2o2->get_object_id()==2); + BOOST_TEST(c2o3->get_object_id()==3); + + // + delete c1o1; + delete c2o2; + c2o2 = new class2; + c1o1 = new class1; + BOOST_TEST(c1o1->get_object_id()==1); + BOOST_TEST(c2o2->get_object_id()==2); + + // test wether the copy ctor doesn't copy the id + delete c1o1; + c1o1 = new class1(*c1o2); + BOOST_TEST(c1o1->get_object_id()==1); + + // test wether the assignment operator doesn't assign the id + *c1o1 = *c1o2; + BOOST_TEST(c1o1->get_object_id()==1); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/parametric_tests.cpp b/src/boost/libs/spirit/classic/test/parametric_tests.cpp new file mode 100644 index 00000000..9fc7b2c9 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/parametric_tests.cpp @@ -0,0 +1,185 @@ +/*============================================================================= + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> +#include <string> + + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_parametric.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_operators.hpp> +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +#include <boost/detail/lightweight_test.hpp> + +/////////////////////////////////////////////////////////////////////////////// +// +// Parametric tests +// +/////////////////////////////////////////////////////////////////////////////// + +template <typename T> +static unsigned +length(T const *p) +{ + unsigned result = 0; + while (*p++) + ++result; + return result; +} + +template <typename T> +bool +is_equal(T const* a, T const* b) +{ + while (*a && *b) + if (*a++ != *b++) + return false; + return true; +} + +typedef rule< scanner<wchar_t const *> > wrule_t; + +void +narrow_f_ch_p() +{ + char ch; + rule<> r = anychar_p[var(ch) = arg1] >> *f_ch_p(const_(ch)); + parse_info<char const*> pi; + + pi = parse("aaaaaaaaa", r); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("aaaaabaaa", r); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(is_equal(pi.stop, "baaa")); +} + +void +wide_f_ch_p() +{ + wchar_t ch; + wrule_t r = anychar_p[var(ch) = arg1] >> *f_ch_p(const_(ch)); + parse_info<wchar_t const*> pi; + + pi = parse(L"aaaaaaaaa", r); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse(L"aaaaabaaa", r); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(is_equal(pi.stop, L"baaa")); +} + +void +narrow_f_range_p() +{ + char from = 'a'; + char to = 'z'; + + parse_info<char const*> pi; + + rule<> r2 = *f_range_p(const_(from), const_(to)); + pi = parse("abcdefghijklmnopqrstuvwxyz", r2); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("abcdefghijklmnopqrstuvwxyz123", r2); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(is_equal(pi.stop, "123")); +} + +void +wide_f_range_p() +{ + wchar_t from = L'a'; + wchar_t to = L'z'; + + parse_info<wchar_t const*> pi; + + wrule_t r2 = *f_range_p(const_(from), const_(to)); + pi = parse(L"abcdefghijklmnopqrstuvwxyz", r2); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse(L"abcdefghijklmnopqrstuvwxyz123", r2); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(is_equal(pi.stop, L"123")); +} + +void +narrow_f_str_p() +{ + parse_info<char const*> pi; + + char const* start = "kim"; + char const* end = start + length(start); + rule<> r3 = +f_str_p(const_(start), const_(end)); + + pi = parse("kimkimkimkimkimkimkimkimkim", r3); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("kimkimkimkimkimkimkimkimkimmama", r3); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(is_equal(pi.stop, "mama")); + + pi = parse("joel", r3); + BOOST_TEST(!pi.hit); +} + +void +wide_f_str_p() +{ + parse_info<wchar_t const*> pi; + + wchar_t const* start = L"kim"; + wchar_t const* end = start + length(start); + wrule_t r3 = +f_str_p(const_(start), const_(end)); + + pi = parse(L"kimkimkimkimkimkimkimkimkim", r3); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse(L"kimkimkimkimkimkimkimkimkimmama", r3); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(is_equal(pi.stop, L"mama")); + + pi = parse(L"joel", r3); + BOOST_TEST(!pi.hit); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// test suite +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + narrow_f_ch_p(); + wide_f_ch_p(); + narrow_f_range_p(); + wide_f_range_p(); + narrow_f_str_p(); + wide_f_str_p(); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/parser_context_test.cpp b/src/boost/libs/spirit/classic/test/parser_context_test.cpp new file mode 100644 index 00000000..7883bab4 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/parser_context_test.cpp @@ -0,0 +1,24 @@ +/*============================================================================= + Copyright (c) 2003 Vaclav Vesely + http://spirit.sourceforge.net/ + + 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/detail/lightweight_test.hpp> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> + +using namespace boost; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +int main() +{ + rule<parser_context<int> > int_rule = int_p; + int result(0); + parse("123", int_rule[assign_a(result)]); + BOOST_TEST(result == 123); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/parser_traits_tests.cpp b/src/boost/libs/spirit/classic/test/parser_traits_tests.cpp new file mode 100644 index 00000000..901cf787 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/parser_traits_tests.cpp @@ -0,0 +1,285 @@ +/*============================================================================= + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// Parser traits tests +// +/////////////////////////////////////////////////////////////////////////////// + +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +typedef ref_value_actor<char, assign_action> assign_actor; + +// Test parser_traits templates +void +parser_traits_tests() +{ +// is_parser_category_tests + typedef chlit<char> plain_t; + typedef optional<chlit<char> > unary_t; + typedef action<chlit<char>, assign_actor> action_t; + typedef sequence<chlit<char>, anychar_parser> binary_t; + +// is_parser + BOOST_STATIC_ASSERT(is_parser<plain_t>::value); + BOOST_STATIC_ASSERT(is_parser<unary_t>::value); + BOOST_STATIC_ASSERT(is_parser<action_t>::value); + BOOST_STATIC_ASSERT(is_parser<binary_t>::value); + +// is_action_parser + BOOST_STATIC_ASSERT(!is_action_parser<plain_t>::value); + BOOST_STATIC_ASSERT(!is_action_parser<unary_t>::value); + BOOST_STATIC_ASSERT(is_action_parser<action_t>::value); + BOOST_STATIC_ASSERT(!is_action_parser<binary_t>::value); + +// is_unary_composite + BOOST_STATIC_ASSERT(!is_unary_composite<plain_t>::value); + BOOST_STATIC_ASSERT(is_unary_composite<unary_t>::value); + BOOST_STATIC_ASSERT(is_unary_composite<action_t>::value); // action_t _is_ an unary_t! + BOOST_STATIC_ASSERT(!is_unary_composite<binary_t>::value); + +// is_binary_composite + BOOST_STATIC_ASSERT(!is_binary_composite<plain_t>::value); + BOOST_STATIC_ASSERT(!is_binary_composite<unary_t>::value); + BOOST_STATIC_ASSERT(!is_binary_composite<action_t>::value); + BOOST_STATIC_ASSERT(is_binary_composite<binary_t>::value); + +// is_composite_parser + BOOST_STATIC_ASSERT(!is_composite_parser<plain_t>::value); + BOOST_STATIC_ASSERT(is_composite_parser<unary_t>::value); + BOOST_STATIC_ASSERT(is_composite_parser<action_t>::value); // action_t _is_ an unary_t! + BOOST_STATIC_ASSERT(is_composite_parser<binary_t>::value); + +// is_composite_type_tests + typedef alternative<chlit<char>, anychar_parser> alternative_t; + typedef sequence<chlit<char>, anychar_parser> sequence_t; + typedef sequential_or<chlit<char>, anychar_parser> sequential_or_t; + typedef intersection<chlit<char>, anychar_parser> intersection_t; + typedef difference<chlit<char>, anychar_parser> difference_t; + typedef exclusive_or<chlit<char>, anychar_parser> exclusive_or_t; + + typedef optional<chlit<char> > optional_t; + typedef kleene_star<chlit<char> > kleene_star_t; + typedef positive<chlit<char> > positive_t; + +// is_parser + BOOST_STATIC_ASSERT(is_parser<alternative_t>::value); + BOOST_STATIC_ASSERT(is_parser<sequence_t>::value); + BOOST_STATIC_ASSERT(is_parser<sequential_or_t>::value); + BOOST_STATIC_ASSERT(is_parser<intersection_t>::value); + BOOST_STATIC_ASSERT(is_parser<difference_t>::value); + BOOST_STATIC_ASSERT(is_parser<exclusive_or_t>::value); + BOOST_STATIC_ASSERT(is_parser<optional_t>::value); + BOOST_STATIC_ASSERT(is_parser<positive_t>::value); + +// is_alternative + BOOST_STATIC_ASSERT(!is_alternative<plain_t>::value); + BOOST_STATIC_ASSERT(!is_alternative<action_t>::value); + + BOOST_STATIC_ASSERT(is_alternative<alternative_t>::value); + BOOST_STATIC_ASSERT(!is_alternative<sequence_t>::value); + BOOST_STATIC_ASSERT(!is_alternative<sequential_or_t>::value); + BOOST_STATIC_ASSERT(!is_alternative<intersection_t>::value); + BOOST_STATIC_ASSERT(!is_alternative<difference_t>::value); + BOOST_STATIC_ASSERT(!is_alternative<exclusive_or_t>::value); + + BOOST_STATIC_ASSERT(!is_alternative<optional_t>::value); + BOOST_STATIC_ASSERT(!is_alternative<kleene_star_t>::value); + BOOST_STATIC_ASSERT(!is_alternative<positive_t>::value); + +// is_sequence + BOOST_STATIC_ASSERT(!is_sequence<plain_t>::value); + BOOST_STATIC_ASSERT(!is_sequence<action_t>::value); + + BOOST_STATIC_ASSERT(!is_sequence<alternative_t>::value); + BOOST_STATIC_ASSERT(is_sequence<sequence_t>::value); + BOOST_STATIC_ASSERT(!is_sequence<sequential_or_t>::value); + BOOST_STATIC_ASSERT(!is_sequence<intersection_t>::value); + BOOST_STATIC_ASSERT(!is_sequence<difference_t>::value); + BOOST_STATIC_ASSERT(!is_sequence<exclusive_or_t>::value); + + BOOST_STATIC_ASSERT(!is_sequence<optional_t>::value); + BOOST_STATIC_ASSERT(!is_sequence<kleene_star_t>::value); + BOOST_STATIC_ASSERT(!is_sequence<positive_t>::value); + +// is_sequential_or + BOOST_STATIC_ASSERT(!is_sequential_or<plain_t>::value); + BOOST_STATIC_ASSERT(!is_sequential_or<action_t>::value); + + BOOST_STATIC_ASSERT(!is_sequential_or<alternative_t>::value); + BOOST_STATIC_ASSERT(!is_sequential_or<sequence_t>::value); + BOOST_STATIC_ASSERT(is_sequential_or<sequential_or_t>::value); + BOOST_STATIC_ASSERT(!is_sequential_or<intersection_t>::value); + BOOST_STATIC_ASSERT(!is_sequential_or<difference_t>::value); + BOOST_STATIC_ASSERT(!is_sequential_or<exclusive_or_t>::value); + + BOOST_STATIC_ASSERT(!is_sequential_or<optional_t>::value); + BOOST_STATIC_ASSERT(!is_sequential_or<kleene_star_t>::value); + BOOST_STATIC_ASSERT(!is_sequential_or<positive_t>::value); + +// is_intersection + BOOST_STATIC_ASSERT(!is_intersection<plain_t>::value); + BOOST_STATIC_ASSERT(!is_intersection<action_t>::value); + + BOOST_STATIC_ASSERT(!is_intersection<alternative_t>::value); + BOOST_STATIC_ASSERT(!is_intersection<sequence_t>::value); + BOOST_STATIC_ASSERT(!is_intersection<sequential_or_t>::value); + BOOST_STATIC_ASSERT(is_intersection<intersection_t>::value); + BOOST_STATIC_ASSERT(!is_intersection<difference_t>::value); + BOOST_STATIC_ASSERT(!is_intersection<exclusive_or_t>::value); + + BOOST_STATIC_ASSERT(!is_intersection<optional_t>::value); + BOOST_STATIC_ASSERT(!is_intersection<kleene_star_t>::value); + BOOST_STATIC_ASSERT(!is_intersection<positive_t>::value); + +// is_difference + BOOST_STATIC_ASSERT(!is_difference<plain_t>::value); + BOOST_STATIC_ASSERT(!is_difference<action_t>::value); + + BOOST_STATIC_ASSERT(!is_difference<alternative_t>::value); + BOOST_STATIC_ASSERT(!is_difference<sequence_t>::value); + BOOST_STATIC_ASSERT(!is_difference<sequential_or_t>::value); + BOOST_STATIC_ASSERT(!is_difference<intersection_t>::value); + BOOST_STATIC_ASSERT(is_difference<difference_t>::value); + BOOST_STATIC_ASSERT(!is_difference<exclusive_or_t>::value); + + BOOST_STATIC_ASSERT(!is_difference<optional_t>::value); + BOOST_STATIC_ASSERT(!is_difference<kleene_star_t>::value); + BOOST_STATIC_ASSERT(!is_difference<positive_t>::value); + +// is_exclusive_or + BOOST_STATIC_ASSERT(!is_exclusive_or<plain_t>::value); + BOOST_STATIC_ASSERT(!is_exclusive_or<action_t>::value); + + BOOST_STATIC_ASSERT(!is_exclusive_or<alternative_t>::value); + BOOST_STATIC_ASSERT(!is_exclusive_or<sequence_t>::value); + BOOST_STATIC_ASSERT(!is_exclusive_or<sequential_or_t>::value); + BOOST_STATIC_ASSERT(!is_exclusive_or<intersection_t>::value); + BOOST_STATIC_ASSERT(!is_exclusive_or<difference_t>::value); + BOOST_STATIC_ASSERT(is_exclusive_or<exclusive_or_t>::value); + + BOOST_STATIC_ASSERT(!is_exclusive_or<optional_t>::value); + BOOST_STATIC_ASSERT(!is_exclusive_or<kleene_star_t>::value); + BOOST_STATIC_ASSERT(!is_exclusive_or<positive_t>::value); + +// is_optional + BOOST_STATIC_ASSERT(!is_optional<plain_t>::value); + BOOST_STATIC_ASSERT(!is_optional<action_t>::value); + + BOOST_STATIC_ASSERT(!is_optional<alternative_t>::value); + BOOST_STATIC_ASSERT(!is_optional<sequence_t>::value); + BOOST_STATIC_ASSERT(!is_optional<sequential_or_t>::value); + BOOST_STATIC_ASSERT(!is_optional<intersection_t>::value); + BOOST_STATIC_ASSERT(!is_optional<difference_t>::value); + BOOST_STATIC_ASSERT(!is_optional<exclusive_or_t>::value); + + BOOST_STATIC_ASSERT(is_optional<optional_t>::value); + BOOST_STATIC_ASSERT(!is_optional<kleene_star_t>::value); + BOOST_STATIC_ASSERT(!is_optional<positive_t>::value); + +// is_kleene_star + BOOST_STATIC_ASSERT(!is_kleene_star<plain_t>::value); + BOOST_STATIC_ASSERT(!is_kleene_star<action_t>::value); + + BOOST_STATIC_ASSERT(!is_kleene_star<alternative_t>::value); + BOOST_STATIC_ASSERT(!is_kleene_star<sequence_t>::value); + BOOST_STATIC_ASSERT(!is_kleene_star<sequential_or_t>::value); + BOOST_STATIC_ASSERT(!is_kleene_star<intersection_t>::value); + BOOST_STATIC_ASSERT(!is_kleene_star<difference_t>::value); + BOOST_STATIC_ASSERT(!is_kleene_star<exclusive_or_t>::value); + + BOOST_STATIC_ASSERT(!is_kleene_star<optional_t>::value); + BOOST_STATIC_ASSERT(is_kleene_star<kleene_star_t>::value); + BOOST_STATIC_ASSERT(!is_kleene_star<positive_t>::value); + +// is_positive + BOOST_STATIC_ASSERT(!is_positive<plain_t>::value); + BOOST_STATIC_ASSERT(!is_positive<action_t>::value); + + BOOST_STATIC_ASSERT(!is_positive<alternative_t>::value); + BOOST_STATIC_ASSERT(!is_positive<sequence_t>::value); + BOOST_STATIC_ASSERT(!is_positive<sequential_or_t>::value); + BOOST_STATIC_ASSERT(!is_positive<intersection_t>::value); + BOOST_STATIC_ASSERT(!is_positive<difference_t>::value); + BOOST_STATIC_ASSERT(!is_positive<exclusive_or_t>::value); + + BOOST_STATIC_ASSERT(!is_positive<optional_t>::value); + BOOST_STATIC_ASSERT(!is_positive<kleene_star_t>::value); + BOOST_STATIC_ASSERT(is_positive<positive_t>::value); +} + +/////////////////////////////////////////////////////////////////////////////// +// Test parser extraction templates +void +parser_extraction_tests() +{ + typedef chlit<char> plain_t; + typedef optional<plain_t> unary_t; + typedef action<plain_t, assign_actor> action_t; + typedef sequence<plain_t, anychar_parser> binary_t; + +// parser type extraction templates + BOOST_STATIC_ASSERT(( + ::boost::is_same< + chlit<char>, unary_subject<unary_t>::type + >::value)); + BOOST_STATIC_ASSERT(( + ::boost::is_same< + chlit<char>, action_subject<action_t>::type + >::value)); + BOOST_STATIC_ASSERT(( + ::boost::is_same< + assign_actor, semantic_action<action_t>::type + >::value)); + BOOST_STATIC_ASSERT(( + ::boost::is_same< + chlit<char>, binary_left_subject<binary_t>::type + >::value)); + BOOST_STATIC_ASSERT(( + ::boost::is_same< + anychar_parser, binary_right_subject<binary_t>::type + >::value)); + +// parser object extraction functions + BOOST_TEST(1 == parse("aaaa", get_unary_subject(*ch_p('a'))).length); + +char c = 'b'; + + BOOST_TEST(1 == parse("aaaa", get_action_subject(ch_p('a')[assign(c)])).length); + BOOST_TEST(c == 'b'); + + BOOST_TEST(1 == parse("aaaa", + ch_p('a')[ get_semantic_action(ch_p('b')[assign(c)]) ]).length); + BOOST_TEST(c == 'a'); + + BOOST_TEST(1 == parse("abab", + get_binary_left_subject(ch_p('a') >> ch_p('b'))).length); + BOOST_TEST(1 == parse("baba", + get_binary_right_subject(ch_p('a') >> ch_p('b'))).length); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Main +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + parser_traits_tests(); + parser_extraction_tests(); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/pch.hpp b/src/boost/libs/spirit/classic/test/pch.hpp new file mode 100644 index 00000000..94dde346 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/pch.hpp @@ -0,0 +1,15 @@ +/*============================================================================= + Copyright (c) 2019 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) +=============================================================================*/ +#ifdef BOOST_BUILD_PCH_ENABLED + +#include <boost/spirit/include/classic.hpp> +#include <boost/core/lightweight_test.hpp> +#include <vector> +#include <string> +#include <iostream> + +#endif diff --git a/src/boost/libs/spirit/classic/test/position_iterator_tests.cpp b/src/boost/libs/spirit/classic/test/position_iterator_tests.cpp new file mode 100644 index 00000000..a1fd6ea3 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/position_iterator_tests.cpp @@ -0,0 +1,583 @@ +/*============================================================================= + Copyright (c) 2003 Giovanni Bajo + http://spirit.sourceforge.net/ + + 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/detail/lightweight_test.hpp> +#include <iostream> +#include <vector> +#include <string> +#include <list> +#include <algorithm> +#include <iterator> +#include <cstddef> +#include <boost/config.hpp> +#include <boost/concept_check.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/list.hpp> +#include <boost/mpl/for_each.hpp> + +// Our baby +#include <boost/spirit/include/classic_position_iterator.hpp> + +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; +namespace mpl = boost::mpl; + +/////////////////////////////////////////////////////////////////////////////// +namespace test_impl { + +template <typename IterT> +void InstanciateTestOne(void) +{ + IterT(); + + // Check that the iterator is a full non-mutable forward iterator + typedef boost::ForwardIteratorConcept<IterT> concept_t; + boost::function_requires<concept_t>(); +} + +struct InstanciateTest +{ + template <typename BaseIterT> + void operator()(BaseIterT ) + { + InstanciateTestOne<position_iterator<BaseIterT> >(); + InstanciateTestOne<position_iterator2<BaseIterT> >(); + InstanciateTestOne<position_iterator<BaseIterT, file_position_without_column> >(); + InstanciateTestOne<position_iterator2<BaseIterT, file_position_without_column> >(); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +} /* namespace test_impl */ + +// These tests are defined after main() to be absolutely sure that the +// instantiation test will happen before any other (since it's mainly +// a compile-time test). +void CheckInstantiation(void); +void CheckConstructors(void); +void CheckBasicFunctionality(void); +void CheckColumnCounting(void); +void CheckLineExtraction(void); +void CheckDistance(void); +void CheckSingular(); + +void CheckInstantiation(void) +{ + typedef mpl::list + < + char* + ,const char* + ,string::iterator + ,string::const_iterator + > iter_list_t; + + mpl::for_each<iter_list_t>(test_impl::InstanciateTest()); +} + +int main(void) +{ + CheckInstantiation(); + CheckConstructors(); + CheckBasicFunctionality(); + CheckColumnCounting(); + CheckLineExtraction(); + CheckDistance(); + CheckSingular(); + + return boost::report_errors(); +} + +/////////////////////////////////////////////////////////////////////////////// +namespace test_impl { + +template <typename IterT> +void CheckIncrement(IterT iter) +{ + IterT end; + + // Check also that copy construction and assignment do not + // interfere with increment + IterT iter2(iter); + IterT iter3 = iter; + + BOOST_TEST(iter != end); + BOOST_TEST(iter2 != end); + BOOST_TEST(iter3 != end); + BOOST_TEST(*iter == '0'); + + ++iter; + ++iter2; + ++iter3; + BOOST_TEST(iter == iter2); + BOOST_TEST(iter == iter3); + BOOST_TEST(*iter == *iter2); + BOOST_TEST(*iter == *iter3); + BOOST_TEST(iter.get_position() == iter2.get_position()); + BOOST_TEST(iter.get_position() == iter3.get_position()); + BOOST_TEST(*iter == '1'); + + BOOST_TEST(*iter++ == '1'); + BOOST_TEST(*iter2++ == '1'); + BOOST_TEST(*iter3++ == '1'); + BOOST_TEST(*iter == *iter2); + BOOST_TEST(*iter == *iter3); + BOOST_TEST(iter.get_position() == iter2.get_position()); + BOOST_TEST(iter.get_position() == iter3.get_position()); + BOOST_TEST(*iter == '2'); + + ++iter; ++iter; ++iter; ++iter; ++iter; ++iter; ++iter; + BOOST_TEST(*iter == '9'); + ++iter; + BOOST_TEST(iter == end); + + // Check that one after end is no more end + ++iter; + BOOST_TEST(iter != end); +} + +template <typename IterT> +void CheckLineCounting(IterT iter) +{ + IterT end; + + BOOST_TEST(*iter == '\n'); + BOOST_TEST(iter.get_position().line == 1); + ++iter; // 0 + BOOST_TEST(iter.get_position().line == 2); + ++iter; // 1 + ++iter; // 2 + ++iter; // 3 + ++iter; // \r + BOOST_TEST(*iter == '\r'); + BOOST_TEST(iter.get_position().line == 2); + ++iter; // \n + BOOST_TEST(*iter == '\n'); + BOOST_TEST(iter.get_position().line == 2); + ++iter; // 4 + BOOST_TEST(iter.get_position().line == 3); + ++iter; // 5 + ++iter; // 6 + ++iter; // 7 + ++iter; // \n + BOOST_TEST(*iter == '\n'); + BOOST_TEST(iter.get_position().line == 3); + ++iter; // 8 + BOOST_TEST(iter.get_position().line == 4); + ++iter; // 9 + ++iter; // \n + BOOST_TEST(iter.get_position().line == 4); + BOOST_TEST(*iter == '\n'); + ++iter; // \r + BOOST_TEST(iter.get_position().line == 5); + BOOST_TEST(*iter == '\r'); + ++iter; // end + BOOST_TEST(iter.get_position().line == 6); + BOOST_TEST(iter == end); +} + +template <typename IterT> +void CheckColumnCounting_Tab4(IterT iter) +{ + IterT end; + + // Don't call set_tabchars() here because + // default must be 3. + BOOST_TEST(*iter == '\t'); + BOOST_TEST(iter.get_position().column == 1); + ++iter; // 0 + BOOST_TEST(iter.get_position().column == 5); + ++iter; // 1 + BOOST_TEST(iter.get_position().column == 6); + ++iter; // 2 + BOOST_TEST(iter.get_position().column == 7); + ++iter; // 3 + BOOST_TEST(iter.get_position().column == 8); + ++iter; // tab + BOOST_TEST(*iter == '\t'); + BOOST_TEST(iter.get_position().column == 9); + ++iter; // 4 + BOOST_TEST(iter.get_position().column == 13); + ++iter; // tab + BOOST_TEST(*iter == '\t'); + BOOST_TEST(iter.get_position().column == 14); + ++iter; // 5 + BOOST_TEST(iter.get_position().column == 17); + ++iter; // tab + BOOST_TEST(*iter == '\t'); + BOOST_TEST(iter.get_position().column == 18); + ++iter; // end + BOOST_TEST(iter == end); +} + +template <typename IterT> +void CheckColumnCounting_Tab3(IterT iter) +{ + IterT end; + + iter.set_tabchars(3); + + // Check also that tab settings propagates through + // assignment and copy construction + IterT iter2(iter); + IterT iter3; iter3 = iter2; + + BOOST_TEST(*iter == '\t'); + BOOST_TEST(iter.get_position().column == 1); + ++iter; // 0 + ++iter2; ++iter3; + BOOST_TEST(iter.get_position().column == 4); + BOOST_TEST(iter2.get_position().column == 4); + BOOST_TEST(iter3.get_position().column == 4); + ++iter; // 1 + BOOST_TEST(iter.get_position().column == 5); + ++iter; // 2 + BOOST_TEST(iter.get_position().column == 6); + ++iter; // 3 + BOOST_TEST(iter.get_position().column == 7); + ++iter; // tab + BOOST_TEST(*iter == '\t'); + BOOST_TEST(iter.get_position().column == 8); + ++iter; // 4 + BOOST_TEST(iter.get_position().column == 10); + ++iter; // tab + BOOST_TEST(*iter == '\t'); + BOOST_TEST(iter.get_position().column == 11); + ++iter; // 5 + BOOST_TEST(iter.get_position().column == 13); + ++iter; // tab + BOOST_TEST(*iter == '\t'); + BOOST_TEST(iter.get_position().column == 14); + ++iter; // end + BOOST_TEST(iter == end); +} + +const string line1 = "abcd"; +const string line2 = "efgh"; +const string linebuf = "\n" + line1 + "\n" + line2 + "\n"; + +template <typename IterT> +void AssertIterString(IterT begin, IterT end, string s) +{ + BOOST_TEST(string(begin, end) == s); +} + +template <typename IterT> +void CheckLineExtractionOne(IterT iter) +{ + IterT end; + + // At the start, we are on a newline, which is an empty + // string + BOOST_TEST(iter.get_currentline() == string()); + BOOST_TEST( + string(iter.get_currentline_begin(), iter.get_currentline_end()) + == string()); + + ++iter; // a + ++iter; // b + ++iter; // c + BOOST_TEST(iter.get_currentline() == line1); + AssertIterString( + iter.get_currentline_begin(), + iter.get_currentline_end(), + line1); + + ++iter; // d + ++iter; // newline + ++iter; // e + + // check that copy construction and assignment do + // not interfere with get_currentline + IterT iter2(iter); + IterT iter3; iter3 = iter; + BOOST_TEST(iter2.get_currentline() == line2); + BOOST_TEST(iter3.get_currentline() == line2); + AssertIterString( + iter2.get_currentline_begin(), + iter2.get_currentline_end(), + line2); + AssertIterString( + iter3.get_currentline_begin(), + iter3.get_currentline_end(), + line2); + + ++iter; // f + ++iter; // g + ++iter; // h + ++iter; // newline + + // Check when the iterator is on a newline + BOOST_TEST(iter.get_currentline() == line2); + AssertIterString( + iter.get_currentline_begin(), + iter.get_currentline_end(), + line2); + + ++iter; + BOOST_TEST(iter == end); +} + + +void CheckLineExtraction(void) +{ + typedef string::const_iterator iter_t; + + CheckLineExtractionOne( + position_iterator2<iter_t, file_position> + (linebuf.begin(), linebuf.end(), "")); + + CheckLineExtractionOne( + position_iterator2<iter_t, file_position_without_column> + (linebuf.begin(), linebuf.end(), "")); +} + +template <typename IterT> +void CheckEmptySequence(void) +{ + typedef IterT iter_t; + char a[10]; + + // Check construction with empty sequence, and + // correct propagation of the information + iter_t iter(a,a, ""); + iter_t iter2(iter); + iter_t iter3; iter3 = iter; + + BOOST_TEST(iter == iter_t()); + BOOST_TEST(iter2 == iter_t()); + BOOST_TEST(iter3 == iter_t()); +} + +template <typename IterC, typename Iter> +void CheckConstructors(void) +{ + char a[20]; + std::string name = "abc"; + + file_position_without_column pos(name,1); + file_position posc(name,1,1); + typedef IterC iterc_t; + typedef Iter iter_t; + + BOOST_TEST(iterc_t(a,a+20,name).get_position() == posc); + BOOST_TEST(iterc_t(a,a+20,name,1).get_position() == posc); + BOOST_TEST(iterc_t(a,a+20,name,1,1).get_position() == posc); + BOOST_TEST(iterc_t(a,a+20,posc).get_position() == posc); + BOOST_TEST(iter_t(a,a+20,name).get_position() == pos); + BOOST_TEST(iter_t(a,a+20,name,1).get_position() == pos); + BOOST_TEST(iter_t(a,a+20,pos).get_position() == pos); + + // Check copy constructor and assignment. Notice that we want + // an implicit copy constructor. + iterc_t ic1(a,a+20,name); + iterc_t ic2 = ic1; + iterc_t ic3; ic3 = ic1; + BOOST_TEST(ic1 == ic2); + BOOST_TEST(ic1 == ic3); + BOOST_TEST(ic1.get_position() == ic2.get_position()); + BOOST_TEST(ic1.get_position() == ic3.get_position()); + + iter_t i1(a,a+20,name); + iter_t i2 = i1; + iter_t i3; i3 = i1; + BOOST_TEST(i1 == i2); + BOOST_TEST(i1 == i3); + BOOST_TEST(i1.get_position() == i2.get_position()); + BOOST_TEST(i1.get_position() == i3.get_position()); + + // Check construction with an empty sequence + CheckEmptySequence<iter_t>(); + CheckEmptySequence<iterc_t>(); +} + +template <typename IterT> +void CheckDistance(IterT begin) +{ + IterT end; + + std::size_t std_distance = std::distance(begin, end); + + std::size_t manual_count = 0; + for(IterT it = begin; it != end; ++it) + ++manual_count; + + BOOST_TEST(std_distance == manual_count); +} + + +/////////////////////////////////////////////////////////////////////////////// +} /* namespace test_impl */ + + +void CheckConstructors(void) +{ + test_impl::CheckConstructors + < + position_iterator<char*, file_position>, + position_iterator<char*, file_position_without_column> + >(); + + test_impl::CheckConstructors + < + position_iterator2<char*, file_position>, + position_iterator2<char*, file_position_without_column> + >(); +} + +void CheckBasicFunctionality(void) +{ + const char* a = "0123456789"; + typedef const char* iter_t; + + test_impl::CheckIncrement(position_iterator<iter_t>(a, a+10, "")); + test_impl::CheckIncrement(position_iterator2<iter_t>(a, a+10, "")); + test_impl::CheckIncrement(position_iterator<iter_t, file_position_without_column>(a, a+10, "")); + test_impl::CheckIncrement(position_iterator2<iter_t, file_position_without_column>(a, a+10, "")); + + const char* b = "\n0123\r\n4567\n89\n\r"; + + test_impl::CheckLineCounting(position_iterator<iter_t>(b, b+16, "")); + test_impl::CheckLineCounting(position_iterator2<iter_t>(b, b+16, "")); + test_impl::CheckLineCounting(position_iterator<iter_t, file_position_without_column>(b, b+16, "")); + test_impl::CheckLineCounting(position_iterator2<iter_t, file_position_without_column>(b, b+16, "")); +} + + +void CheckColumnCounting(void) +{ + const char* a = "\t0123\t4\t5\t"; + typedef const char* iter_t; + + test_impl::CheckColumnCounting_Tab4(position_iterator<iter_t>(a, a+10, "")); + test_impl::CheckColumnCounting_Tab4(position_iterator2<iter_t>(a, a+10, "")); + test_impl::CheckColumnCounting_Tab3(position_iterator<iter_t>(a, a+10, "")); + test_impl::CheckColumnCounting_Tab3(position_iterator2<iter_t>(a, a+10, "")); +} + +void CheckLineExtraction(void) +{ + test_impl::CheckLineExtraction(); +} + +void CheckDistance(void) +{ + const char* b = "\n0123\r\n4567\n89\n\r"; + typedef const char* iter_t; + + test_impl::CheckDistance(position_iterator<iter_t>(b, b+15, "")); + test_impl::CheckDistance(position_iterator2<iter_t>(b, b+15, "")); + test_impl::CheckDistance(position_iterator<iter_t, file_position_without_column>(b, b+15, "")); + test_impl::CheckDistance(position_iterator2<iter_t, file_position_without_column>(b, b+15, "")); +} + +/////////////////////////////////////////////////////////////////////////////// + +namespace test_impl { + + template <bool AsValue = false> + class check_singular_iterator + { + bool singular_; + int count_; + + public: + typedef std::forward_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int const* pointer; + typedef typename boost::mpl::if_c<AsValue, int, int const&>::type reference; + + check_singular_iterator() : singular_(true), count_(0) {} + explicit check_singular_iterator(int x) : singular_(false), count_(x) {} + + reference operator*() const { + BOOST_TEST(!singular_); + return count_; + } + + pointer operator->() const { + BOOST_TEST(!singular_); + return &count_; + } + + check_singular_iterator& operator++() { + BOOST_TEST(count_ > 0); + --count_; + return *this; + } + + check_singular_iterator operator++(int) { + check_singular_iterator tmp(*this); + ++(*this); + return tmp; + } + + bool operator==(check_singular_iterator const& other) const { + BOOST_TEST(!singular_ && !other.singular_); + return count_ == other.count_; + } + + bool operator!=(check_singular_iterator const& other) const { + return !(*this == other); + } + }; + + template <typename CountIterator, typename Iterator> + void CheckSingularImpl() + { + CountIterator begin(Iterator(5), Iterator(0)); + CountIterator end1(Iterator(0), Iterator(0)); + CountIterator end2; + + BOOST_TEST(begin == begin); + BOOST_TEST(begin != end1); + BOOST_TEST(begin != end2); + + BOOST_TEST(end1 != begin); + BOOST_TEST(end1 == end1); + BOOST_TEST(end1 == end2); + + BOOST_TEST(end2 != begin); + BOOST_TEST(end2 == end1); + BOOST_TEST(end2 == end2); + + BOOST_TEST(std::distance(begin, begin) == 0); + BOOST_TEST(std::distance(begin, end1) == 5); + BOOST_TEST(std::distance(begin, end2) == 5); + + BOOST_TEST(std::distance(end1, end1) == 0); + BOOST_TEST(std::distance(end1, end2) == 0); + + BOOST_TEST(std::distance(end2, end1) == 0); + BOOST_TEST(std::distance(end2, end2) == 0); + + BOOST_TEST(*begin == 5); + } + + template <typename PositionT> + void CheckSingular() + { + { + typedef check_singular_iterator<false> interator_type; + CheckSingularImpl<position_iterator<interator_type, PositionT>, interator_type>(); + CheckSingularImpl<position_iterator2<interator_type, PositionT>, interator_type>(); + } + { + typedef check_singular_iterator<true> interator_type; + CheckSingularImpl<position_iterator<interator_type, PositionT>, interator_type>(); + CheckSingularImpl<position_iterator2<interator_type, PositionT>, interator_type>(); + } + } +} + +void CheckSingular() +{ + test_impl::CheckSingular<file_position>(); + test_impl::CheckSingular<file_position_without_column>(); +} diff --git a/src/boost/libs/spirit/classic/test/post_skips.cpp b/src/boost/libs/spirit/classic/test/post_skips.cpp new file mode 100644 index 00000000..97b8aba1 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/post_skips.cpp @@ -0,0 +1,113 @@ +/*============================================================================= + Copyright (c) 2004 Joao Abecasis + http://spirit.sourceforge.net/ + + 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/include/classic_parser.hpp> +#include <boost/spirit/include/classic_skipper.hpp> +#include <boost/spirit/include/classic_primitives.hpp> +#include <boost/spirit/include/classic_optional.hpp> +#include <boost/spirit/include/classic_sequence.hpp> +#include <boost/spirit/include/classic_ast.hpp> +#include <boost/spirit/include/classic_parse_tree.hpp> + +#include <boost/detail/lightweight_test.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +char const * test1 = " 12345 "; +char const * test2 = " 12345 x"; + +void parse_tests() +{ + parse_info<> info; + + // Warming up... + info = parse(test1, str_p("12345")); + BOOST_TEST(!info.hit); + + // No post-skips! + info = parse(test1, str_p("12345"), blank_p); + BOOST_TEST(info.hit); + BOOST_TEST(!info.full); + + // Require a full match + info = parse(test1, str_p("12345") >> end_p, blank_p); + BOOST_TEST(info.full); + info = parse(test2, str_p("12345") >> end_p, blank_p); + BOOST_TEST(!info.hit); + + // Check for a full match but don't make it a requirement + info = parse(test1, str_p("12345") >> !end_p, blank_p); + BOOST_TEST(info.full); + info = parse(test2, str_p("12345") >> !end_p, blank_p); + BOOST_TEST(info.hit); + BOOST_TEST(!info.full); +} + +void ast_parse_tests() +{ + tree_parse_info<> info; + + // Warming up... + info = ast_parse(test1, str_p("12345")); + BOOST_TEST(!info.match); + + // No post-skips! + info = ast_parse(test1, str_p("12345"), blank_p); + BOOST_TEST(info.match); + BOOST_TEST(!info.full); + + // Require a full match + info = ast_parse(test1, str_p("12345") >> end_p, blank_p); + BOOST_TEST(info.full); + info = ast_parse(test2, str_p("12345") >> end_p, blank_p); + BOOST_TEST(!info.match); + + // Check for a full match but don't make it a requirement + info = ast_parse(test1, str_p("12345") >> !end_p, blank_p); + BOOST_TEST(info.full); + info = ast_parse(test2, str_p("12345") >> !end_p, blank_p); + BOOST_TEST(info.match); + BOOST_TEST(!info.full); +} + +void pt_parse_tests() +{ + tree_parse_info<> info; + + // Warming up... + info = pt_parse(test1, str_p("12345")); + BOOST_TEST(!info.match); + + // No post-skips! + info = pt_parse(test1, str_p("12345"), blank_p); + BOOST_TEST(info.match); + BOOST_TEST(!info.full); + + // Require a full match + info = pt_parse(test1, str_p("12345") >> end_p, blank_p); + BOOST_TEST(info.full); + info = pt_parse(test2, str_p("12345") >> end_p, blank_p); + BOOST_TEST(!info.match); + + // Check for a full match but don't make it a requirement + info = pt_parse(test1, str_p("12345") >> !end_p, blank_p); + BOOST_TEST(info.full); + info = pt_parse(test2, str_p("12345") >> !end_p, blank_p); + BOOST_TEST(info.match); + BOOST_TEST(!info.full); +} + +int main() +{ + parse_tests(); + ast_parse_tests(); + pt_parse_tests(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/primitives_tests.cpp b/src/boost/libs/spirit/classic/test/primitives_tests.cpp new file mode 100644 index 00000000..c5772e02 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/primitives_tests.cpp @@ -0,0 +1,135 @@ +/*============================================================================= + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2002-2003 Martin Wille + http://spirit.sourceforge.net/ + + 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 <iostream> + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "impl/string_length.hpp" +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Primitives tests +// +/////////////////////////////////////////////////////////////////////////////// +void +primitives_tests() +{ + char const* cp = "xyz.Jambalaya"; + char const* cp_first = cp; + char const* cp_last = cp + test_impl::string_length(cp); + + chlit<> cpx('x'); + parse_info<char const*> pi = parse(cp_first, cp_last, cpx); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(pi.length == 1); + BOOST_TEST(pi.stop == &cp[1]); + + pi = parse(pi.stop, ch_p('y')); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(pi.length == 1); + BOOST_TEST(pi.stop == &cp[2]); + + scanner<char const*> scan(pi.stop, cp_last); + match<char> hit = ch_p('z').parse(scan); + BOOST_TEST(hit); + BOOST_TEST(hit.value() == 'z'); + BOOST_TEST(pi.stop == &cp[3]); + + pi = parse(pi.stop, eps_p); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(pi.length == 0); + BOOST_TEST(pi.stop == &cp[3]); + + pi = parse(pi.stop, nothing_p); + BOOST_TEST(!pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(pi.stop == &cp[3]); + + pi = parse(pi.stop, anychar_p); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(pi.length == 1); + BOOST_TEST(pi.stop == &cp[4]); + + scan.first = pi.stop; + hit = range_p('A','Z').parse(scan); + BOOST_TEST(hit); + BOOST_TEST(hit.value() == 'J'); + BOOST_TEST(pi.stop == &cp[5]); + + strlit<char const*> sp("ambalaya"); + strlit<wchar_t const*> wsp(L"ambalaya"); + + char const* save = pi.stop; + pi = parse(save, sp); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 8); + BOOST_TEST(pi.stop == cp_last); + + pi = parse(save, wsp); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 8); + BOOST_TEST(pi.stop == cp_last); + + pi = parse("\n", eol_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("\r", eol_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("\r\n", eol_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("\n\r", eol_p); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + + pi = parse("", end_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("1", ~alpha_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("a", ~alpha_p); + BOOST_TEST(!pi.hit); + + pi = parse("a", ~~alpha_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("1", ~~alpha_p); + BOOST_TEST(!pi.hit); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Main +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + primitives_tests(); + if (boost::report_errors() == 0) + std::cout << "Tests concluded successfully\n"; + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/repeat_ast_tests.cpp b/src/boost/libs/spirit/classic/test/repeat_ast_tests.cpp new file mode 100644 index 00000000..5091f76e --- /dev/null +++ b/src/boost/libs/spirit/classic/test/repeat_ast_tests.cpp @@ -0,0 +1,95 @@ +/*============================================================================= + Copyright (c) 2004 Chris Hoeppler + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +// This test verifies, that reapeat_p et.al. work correctly while using AST's + +# include <map> +# include <boost/detail/lightweight_test.hpp> +# include <iostream> +# include <string> + +# include <boost/spirit/include/classic_core.hpp> +# include <boost/spirit/include/classic_loops.hpp> +# include <boost/spirit/include/classic_ast.hpp> +# include <boost/spirit/include/classic_tree_to_xml.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +static const int numID = 1; +static const int funcID = 2; +static const int expressionID = 3; + +struct grammar_fail : public grammar<grammar_fail> +{ + template <typename ScannerT> + struct definition + { + definition(grammar_fail const& /*self */) + { + num = leaf_node_d[real_p]; + func = root_node_d[ch_p('+') | '-'] + >> repeat_p(2)[expression]; + expression = func | num; + } + rule<ScannerT, parser_context<>, parser_tag<numID> > num; + rule<ScannerT, parser_context<>, parser_tag<funcID> > func; + typedef rule<ScannerT, parser_context<>, parser_tag<expressionID> > expr_t; + expr_t expression; + expr_t const& start() const { return expression; } + }; +}; +struct grammar_success : public grammar<grammar_success> +{ + template <typename ScannerT> + struct definition + { + definition(grammar_success const& /*self */) + { + num = leaf_node_d[real_p]; + func = root_node_d[ch_p('+') | '-'] + >> expression >> expression; // line differing from grammar_fail + expression = func | num; + } + rule<ScannerT, parser_context<>, parser_tag<numID> > num; + rule<ScannerT, parser_context<>, parser_tag<funcID> > func; + typedef rule<ScannerT, parser_context<>, parser_tag<expressionID> > expr_t; + expr_t expression; + expr_t const& start() const { return expression; } + }; +}; + +int main() { + + std::map<parser_id, std::string> rule_names; + rule_names[expressionID] = "expression"; + rule_names[funcID] = "func"; + rule_names[numID] = "num"; + + std::string test("+ 1 - 2 3"); + +// case 1 + grammar_fail g_fail; + tree_parse_info<> info1 = ast_parse(test.c_str(), g_fail, space_p); + BOOST_TEST(info1.full); + + //std::cout << "...Case 1: Using repeat_p\n"; + //tree_to_xml(std::cerr, info1.trees, test, rule_names); + +// case 2 + grammar_success g_success; + tree_parse_info<> info2 = ast_parse(test.c_str(), g_success, space_p); + BOOST_TEST(info2.full); + + //std::cout << "...Case 2: No repeat_p\n"; + //tree_to_xml(std::cerr, info2.trees, test, rule_names); + // could be used for test case instead of printing the xml stuff: + BOOST_TEST(info2.trees.begin()->children.size() == 2); + BOOST_TEST(info1.trees.begin()->children.size() == 2); + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/rule_tests.cpp b/src/boost/libs/spirit/classic/test/rule_tests.cpp new file mode 100644 index 00000000..65210a03 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/rule_tests.cpp @@ -0,0 +1,264 @@ +/*============================================================================= + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> + + +//#define BOOST_SPIRIT_DEBUG +#define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 3 + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_stored_rule.hpp> +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Rule tests +// +/////////////////////////////////////////////////////////////////////////////// +void +aliasing_tests() +{ + rule<> a = ch_p('a'); + rule<> b = ch_p('b'); + rule<> c = ch_p('c'); + + std::cout << "sizeof(rule<>): " << sizeof(rule<>) << std::endl; + + BOOST_SPIRIT_DEBUG_RULE(a); + BOOST_SPIRIT_DEBUG_RULE(b); + BOOST_SPIRIT_DEBUG_RULE(c); + + rule<> start; + BOOST_SPIRIT_DEBUG_RULE(start); + + rule<> d; + d = start; // aliasing + + parse_info<char const*> pi; + + start = *(a | b | c); + pi = parse("abcabcacb", d); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 9); + BOOST_TEST(*pi.stop == 0); + + start = (a | b) >> (start | b); + pi = parse("aaaabababaaabbb", d); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 15); + BOOST_TEST(*pi.stop == 0); +} + +void +rule_template_param_tests() +{ + // test that rules can be issued its template params in any order: + + rule<> rx1; + rule<scanner<> > rx2; + rule<scanner<>, parser_context<> > rx3; + rule<scanner<>, parser_context<>, parser_address_tag> rx4; + + rule<parser_context<> > rx5; + rule<parser_context<>, parser_address_tag> rx6; + rule<parser_context<>, parser_address_tag, scanner<> > rx7; + + rule<parser_address_tag> rx8; + rule<parser_address_tag, scanner<> > rx9; + rule<parser_address_tag, scanner<>, parser_context<> > rx10; + + rule<parser_address_tag, parser_context<> > rx11; + rule<parser_address_tag, parser_context<>, scanner<> > rx12; + + rule<parser_context<>, scanner<> > rx13; + rule<parser_context<>, scanner<>, parser_address_tag> rx14; +} + +struct my_grammar : public grammar<my_grammar> +{ + template <typename ScannerT> + struct definition + { + definition(my_grammar const& /*self*/) + { + r = lower_p; + rr = +(lexeme_d[r] >> as_lower_d[r] >> r); + } + + typedef scanner_list< + ScannerT + , typename lexeme_scanner<ScannerT>::type + , typename as_lower_scanner<ScannerT>::type + > scanners; + + rule<scanners> r; + rule<ScannerT> rr; + rule<ScannerT> const& start() const { return rr; } + }; +}; + +void +rule_2_or_more_scanners_tests() +{ + { // 2 scanners + typedef scanner_list<scanner<>, phrase_scanner_t> scanners; + + rule<scanners> r = +anychar_p; + BOOST_TEST(parse("abcdefghijk", r).full); + BOOST_TEST(parse("a b c d e f g h i j k", r, space_p).full); + } + + { // 3 scanners + my_grammar g; + BOOST_TEST(parse("abcdef aBc d e f aBc d E f", g, space_p).full); + } +} + +void +rule_basic_tests() +{ + rule<> a = ch_p('a'); + rule<> b = ch_p('b'); + rule<> c = ch_p('c'); + + BOOST_SPIRIT_DEBUG_RULE(a); + BOOST_SPIRIT_DEBUG_RULE(b); + BOOST_SPIRIT_DEBUG_RULE(c); + + parse_info<char const*> pi; + + rule<> start = *(a | b | c); + + BOOST_SPIRIT_DEBUG_RULE(start); + + pi = parse("abcabcacb", start); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 9); + BOOST_TEST(*pi.stop == 0); + + start = (a | b) >> (start | b); + pi = parse("aaaabababaaabbb", start); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 15); + BOOST_TEST(*pi.stop == 0); + + pi = parse("aaaabababaaabba", start); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(pi.length == 14); + + rule<> r = anychar_p; + r.copy(); // copy test (compile only) +} + +void +stored_rule_basic_tests() +{ + stored_rule<> a = ch_p('a'); + stored_rule<> b = ch_p('b'); + stored_rule<> c = ch_p('c'); + + BOOST_SPIRIT_DEBUG_RULE(a); + BOOST_SPIRIT_DEBUG_RULE(b); + BOOST_SPIRIT_DEBUG_RULE(c); + + parse_info<char const*> pi; + + stored_rule<> start = *(a | b | c); + + BOOST_SPIRIT_DEBUG_RULE(start); + + pi = parse("abcabcacb", start); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 9); + BOOST_TEST(*pi.stop == 0); + + start = (a | b) >> (start | b); + pi = parse("aaaabababaaabbb", start); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 15); + BOOST_TEST(*pi.stop == 0); + + pi = parse("aaaabababaaabba", start); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(pi.length == 14); +} + +void +stored_rule_dynamic_tests() +{ + rule<> a = ch_p('a'); + rule<> b = ch_p('b'); + rule<> c = ch_p('c'); + + BOOST_SPIRIT_DEBUG_RULE(a); + BOOST_SPIRIT_DEBUG_RULE(b); + BOOST_SPIRIT_DEBUG_RULE(c); + + parse_info<char const*> pi; + + // The FF is the dynamic equivalent of start = *(a | b | c); + stored_rule<> start = a; + start = start.copy() | b; + start = start.copy() | c; + start = *(start.copy()); + + std::cout << "sizeof(stored_rule<>): " << sizeof(stored_rule<>) << std::endl; + + BOOST_SPIRIT_DEBUG_RULE(start); + + pi = parse("abcabcacb", start); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 9); + BOOST_TEST(*pi.stop == 0); + + // The FF is the dynamic equivalent of start = (a | b) >> (start | b); + start = b; + start = a | start.copy(); + start = start.copy() >> (start | b); + + pi = parse("aaaabababaaabbb", start); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 15); + BOOST_TEST(*pi.stop == 0); + + pi = parse("aaaabababaaabba", start); + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(pi.length == 14); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Main +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + rule_basic_tests(); + aliasing_tests(); + rule_template_param_tests(); + rule_2_or_more_scanners_tests(); + stored_rule_basic_tests(); + stored_rule_dynamic_tests(); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/scanner_tests.cpp b/src/boost/libs/spirit/classic/test/scanner_tests.cpp new file mode 100644 index 00000000..69f69509 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/scanner_tests.cpp @@ -0,0 +1,140 @@ +/*============================================================================= + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> +#include <list> + + +#include <boost/spirit/include/classic_core.hpp> +#include "impl/string_length.hpp" +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Scanner tests +// +/////////////////////////////////////////////////////////////////////////////// +struct to_upper_iter_policy : public iteration_policy { + + char filter(char ch) const + { using namespace std; return char(toupper(ch)); } +}; + +inline bool test_isspace(char c) +{ + using namespace std; return isspace(c) != 0; +} + +inline bool test_islower(char c) +{ + using namespace std; return islower(c) != 0; +} + +struct skip_white_iter_policy : public iteration_policy { + + template <typename ScannerT> + void + advance(ScannerT const& scan) const + { + do + ++scan.first; + while (!at_end(scan) && test_isspace(get(scan))); + } +}; + +void +scanner_tests() +{ + char const* cp = "The Big Brown Fox Jumped \n\tOver The Lazy Dog's Back"; + char const* cp_first = cp; + char const* cp_last = cp + test_impl::string_length(cp); + + scanner<char const*> + pp1(cp_first, cp_last); + + // compile check only... + scanner<> spp1(pp1); (void)spp1; + scanner<> spp2(pp1); (void)spp2; + // spp1 = spp2; + // compile check only... + + while (!pp1.at_end()) + { + std::cout << *pp1; + ++pp1; + } + std::cout << '\n'; + cp_first = cp; + + std::list<char> li(cp_first, cp_last); + std::list<char>::iterator li_first = li.begin(); + std::list<char>::iterator li_last = li.end(); + + scanner<std::list<char>::iterator> + pp2(li_first, li_last); + + while (!pp2.at_end()) + { + std::cout << *pp2; + ++pp2; + } + std::cout << '\n'; + li_first = li.begin(); + + scanner<char const*, scanner_policies<to_upper_iter_policy> > + pp3(cp_first, cp_last); + + while (!pp3.at_end()) + { + std::cout << *pp3; + BOOST_TEST(!test_islower(*pp3)); + ++pp3; + } + std::cout << '\n'; + cp_first = cp; + + scanner<char const*, scanner_policies<skip_white_iter_policy> > + pp4(cp_first, cp_last); + + // compile check only... + pp1.change_policies(scanner_policies<skip_white_iter_policy>()); + // compile check only... + + while (!pp4.at_end()) + { + std::cout << *pp4; + BOOST_TEST(!test_isspace(*pp4)); + ++pp4; + } + std::cout << '\n'; + cp_first = cp; + + std::cout << "sizeof(scanner<>) == " << sizeof(scanner<>) << '\n'; + + parse_info<> pi = parse("12abcdefg12345ABCDEFG789", +digit_p, alpha_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + pi = parse("abcdefg12345ABCDEFG789", +digit_p, alpha_p); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Main +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + scanner_tests(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/scanner_value_type_tests.cpp b/src/boost/libs/spirit/classic/test/scanner_value_type_tests.cpp new file mode 100644 index 00000000..ac7f4ff6 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/scanner_value_type_tests.cpp @@ -0,0 +1,139 @@ +/*============================================================================= + Copyright (c) 2005 Jordan DeLong + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +// Some tests of parsing on value_t's that aren't char or wchar_t. +// +// Part of what this is testing is that BOOST_SPIRIT_DEBUG doesn't +// break when the scanner::value_t is some sort of non-char. +#define SPIRIT_DEBUG_NODE + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <deque> +#include <iostream> + +namespace sp = BOOST_SPIRIT_CLASSIC_NS; + +namespace { + + struct grammar : sp::grammar<grammar> { + template<class Scanner> + struct definition { + definition(grammar const&) + { + foo + = sp::alpha_p + | sp::alnum_p + | sp::cntrl_p + | sp::print_p + | sp::blank_p + | sp::digit_p + | sp::graph_p + | sp::lower_p + | sp::upper_p + | sp::xdigit_p + | sp::punct_p + ; + } + + sp::rule<Scanner> foo; + sp::rule<Scanner> const& + start() const + { + return foo; + } + }; + }; + + struct non_pod { + non_pod() : value('1') {} + char value; + bool operator==(non_pod const& o) const { return value == o.value; } + }; + + BOOST_ATTRIBUTE_UNUSED + std::ostream& + operator<<(std::ostream& out, non_pod const& x) + { + out << x.value; + return out; + } + + template<class T> + struct convertable_non_pod : non_pod { + operator T() { return value; } + }; + + struct nonpod_gram : sp::grammar<nonpod_gram> { + template<class Scanner> + struct definition { + definition(nonpod_gram const&) + { + foo = sp::ch_p(typename Scanner::value_t()); + } + + sp::rule<Scanner> foo; + sp::rule<Scanner> const& + start() const + { + return foo; + } + }; + }; + + template<class Grammar, class ValueType> + void + test_type() + { + typedef std::deque<ValueType> container; + typedef typename container::iterator iterator; + typedef sp::scanner<iterator> scanner; + + container blah; + blah.push_back(typename container::value_type()); + blah.push_back(typename container::value_type()); + + iterator first = blah.begin(); + iterator last = blah.end(); + + scanner scan(first, last); + + // Make sure this actually tries what we think it tries. + BOOST_STATIC_ASSERT(( + boost::is_same<typename scanner::value_t, ValueType>::value + )); + + Grammar().parse(scan); + } + +} + +int +main() +{ + // Make sure isfoo() style functions work for integral types. + test_type<grammar, char>(); + test_type<grammar, unsigned char>(); + test_type<grammar, wchar_t>(); + test_type<grammar, int>(); + test_type<grammar, long>(); + test_type<grammar, short>(); + test_type<grammar, bool>(); + + // Non-POD's should work with things like alpha_p as long as we + // can turn them into a type that can do isalpha(). + test_type<grammar, convertable_non_pod<char> >(); + test_type<grammar, convertable_non_pod<wchar_t> >(); + test_type<grammar, convertable_non_pod<int> >(); + + // BOOST_SPIRIT_DEBUG should work with grammars that parse + // non-POD's even if they can't do things like isalpha(). + test_type<nonpod_gram, non_pod>(); +} diff --git a/src/boost/libs/spirit/classic/test/scoped_lock_tests.cpp b/src/boost/libs/spirit/classic/test/scoped_lock_tests.cpp new file mode 100644 index 00000000..4c4fde0c --- /dev/null +++ b/src/boost/libs/spirit/classic/test/scoped_lock_tests.cpp @@ -0,0 +1,61 @@ +/*============================================================================= + Copyright (C) 2003 Martin Wille + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +// Nota bene: the actual locking is _not_ tested here! + +#include <iostream> +#include <boost/config.hpp> + +void banner() +{ + std::cout << "/////////////////////////////////////////////////////////\n"; + std::cout << "\n"; + std::cout << " scoped_lock test\n"; + std::cout << "\n"; + std::cout << "/////////////////////////////////////////////////////////\n"; + std::cout << "\n"; +} + +#if defined(DONT_HAVE_BOOST) || !defined(BOOST_HAS_THREADS) || defined(BOOST_DISABLE_THREADS) +// if boost libraries are not available we have to skip the tests +int +main() +{ + banner(); + std::cout << "Test skipped (Boost libaries not available)\n"; + return 0; +} +#else + +#include <boost/thread/mutex.hpp> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_scoped_lock.hpp> +#include <boost/detail/lightweight_test.hpp> + +int +main() +{ + banner(); + + using BOOST_SPIRIT_CLASSIC_NS::rule; + using BOOST_SPIRIT_CLASSIC_NS::scoped_lock_d; + using BOOST_SPIRIT_CLASSIC_NS::parse_info; + using BOOST_SPIRIT_CLASSIC_NS::parse; + using boost::mutex; + + mutex m; + rule<> r = scoped_lock_d(m)['x']; + parse_info<> pi = parse("x", r); + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + + return boost::report_errors(); +} + +#endif // defined(DONT_HAVE_BOOST) diff --git a/src/boost/libs/spirit/classic/test/select_p_with_rule.cpp b/src/boost/libs/spirit/classic/test/select_p_with_rule.cpp new file mode 100644 index 00000000..54142afe --- /dev/null +++ b/src/boost/libs/spirit/classic/test/select_p_with_rule.cpp @@ -0,0 +1,89 @@ +/*============================================================================= + Copyright (c) 2004 Vyacheslav E. Andrejev + http://spirit.sourceforge.net/ + + 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 <iostream> + +#define PHOENIX_LIMIT 2 +#define BOOST_SPIRIT_SELECT_LIMIT 2 +#define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 2 + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_lists.hpp> +#include <boost/spirit/include/classic_select.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace std; + +struct format_grammar : public grammar<format_grammar> +{ + template <typename ScannerT> + struct definition + { + definition(format_grammar const& /*self*/) + { + descriptor_list = + list_p(format_descriptor, ch_p(',')) + ; + + format_descriptor = + select_p(E_descriptor, EN_descriptor) + ; + + E_descriptor = // E[w[.d][Ee]] + lexeme_d + [ + (ch_p('E') - (str_p("EN"))) + >> !( + min_limit_d(1u)[uint_p] + >> !(ch_p('.') >> uint_p) + >> !(ch_p('E') >> min_limit_d(1u)[uint_p]) + ) + ] + ; + + EN_descriptor = // EN[w[.d][Ee]] + lexeme_d + [ + str_p("EN") + >> !( + min_limit_d(1u)[uint_p] + >> !(ch_p('.') >> uint_p) + >> !(ch_p('E') >> min_limit_d(1u)[uint_p]) + ) + ] + ; + } + + rule<ScannerT> descriptor_list; + rule<ScannerT> format_descriptor; + rule<ScannerT> E_descriptor; + rule<ScannerT> EN_descriptor; + + rule<ScannerT> const& start() const + { + return descriptor_list; + } + }; +}; + +int main() +{ + format_grammar grammar; + const char* format = "E2, EN15.7, E20.10E3, E, EN"; + + parse_info<> pi = parse(format, grammar, blank_p); + + if (pi.full) { + cout << "Test concluded successful" << endl; + return 0; + } + else { + BOOST_SPIRIT_ASSERT(false); // Test fails + return -1; + } +} diff --git a/src/boost/libs/spirit/classic/test/sf_bug_720917.cpp b/src/boost/libs/spirit/classic/test/sf_bug_720917.cpp new file mode 100644 index 00000000..4e2724d5 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/sf_bug_720917.cpp @@ -0,0 +1,115 @@ +/*============================================================================= + Copyright (c) 2003 Giovanni Bajo + Copyrigh (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + 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/include/classic_multi_pass.hpp> +#include <iterator> +#include "impl/sstream.hpp" +#include <boost/detail/lightweight_test.hpp> + +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +// Test for bug #720917 +// http://sf.net/tracker/index.php?func=detail&aid=720917&group_id=28447&atid=393386 +// +// Check that it's possible to use multi_pass +// together with standard library as a normal iterator +// + +// a functor to test out the functor_multi_pass +class my_functor +{ + public: + typedef char result_type; + my_functor() + : c('A') + {} + + char operator()() + { + if (c == 'M') + return eof; + else + return c++; + } + + static result_type eof; + private: + char c; +}; + +my_functor::result_type my_functor::eof = '\0'; + +//////////////////////////////////////////////// +// four types of multi_pass iterators +typedef multi_pass< + my_functor, + multi_pass_policies::functor_input, + multi_pass_policies::first_owner, + multi_pass_policies::no_check, + multi_pass_policies::std_deque +> functor_multi_pass_t; + +typedef multi_pass<istream_iterator<char> > default_multi_pass_t; +typedef look_ahead<istream_iterator<char>, 6> fixed_multi_pass_t; + +typedef multi_pass< + istream_iterator<char>, + multi_pass_policies::input_iterator, + multi_pass_policies::first_owner, + multi_pass_policies::buf_id_check, + multi_pass_policies::std_deque +> first_owner_multi_pass_t; + + +//////////////////////////////////////////////// +// the test cases +template <typename IterT> +void construct_string_from(void) +{ + sstream_t ss; + ss << "test string"; + + IterT mpend; + istream_iterator<char> a(ss); + IterT mp1(a); + + std::string dummy; +#ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS + dummy.assign(mp1, mpend); +#else + copy(mp1, mpend, inserter(dummy, dummy.end())); +#endif +} + +template <> +void construct_string_from<functor_multi_pass_t>(void) +{ + functor_multi_pass_t mpend; + functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor()); + + std::string dummy; +#ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS + dummy.assign(mp1, mpend); +#else + copy(mp1, mpend, inserter(dummy, dummy.end())); +#endif +} + +//////////////////////////////////////////////// +// Definition of the test suite +int +main() +{ + construct_string_from<default_multi_pass_t>(); + construct_string_from<fixed_multi_pass_t>(); + construct_string_from<first_owner_multi_pass_t>(); + construct_string_from<functor_multi_pass_t>(); + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/shortest_alternative_tests.cpp b/src/boost/libs/spirit/classic/test/shortest_alternative_tests.cpp new file mode 100644 index 00000000..1169fbc6 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/shortest_alternative_tests.cpp @@ -0,0 +1,58 @@ +// +// Copyright (c) 2004 Joao Abecasis +// +// 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/include/classic_core.hpp> +#include <boost/detail/lightweight_test.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +void shortest_alternative_parser_test() +{ + typedef + shortest_alternative< + shortest_alternative< + shortest_alternative< + strlit<>, + strlit<> >, + strlit<> >, + strlit<> > + parser_t; + + parser_t short_rule = + shortest_d[ + str_p("a") + | str_p("aa") + | str_p("aaa") + | str_p("aaaa") + ]; + + BOOST_TEST(parse("a", short_rule).full); + BOOST_TEST(parse("aa", short_rule).length == 1); + BOOST_TEST(parse("aaa", short_rule).length == 1); + BOOST_TEST(parse("aaaa", short_rule).length == 1); + + short_rule = + shortest_d[ + str_p("d") + | str_p("cd") + | str_p("bcd") + | str_p("abcd") + ]; + + BOOST_TEST(parse("d", short_rule).full); + BOOST_TEST(parse("cd", short_rule).full); + BOOST_TEST(parse("bcd", short_rule).full); + BOOST_TEST(parse("abcd", short_rule).full); +} + +int +main() +{ + shortest_alternative_parser_test(); + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/subrule_tests.cpp b/src/boost/libs/spirit/classic/test/subrule_tests.cpp new file mode 100644 index 00000000..fd0a66cc --- /dev/null +++ b/src/boost/libs/spirit/classic/test/subrule_tests.cpp @@ -0,0 +1,92 @@ +/*============================================================================= + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> + + +#include <boost/spirit/include/classic_core.hpp> +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Sub Rules tests +// +/////////////////////////////////////////////////////////////////////////////// +void +subrules_tests() +{ + subrule<0> start; + subrule<1> a; + subrule<2> b; + subrule<3> c; + + parse_info<char const*> pi; + pi = parse("abcabcacb", + ( + start = *(a | b | c), + a = ch_p('a'), + b = ch_p('b'), + c = ch_p('c') + ) + ); + + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 9); + BOOST_TEST(*pi.stop == 0); + + pi = parse("aaaabababaaabbb", + ( + start = (a | b) >> (start | b), + a = ch_p('a'), + b = ch_p('b') + ) + ); + + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 15); + BOOST_TEST(*pi.stop == 0); + + pi = parse("aaaabababaaabba", + ( + start = (a | b) >> (start | b), + a = ch_p('a'), + b = ch_p('b') + ) + ); + + BOOST_TEST(pi.hit); + BOOST_TEST(!pi.full); + BOOST_TEST(pi.length == 14); + + pi = parse("aaaabababaaabbb", + + // single subrule test + start = (ch_p('a') | 'b') >> (start | 'b') + ); + + BOOST_TEST(pi.hit); + BOOST_TEST(pi.full); + BOOST_TEST(pi.length == 15); + BOOST_TEST(*pi.stop == 0); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Main +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + subrules_tests(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/switch_problem.cpp b/src/boost/libs/spirit/classic/test/switch_problem.cpp new file mode 100644 index 00000000..b2a7131a --- /dev/null +++ b/src/boost/libs/spirit/classic/test/switch_problem.cpp @@ -0,0 +1,107 @@ +/*============================================================================= + Copyright (c) 2004 Angus Leeming + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// +// The switch_p parser was broken sometime during the boost 1.32 development +// cycle. This little program tests it, the for_p parser and the limit_d +// directive. +// +/////////////////////////////////////////////////////////////////////////////// + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_for.hpp> +#include <boost/spirit/include/classic_switch.hpp> +#include <boost/spirit/include/classic_position_iterator.hpp> +#include <boost/spirit/include/classic_confix.hpp> + +#include <boost/spirit/include/phoenix1.hpp> + +#include <iostream> +#include <string> + +namespace spirit = BOOST_SPIRIT_CLASSIC_NS; + +typedef unsigned int uint; + +struct switch_grammar : public spirit::grammar<switch_grammar> { + template <typename ScannerT> + struct definition { + definition(switch_grammar const & self); + + typedef spirit::rule<ScannerT> rule_t; + rule_t const & start() const { return expression; } + + private: + rule_t expression; + uint index; + uint nnodes; + }; +}; + + +template <typename ScannerT> +switch_grammar::definition<ScannerT>::definition(switch_grammar const & /*self*/) +{ + using boost::cref; + + using phoenix::arg1; + using phoenix::var; + + using spirit::case_p; + using spirit::for_p; + using spirit::limit_d; + using spirit::str_p; + using spirit::switch_p; + using spirit::uint_p; + + expression = + str_p("NNODES") >> + uint_p[var(nnodes) = arg1] >> + + for_p(var(index) = 1, + var(index) <= var(nnodes), + var(index)++) + [ + limit_d(cref(index), cref(index))[uint_p] >> + + switch_p[ + case_p<'s'>(uint_p), + case_p<'d'>(uint_p), + case_p<'n'>(uint_p) + ] + ]; +} + + +int main() +{ + std::string const data("NNODES 3\n" + "1 s 1\n" + "2 d 2\n" + "3 n 3"); // JDG 10-18-2005 removed trailing \n to + // avoid post skip problems + + typedef spirit::position_iterator<std::string::const_iterator> + iterator_t; + + spirit::parse_info<iterator_t> const info = + parse(iterator_t(data.begin(), data.end(), "switch test"), + iterator_t(), + switch_grammar(), + spirit::space_p); + + if (!info.full) { + spirit::file_position const fp = info.stop.get_position(); + std::cerr << "Parsing failed at line " << fp.line + << ", column " << fp.column << ".\n"; + } + + return info.full ? 0 : 1; +} diff --git a/src/boost/libs/spirit/classic/test/switch_tests_eps_default.cpp b/src/boost/libs/spirit/classic/test/switch_tests_eps_default.cpp new file mode 100644 index 00000000..747164d8 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/switch_tests_eps_default.cpp @@ -0,0 +1,327 @@ +/*============================================================================= + Copyright (c) 2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> + + +#define BOOST_SPIRIT_SWITCH_CASE_LIMIT 6 +#define BOOST_SPIRIT_SELECT_LIMIT 6 +#define PHOENIX_LIMIT 6 + +//#define BOOST_SPIRIT_DEBUG +#include <boost/mpl/list.hpp> +#include <boost/mpl/for_each.hpp> + +#include <boost/spirit/include/classic_primitives.hpp> +#include <boost/spirit/include/classic_numerics.hpp> +#include <boost/spirit/include/classic_actions.hpp> +#include <boost/spirit/include/classic_operators.hpp> +#include <boost/spirit/include/classic_rule.hpp> +#include <boost/spirit/include/classic_grammar.hpp> +#include <boost/spirit/include/classic_switch.hpp> +#include <boost/spirit/include/classic_select.hpp> +#include <boost/spirit/include/classic_closure.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +namespace test_grammars { + +/////////////////////////////////////////////////////////////////////////////// +// Test the direct switch_p usage (with default_p) + struct switch_grammar_direct_default4 + : public grammar<switch_grammar_direct_default4> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_direct_default4 const& /*self*/) + { + r = switch_p [ + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + case_p<'c'>(str_p("bcd")), + default_p + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + + struct switch_grammar_direct_default5 + : public grammar<switch_grammar_direct_default5> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_direct_default5 const& /*self*/) + { + r = switch_p [ + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + default_p, + case_p<'c'>(str_p("bcd")) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + + struct switch_grammar_direct_default6 + : public grammar<switch_grammar_direct_default6> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_direct_default6 const& /*self*/) + { + r = switch_p [ + default_p, + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + case_p<'c'>(str_p("bcd")) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + +/////////////////////////////////////////////////////////////////////////////// +// Test the switch_p usage given a parser as the switch condition + struct switch_grammar_parser_default4 + : public grammar<switch_grammar_parser_default4> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_parser_default4 const& /*self*/) + { + r = switch_p(anychar_p) [ + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + case_p<'c'>(str_p("bcd")), + default_p + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + + struct switch_grammar_parser_default5 + : public grammar<switch_grammar_parser_default5> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_parser_default5 const& /*self*/) + { + r = switch_p(anychar_p) [ + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + default_p, + case_p<'c'>(str_p("bcd")) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + + struct switch_grammar_parser_default6 + : public grammar<switch_grammar_parser_default6> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_parser_default6 const& /*self*/) + { + r = switch_p(anychar_p) [ + default_p, + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + case_p<'c'>(str_p("bcd")) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + +/////////////////////////////////////////////////////////////////////////////// +// Test the switch_p usage given an actor as the switch condition + struct select_result : public BOOST_SPIRIT_CLASSIC_NS::closure<select_result, int> + { + member1 val; + }; + + struct switch_grammar_actor_default4 + : public grammar<switch_grammar_actor_default4> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_actor_default4 const& /*self*/) + { + using phoenix::arg1; + r = select_p('a', 'b', 'c', 'd')[r.val = arg1] >> + switch_p(r.val) [ + case_p<0>(int_p), + case_p<1>(ch_p(',')), + case_p<2>(str_p("bcd")), + default_p + ]; + } + + rule<ScannerT, select_result::context_t> r; + rule<ScannerT, select_result::context_t> const& + start() const { return r; } + }; + }; + + struct switch_grammar_actor_default5 + : public grammar<switch_grammar_actor_default5> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_actor_default5 const& /*self*/) + { + using phoenix::arg1; + r = select_p('a', 'b', 'c', 'd')[r.val = arg1] >> + switch_p(r.val) [ + case_p<0>(int_p), + case_p<1>(ch_p(',')), + default_p, + case_p<2>(str_p("bcd")) + ]; + } + + rule<ScannerT, select_result::context_t> r; + rule<ScannerT, select_result::context_t> const& + start() const { return r; } + }; + }; + + struct switch_grammar_actor_default6 + : public grammar<switch_grammar_actor_default6> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_actor_default6 const& /*self*/) + { + using phoenix::arg1; + r = select_p('a', 'b', 'c', 'd')[r.val = arg1] >> + switch_p(r.val) [ + default_p, + case_p<0>(int_p), + case_p<1>(ch_p(',')), + case_p<2>(str_p("bcd")) + ]; + } + + rule<ScannerT, select_result::context_t> r; + rule<ScannerT, select_result::context_t> const& + start() const { return r; } + }; + }; + +} // namespace test_grammars + +/////////////////////////////////////////////////////////////////////////////// +namespace tests { + + // Tests for known (to the grammars) sequences + struct check_grammar_known { + + template <typename GrammarT> + void operator()(GrammarT) + { + GrammarT g; + + BOOST_TEST(parse("a1", g).full); + BOOST_TEST(!parse("a,", g).hit); + BOOST_TEST(!parse("abcd", g).hit); + + BOOST_TEST(parse("a 1", g, space_p).full); + BOOST_TEST(!parse("a ,", g, space_p).hit); + BOOST_TEST(!parse("a bcd", g, space_p).hit); + + BOOST_TEST(!parse("b1", g).hit); + BOOST_TEST(parse("b,", g).full); + BOOST_TEST(!parse("bbcd", g).hit); + + BOOST_TEST(!parse("b 1", g, space_p).hit); + BOOST_TEST(parse("b ,", g, space_p).full); + BOOST_TEST(!parse("b bcd", g, space_p).hit); + + BOOST_TEST(!parse("c1", g).hit); + BOOST_TEST(!parse("c,", g).hit); + BOOST_TEST(parse("cbcd", g).full); + + BOOST_TEST(!parse("c 1", g, space_p).hit); + BOOST_TEST(!parse("c ,", g, space_p).hit); + BOOST_TEST(parse("c bcd", g, space_p).full); + } + }; + + // Tests for known (to the grammars) sequences + // Tests for the default branches (without parsers) of the grammars + struct check_grammar_default_plain { + + template <typename GrammarT> + void operator()(GrammarT) + { + GrammarT g; + + BOOST_TEST(parse("d", g).full); + BOOST_TEST(parse(" d", g, space_p).full); // JDG 10-18-2005 removed trailing ' ' to + // avoid post skip problems + } + }; + +} // namespace tests + +int +main() +{ + // Test switch_p parsers containing special (epsilon) default_p case + // branches + typedef boost::mpl::list< + // switch_p syntax + test_grammars::switch_grammar_direct_default4, + test_grammars::switch_grammar_direct_default5, + test_grammars::switch_grammar_direct_default6, + + // switch_p(parser) syntax + test_grammars::switch_grammar_parser_default4, + test_grammars::switch_grammar_parser_default5, + test_grammars::switch_grammar_parser_default6, + + // switch_p(actor) syntax + test_grammars::switch_grammar_actor_default4, + test_grammars::switch_grammar_actor_default5, + test_grammars::switch_grammar_actor_default6 + > default_epsilon_list_t; + + boost::mpl::for_each<default_epsilon_list_t>(tests::check_grammar_known()); + boost::mpl::for_each<default_epsilon_list_t>( + tests::check_grammar_default_plain()); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/switch_tests_general_def.cpp b/src/boost/libs/spirit/classic/test/switch_tests_general_def.cpp new file mode 100644 index 00000000..7abfeb58 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/switch_tests_general_def.cpp @@ -0,0 +1,343 @@ +/*============================================================================= + Copyright (c) 2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> + + +#define BOOST_SPIRIT_SWITCH_CASE_LIMIT 6 +#define BOOST_SPIRIT_SELECT_LIMIT 6 +#define PHOENIX_LIMIT 6 + +//#define BOOST_SPIRIT_DEBUG +#include <boost/mpl/list.hpp> +#include <boost/mpl/for_each.hpp> + +#include <boost/spirit/include/classic_primitives.hpp> +#include <boost/spirit/include/classic_numerics.hpp> +#include <boost/spirit/include/classic_actions.hpp> +#include <boost/spirit/include/classic_operators.hpp> +#include <boost/spirit/include/classic_rule.hpp> +#include <boost/spirit/include/classic_grammar.hpp> +#include <boost/spirit/include/classic_switch.hpp> +#include <boost/spirit/include/classic_select.hpp> +#include <boost/spirit/include/classic_closure.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +namespace test_grammars { + +/////////////////////////////////////////////////////////////////////////////// +// Test the direct switch_p usage (with default_p) + struct switch_grammar_direct_default1 + : public grammar<switch_grammar_direct_default1> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_direct_default1 const& /*self*/) + { + r = switch_p [ + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + case_p<'c'>(str_p("bcd")), + default_p(str_p("default")) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + + struct switch_grammar_direct_default2 + : public grammar<switch_grammar_direct_default2> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_direct_default2 const& /*self*/) + { + r = switch_p [ + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + default_p(str_p("default")), + case_p<'c'>(str_p("bcd")) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + + struct switch_grammar_direct_default3 + : public grammar<switch_grammar_direct_default3> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_direct_default3 const& /*self*/) + { + r = switch_p [ + default_p(str_p("default")), + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + case_p<'c'>(str_p("bcd")) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + +/////////////////////////////////////////////////////////////////////////////// +// Test the switch_p usage given a parser as the switch condition + struct switch_grammar_parser_default1 + : public grammar<switch_grammar_parser_default1> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_parser_default1 const& /*self*/) + { + r = switch_p(anychar_p) [ + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + case_p<'c'>(str_p("bcd")), + default_p(str_p("default")) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + + struct switch_grammar_parser_default2 + : public grammar<switch_grammar_parser_default2> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_parser_default2 const& /*self*/) + { + r = switch_p(anychar_p) [ + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + default_p(str_p("default")), + case_p<'c'>(str_p("bcd")) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + + struct switch_grammar_parser_default3 + : public grammar<switch_grammar_parser_default3> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_parser_default3 const& /*self*/) + { + r = switch_p(anychar_p) [ + default_p(str_p("default")), + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + case_p<'c'>(str_p("bcd")) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + +/////////////////////////////////////////////////////////////////////////////// +// Test the switch_p usage given an actor as the switch condition + struct select_result : public BOOST_SPIRIT_CLASSIC_NS::closure<select_result, int> + { + member1 val; + }; + + /////////////////////////////////////////////////////////////////////////// + struct switch_grammar_actor_default1 + : public grammar<switch_grammar_actor_default1> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_actor_default1 const& /*self*/) + { + using phoenix::arg1; + r = select_p('a', 'b', 'c', 'd')[r.val = arg1] >> + switch_p(r.val) [ + case_p<0>(int_p), + case_p<1>(ch_p(',')), + case_p<2>(str_p("bcd")), + default_p(str_p("default")) + ]; + } + + rule<ScannerT, select_result::context_t> r; + rule<ScannerT, select_result::context_t> const& + start() const { return r; } + }; + }; + + struct switch_grammar_actor_default2 + : public grammar<switch_grammar_actor_default2> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_actor_default2 const& /*self*/) + { + using phoenix::arg1; + r = select_p('a', 'b', 'c', 'd')[r.val = arg1] >> + switch_p(r.val) [ + case_p<0>(int_p), + case_p<1>(ch_p(',')), + default_p(str_p("default")), + case_p<2>(str_p("bcd")) + ]; + } + + rule<ScannerT, select_result::context_t> r; + rule<ScannerT, select_result::context_t> const& + start() const { return r; } + }; + }; + + struct switch_grammar_actor_default3 + : public grammar<switch_grammar_actor_default3> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_actor_default3 const& /*self*/) + { + using phoenix::arg1; + r = select_p('a', 'b', 'c', 'd')[r.val = arg1] >> + switch_p(r.val) [ + default_p(str_p("default")), + case_p<0>(int_p), + case_p<1>(ch_p(',')), + case_p<2>(str_p("bcd")) + ]; + } + + rule<ScannerT, select_result::context_t> r; + rule<ScannerT, select_result::context_t> const& + start() const { return r; } + }; + }; + +} // namespace test_grammars + +/////////////////////////////////////////////////////////////////////////////// +namespace tests { + + // Tests for known (to the grammars) sequences + struct check_grammar_known { + + template <typename GrammarT> + void operator()(GrammarT) + { + GrammarT g; + + BOOST_TEST(parse("a1", g).full); + BOOST_TEST(!parse("a,", g).hit); + BOOST_TEST(!parse("abcd", g).hit); + + BOOST_TEST(parse("a 1", g, space_p).full); + BOOST_TEST(!parse("a ,", g, space_p).hit); + BOOST_TEST(!parse("a bcd", g, space_p).hit); + + BOOST_TEST(!parse("b1", g).hit); + BOOST_TEST(parse("b,", g).full); + BOOST_TEST(!parse("bbcd", g).hit); + + BOOST_TEST(!parse("b 1", g, space_p).hit); + BOOST_TEST(parse("b ,", g, space_p).full); + BOOST_TEST(!parse("b bcd", g, space_p).hit); + + BOOST_TEST(!parse("c1", g).hit); + BOOST_TEST(!parse("c,", g).hit); + BOOST_TEST(parse("cbcd", g).full); + + BOOST_TEST(!parse("c 1", g, space_p).hit); + BOOST_TEST(!parse("c ,", g, space_p).hit); + BOOST_TEST(parse("c bcd", g, space_p).full); + } + }; + + // Tests for unknown (to the grammar) sequences + struct check_grammar_unknown_default { + + template <typename GrammarT> + void operator()(GrammarT) + { + GrammarT g; + + BOOST_TEST(!parse("d1", g).hit); + BOOST_TEST(!parse("d,", g).hit); + BOOST_TEST(!parse("dbcd", g).hit); + + BOOST_TEST(!parse("d 1", g, space_p).hit); + BOOST_TEST(!parse("d ,", g, space_p).hit); + BOOST_TEST(!parse("d bcd", g, space_p).hit); + } + }; + + // Tests for the default branches (with parsers) of the grammars + struct check_grammar_default { + + template <typename GrammarT> + void operator()(GrammarT) + { + GrammarT g; + + BOOST_TEST(parse("ddefault", g).full); + BOOST_TEST(parse("d default", g, space_p).full); + } + }; + +} // namespace tests + +int +main() +{ + // Test switch_p parsers containing general default_p(...) case branches + typedef boost::mpl::list< + // switch_p syntax + test_grammars::switch_grammar_direct_default1, + test_grammars::switch_grammar_direct_default2, + test_grammars::switch_grammar_direct_default3, + + // switch_p(parser) syntax + test_grammars::switch_grammar_parser_default1, + test_grammars::switch_grammar_parser_default2, + test_grammars::switch_grammar_parser_default3, + + // switch_p(actor) syntax + test_grammars::switch_grammar_actor_default1, + test_grammars::switch_grammar_actor_default2, + test_grammars::switch_grammar_actor_default3 + > default_list_t; + + boost::mpl::for_each<default_list_t>(tests::check_grammar_known()); + boost::mpl::for_each<default_list_t>(tests::check_grammar_unknown_default()); + boost::mpl::for_each<default_list_t>(tests::check_grammar_default()); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/switch_tests_single.cpp b/src/boost/libs/spirit/classic/test/switch_tests_single.cpp new file mode 100644 index 00000000..780f4195 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/switch_tests_single.cpp @@ -0,0 +1,350 @@ +/*============================================================================= + Copyright (c) 2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> + + +#define BOOST_SPIRIT_SWITCH_CASE_LIMIT 6 +#define BOOST_SPIRIT_SELECT_LIMIT 6 +#define PHOENIX_LIMIT 6 + +//#define BOOST_SPIRIT_DEBUG +#include <boost/mpl/list.hpp> +#include <boost/mpl/for_each.hpp> + +#include <boost/spirit/include/classic_primitives.hpp> +#include <boost/spirit/include/classic_numerics.hpp> +#include <boost/spirit/include/classic_actions.hpp> +#include <boost/spirit/include/classic_operators.hpp> +#include <boost/spirit/include/classic_rule.hpp> +#include <boost/spirit/include/classic_grammar.hpp> +#include <boost/spirit/include/classic_switch.hpp> +#include <boost/spirit/include/classic_select.hpp> +#include <boost/spirit/include/classic_closure.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +namespace test_grammars { + +/////////////////////////////////////////////////////////////////////////////// +// Test the direct switch_p usage + struct switch_grammar_direct_single + : public grammar<switch_grammar_direct_single> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_direct_single const& /*self*/) + { + r = switch_p [ + case_p<'a'>(int_p) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + + struct switch_grammar_direct_default_single1 + : public grammar<switch_grammar_direct_default_single1> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_direct_default_single1 const& /*self*/) + { + r = switch_p [ + default_p(str_p("default")) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + + struct switch_grammar_direct_default_single2 + : public grammar<switch_grammar_direct_default_single2> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_direct_default_single2 const& /*self*/) + { + r = switch_p [ + default_p + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + +/////////////////////////////////////////////////////////////////////////////// +// Test the switch_p usage given a parser as the switch condition + struct switch_grammar_parser_single + : public grammar<switch_grammar_parser_single> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_parser_single const& /*self*/) + { + r = switch_p(anychar_p) [ + case_p<'a'>(int_p) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + + struct switch_grammar_parser_default_single1 + : public grammar<switch_grammar_parser_default_single1> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_parser_default_single1 const& /*self*/) + { + r = switch_p(anychar_p) [ + default_p(str_p("default")) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + + struct switch_grammar_parser_default_single2 + : public grammar<switch_grammar_parser_default_single2> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_parser_default_single2 const& /*self*/) + { + r = switch_p(anychar_p) [ + default_p + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + +/////////////////////////////////////////////////////////////////////////////// +// Test the switch_p usage given an actor as the switch condition + struct select_result : public BOOST_SPIRIT_CLASSIC_NS::closure<select_result, int> + { + member1 val; + }; + + struct switch_grammar_actor_single + : public grammar<switch_grammar_actor_single> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_actor_single const& /*self*/) + { + using phoenix::arg1; + r = select_p('a')[r.val = arg1] >> + switch_p(r.val) [ + case_p<0>(int_p) + ]; + } + + rule<ScannerT, select_result::context_t> r; + rule<ScannerT, select_result::context_t> const& + start() const { return r; } + }; + }; + + struct switch_grammar_actor_default_single1 + : public grammar<switch_grammar_actor_default_single1> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_actor_default_single1 const& /*self*/) + { + using phoenix::arg1; + r = select_p('d')[r.val = arg1] >> + switch_p(r.val) [ + default_p(str_p("default")) + ]; + } + + rule<ScannerT, select_result::context_t> r; + rule<ScannerT, select_result::context_t> const& + start() const { return r; } + }; + }; + + struct switch_grammar_actor_default_single2 + : public grammar<switch_grammar_actor_default_single2> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_actor_default_single2 const& /*self*/) + { + using phoenix::arg1; + r = select_p('d')[r.val = arg1] >> + switch_p(r.val) [ + default_p + ]; + } + + rule<ScannerT, select_result::context_t> r; + rule<ScannerT, select_result::context_t> const& + start() const { return r; } + }; + }; + +} // namespace test_grammars + +/////////////////////////////////////////////////////////////////////////////// +namespace tests { + + // Tests for known (to the grammars) sequences + struct check_grammar_unknown { + + template <typename GrammarT> + void operator()(GrammarT) + { + GrammarT g; + + BOOST_TEST(!parse("a1", g).hit); + BOOST_TEST(!parse("a,", g).hit); + BOOST_TEST(!parse("abcd", g).hit); + + BOOST_TEST(!parse("a 1", g, space_p).hit); + BOOST_TEST(!parse("a ,", g, space_p).hit); + BOOST_TEST(!parse("a bcd", g, space_p).hit); + + BOOST_TEST(!parse("b1", g).hit); + BOOST_TEST(!parse("b,", g).hit); + BOOST_TEST(!parse("bbcd", g).hit); + + BOOST_TEST(!parse("b 1", g, space_p).hit); + BOOST_TEST(!parse("b ,", g, space_p).hit); + BOOST_TEST(!parse("b bcd", g, space_p).hit); + + BOOST_TEST(!parse("c1", g).hit); + BOOST_TEST(!parse("c,", g).hit); + BOOST_TEST(!parse("cbcd", g).hit); + + BOOST_TEST(!parse("c 1", g, space_p).hit); + BOOST_TEST(!parse("c ,", g, space_p).hit); + BOOST_TEST(!parse("c bcd", g, space_p).hit); + } + }; + + // Tests for the default branches (with parsers) of the grammars + struct check_grammar_default { + + template <typename GrammarT> + void operator()(GrammarT) + { + GrammarT g; + + BOOST_TEST(parse("ddefault", g).full); + BOOST_TEST(parse("d default", g, space_p).full); + } + }; + + // Tests for the default branches (without parsers) of the grammars + struct check_grammar_default_plain { + + template <typename GrammarT> + void operator()(GrammarT) + { + GrammarT g; + + BOOST_TEST(parse("d", g).full); + BOOST_TEST(parse(" d", g, space_p).full); // JDG 10-18-2005 removed trailing ' ' to + // avoid post skip problems + } + }; + + // Tests grammars with a single case_p branch + struct check_grammar_single { + + template <typename GrammarT> + void operator()(GrammarT) + { + GrammarT g; + + BOOST_TEST(parse("a1", g).full); + BOOST_TEST(!parse("a,", g).hit); + BOOST_TEST(!parse("abcd", g).hit); + + BOOST_TEST(parse("a 1", g, space_p).full); + BOOST_TEST(!parse("a ,", g, space_p).hit); + BOOST_TEST(!parse("a bcd", g, space_p).hit); + + BOOST_TEST(!parse("b1", g).hit); + BOOST_TEST(!parse("b,", g).hit); + BOOST_TEST(!parse("bbcd", g).hit); + + BOOST_TEST(!parse("b 1", g, space_p).hit); + BOOST_TEST(!parse("b ,", g, space_p).hit); + BOOST_TEST(!parse("b bcd", g, space_p).hit); + + BOOST_TEST(!parse("c1", g).hit); + BOOST_TEST(!parse("c,", g).hit); + BOOST_TEST(!parse("cbcd", g).hit); + + BOOST_TEST(!parse("c 1", g, space_p).hit); + BOOST_TEST(!parse("c ,", g, space_p).hit); + BOOST_TEST(!parse("c bcd", g, space_p).hit); + } + }; + +} // namespace tests + +int +main() +{ + // Test switch_p with a single case_p branch + typedef boost::mpl::list< + test_grammars::switch_grammar_direct_single, + test_grammars::switch_grammar_parser_single, + test_grammars::switch_grammar_actor_single + > single_list_t; + + boost::mpl::for_each<single_list_t>(tests::check_grammar_single()); + + typedef boost::mpl::list< + test_grammars::switch_grammar_direct_default_single1, + test_grammars::switch_grammar_parser_default_single1, + test_grammars::switch_grammar_actor_default_single1 + > default_single_t; + + boost::mpl::for_each<default_single_t>(tests::check_grammar_default()); + boost::mpl::for_each<default_single_t>(tests::check_grammar_unknown()); + + typedef boost::mpl::list< + test_grammars::switch_grammar_direct_default_single2, + test_grammars::switch_grammar_parser_default_single2, + test_grammars::switch_grammar_actor_default_single2 + > default_plain_single_t; + + boost::mpl::for_each<default_plain_single_t>( + tests::check_grammar_default_plain()); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/switch_tests_wo_default.cpp b/src/boost/libs/spirit/classic/test/switch_tests_wo_default.cpp new file mode 100644 index 00000000..2671a09f --- /dev/null +++ b/src/boost/libs/spirit/classic/test/switch_tests_wo_default.cpp @@ -0,0 +1,202 @@ +/*============================================================================= + Copyright (c) 2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <boost/detail/lightweight_test.hpp> + + +#define BOOST_SPIRIT_SWITCH_CASE_LIMIT 6 +#define BOOST_SPIRIT_SELECT_LIMIT 6 +#define PHOENIX_LIMIT 6 + +//#define BOOST_SPIRIT_DEBUG +#include <boost/mpl/list.hpp> +#include <boost/mpl/for_each.hpp> + +#include <boost/spirit/include/classic_primitives.hpp> +#include <boost/spirit/include/classic_numerics.hpp> +#include <boost/spirit/include/classic_actions.hpp> +#include <boost/spirit/include/classic_operators.hpp> +#include <boost/spirit/include/classic_rule.hpp> +#include <boost/spirit/include/classic_grammar.hpp> +#include <boost/spirit/include/classic_switch.hpp> +#include <boost/spirit/include/classic_select.hpp> +#include <boost/spirit/include/classic_closure.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +namespace test_grammars { + +/////////////////////////////////////////////////////////////////////////////// +// Test the direct switch_p usage + struct switch_grammar_direct : public grammar<switch_grammar_direct> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_direct const& /*self*/) + { + r = switch_p [ + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + case_p<'c'>(str_p("bcd")), + case_p<'d'>(eps_p) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + +/////////////////////////////////////////////////////////////////////////////// +// Test the switch_p usage given a parser as the switch condition + struct switch_grammar_parser : public grammar<switch_grammar_parser> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_parser const& /*self*/) + { + r = switch_p(anychar_p) [ + case_p<'a'>(int_p), + case_p<'b'>(ch_p(',')), + case_p<'c'>(str_p("bcd")), + case_p<'d'>(eps_p) + ]; + } + + rule<ScannerT> r; + rule<ScannerT> const& start() const { return r; } + }; + }; + +/////////////////////////////////////////////////////////////////////////////// +// Test the switch_p usage given an actor as the switch condition + struct select_result : public BOOST_SPIRIT_CLASSIC_NS::closure<select_result, int> + { + member1 val; + }; + + struct switch_grammar_actor : public grammar<switch_grammar_actor> + { + template <typename ScannerT> + struct definition + { + definition(switch_grammar_actor const& /*self*/) + { + using phoenix::arg1; + r = select_p('a', 'b', 'c', 'd')[r.val = arg1] >> + switch_p(r.val) [ + case_p<0>(int_p), + case_p<1>(ch_p(',')), + case_p<2>(str_p("bcd")), + case_p<3>(eps_p) + ]; + } + + rule<ScannerT, select_result::context_t> r; + rule<ScannerT, select_result::context_t> const& + start() const { return r; } + }; + }; + +} // namespace test_grammars + +/////////////////////////////////////////////////////////////////////////////// +namespace tests { + + // Tests for known (to the grammars) sequences + struct check_grammar_known { + + template <typename GrammarT> + void operator()(GrammarT) + { + GrammarT g; + + BOOST_TEST(parse("a1", g).full); + BOOST_TEST(!parse("a,", g).hit); + BOOST_TEST(!parse("abcd", g).hit); + BOOST_TEST(!parse("a", g).hit); + + BOOST_TEST(parse("a 1", g, space_p).full); + BOOST_TEST(!parse("a ,", g, space_p).hit); + BOOST_TEST(!parse("a bcd", g, space_p).hit); + BOOST_TEST(!parse("a ", g, space_p).hit); + + BOOST_TEST(!parse("b1", g).hit); + BOOST_TEST(parse("b,", g).full); + BOOST_TEST(!parse("bbcd", g).hit); + BOOST_TEST(!parse("b", g).hit); + + BOOST_TEST(!parse("b 1", g, space_p).hit); + BOOST_TEST(parse("b ,", g, space_p).full); + BOOST_TEST(!parse("b bcd", g, space_p).hit); + BOOST_TEST(!parse("b ", g, space_p).hit); + + BOOST_TEST(!parse("c1", g).hit); + BOOST_TEST(!parse("c,", g).hit); + BOOST_TEST(parse("cbcd", g).full); + BOOST_TEST(!parse("c", g).hit); + + BOOST_TEST(!parse("c 1", g, space_p).hit); + BOOST_TEST(!parse("c ,", g, space_p).hit); + BOOST_TEST(parse("c bcd", g, space_p).full); + BOOST_TEST(!parse("c ", g, space_p).hit); + + BOOST_TEST(parse("d1", g).hit); + BOOST_TEST(parse("d,", g).hit); + BOOST_TEST(parse("dbcd", g).hit); + BOOST_TEST(parse("d", g).full); + + BOOST_TEST(parse("d 1", g, space_p).hit); + BOOST_TEST(parse("d ,", g, space_p).hit); + BOOST_TEST(parse("d bcd", g, space_p).hit); + BOOST_TEST(parse(" d", g, space_p).full); // JDG 10-18-2005 removed trailing ' ' to + // avoid post skip problems + + BOOST_TEST(parse(" a 1 b , c bcd d", *g, space_p).full); + // JDG 10-18-2005 removed trailing ' ' to avoid post skip problems + } + }; + + // Tests for unknown (to the grammar) sequences + struct check_grammar_unknown_default { + + template <typename GrammarT> + void operator()(GrammarT) + { + GrammarT g; + + BOOST_TEST(!parse("x1", g).hit); + BOOST_TEST(!parse("x,", g).hit); + BOOST_TEST(!parse("xbcd", g).hit); + + BOOST_TEST(!parse("x 1", g, space_p).hit); + BOOST_TEST(!parse("x ,", g, space_p).hit); + BOOST_TEST(!parse("x bcd", g, space_p).hit); + } + }; + +} // namespace tests + +int +main() +{ + // Test switch_p without any default_p case branches + typedef boost::mpl::list< + test_grammars::switch_grammar_direct, + test_grammars::switch_grammar_parser, + test_grammars::switch_grammar_actor + > grammar_list_t; + + boost::mpl::for_each<grammar_list_t>(tests::check_grammar_known()); + boost::mpl::for_each<grammar_list_t>(tests::check_grammar_unknown_default()); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/symbols_add_null.cpp b/src/boost/libs/spirit/classic/test/symbols_add_null.cpp new file mode 100644 index 00000000..12597770 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/symbols_add_null.cpp @@ -0,0 +1,79 @@ +/*============================================================================= + Copyright (c) 2004 Joao Abecasis + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +// This test requires NDEBUG to be undefined, because it depends on +// BOOST_SPIRIT_ASSERT throwing an exception. +#ifdef NDEBUG +# undef NDEBUG +#endif + +#include <boost/config.hpp> +#include <stdexcept> + +#define BOOST_SPIRIT_ASSERT_EXCEPTION ::spirit_exception + +struct spirit_exception : std::exception +{ + spirit_exception(char const * msg) + : message(msg) + { + } + ~spirit_exception() BOOST_NOEXCEPT_OR_NOTHROW {} + + char const* what() const BOOST_NOEXCEPT_OR_NOTHROW { return message; } + + char const * message; +}; + +#include <boost/spirit/include/classic_scanner.hpp> +#include <boost/spirit/home/classic/symbols/impl/tst.ipp> +#include <boost/utility/addressof.hpp> + +#include <boost/detail/lightweight_test.hpp> + +typedef char char_type; +typedef char const * iterator; + +char_type data_[] = "whatever"; + +iterator begin = data_; +iterator end = data_ + + sizeof(data_)/sizeof(char_type); // Yes, this is an intentional bug ;) + +char_type data2_[] = "\0something"; +iterator begin2 = data2_; +iterator end2 = data2_ + sizeof(data2_)/sizeof(char_type) - 1; + +int main() +{ + typedef BOOST_SPIRIT_CLASSIC_NS::impl::tst<void *, char_type> symbols; + + symbols symbols_; + + try + { + // It is not ok to add strings containing the null character. + symbols_.add(begin, end, (void*) boost::addressof(symbols_)); + BOOST_TEST(0); + } + catch (spirit_exception &/*e*/) + { + } + + try + { + // It is not ok to add strings containing the null character. + symbols_.add(begin2, end2, (void*) boost::addressof(symbols_)); + BOOST_TEST(0); + } + catch (spirit_exception &/*e*/) + { + } + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/symbols_find_null.cpp b/src/boost/libs/spirit/classic/test/symbols_find_null.cpp new file mode 100644 index 00000000..bf5a657b --- /dev/null +++ b/src/boost/libs/spirit/classic/test/symbols_find_null.cpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2004 Joao Abecasis + http://spirit.sourceforge.net/ + + 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/include/classic_scanner.hpp> +#include <boost/spirit/home/classic/symbols/impl/tst.ipp> +#include <boost/utility/addressof.hpp> + +typedef char char_type; +typedef char const * iterator; + +char_type data_[] = "whatever"; + +iterator begin = data_; +iterator end = data_ + + sizeof(data_)/sizeof(char_type); // Yes, this is an intencional bug ;) + +int main() +{ + typedef BOOST_SPIRIT_CLASSIC_NS::scanner<> scanner; + typedef BOOST_SPIRIT_CLASSIC_NS::impl::tst<void *, char_type> symbols; + + symbols symbols_; + + symbols_.add(begin, end - 1, (void*) boost::addressof(symbols_)); + + // The symbol table parser should not choke on input containing the null + // character. + symbols_.find(scanner(begin, end)); +} diff --git a/src/boost/libs/spirit/classic/test/symbols_tests.cpp b/src/boost/libs/spirit/classic/test/symbols_tests.cpp new file mode 100644 index 00000000..a0bcc265 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/symbols_tests.cpp @@ -0,0 +1,318 @@ +/*============================================================================= + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + 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 <iostream> +#include <string> +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_symbols.hpp> +#include <boost/detail/lightweight_test.hpp> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// + +template <typename IteratorT> +bool +equal(IteratorT p, IteratorT q) +{ + while (*p && *p == *q) + { + ++p; + ++q; + } + return *p == *q; +} + +template <class SymbolsT, typename CharT> +void +docheck +( + SymbolsT const &sym, + CharT const *candidate, + bool hit, + CharT const *result, + int length +) +{ + parse_info<CharT const*> info = parse(candidate, sym); + +#define correctly_matched hit == info.hit +#define correct_match_length unsigned(length) == info.length +#define correct_tail equal(candidate + (hit?1:0)*length, result) + + BOOST_TEST(correctly_matched); + + if (hit) + { + BOOST_TEST(correct_match_length); + BOOST_TEST(correct_tail); + } + else + { + BOOST_TEST(correct_tail); + } +} + +template <typename T> +struct store_action +{ + store_action(T const &v) : value(v) {} + void operator()(T &v) const { v = value; } +private: + T const value; +}; + +template <typename T> +store_action<T> +store(T const &v) +{ + return v; +} + +template <typename T> +struct check_action +{ + check_action(T const &v) : value(v) {} + +#define correct_value_stored (v==value) + void operator()(T const &v) const { BOOST_TEST(correct_value_stored); } +private: + T const value; +}; + +template <typename T> +check_action<T> +docheck(T const &v) +{ + return v; +} + + +static void +default_constructible() +{ // this actually a compile time test + symbols<> ns1; + symbols<int, wchar_t> ws1; + symbols<std::string, char> ns2; + symbols<std::string, wchar_t> ws2; + + (void)ns1; (void)ws1; (void)ns2; (void)ws2; +} + +static void +narrow_match_tests() +{ + symbols<> sym; + sym = "pineapple", "orange", "banana", "applepie", "apple"; + + docheck(sym, "pineapple", true, "", 9); + docheck(sym, "orange", true, "", 6); + docheck(sym, "banana", true, "", 6); + docheck(sym, "apple", true, "", 5); + docheck(sym, "pizza", false, "pizza", -1); + docheck(sym, "steak", false, "steak", -1); + docheck(sym, "applepie", true, "", 8); + docheck(sym, "bananarama", true, "rama", 6); + docheck(sym, "applet", true, "t", 5); + docheck(sym, "applepi", true, "pi", 5); + docheck(sym, "appl", false, "appl", -1); + + docheck(sym, "pineapplez", true, "z", 9); + docheck(sym, "orangez", true, "z", 6); + docheck(sym, "bananaz", true, "z", 6); + docheck(sym, "applez", true, "z", 5); + docheck(sym, "pizzaz", false, "pizzaz", -1); + docheck(sym, "steakz", false, "steakz", -1); + docheck(sym, "applepiez", true, "z", 8); + docheck(sym, "bananaramaz", true, "ramaz", 6); + docheck(sym, "appletz", true, "tz", 5); + docheck(sym, "applepix", true, "pix", 5); +} + +static void +narrow_copy_ctor_tests() +{ + symbols<> sym; + sym = "pineapple", "orange", "banana", "applepie", "apple"; + + symbols<> sym2(sym); + docheck(sym2, "pineapple", true, "", 9); + docheck(sym2, "pizza", false, "pizza", -1); + docheck(sym2, "bananarama", true, "rama", 6); +} + +static void +narrow_assigment_operator_tests() +{ + symbols<> sym; + sym = "pineapple", "orange", "banana", "applepie", "apple"; + + symbols<> sym2; + sym2 = sym; + + docheck(sym2, "pineapple", true, "", 9); + docheck(sym2, "pizza", false, "pizza", -1); + docheck(sym2, "bananarama", true, "rama", 6); +} + +static void +narrow_value_tests() +{ // also tests the add member functions + symbols<> sym; + + sym = "orange", "banana"; + sym.add("pineapple",1234); + sym.add("lemon"); + + parse("orange", sym[store(12345)]); + parse("orange", sym[docheck(12345)]); + parse("pineapple", sym[docheck(1234)]); + parse("banana", sym[docheck(int())]); + parse("lemon", sym[docheck(int())]); +} + +static void +narrow_free_functions_tests() +{ + symbols<> sym; + +#define add_returned_non_null_value (res!=0) +#define add_returned_null (res==0) +#define find_returned_non_null_value (res!=0) +#define find_returned_null (res==0) + + int *res = add(sym,"pineapple"); + BOOST_TEST(add_returned_non_null_value); + res = add(sym,"pineapple"); + BOOST_TEST(add_returned_null); + + res = find(sym, "pineapple"); + BOOST_TEST(find_returned_non_null_value); + res = find(sym, "banana"); + BOOST_TEST(find_returned_null); +} + +static void +wide_match_tests() +{ + symbols<int, wchar_t> sym; + sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple"; + + docheck(sym, L"pineapple", true, L"", 9); + docheck(sym, L"orange", true, L"", 6); + docheck(sym, L"banana", true, L"", 6); + docheck(sym, L"apple", true, L"", 5); + docheck(sym, L"pizza", false, L"pizza", -1); + docheck(sym, L"steak", false, L"steak", -1); + docheck(sym, L"applepie", true, L"", 8); + docheck(sym, L"bananarama", true, L"rama", 6); + docheck(sym, L"applet", true, L"t", 5); + docheck(sym, L"applepi", true, L"pi", 5); + docheck(sym, L"appl", false, L"appl", -1); + + docheck(sym, L"pineapplez", true, L"z", 9); + docheck(sym, L"orangez", true, L"z", 6); + docheck(sym, L"bananaz", true, L"z", 6); + docheck(sym, L"applez", true, L"z", 5); + docheck(sym, L"pizzaz", false, L"pizzaz", -1); + docheck(sym, L"steakz", false, L"steakz", -1); + docheck(sym, L"applepiez", true, L"z", 8); + docheck(sym, L"bananaramaz", true, L"ramaz", 6); + docheck(sym, L"appletz", true, L"tz", 5); + docheck(sym, L"applepix", true, L"pix", 5); +} + +static void +wide_copy_ctor_tests() +{ + symbols<int, wchar_t> sym; + sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple"; + + symbols<int, wchar_t> sym2(sym); + docheck(sym2, L"pineapple", true, L"", 9); + docheck(sym2, L"pizza", false, L"pizza", -1); + docheck(sym2, L"bananarama", true, L"rama", 6); +} + +static void +wide_assigment_operator_tests() +{ + symbols<int, wchar_t> sym; + sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple"; + + symbols<int, wchar_t> sym2; + sym2 = sym; + + docheck(sym2, L"pineapple", true, L"", 9); + docheck(sym2, L"pizza", false, L"pizza", -1); + docheck(sym2, L"bananarama", true, L"rama", 6); +} + +static void +wide_value_tests() +{ // also tests the add member functions + symbols<int, wchar_t> sym; + + sym = L"orange", L"banana"; + sym.add(L"pineapple",1234); + sym.add(L"lemon"); + + parse(L"orange", sym[store(12345)]); + parse(L"orange", sym[docheck(12345)]); + parse(L"pineapple", sym[docheck(1234)]); + parse(L"banana", sym[docheck(int())]); + parse(L"lemon", sym[docheck(int())]); +} + +static void +wide_free_functions_tests() +{ + symbols<int, wchar_t> sym; + + int *res = add(sym,L"pineapple"); + BOOST_TEST(add_returned_non_null_value); + res = add(sym,L"pineapple"); + BOOST_TEST(add_returned_null); + + res = find(sym, L"pineapple"); + BOOST_TEST(find_returned_non_null_value); + res = find(sym, L"banana"); + BOOST_TEST(find_returned_null); +} + +static +void free_add_find_functions_tests() +{ + symbols<> sym; + BOOST_TEST(*add(sym, "a", 0) == 0); + BOOST_TEST(*add(sym, "a2", 1) == 1); + BOOST_TEST(find(sym, "a2")); + BOOST_TEST(find(sym, "a")); +} + +int +main() +{ + default_constructible(); + narrow_match_tests(); + narrow_copy_ctor_tests(); + narrow_assigment_operator_tests(); + narrow_value_tests(); + narrow_free_functions_tests(); + wide_match_tests(); + wide_copy_ctor_tests(); + wide_assigment_operator_tests(); + wide_value_tests(); + wide_free_functions_tests(); + free_add_find_functions_tests(); + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/threads_disabled_compile.cpp b/src/boost/libs/spirit/classic/test/threads_disabled_compile.cpp new file mode 100644 index 00000000..208cd112 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/threads_disabled_compile.cpp @@ -0,0 +1,19 @@ +/*============================================================================= + Copyright (c) 2017 Nikita Kniazev + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +// Spirit should not include any Boost.Thread header until user explicitly +// requested threadsafe support with BOOST_SPIRIT_THREADSAFE defined. + +#undef BOOST_SPIRIT_THREADSAFE +#ifndef BOOST_DISABLE_THREADS +# define BOOST_DISABLE_THREADS +#endif +#include <boost/spirit/include/classic.hpp> + +int main() { return 0; } diff --git a/src/boost/libs/spirit/classic/test/traverse_tests.cpp b/src/boost/libs/spirit/classic/test/traverse_tests.cpp new file mode 100644 index 00000000..17512667 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/traverse_tests.cpp @@ -0,0 +1,517 @@ +/*============================================================================= + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// Traversal tests +// +/////////////////////////////////////////////////////////////////////////////// + +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include <string> +#include <vector> + +#include <boost/config.hpp> +#include <boost/static_assert.hpp> + +#ifdef BOOST_NO_STRINGSTREAM +#include <strstream> +#define OSSTREAM std::ostrstream +std::string GETSTRING(std::ostrstream& ss) +{ + ss << ends; + std::string rval = ss.str(); + ss.freeze(false); + return rval; +} +#else +#include <sstream> +#define GETSTRING(ss) ss.str() +#define OSSTREAM std::ostringstream +#endif + +#ifndef BOOST_SPIRIT_DEBUG +#define BOOST_SPIRIT_DEBUG // needed for parser_name functions +#endif + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> +#include <boost/spirit/include/classic_meta.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +typedef ref_value_actor<char, assign_action> assign_actor; + +/////////////////////////////////////////////////////////////////////////////// +// +// Test identity transformation +// +/////////////////////////////////////////////////////////////////////////////// +void +traverse_identity_tests() +{ + // test type equality + typedef sequence<chlit<char>, chlit<char> > test_sequence1_t; + BOOST_STATIC_ASSERT(( + ::boost::is_same< + test_sequence1_t, + post_order::result<identity_transform, test_sequence1_t>::type + >::value + )); + + // test (rough) runtime equality + BOOST_TEST( + parse( + "ab", + post_order::traverse(identity_transform(), ch_p('a') >> 'b') + ).full + ); + BOOST_TEST( + !parse( + "ba", + post_order::traverse(identity_transform(), ch_p('a') >> 'b') + ).hit + ); + + /////////////////////////////////////////////////////////////////////////// + BOOST_TEST( + !parse( + "cba", + post_order::traverse( + identity_transform(), + ch_p('a') >> 'b' >> 'c' + ) + ).hit + ); + +/////////////////////////////////////////////////////////////////////////////// +// Test more complex sequences +char c; + +/////////////////////////////////////////////////////////////////////////////// +// test: ((a >> b) >> c) >> d + typedef + sequence< + sequence< + sequence< + kleene_star<chlit<> >, + action<chlit<>, assign_actor> + >, + chlit<> + >, + optional<chlit<> > + > test_sequence2_t; + + BOOST_STATIC_ASSERT(( + ::boost::is_same< + test_sequence2_t, + post_order::result<identity_transform, test_sequence2_t>::type + >::value + )); + + c = 0; + BOOST_TEST( + parse( + "aabcd", + post_order::traverse( + identity_transform(), + ((*ch_p('a') >> ch_p('b')[assign_a(c)]) >> 'c') >> !ch_p('d') + ) + ).full + ); + BOOST_TEST(c == 'b'); + +/////////////////////////////////////////////////////////////////////////////// +// test: (a >> (b >> c)) >> d + typedef + sequence< + sequence< + kleene_star<chlit<> >, + sequence< + action<chlit<>, assign_actor>, + chlit<> + > + >, + optional<chlit<char> > + > test_sequence3_t; + + BOOST_STATIC_ASSERT(( + ::boost::is_same< + test_sequence3_t, + post_order::result<identity_transform, test_sequence3_t>::type + >::value + )); + + c = 0; + BOOST_TEST( + parse( + "aabcd", + post_order::traverse( + identity_transform(), + (*ch_p('a') >> (ch_p('b')[assign_a(c)] >> 'c')) >> !ch_p('d') + ) + ).full + ); + BOOST_TEST(c == 'b'); + +/////////////////////////////////////////////////////////////////////////////// +// test: a >> (b >> (c >> d)) + typedef + sequence< + kleene_star<chlit<> >, + sequence< + action<chlit<>, assign_actor>, + sequence< + chlit<>, + optional<chlit<> > + > + > + > test_sequence4_t; + + BOOST_STATIC_ASSERT(( + ::boost::is_same< + test_sequence4_t, + post_order::result<identity_transform, test_sequence4_t>::type + >::value + )); + + c = 0; + BOOST_TEST( + parse( + "aabcd", + post_order::traverse( + identity_transform(), + *ch_p('a') >> (ch_p('b')[assign_a(c)] >> ('c' >> !ch_p('d'))) + ) + ).full + ); + BOOST_TEST(c == 'b'); + +/////////////////////////////////////////////////////////////////////////////// +// test: a >> ((b >> c) >> d) + typedef + sequence< + kleene_star<chlit<> >, + sequence< + sequence< + action<chlit<>, assign_actor>, + chlit<> + >, + optional<chlit<> > + > + > test_sequence5_t; + + BOOST_STATIC_ASSERT(( + ::boost::is_same< + test_sequence5_t, + post_order::result<identity_transform, test_sequence5_t>::type + >::value + )); + + c = 0; + BOOST_TEST( + parse( + "aabcd", + post_order::traverse( + identity_transform(), + *ch_p('a') >> ((ch_p('b')[assign_a(c)] >> 'c') >> !ch_p('d')) + ) + ).full + ); + BOOST_TEST(c == 'b'); + +/////////////////////////////////////////////////////////////////////////////// +// test: (a >> b) >> (c >> d) + typedef + sequence< + sequence< + kleene_star<chlit<> >, + action<chlit<>, assign_actor> + >, + sequence< + chlit<>, + optional<chlit<> > + > + > test_sequence6_t; + + BOOST_STATIC_ASSERT(( + ::boost::is_same< + test_sequence6_t, + post_order::result<identity_transform, test_sequence6_t>::type + >::value + )); + + c = 0; + BOOST_TEST( + parse( + "aabcd", + post_order::traverse( + identity_transform(), + (*ch_p('a') >> ch_p('b')[assign_a(c)]) >> ('c' >> !ch_p('d')) + ) + ).full + ); + BOOST_TEST(c == 'b'); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// The following is a tracing identity_transform traverse metafunction +// +/////////////////////////////////////////////////////////////////////////////// + +class trace_identity_transform +: public transform_policies<trace_identity_transform> { + +public: + typedef trace_identity_transform self_t; + typedef transform_policies<trace_identity_transform> base_t; + + template <typename ParserT, typename EnvT> + typename parser_traversal_plain_result<self_t, ParserT, EnvT>::type + generate_plain(ParserT const &parser_, EnvT const &env) const + { + OSSTREAM strout; + strout + << EnvT::node + << ": plain (" + << EnvT::level << ", " + << EnvT::index + << "): " + << parser_name(parser_); + traces.push_back(GETSTRING(strout)); + + return this->base_t::generate_plain(parser_, env); + } + + template <typename UnaryT, typename SubjectT, typename EnvT> + typename parser_traversal_unary_result<self_t, UnaryT, SubjectT, EnvT>::type + generate_unary(UnaryT const &unary_, SubjectT const &subject_, + EnvT const &env) const + { + OSSTREAM strout; + strout + << EnvT::node << ": unary (" + << EnvT::level + << "): " + << parser_name(unary_); + traces.push_back(GETSTRING(strout)); + + return this->base_t::generate_unary(unary_, subject_, env); + } + + template <typename ActionT, typename SubjectT, typename EnvT> + typename parser_traversal_action_result<self_t, ActionT, SubjectT, EnvT>::type + generate_action(ActionT const &action_, SubjectT const &subject_, + EnvT const &env) const + { + OSSTREAM strout; + strout + << EnvT::node << ": action(" + << EnvT::level + << "): " + << parser_name(action_); + traces.push_back(GETSTRING(strout)); + + return this->base_t::generate_action(action_, subject_, env); + } + + template <typename BinaryT, typename LeftT, typename RightT, typename EnvT> + typename parser_traversal_binary_result<self_t, BinaryT, LeftT, RightT, EnvT>::type + generate_binary(BinaryT const &binary_, LeftT const& left_, + RightT const& right_, EnvT const &env) const + { + OSSTREAM strout; + strout + << EnvT::node << ": binary(" + << EnvT::level + << "): " + << parser_name(binary_); + traces.push_back(GETSTRING(strout)); + + return this->base_t::generate_binary(binary_, left_, right_, env); + } + + std::vector<std::string> const &get_output() const { return traces; } + +private: + mutable std::vector<std::string> traces; +}; + +template <typename ParserT> +void +post_order_trace_test(ParserT const &parser_, char const *first[], size_t cnt) +{ +// traverse +trace_identity_transform trace_vector; + + post_order::traverse(trace_vector, parser_); + +// The following two re-find loops ensure, that both string arrays contain the +// same entries, only their order may differ. The differences in the trace +// string order is based on the different parameter evaluation order as it is +// implemented by different compilers. + +// re-find all trace strings in the array of expected strings +std::vector<std::string>::const_iterator it = trace_vector.get_output().begin(); +std::vector<std::string>::const_iterator end = trace_vector.get_output().end(); + + BOOST_TEST(cnt == trace_vector.get_output().size()); + for (/**/; it != end; ++it) + { + if (std::find(first, first + cnt, *it) == first + cnt) + std::cerr << "node in question: " << *it << std::endl; + + BOOST_TEST(std::find(first, first + cnt, *it) != first + cnt); + } + +// re-find all expected strings in the vector of trace strings +std::vector<std::string>::const_iterator begin = trace_vector.get_output().begin(); +char const *expected = first[0]; + + for (size_t i = 0; i < cnt - 1; expected = first[++i]) + { + if (std::find(begin, end, std::string(expected)) == end) + std::cerr << "node in question: " << expected << std::endl; + + BOOST_TEST(std::find(begin, end, std::string(expected)) != end); + } +} + +#if defined(_countof) +#undef _countof +#endif +#define _countof(x) (sizeof(x)/sizeof(x[0])) + +void +traverse_trace_tests() +{ +const char *test_result1[] = { + "0: plain (1, 0): chlit('a')", + "1: plain (1, 1): chlit('b')", + "2: binary(0): sequence[chlit('a'), chlit('b')]", + }; + + post_order_trace_test( + ch_p('a') >> 'b', + test_result1, _countof(test_result1) + ); + +char c = 0; + +// test: ((a >> b) >> c) >> d +const char *test_result2[] = { + "0: plain (4, 0): chlit('a')", + "1: unary (3): kleene_star[chlit('a')]", + "2: plain (4, 1): chlit('b')", + "3: action(3): action[chlit('b')]", + "4: binary(2): sequence[kleene_star[chlit('a')], action[chlit('b')]]", + "5: plain (2, 2): chlit('c')", + "6: binary(1): sequence[sequence[kleene_star[chlit('a')], action[chlit('b')]], chlit('c')]", + "7: plain (2, 3): chlit('d')", + "8: unary (1): optional[chlit('d')]", + "9: binary(0): sequence[sequence[sequence[kleene_star[chlit('a')], action[chlit('b')]], chlit('c')], optional[chlit('d')]]", + }; + + post_order_trace_test( + ((*ch_p('a') >> ch_p('b')[assign_a(c)]) >> 'c') >> !ch_p('d'), + test_result2, _countof(test_result2) + ); + +// test: (a >> (b >> c)) >> d +const char *test_result3[] = { + "0: plain (3, 0): chlit('a')", + "1: unary (2): kleene_star[chlit('a')]", + "2: plain (4, 1): chlit('b')", + "3: action(3): action[chlit('b')]", + "4: plain (3, 2): chlit('c')", + "5: binary(2): sequence[action[chlit('b')], chlit('c')]", + "6: binary(1): sequence[kleene_star[chlit('a')], sequence[action[chlit('b')], chlit('c')]]", + "7: plain (2, 3): chlit('d')", + "8: unary (1): optional[chlit('d')]", + "9: binary(0): sequence[sequence[kleene_star[chlit('a')], sequence[action[chlit('b')], chlit('c')]], optional[chlit('d')]]", + }; + + post_order_trace_test( + (*ch_p('a') >> (ch_p('b')[assign_a(c)] >> 'c')) >> !ch_p('d'), + test_result3, _countof(test_result3) + ); + +// test: a >> (b >> (c >> d)) +const char *test_result4[] = { + "0: plain (2, 0): chlit('a')", + "1: unary (1): kleene_star[chlit('a')]", + "2: plain (3, 1): chlit('b')", + "3: action(2): action[chlit('b')]", + "4: plain (3, 2): chlit('c')", + "5: plain (4, 3): chlit('d')", + "6: unary (3): optional[chlit('d')]", + "7: binary(2): sequence[chlit('c'), optional[chlit('d')]]", + "8: binary(1): sequence[action[chlit('b')], sequence[chlit('c'), optional[chlit('d')]]]", + "9: binary(0): sequence[kleene_star[chlit('a')], sequence[action[chlit('b')], sequence[chlit('c'), optional[chlit('d')]]]]", + }; + + post_order_trace_test( + *ch_p('a') >> (ch_p('b')[assign_a(c)] >> ('c' >> !ch_p('d'))), + test_result4, _countof(test_result4) + ); + +// test: a >> ((b >> c) >> d) +const char *test_result5[] = { + "0: plain (2, 0): chlit('a')", + "1: unary (1): kleene_star[chlit('a')]", + "2: plain (4, 1): chlit('b')", + "3: action(3): action[chlit('b')]", + "4: plain (3, 2): chlit('c')", + "5: binary(2): sequence[action[chlit('b')], chlit('c')]", + "6: plain (3, 3): chlit('d')", + "7: unary (2): optional[chlit('d')]", + "8: binary(1): sequence[sequence[action[chlit('b')], chlit('c')], optional[chlit('d')]]", + "9: binary(0): sequence[kleene_star[chlit('a')], sequence[sequence[action[chlit('b')], chlit('c')], optional[chlit('d')]]]", + }; + + post_order_trace_test( + *ch_p('a') >> ((ch_p('b')[assign_a(c)] >> 'c') >> !ch_p('d')), + test_result5, _countof(test_result5) + ); + +// test: (a >> b) >> (c >> d) +const char *test_result6[] = { + "0: plain (3, 0): chlit('a')", + "1: unary (2): kleene_star[chlit('a')]", + "2: plain (3, 1): chlit('b')", + "3: action(2): action[chlit('b')]", + "4: binary(1): sequence[kleene_star[chlit('a')], action[chlit('b')]]", + "5: plain (2, 2): chlit('c')", + "6: plain (3, 3): chlit('d')", + "7: unary (2): optional[chlit('d')]", + "8: binary(1): sequence[chlit('c'), optional[chlit('d')]]", + "9: binary(0): sequence[sequence[kleene_star[chlit('a')], action[chlit('b')]], sequence[chlit('c'), optional[chlit('d')]]]", + }; + + post_order_trace_test( + (*ch_p('a') >> ch_p('b')[assign_a(c)]) >> ('c' >> !ch_p('d')), + test_result6, _countof(test_result6) + ); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Main +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + traverse_identity_tests(); + traverse_trace_tests(); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/test/tree_tests.cpp b/src/boost/libs/spirit/classic/test/tree_tests.cpp new file mode 100644 index 00000000..be9b5ee5 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/tree_tests.cpp @@ -0,0 +1,383 @@ +/*============================================================================= + Copyright (c) 2003 Giovanni Bajo + http://spirit.sourceforge.net/ + + 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/include/classic_core.hpp> +#include <boost/spirit/include/classic_ast.hpp> +#include <boost/spirit/include/classic_tree_to_xml.hpp> +#include <boost/preprocessor/arithmetic/inc.hpp> +#include <boost/preprocessor/punctuation/comma_if.hpp> +#include <boost/preprocessor/repetition.hpp> +#include <boost/preprocessor/arithmetic/sub.hpp> +#include <boost/mpl/list.hpp> +#include <boost/mpl/apply.hpp> +#include <boost/mpl/remove.hpp> +#include <boost/mpl/size.hpp> +#include <boost/mpl/for_each.hpp> + +#include <map> +#include <string> + +#include <fstream> +#include <boost/detail/lightweight_test.hpp> +#include "impl/string_length.hpp" + +#define DEBUG_DUMP_TREES (1) + +////////////////////////////////////////////////////////////////////////////// +// rule_id helper +// http://sf.net/tracker/index.php?func=detail&aid=715483&group_id=28447&atid=393389) + +namespace boost { namespace spirit { + + template < + typename ScannerT, + unsigned long ID = 0, + typename ContextT = parser_context<> > + class rule_id + : public rule<ScannerT, ContextT, parser_tag<ID> > + { + typedef rule<ScannerT, ContextT, parser_tag<ID> > base_t; + + public: + // Forward ctors and operator=. + rule_id() + {} + + template <typename T> + rule_id(const T& a) + : base_t(a) {} + + template <typename T> + rule_id& operator=(const T& a) + { base_t::operator=(a); return *this; } + }; +}} + + +////////////////////////////////////////////////////////////////////////////// +// Framework setup + +namespace mpl = boost::mpl; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace std; + + +enum RULE_ID +{ + ID_A = 1, + ID_B, + ID_C, + ID_ROOT +}; + +map<parser_id, string> rule_names; + + +////////////////////////////////////////////////////////////////////////////// +// Generic tree manipulation tools + +template <typename TreeT> +RULE_ID id(TreeT& t) +{ return (RULE_ID)t.value.id().to_long(); } + + +template <typename TreeT> +TreeT& child(TreeT& t, unsigned n) +{ + return t.children[n]; +} + +template <typename TreeT> +size_t num_children(const TreeT& t) +{ return t.children.size(); } + +template <typename TreeT> +typename TreeT::parse_node_t::iterator_t ValueBeginIterator(TreeT& t) +{ return t.value.begin(); } + +template <typename TreeT> +typename TreeT::parse_node_t::iterator_t ValueEndIterator(TreeT& t) +{ return t.value.end(); } + +template <typename TreeT> +bool equal(TreeT& a, TreeT& b) +{ + if (id(a) != id(b)) + return false; + + if (num_children(a) != num_children(b)) + return false; + + unsigned n = num_children(a); + for (unsigned i=0;i<n;i++) + if (!equal(child(a, i), child(b, i))) + return false; + + return true; +} + +template <typename TreeT> +void dump(ostream& o, TreeT& t, int level = 0) +{ + string name; + string value; + map<parser_id, string>::iterator iter = + rule_names.find(id(t)); + + if (iter == rule_names.end()) + name = "noname"; + else + name = iter->second; + + value.assign(ValueBeginIterator(t), ValueEndIterator(t)); + + for (int i=0;i<level;i++) + o << " "; + + + o << name << ": " << value << endl; + + unsigned n = num_children(t); + for (unsigned c=0;c<n;c++) + dump(o, child(t, c), level+1); +} + + +////////////////////////////////////////////////////////////////////////////// +// Tree folding + +namespace test_impl { + + template <typename ParmT> + struct fold_node + { + // assign a subtree + void operator()(ParmT& t, ParmT ch) const + { t = ch; } + + // wrong specialization + template <typename TreeT> + void operator()(TreeT& t, ParmT p) const + { typedef typename TreeT::this_should_never_be_compiled type; } + }; + + template <> + struct fold_node<nil_t> + { + template <typename TreeT> + void operator()(TreeT& t, nil_t) const + { typedef typename TreeT::this_should_never_be_compiled type; } + }; + + template <> + struct fold_node<RULE_ID> + { + template <typename TreeT> + void operator()(TreeT& t, RULE_ID id) const + { t.value.id(id); } + }; + + template <typename ParmT> + struct fold_child + { + template <typename TreeT> + void operator()(TreeT& t, ParmT p, unsigned n) const + { fold_node<ParmT>()(t.children[n], p); } + }; + + template <> + struct fold_child<nil_t> + { + template <typename TreeT> + void operator()(TreeT& t, nil_t, unsigned n) const + {} + }; +} + +template <typename TreeT, + typename T, typename T1, typename T2, typename T3, typename T4, + typename T5, typename T6, typename T7, typename T8> +TreeT fold(T p, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8) +{ + // Prepare a list with all the template types + typedef mpl::list<T1,T2,T3,T4,T5,T6,T7,T8> full_list_t; + + // Remove the ones equal to nil_t: they are the default parameters + // unspecified from the user + typedef typename mpl::remove<full_list_t, nil_t>::type parm_list_t; + + // Get the size of the list = number of parameters specified by the user + typedef typename mpl::size<parm_list_t>::type parm_list_size_t; + enum { NUM_CHILDREN = parm_list_size_t::value }; + + TreeT t; + + // Generate the root of the tree (specialized for the first parameter) + test_impl::fold_node<T>()(t, p); + + // Make room for the children + if (NUM_CHILDREN > 0) + t.children.resize(NUM_CHILDREN); + + // For each children, call the GenerateChild function, which is specialized + // on the different types + test_impl::fold_child<T1>()(t, p1, 0); + test_impl::fold_child<T2>()(t, p2, 1); + test_impl::fold_child<T3>()(t, p3, 2); + test_impl::fold_child<T4>()(t, p4, 3); + test_impl::fold_child<T5>()(t, p5, 4); + test_impl::fold_child<T6>()(t, p6, 5); + test_impl::fold_child<T7>()(t, p7, 6); + test_impl::fold_child<T8>()(t, p8, 7); + + return t; +} + + +// Define fold() wrapper for 1->7 parameters: they just call the 8 parameter +// version passing nil_t for the other arguments +#define PUT_EMPTY(Z, N, _) nil_t() + +#define DEFINE_FOLD(Z, N, _) \ + template <typename TreeT, typename T BOOST_PP_COMMA_IF(N) \ + BOOST_PP_ENUM_PARAMS(N, typename T) > \ + TreeT fold(T p BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS(N, T, p)) \ + { \ + return fold<TreeT>(p \ + BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(N, p) \ + BOOST_PP_COMMA_IF(BOOST_PP_SUB(8,N)) \ + BOOST_PP_ENUM(BOOST_PP_SUB(8,N), PUT_EMPTY, _)); \ + } + +BOOST_PP_REPEAT(7, DEFINE_FOLD, _) + +#undef PUT_EMPTY +#undef DEFINE_FOLD + + + +////////////////////////////////////////////////////////////////////////////// +// test_banal: simple tree construction + +struct test_banal : public grammar<test_banal> +{ + template <class T> + struct definition + { + rule_id<T, ID_ROOT> root; + rule_id<T, ID_A> a; + rule_id<T, ID_B> b; + rule_id<T, ID_C> c; + + definition(const test_banal&) + { + root = a >> c; + a = b; + b = chlit<>('b'); + c = chlit<>('c'); + } + + const rule_id<T, ID_ROOT>& start() + { return root; } + }; + + const char* pattern(void) + { + return "bc"; + } + + template <typename TreeT> + TreeT expected_tree(void) + { + return fold<TreeT>( + ID_ROOT, fold<TreeT>( + ID_A, + ID_B), + ID_C); + } +}; + + +////////////////////////////////////////////////////////////////////////////// +// All the tests + +typedef mpl::list +< + test_banal + +> tests_t; + + +////////////////////////////////////////////////////////////////////////////// +// run_test - code to run a test + +struct run_test +{ + template <typename TestT> + void operator()(TestT gram) + { + typedef const char* iterator_t; + typedef node_val_data_factory<nil_t> factory_t; + typedef typename + factory_t + ::BOOST_NESTED_TEMPLATE factory<iterator_t> + ::node_t node_t; + typedef tree_node<node_t> tree_t; + + iterator_t text_begin = gram.pattern(); + iterator_t text_end = text_begin + test_impl::string_length(text_begin); + + tree_parse_info<iterator_t, factory_t> info = + ast_parse(text_begin, text_end, gram); + + BOOST_TEST(info.full); + + tree_t expected = gram.template expected_tree<tree_t>(); + +#if DEBUG_DUMP_TREES + dump(cout, info.trees[0]); + dump(cout, expected); +#endif + + BOOST_TEST(equal(info.trees[0], expected)); + } +}; + +////////////////////////////////////////////////////////////////////////////// +// main() stuff + +#ifdef BOOST_NO_EXCEPTIONS +namespace boost +{ + void throw_exception(std::exception const & ) + { + std::cerr << "Exception caught" << std::endl; + BOOST_TEST(0); + } +} + +#endif + + +void init(void) +{ + rule_names[ID_ROOT] = "ID_ROOT"; + rule_names[ID_A] = "ID_A"; + rule_names[ID_B] = "ID_B"; + rule_names[ID_C] = "ID_C"; +} + + +int main() +{ + init(); + + mpl::for_each<tests_t, mpl::_> (run_test()); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/tree_to_xml.cpp b/src/boost/libs/spirit/classic/test/tree_to_xml.cpp new file mode 100644 index 00000000..d6a4724b --- /dev/null +++ b/src/boost/libs/spirit/classic/test/tree_to_xml.cpp @@ -0,0 +1,186 @@ +/*============================================================================= + Copyright (c) 2001-2007 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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/detail/lightweight_test.hpp> +#include <boost/preprocessor/cat.hpp> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_ast.hpp> +#include <boost/spirit/include/classic_tree_to_xml.hpp> + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4702) // unreachable code +#endif +#include <boost/iostreams/stream.hpp> +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#include <iostream> +#include <fstream> +#include <string> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +struct calculator : public grammar<calculator> +{ + static const int integerID = 1; + static const int factorID = 2; + static const int termID = 3; + static const int expressionID = 4; + + template <typename ScannerT> + struct definition + { + definition(calculator const& /*self*/) + { + // Start grammar definition + integer = leaf_node_d[ lexeme_d[ + (!ch_p('-') >> +digit_p) + ] ]; + + factor = integer + | inner_node_d[ch_p('(') >> expression >> ch_p(')')] + | (root_node_d[ch_p('-')] >> factor); + + term = factor >> + *( (root_node_d[ch_p('*')] >> factor) + | (root_node_d[ch_p('/')] >> factor) + ); + + expression = term >> + *( (root_node_d[ch_p('+')] >> term) + | (root_node_d[ch_p('-')] >> term) + ); + // End grammar definition + + // turn on the debugging info. + BOOST_SPIRIT_DEBUG_RULE(integer); + BOOST_SPIRIT_DEBUG_RULE(factor); + BOOST_SPIRIT_DEBUG_RULE(term); + BOOST_SPIRIT_DEBUG_RULE(expression); + } + + rule<ScannerT, parser_context<>, parser_tag<expressionID> > expression; + rule<ScannerT, parser_context<>, parser_tag<termID> > term; + rule<ScannerT, parser_context<>, parser_tag<factorID> > factor; + rule<ScannerT, parser_context<>, parser_tag<integerID> > integer; + + rule<ScannerT, parser_context<>, parser_tag<expressionID> > const& + start() const { return expression; } + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +/// this is a Boost.IoStreams source device usable to create a istream on +/// top of a random access container (i.e. vector<>) +template<typename Container> +class container_device +{ +public: + typedef typename Container::value_type char_type; + typedef boost::iostreams::sink_tag category; + + container_device(Container& container) + : container_(container), pos_(0) + {} + + /// Write up to n characters to the underlying data sink into the + /// buffer s, returning the number of characters written + std::streamsize write(const char_type* s, std::streamsize n) + { + std::streamsize result = 0; + if (pos_ != container_.size()) { + std::streamsize amt = + static_cast<std::streamsize>(container_.size() - pos_); + result = (std::min)(n, amt); + std::copy(s, s + result, container_.begin() + pos_); + pos_ += static_cast<size_type>(result); + } + if (result < n) { + container_.insert(container_.end(), s, s + n); + pos_ = container_.size(); + } + return n; + } + + Container& container() { return container_; } + +private: + typedef typename Container::size_type size_type; + Container& container_; + size_type pos_; +}; + +/////////////////////////////////////////////////////////////////////////////// +#define EXPECTED_XML_OUTPUT "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n\ +<!DOCTYPE parsetree SYSTEM \"parsetree.dtd\">\n\ +<!-- 1+2 -->\n\ +<parsetree version=\"1.0\">\n\ + <parsenode>\n\ + <value>+</value>\n\ + <parsenode>\n\ + <value>1</value>\n\ + </parsenode>\n\ + <parsenode>\n\ + <value>2</value>\n\ + </parsenode>\n\ + </parsenode>\n\ +</parsetree>\n" + +#define EXPECTED_XML_OUTPUT_WIDE BOOST_PP_CAT(L, EXPECTED_XML_OUTPUT) + +bool test(wchar_t const *text) +{ + typedef std::basic_string<wchar_t>::iterator iterator_t; + + std::basic_string<wchar_t> input(text); + calculator calc; + tree_parse_info<iterator_t> ast_info = + ast_parse(iterator_t(input.begin()), iterator_t(input.end()), + calc >> end_p, space_p); + + std::basic_string<wchar_t> out; + { + typedef container_device<std::basic_string<wchar_t> > device_type; + boost::iostreams::stream<device_type> outsink(out); + basic_tree_to_xml<wchar_t>(outsink, ast_info.trees, input); + } + return out == EXPECTED_XML_OUTPUT_WIDE; +} + +bool test(char const *text) +{ + typedef std::string::iterator iterator_t; + + std::string input(text); + calculator calc; + tree_parse_info<iterator_t> ast_info = + ast_parse(iterator_t(input.begin()), iterator_t(input.end()), + calc >> end_p, space_p); + + std::string out; + { + typedef container_device<std::string> device_type; + boost::iostreams::stream<device_type> outsink(out); + basic_tree_to_xml<char>(outsink, ast_info.trees, input); + } + return out == EXPECTED_XML_OUTPUT; +} + +int main() +{ + BOOST_TEST(test("1+2")); + if (std::has_facet<std::ctype<wchar_t> >(std::locale())) + { + BOOST_TEST(test(L"1+2")); + } + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/test/typeof_support/typeof_actor.cpp b/src/boost/libs/spirit/classic/test/typeof_support/typeof_actor.cpp new file mode 100644 index 00000000..447d06d8 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/typeof_support/typeof_actor.cpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2006 Tobias Schwinger + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +#define BOOST_TYPEOF_EMULATION +#include <boost/spirit/include/classic_typeof.hpp> +#include <boost/spirit/include/classic_actor.hpp> + diff --git a/src/boost/libs/spirit/classic/test/typeof_support/typeof_attribute.cpp b/src/boost/libs/spirit/classic/test/typeof_support/typeof_attribute.cpp new file mode 100644 index 00000000..bb1e8ffb --- /dev/null +++ b/src/boost/libs/spirit/classic/test/typeof_support/typeof_attribute.cpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2006 Tobias Schwinger + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +#define BOOST_TYPEOF_EMULATION +#include <boost/spirit/include/classic_typeof.hpp> +#include <boost/spirit/include/classic_attribute.hpp> + diff --git a/src/boost/libs/spirit/classic/test/typeof_support/typeof_core.cpp b/src/boost/libs/spirit/classic/test/typeof_support/typeof_core.cpp new file mode 100644 index 00000000..5b08f964 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/typeof_support/typeof_core.cpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2006 Tobias Schwinger + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +#define BOOST_TYPEOF_EMULATION +#include <boost/spirit/include/classic_typeof.hpp> +#include <boost/spirit/include/classic_core.hpp> + diff --git a/src/boost/libs/spirit/classic/test/typeof_support/typeof_debug.cpp b/src/boost/libs/spirit/classic/test/typeof_support/typeof_debug.cpp new file mode 100644 index 00000000..2cdc5637 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/typeof_support/typeof_debug.cpp @@ -0,0 +1,15 @@ +/*============================================================================= + Copyright (c) 2006 Tobias Schwinger + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +#define BOOST_TYPEOF_EMULATION +#define BOOST_SPIRIT_DEBUG + +#include <boost/spirit/include/classic_typeof.hpp> +#include <boost/spirit/include/classic_debug.hpp> + diff --git a/src/boost/libs/spirit/classic/test/typeof_support/typeof_dynamic.cpp b/src/boost/libs/spirit/classic/test/typeof_support/typeof_dynamic.cpp new file mode 100644 index 00000000..9ebb546a --- /dev/null +++ b/src/boost/libs/spirit/classic/test/typeof_support/typeof_dynamic.cpp @@ -0,0 +1,17 @@ +/*============================================================================= + Copyright (c) 2006 Tobias Schwinger + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +#define BOOST_TYPEOF_EMULATION +#include <boost/spirit/include/classic_typeof.hpp> +#include <boost/spirit/include/classic_dynamic.hpp> + +// currently not in the master header +#include <boost/spirit/include/classic_switch.hpp> +#include <boost/spirit/include/classic_select.hpp> + diff --git a/src/boost/libs/spirit/classic/test/typeof_support/typeof_error_handling.cpp b/src/boost/libs/spirit/classic/test/typeof_support/typeof_error_handling.cpp new file mode 100644 index 00000000..1d1d7f37 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/typeof_support/typeof_error_handling.cpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2006 Tobias Schwinger + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +#define BOOST_TYPEOF_EMULATION +#include <boost/spirit/include/classic_typeof.hpp> +#include <boost/spirit/include/classic_error_handling.hpp> + diff --git a/src/boost/libs/spirit/classic/test/typeof_support/typeof_iterator.cpp b/src/boost/libs/spirit/classic/test/typeof_support/typeof_iterator.cpp new file mode 100644 index 00000000..a3517616 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/typeof_support/typeof_iterator.cpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2006 Tobias Schwinger + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +#define BOOST_TYPEOF_EMULATION +#include <boost/spirit/include/classic_typeof.hpp> +#include <boost/spirit/include/classic_iterator.hpp> + diff --git a/src/boost/libs/spirit/classic/test/typeof_support/typeof_symbols.cpp b/src/boost/libs/spirit/classic/test/typeof_support/typeof_symbols.cpp new file mode 100644 index 00000000..c88c9410 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/typeof_support/typeof_symbols.cpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2006 Tobias Schwinger + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +#define BOOST_TYPEOF_EMULATION +#include <boost/spirit/include/classic_typeof.hpp> +#include <boost/spirit/include/classic_symbols.hpp> + diff --git a/src/boost/libs/spirit/classic/test/typeof_support/typeof_tree.cpp b/src/boost/libs/spirit/classic/test/typeof_support/typeof_tree.cpp new file mode 100644 index 00000000..b18ea487 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/typeof_support/typeof_tree.cpp @@ -0,0 +1,15 @@ +/*============================================================================= + Copyright (c) 2006 Tobias Schwinger + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +#define BOOST_TYPEOF_EMULATION +#include <boost/spirit/include/classic_typeof.hpp> + +#include <boost/spirit/include/classic_ast.hpp> +#include <boost/spirit/include/classic_parse_tree.hpp> + diff --git a/src/boost/libs/spirit/classic/test/typeof_support/typeof_utility.cpp b/src/boost/libs/spirit/classic/test/typeof_support/typeof_utility.cpp new file mode 100644 index 00000000..eb947818 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/typeof_support/typeof_utility.cpp @@ -0,0 +1,18 @@ +/*============================================================================= + Copyright (c) 2006 Tobias Schwinger + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ + +#define BOOST_TYPEOF_EMULATION +#include <boost/spirit/include/classic_typeof.hpp> + +#include <boost/spirit/include/classic_utility.hpp> + +// currently not in the master header +#include <boost/spirit/include/classic_regex.hpp> +#include <boost/spirit/include/classic_grammar_def.hpp> + diff --git a/src/boost/libs/spirit/classic/test/while_p_as_parser_tests.cpp b/src/boost/libs/spirit/classic/test/while_p_as_parser_tests.cpp new file mode 100644 index 00000000..e1aee4f9 --- /dev/null +++ b/src/boost/libs/spirit/classic/test/while_p_as_parser_tests.cpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + 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/include/classic_core.hpp> +#include <boost/spirit/include/classic_while.hpp> + +extern bool fun(); + +struct ftor +{ + bool operator()() const; +}; + +int +main() +{ + ////////////////////////////////// + // compile time check wether as_parser<> works for while_p + + ::BOOST_SPIRIT_CLASSIC_NS::rule<> r; + + r = ::BOOST_SPIRIT_CLASSIC_NS::while_p('-')['-']; + r = ::BOOST_SPIRIT_CLASSIC_NS::while_p("-")["-"]; + + r = ::BOOST_SPIRIT_CLASSIC_NS::while_p(&fun)["foo"]; + r = ::BOOST_SPIRIT_CLASSIC_NS::while_p(ftor())["foo"]; + + r = ::BOOST_SPIRIT_CLASSIC_NS::while_p(r)[r]; + + r = ::BOOST_SPIRIT_CLASSIC_NS::do_p['-'].while_p('-'); + r = ::BOOST_SPIRIT_CLASSIC_NS::do_p["-"].while_p("-"); + + r = ::BOOST_SPIRIT_CLASSIC_NS::do_p["foo"].while_p(&fun); + r = ::BOOST_SPIRIT_CLASSIC_NS::do_p["foo"].while_p(ftor()); + + r = ::BOOST_SPIRIT_CLASSIC_NS::do_p[r].while_p(r); +} diff --git a/src/boost/libs/spirit/classic/test/while_tests.cpp b/src/boost/libs/spirit/classic/test/while_tests.cpp new file mode 100644 index 00000000..33219e5a --- /dev/null +++ b/src/boost/libs/spirit/classic/test/while_tests.cpp @@ -0,0 +1,202 @@ +/*============================================================================= + Phoenix V1.0 + Copyright (c) 2002-2003 Martin Wille + + 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) +==============================================================================*/ +// vi:ts=4:sw=4:et +// Tests for BOOST_SPIRIT_CLASSIC_NS::while_p +// [28-Dec-2002] +//////////////////////////////////////////////////////////////////////////////// +#include <iostream> +#include <cstring> + +#include "impl/string_length.hpp" +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> +#include <boost/spirit/include/classic_while.hpp> +#include <boost/ref.hpp> + +namespace local +{ + template <typename T> + struct var_wrapper + : public ::boost::reference_wrapper<T> + { + typedef boost::reference_wrapper<T> parent; + + explicit inline var_wrapper(T& t) : parent(t) {} + + inline T& operator()() const { return parent::get(); } + }; + + template <typename T> + inline var_wrapper<T> + var(T& t) + { + return var_wrapper<T>(t); + } +} + +namespace +{ + template <typename T> + class add_actor + { + public: + explicit add_actor(T &ref_) : ref(ref_) {} + + template <typename T2> + void operator()(T2 const &val) const + { ref += val; } + + private: + T& ref; + }; + + template <typename T> + inline add_actor<T> const + add(T& ref) + { + return add_actor<T>(ref); + } +} + +typedef BOOST_SPIRIT_CLASSIC_NS::rule<> rule_t; + +unsigned int test_count = 0; +unsigned int error_count = 0; +unsigned int iterations_performed; + +unsigned int number_result; +static const unsigned int kError = 999; +static const bool good = true; +static const bool bad = false; + +rule_t while_rule; +rule_t do_while_rule; + +void +test_while( + char const *s, + unsigned int wanted, + rule_t const &r, + unsigned int iterations_wanted) +{ + using namespace std; + + ++test_count; + + number_result = 0; + iterations_performed = 0; + + BOOST_SPIRIT_CLASSIC_NS::parse_info<> m = BOOST_SPIRIT_CLASSIC_NS::parse(s, s+ test_impl::string_length(s), r); + + bool result = wanted == kError?(m.full?bad:good): (number_result==wanted); + + result &= iterations_performed == iterations_wanted; + + if (m.full && (m.length != test_impl::string_length(s))) + result = bad; + + if (result==good) + cout << "PASSED"; + else + { + ++error_count; + cout << "FAILED"; + } + + cout << ": \"" << s << "\" ==> "; + if (!m.full) + cout << "<error>"; + else + cout << number_result; + cout << " " << iterations_performed << " of " + << iterations_wanted << " iterations\n"; +} + +template<typename T> +struct inc_actor +{ + explicit inc_actor(T &t) : var(t) {} + template<typename IteratorT> + void operator()(IteratorT const &, IteratorT const &) const + { + ++var; + } + template<typename U> + void operator()(U) const + { + ++var; + } + T &var; +}; + +template<typename T> +inc_actor<T> +inc(T &t) +{ + return inc_actor<T>(t); +} + +int +main() +{ + using namespace std; + using ::BOOST_SPIRIT_CLASSIC_NS::uint_p; + using ::BOOST_SPIRIT_CLASSIC_NS::while_p; + using ::BOOST_SPIRIT_CLASSIC_NS::do_p; + using ::BOOST_SPIRIT_CLASSIC_NS::assign_a; + +#if qDebug + BOOST_SPIRIT_DEBUG_RULE(while_rule); + BOOST_SPIRIT_DEBUG_RULE(do_while_rule); +#endif + + while_rule + = uint_p[assign_a(number_result)] + >> while_p('+') + [ + uint_p[add(number_result)][inc(iterations_performed)] + ]; + + do_while_rule + = do_p + [ + uint_p[add(number_result)][inc(iterations_performed)] + ].while_p('+'); + + cout << "/////////////////////////////////////////////////////////\n"; + cout << "\n"; + cout << " while_p test\n"; + cout << "\n"; + cout << "/////////////////////////////////////////////////////////\n"; + cout << "\n"; + + cout << "while_p()[]\n"; + test_while("", kError, while_rule, 0); + test_while("1", 1, while_rule, 0); + test_while("1+1", 2, while_rule, 1); + test_while("1+1+12", 14, while_rule, 2); + test_while("1+1+x", kError, while_rule, 1); + + cout << "do_p[].while_p()\n"; + test_while("", kError, do_while_rule, 0); + test_while("1", 1, do_while_rule, 1); + test_while("1+1", 2, do_while_rule, 2); + test_while("1+1+12", 14, do_while_rule, 3); + test_while("1+1+x", kError, do_while_rule, 2); + + std::cout << "\n "; + if (error_count==0) + cout << "All " << test_count << " while_p-tests passed.\n" + << "Test concluded successfully\n"; + else + cout << error_count << " of " << test_count << " while_p-tests failed\n" + << "Test failed\n"; + + return error_count!=0; +} |