diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/spirit/classic | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/spirit/classic')
192 files changed, 24480 insertions, 0 deletions
diff --git a/src/boost/libs/spirit/classic/change_log.html b/src/boost/libs/spirit/classic/change_log.html new file mode 100644 index 00000000..8ed8eed5 --- /dev/null +++ b/src/boost/libs/spirit/classic/change_log.html @@ -0,0 +1,294 @@ +<html> +<head> +<title>Spirit Change Log</title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<link rel="stylesheet" href="doc/theme/style.css" type="text/css"> +</head> + +<body> + +<h2>Spirit Change Log</h2> +<h2>1.8.11</h2> +<ul> + <li>Fixed <tt>position_iterator</tt> forming reference to local when the + underlying iterator dereference operator returns a non-reference type. + <a href="https://github.com/boostorg/spirit/pull/422">PR#422</a> + <a href="https://svn.boost.org/trac10/ticket/9737">TRAC#9737</a></li> + <li>Removed use of deprecated <tt>boost/detail/iterator.hpp</tt> header. + <a href="https://github.com/boostorg/spirit/pull/432">GH#432</a></li> +</ul> +<h2>1.8.10</h2> +<ul> + <li>Missing visibility mark on exception types. + <a href="https://github.com/boostorg/spirit/pull/409">GH#409</a></li> +</ul> +<h2>1.8.9</h2> +<ul> + <li>Fixed a regression introduced in + <a href="https://github.com/boostorg/spirit/pull/336">GH#336</a>. + <a href="https://github.com/boostorg/spirit/pull/386">GH#386</a></li> + <li>Minor code improvements. + <a href="https://github.com/boostorg/spirit/pull/367">GH#367</a></li> +</ul> +<h2>1.8.8</h2> +<ul> + <li>Fixed <tt>remove_reference</tt> usage without a namespace in Phoenix. + <a href="https://github.com/boostorg/spirit/pull/274">GH#274</a></li> + <li>Fixed <tt>std::complex</tt> usage without the include. + <a href="https://github.com/boostorg/spirit/pull/273">GH#273</a></li> + <li>Fixed compilation of <tt>match<T&></tt>. + <a href="https://github.com/boostorg/spirit/pull/275">GH#275</a></li> + <li>Fixed compilation with <tt>BOOST_DISABLE_THREADS</tt> defined. + <a href="https://github.com/boostorg/spirit/pull/323">GH#323</a> + <a href="https://svn.boost.org/trac10/ticket/12639">#12639</a></li> + <li>Increment scanner through iterator policy. + <a href="https://github.com/boostorg/spirit/pull/336">GH#336</a> + <a href="https://svn.boost.org/trac10/ticket/7371">TRAC#7371</a></li> + <li>Removed deprecated in C++17 <tt>std::iterator</tt> usage. + <a href="https://github.com/boostorg/spirit/pull/345">GH#345</a></li> +</ul> +<h2>1.8.7</h2> +<ul> + <li>Integrated the Spirit V1.8.x code base with Spirit V2. Spirit V1.8.x is + now called + <strong>Spirit Classic.</strong> Even if the directory + structure has changed (the + <strong>Spirit Classic</strong> headers are now moved to the + '$BOOST_ROOT/boost/spirit/home/classic' directory), we created forwarding + headers allowing to compile existing applications without any change. + These forwarding headers are deprecated, though, which will result in + corresponding warnings generated for each of the headers. The forwarding + headers are expected to be removed in the future. + <br /> + The recommended way of using Spirit Classic is now to include header + files from the directory '$BOOST_ROOT/boost/spirit/include'. All files of + <strong>Spirit Classic</strong> + have now a 'classic_' prefixed to their name. For example the include + <br/> + <br><code> #include <boost/spirit/core/core.hpp></code><br/> + <br/> + now should be written as: + <br/> + <br/><code> #include <boost/spirit/include/classic_core.hpp></code><br/> + <br/> + To avoid namespace conflicts with the new Spirit V2 library we moved <strong>Spirit + Classic</strong> into the <tt>namespace boost::spirit::classic</tt>. This change will be automatically deactivated whenever the deprecated include files are + being used. This ensures full backwards compatibility for existing applications. + <br /> + For more details about this change please consult the documentation.</li> +</ul> +<h2>1.8.6</h2> +<ul> + <li>Fixed a integer overflow bug preventing to fail parsing on certain large integers. This bug was reported and fixed by Michael Andersen Nexø</li> +</ul> +<h2>1.8.5</h2> +<ul> + <li>For performance reasons, leaf_node_d/token_node_d have been changed to implicit lexems that create leaf nodes in one shot. The old token_node_d is still available and called reduced_node_d, now.</li> + <li>It's now possible to phoenix::bind (version 1) symbols::add.</li> +</ul> +<h2>1.8.4</h2> +<ul> + <li>Fixed no_actions bug where no_action is applied recursively.</li> + <li>Fixed the regex_p parser for Boost >= V1.33.0 </li> + <li>Implemented a workaround for namespace issues VC++ has with Spirit's file_iterators</li> + <li>Fixed bug in tree match policies that prevented using gen_pt/ast_node_d, + <a href="http://article.gmane.org/gmane.comp.parsers.spirit.general/9013">reported + by Jascha Wetzel</a>.</li> + <li>Made position_iterator usable with wchar_t based strings. </li> +</ul> +<h2>1.8.3</h2> +<ul> + <li>Config correction for Sun C++ by + + + Steve Clamage (see <a href="https://sourceforge.net/tracker/?func=detail&atid=107586&aid=1220782&group_id=7586">this link</a>). </li> + <li>Fixed multi_pass_iterator for 64 platforms, where sizeof(int) != sizeof(ptr_type).Fixed bug that prevents the use of closures with grammars with multiple entry points, <a href="http://article.gmane.org/gmane.comp.parsers.spirit.general/8868">reported by David Pierre</a></li> + <li>Fixed bug that prevented embedding of grammars with multiple entry points, <a href="http://article.gmane.org/gmane.comp.parsers.spirit.general/8860">reported by David Pierre</a></li> + <li>Added '\0' to the set of valid escaped characters for escape_ch_p.</li> + <li>Fixed a switch_p bug when used with a phoenix::actor as the conditional expression.</li> + <li>__LINE__ macro now gets expanded in BOOST_SPIRIT_ASSERT_EXCEPTION</li> + <li>Fixed a bug in the intersection parser <a href="http://article.gmane.org/gmane.comp.parsers.spirit.general/8544">reported by Yusaku Sugai</a></li> + <li>The symbol parser uses the null character internally. Checks were added so that: + <ul> + <li>tst.add asserts if string contains the null character</li> + <li>tst.find doesn't match null characters in the input</li> + </ul></li> + <li>Fixed match_attr_traits.ipp to allow non-POD to pass through. The previous version taking in the ellipsis "..." does not allow PODs to pass through.</li> + <li>Allow evaluation to int as condition to if_p parser.</li> + <li>Applied performance improvement changes to the PT/AST code as suggested by Stefan Slapeta. </li> + <li>Fixed several problems with AST tree node directives (inner_node_d[], discard_first_node[], discard_last_node[] and infix_node_d[]). </li> +</ul> +<h2>1.8.2</h2> +<p>Maintenance release (almost the same as 1.8.1 plus a few fixes here and there)</p> +<ul> + <li>Added specializations to str_p and ch_p to allow str_p('c') and ch_p("c") thus fixing some non-bugs</li> + <li>Fixed bug where a match<T> is a variant.</li> + <li>added Jamfile/Jamrules from CVS to spirit-1.8.1/</li> + <li>added boost-build.jam from boost to spirit-1.8.1/</li> + <li>disabled template multi-threading in libs/spirit/test/Jamfile</li> + <li>added a boost-header-include rule (from spirit-header-include) pointing to miniboost in libs/spirit/test/Jamfile</li> + <li>Fixed if_p inconsistency</li> +</ul> +<h2>1.6.2</h2> +<p>The Spirit 1.6.2 release is a bug-fix release only, no new features were introduced.</p> +<ul> + <li>wchar_t friendly implementation of graph_p</li> + <li>Modified escape_char_parser::parse() to use a static parser instead of a rule. This will make it more friendly to use in trees. It should also be a little more efficient.</li> + <li>Moved to + + + Boost Software license 1.0. </li> + <li> workaround for Error 322 name lookup in base class specialization finds type</li> + <li> fixed limit_d bug</li> + <li> [numerics] Workaround for aC++</li> + <li> Fixed a bug in the switch_p parser.</li> + <li> Fixed a EOI problem in multi_pass</li> + <li>added Jamfile/Jamrules from CVS to spirit-1.6.1/</li> + <li>added boost-build.jam from boost to spirit-1.6.1/</li> + <li>disabled template multi-threading in libs/spirit/test/Jamfile</li> + <li>added a boost-header-include rule (from spirit-header-include) pointing to miniboost in libs/spirit/test/Jamfile</li> +</ul> +<h2>1.8.1 (Released with Boost 1.32.0)</h2> +<p>The Spirit 1.8.1 release is a bug-fix release only, no new features were introduced.</p> +<ul> + <li>Spirit now requires at least Boost 1.32.0 to compile correctly</li> + <li>Removed the support for the older iterator adaptor library and </li> + <li>Moved to use the new MPL library</li> + <li>Spirit was moved to use the Boost Software License 1.0.</li> + <li>Fixed several parsers to support post-skips more correctly.</li> + <li>Fixed a no_node_d[] bug.</li> + <li>Fixed a bug in shortest_d[].</li> + <li>Fixed a bug in limit_d[].</li> + <li>Fixed parser traversal meta code.</li> + <li>Fixed several bugs in switch_p.</li> + <li>Fixed AST generating problems, in particular with the loops related parsers.</li> + <li>Fixed several bugs in the multi_pass iterator. + <ul> + <li>Fixed a problem, when the used base iterator returned a value_type and not a reference from its dereferencing operator.</li> + <li>Fixed iterator_traits problem</li> + <li>Fixed an EOI problem</li> + <li>Fixed a bug, when used with std::cin</li> + </ul> + </li> + <li>Found a bug in grammar.ipp when BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE is defined</li> + <li>Rewritten safe_bool to use CRTP - now works also on MWCW, fixed several bugs with the implementation.</li> + <li>Fixed and extended the debug diagnostics printed by the parse tree code.</li> +</ul> +<h2>1.8.0 (Released with Boost 1.31.0; Includes unreleased 1.7.1)</h2> +<ul> + <li>Fixed a wchar_t problem in the regex_p parser.</li> + <li>removed code and workarounds for old compilers (VC6/7 and Borland)</li> + <li> Changed license to the new boost license.</li> + <li> Modified escape_char_parser::parse() to use a static parser instead of a rule. This will make it more friendly to use in trees. It should also be a little more efficient.</li> +</ul> +<h2>1.7.1 (Unreleased; becomes 1.8.0)</h2> +<ul> + <li>Added a full suite of predefined actors.</li> + <li>Moved rule_alias and stored_rule from core/non-terminal to dynamic.<br> + Made as_parser a public API in meta/as_parser.hpp</li> + <li>Separated Core.Meta into its own module</li> + <li>Refactored Utility module<br> + Moved some files into Utility.Parsers</li> +</ul> +<blockquote> + <ul> + <li>utilities + <ul> + <li>parsers + <ul> + <li>chset, regex, escape_char<br> + confix, list, distinct<br> + functor_parser</li> + </ul> + </li> + </ul> + </li> + <li> support + <ul> + <li>scoped_lock<br> + flush_multi_pass<br> + grammar_def</li> + </ul> + </li> + <li> actors + <ul> + <li>assign</li> + </ul> + </li> + </ul> +</blockquote> +<ul> + <li>Stored rules</li> + <li>Added the switch_p and select_p dynamic parsers.</li> + <li>Multiple scanner support for rules.</li> + <li>The Rule's Scanner, Context and Tag template parameters can be specified in any order now. If a template parameter is missing, it will assume the defaults. See test/rule_tests.cpp.</li> + <li>Introduced the possibility to specify more than one start rule from a grammar.</li> + <li>Added an implementation of the file_iterator iterator based on the new Boost iterator_adaptors (submitted originally by Thomas Witt).</li> +</ul> +<p><em> [The transition to the new iterator_adaptors should be complete now.]</em></p> +<ul> + <li>Added an implementation of the fixed_size_queue iterator based on the new Boost iterator_adaptors.</li> + <li> wchar_t friendly implementation of graph_p</li> + <li>made the copy-constructor and assignment-operator of parser_error_base public to clear VC7.1 C4673 warning. Added copy-constructor and assignment operator to parser_error for clarity of intent.</li> +</ul> +<h2>1.7.0</h2> +<ul> + <li> assign(string) semantic action now works in VC6</li> + <li>parsers need not be default constructible </li> + <li>simplified aggregation of binary and unary parsers (more compiler friendly)</li> + <li>epsilon workarounds for VC++</li> + <li>match's attribute now uses boost.optional</li> + <li>subrules can now have closures</li> + <li>project wide 64 bit compatibility</li> + <li>dynamic_parser_tag, reissue of rule.set_id(id);</li> + <li>numerous primitives improvements and workarounds for problematic compilers</li> + <li>proper complement (~) of single char parser primitives and chsets</li> + <li>intuitive handling of lexeme_d </li> + <li>wide_phrase_scanner_t typedef</li> + <li>dynamic parser improvements (better support for more compilers)</li> + <li>complete rewrite of the file_iterator (using boost.iterator_adapters). Supports + memory maps wherever available</li> + <li>multi_pass updates (compatibility with more compilers (e.g VC7) and more)</li> + <li>position_iterator improvements</li> + <li>better phoenix support for more compilers</li> + <li>phoenix new_(...) construct</li> + <li>new lazy_p parser</li> + <li>utility.distinct parser (undocumented)</li> + <li>chset operators improvements </li> + <li>confix_p streamlining and improvements</li> + <li>numerous Boost integration improvements</li> +</ul> +<h2>Bug fixes (1.7.0 and 1.6.0)</h2> +<ul> + <li> Fixed. Using MSVC++6 (SP5), calling the assign action with a string value + on parsers using the file_iterator will not work. </li> + <li> Fixed: using assign semantic action in a grammar with a multi_pass iterator + adaptor applied to an std::istream_iterator resulted in a failure to compile + under msvc 7.0. </li> + <li> Fixed: There is a bug in the "range_run<CharT>::set (range<CharT> + const& r)" function in the "boost\spirit\utility\impl\chset\range_run.ipp". + </li> + <li> Fixed: handling of trailing whitespace bug (ast_parse/pt_parse related)</li> + <li> Fixed: comment_p and end of data bug</li> + <li> Fixed: <a href="http://article.gmane.org/gmane.comp.parsers.spirit.general/4029">Most + trailing space bug</a>:</li> + <li> Fixed:<br> + chset<>::operator~(range<>) bug<br> + operator&(chset<>, range<>) bug<br> + operator&(range<>, chset<>) bug</li> + <li> Fixed: <a href="http://sourceforge.net/mailarchive/forum.php?thread_id=2008510&forum_id=25901">impl::detach_clear + bug</a></li> + <li> Fixed: <a href="http://article.gmane.org/gmane.comp.parsers.spirit.general/3678">mismatch + closure return type bug</a></li> + <li> Fixed: <a href="http://sf.net/mailarchive/forum.php?thread_id=1963157&forum_id=1595">access_node_d[]</a> + and <a href="http://sf.net/mailarchive/forum.php?thread_id=1966224&forum_id=1595">access_match_d[]</a> + iterator bugs</li> + <li> Fixed a bug regarding threadsafety of Phoenix/Spirit closures.</li> + <li> Added missing include files to miniboost</li> +</ul> +<p> <font size="2" color="#666666">Copyright © 1998-2005 Joel de Guzman, Hartmut Kaiser</font><br> +<font size="2"><font color="#666666">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) </font> </font></p> +<p> </p> + +</body> +</html> diff --git a/src/boost/libs/spirit/classic/example/Jamfile b/src/boost/libs/spirit/classic/example/Jamfile new file mode 100644 index 00000000..7079152f --- /dev/null +++ b/src/boost/libs/spirit/classic/example/Jamfile @@ -0,0 +1,300 @@ +#============================================================================== +# Copyright (c) 2002 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) +#============================================================================== +# +# Spirit examples boost-jam file +# Joel de Guzman [Sep 27, 2002] : created +# Joel de Guzman [Oct 30, 2003] : separated the applications +# Martin Wille [Jan 15, 2004] : changes for new directory structure +# Martin Wille [Jan 20, 2004] : more changes for new directory structure +# Joel de Guzman [Jul 29, 2004] : added calc_debug.cpp +# + +exe ast_calc + : fundamental/ast_calc.cpp + : + ; + +exe "bind" + : fundamental/bind.cpp + : + ; + +exe boiler_plate + : fundamental/boiler_plate.cpp + : + ; + +exe calc_plain + : fundamental/calc_plain.cpp + : + ; + +exe calc_debug + : fundamental/calc_debug.cpp + : + ; + +exe comments + : fundamental/comments.cpp + : + ; + +exe complex_number + : fundamental/complex_number.cpp + : + ; + +exe error_handling + : fundamental/error_handling.cpp + : + ; + +exe error_reporting + : fundamental/error_reporting.cpp + : + ; + +exe file_parser + : fundamental/file_parser.cpp + : + ; + +exe full_calc + : fundamental/full_calc.cpp + : + ; + +exe functor_parser + : fundamental/functor_parser.cpp + : + ; + +exe list_parser + : fundamental/list_parser.cpp + : + ; + +exe matching_tags + : fundamental/matching_tags.cpp + : + ; + +exe no_actions + : fundamental/no_actions.cpp + : + ; + +exe number_list + : fundamental/number_list.cpp + : + ; + +exe parse_tree_calc1 + : fundamental/parse_tree_calc1.cpp + : + ; + +exe parser_context + : fundamental/parser_context.cpp + : + ; + +exe phoenix_calc + : fundamental/phoenix_calc.cpp + : + ; + +exe position_iterator + : fundamental/position_iterator/position_iterator.cpp + : + ; + +exe refactoring + : fundamental/refactoring.cpp + : + ; + +exe regular_expression + : fundamental/regular_expression.cpp + /boost//regex + : + ; + +exe roman_numerals + : fundamental/roman_numerals.cpp + : + ; + +exe stuff_vector + : fundamental/stuff_vector.cpp + : + ; + +exe stuff_vector2 + : fundamental/stuff_vector2.cpp + : + ; + +exe subrule_calc + : fundamental/subrule_calc.cpp + : + ; + +exe sum + : fundamental/sum.cpp + : + ; + +exe thousand_separated + : fundamental/thousand_separated.cpp + : + ; + +exe ast_calc2 + : fundamental/more_calculators/ast_calc2.cpp + : + ; + +exe calc_with_variables + : fundamental/more_calculators/calc_with_variables.cpp + : + ; + +exe phoenix_subrule_calc + : fundamental/more_calculators/phoenix_subrule_calc.cpp + : + ; + +exe primitive_calc + : fundamental/more_calculators/primitive_calc.cpp + : + ; + +exe rpn_calc + : fundamental/more_calculators/rpn_calc.cpp + : + ; + +exe vmachine_calc + : fundamental/more_calculators/vmachine_calc.cpp + : + ; + +exe distinct_parser + : fundamental/distinct/distinct_parser.cpp + : + ; + +exe distinct_parser_dynamic + : fundamental/distinct/distinct_parser_dynamic.cpp + : + ; + +################################################################################ + +exe ipv4 + : intermediate/ipv4.cpp + : + ; + +exe ipv4_opt + : intermediate/ipv4_opt.cpp + : + ; + +exe lazy_parser + : intermediate/lazy_parser.cpp + : + ; + +exe parameters + : intermediate/parameters.cpp + : + ; + +exe regex_convert + : intermediate/regex_convert.cpp + /boost//regex + : + ; + +exe simple_xml + : intermediate/simple_xml/driver.cpp + intermediate/simple_xml/tag.cpp + intermediate/simple_xml/tag.cpp + : + ; + +################################################################################ + +exe dynamic_rule + : techniques/dynamic_rule.cpp + : + ; + +exe epsilon + : techniques/epsilon.cpp + : + ; + +exe multiple_scanners + : techniques/multiple_scanners.cpp + : + ; + +exe nabialek + : techniques/nabialek.cpp + : + ; + +exe no_rule1 + : techniques/no_rules/no_rule1.cpp + : + ; + +exe no_rule2 + : techniques/no_rules/no_rule2.cpp + : + ; + +exe no_rule3 + : techniques/no_rules/no_rule3.cpp + : + ; + +exe typeof + : techniques/typeof.cpp + : + ; + +exe rule_parser_1_1 + : techniques/no_rules_with_typeof/rule_parser_1_1.cpp + : + ; + +exe rule_parser_1_2 + : techniques/no_rules_with_typeof/rule_parser_1_2.cpp + : + ; + +exe rule_parser_2_1 + : techniques/no_rules_with_typeof/rule_parser_2_1.cpp + : + ; + +exe rule_parser_2_2 + : techniques/no_rules_with_typeof/rule_parser_2_2.cpp + : + ; + +exe opaque_rule_parser + : techniques/no_rules_with_typeof/opaque_rule_parser.cpp + : + ; + diff --git a/src/boost/libs/spirit/classic/example/fundamental/ast_calc.cpp b/src/boost/libs/spirit/classic/example/fundamental/ast_calc.cpp new file mode 100644 index 00000000..33c5e0f1 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/ast_calc.cpp @@ -0,0 +1,159 @@ +/*============================================================================= + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// Demonstrates the ASTs. This is discussed in the +// "Trees" chapter in the Spirit User's Guide. +// +/////////////////////////////////////////////////////////////////////////////// +#define BOOST_SPIRIT_DUMP_PARSETREE_AS_XML + +#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/assert.hpp> +#include "tree_calc_grammar.hpp" + +#include <iostream> +#include <stack> +#include <functional> +#include <string> + +#if defined(BOOST_SPIRIT_DUMP_PARSETREE_AS_XML) +#include <map> +#endif + +// This example shows how to use an AST. +//////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +typedef char const* iterator_t; +typedef tree_match<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) +{ + cout << "In eval_expression. i->value = " << + string(i->value.begin(), i->value.end()) << + " i->children.size() = " << i->children.size() << endl; + + if (i->value.id() == calculator::integerID) + { + BOOST_ASSERT(i->children.size() == 0); + + // extract integer (not always delimited by '\0') + string integer(i->value.begin(), i->value.end()); + + return strtol(integer.c_str(), 0, 10); + } + else if (i->value.id() == calculator::factorID) + { + // factor can only be unary minus + BOOST_ASSERT(*i->value.begin() == '-'); + return - eval_expression(i->children.begin()); + } + else if (i->value.id() == calculator::termID) + { + if (*i->value.begin() == '*') + { + BOOST_ASSERT(i->children.size() == 2); + return eval_expression(i->children.begin()) * + eval_expression(i->children.begin()+1); + } + else if (*i->value.begin() == '/') + { + BOOST_ASSERT(i->children.size() == 2); + return eval_expression(i->children.begin()) / + eval_expression(i->children.begin()+1); + } + else + BOOST_ASSERT(0); + } + else if (i->value.id() == calculator::expressionID) + { + if (*i->value.begin() == '+') + { + BOOST_ASSERT(i->children.size() == 2); + return eval_expression(i->children.begin()) + + eval_expression(i->children.begin()+1); + } + else if (*i->value.begin() == '-') + { + BOOST_ASSERT(i->children.size() == 2); + return eval_expression(i->children.begin()) - + eval_expression(i->children.begin()+1); + } + else + BOOST_ASSERT(0); + } + else + { + BOOST_ASSERT(0); // error + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + // look in tree_calc_grammar for the definition of calculator + calculator calc; + + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tThe simplest working calculator...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type an expression...or [q or Q] to quit\n\n"; + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + tree_parse_info<> info = ast_parse(str.c_str(), calc); + + if (info.full) + { +#if defined(BOOST_SPIRIT_DUMP_PARSETREE_AS_XML) + // dump parse tree as XML + std::map<parser_id, std::string> rule_names; + rule_names[calculator::integerID] = "integer"; + rule_names[calculator::factorID] = "factor"; + rule_names[calculator::termID] = "term"; + rule_names[calculator::expressionID] = "expression"; + tree_to_xml(cout, info.trees, str.c_str(), rule_names); +#endif + + // print the result + cout << "parsing succeeded\n"; + cout << "result = " << evaluate(info) << "\n\n"; + } + else + { + cout << "parsing failed\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/bind.cpp b/src/boost/libs/spirit/classic/example/fundamental/bind.cpp new file mode 100644 index 00000000..f38e9c23 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/bind.cpp @@ -0,0 +1,126 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// Demonstrates use of boost::bind and spirit +// This is discussed in the "Functional" chapter in the Spirit User's Guide. +// +// [ JDG 9/29/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/bind.hpp> +#include <iostream> +#include <vector> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace boost; + +/////////////////////////////////////////////////////////////////////////////// +// +// Our comma separated list parser +// +/////////////////////////////////////////////////////////////////////////////// +class list_parser +{ +public: + + typedef list_parser self_t; + + bool + parse(char const* str) + { + return BOOST_SPIRIT_CLASSIC_NS::parse(str, + + // Begin grammar + ( + real_p + [ + bind(&self_t::add, this, _1) + ] + + >> *( ',' + >> real_p + [ + bind(&self_t::add, this, _1) + ] + ) + ) + , + // End grammar + + space_p).full; + } + + void + add(double n) + { + v.push_back(n); + } + + void + print() const + { + for (vector<double>::size_type i = 0; i < v.size(); ++i) + cout << i << ": " << v[i] << endl; + } + + vector<double> v; +}; + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\tA comma separated list parser for Spirit...\n"; + cout << "\tDemonstrates use of boost::bind and spirit\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + + cout << "Give me a comma separated list of numbers.\n"; + cout << "The numbers will be inserted in a vector of numbers\n"; + cout << "Type [q or Q] to quit\n\n"; + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + list_parser lp; + if (lp.parse(str.c_str())) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << str << " Parses OK: " << endl; + + lp.print(); + + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/boiler_plate.cpp b/src/boost/libs/spirit/classic/example/fundamental/boiler_plate.cpp new file mode 100644 index 00000000..91c9fc73 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/boiler_plate.cpp @@ -0,0 +1,97 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// Boiler plate [ A template for writing your parser ] +// +// [ JDG 9/17/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <iostream> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Semantic actions +// +/////////////////////////////////////////////////////////////////////////////// +struct my_action +{ + template <typename IteratorT> + void operator()(IteratorT first, IteratorT last) const + { + string s(first, last); + cout << "\tMy Action got: " << s << endl; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// My grammar +// +/////////////////////////////////////////////////////////////////////////////// +struct my_grammar : public grammar<my_grammar> +{ + template <typename ScannerT> + struct definition + { + definition(my_grammar const& self) + { + my_rule = + *lexeme_d[(+graph_p)[my_action()]] + ; + } + + rule<ScannerT> my_rule; + rule<ScannerT> const& + start() const { return my_rule; } + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Main program +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\t A boiler-plate parser...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type anything or [q or Q] to quit\n\n"; + + my_grammar g; + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + if (parse(str.c_str(), g, space_p).full) + { + cout << "parsing succeeded\n"; + } + else + { + cout << "parsing failed\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/calc_debug.cpp b/src/boost/libs/spirit/classic/example/fundamental/calc_debug.cpp new file mode 100644 index 00000000..f0ddf425 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/calc_debug.cpp @@ -0,0 +1,199 @@ +/*============================================================================= + Copyright (c) 2001-2003 Dan Nuffer + Copyright (c) 2002-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) +=============================================================================*/ +//////////////////////////////////////////////////////////////////////////// +// +// Full calculator example using STL functors with debugging enabled. +// This is discussed in the "Functional" chapter in the Spirit User's Guide +// and the Debugging chapter. +// +// Ported to Spirit v1.5 from v1.2/1.3 example by Dan Nuffer +// [ JDG 9/18/2002 ] +// [ JDG 7/29/2004 ] +// +//////////////////////////////////////////////////////////////////////////// + +#define BOOST_SPIRIT_DEBUG +#include <boost/spirit/include/classic_core.hpp> +#include <iostream> +#include <stack> +#include <functional> +#include <string> + +//////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +//////////////////////////////////////////////////////////////////////////// +// +// Semantic actions +// +//////////////////////////////////////////////////////////////////////////// +struct push_int +{ + push_int(stack<long>& eval_) + : eval(eval_) {} + + void operator()(char const* str, char const* /*end*/) const + { + long n = strtol(str, 0, 10); + eval.push(n); + cout << "push\t" << long(n) << endl; + } + + stack<long>& eval; +}; + +template <typename op> +struct do_op +{ + do_op(op const& the_op, stack<long>& eval_) + : m_op(the_op), eval(eval_) {} + + void operator()(char const*, char const*) const + { + long rhs = eval.top(); + eval.pop(); + long lhs = eval.top(); + eval.pop(); + + cout << "popped " << lhs << " and " << rhs << " from the stack. "; + cout << "pushing " << m_op(lhs, rhs) << " onto the stack.\n"; + eval.push(m_op(lhs, rhs)); + } + + op m_op; + stack<long>& eval; +}; + +template <class op> +do_op<op> +make_op(op const& the_op, stack<long>& eval) +{ + return do_op<op>(the_op, eval); +} + +struct do_negate +{ + do_negate(stack<long>& eval_) + : eval(eval_) {} + + void operator()(char const*, char const*) const + { + long lhs = eval.top(); + eval.pop(); + + cout << "popped " << lhs << " from the stack. "; + cout << "pushing " << -lhs << " onto the stack.\n"; + eval.push(-lhs); + } + + stack<long>& eval; +}; + +//////////////////////////////////////////////////////////////////////////// +// +// Our calculator grammar +// +//////////////////////////////////////////////////////////////////////////// +struct calculator : public grammar<calculator> +{ + calculator(stack<long>& eval_) + : eval(eval_) {} + + template <typename ScannerT> + struct definition + { + definition(calculator const& self) + { + integer = + lexeme_d[ (+digit_p)[push_int(self.eval)] ] + ; + + factor = + integer + | '(' >> expression >> ')' + | ('-' >> factor)[do_negate(self.eval)] + | ('+' >> factor) + ; + + term = + factor + >> *( ('*' >> factor)[make_op(multiplies<long>(), self.eval)] + | ('/' >> factor)[make_op(divides<long>(), self.eval)] + ) + ; + + expression = + term + >> *( ('+' >> term)[make_op(plus<long>(), self.eval)] + | ('-' >> term)[make_op(minus<long>(), self.eval)] + ) + ; + + BOOST_SPIRIT_DEBUG_NODE(integer); + BOOST_SPIRIT_DEBUG_NODE(factor); + BOOST_SPIRIT_DEBUG_NODE(term); + BOOST_SPIRIT_DEBUG_NODE(expression); + } + + rule<ScannerT> expression, term, factor, integer; + rule<ScannerT> const& + start() const { return expression; } + }; + + stack<long>& eval; +}; + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tThe simplest working calculator...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type an expression...or [q or Q] to quit\n\n"; + + stack<long> eval; + calculator calc(eval); // Our parser + BOOST_SPIRIT_DEBUG_NODE(calc); + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + parse_info<> info = parse(str.c_str(), calc, space_p); + + if (info.full) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << "result = " << calc.eval.top() << endl; + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "stopped at: \": " << info.stop << "\"\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/calc_plain.cpp b/src/boost/libs/spirit/classic/example/fundamental/calc_plain.cpp new file mode 100644 index 00000000..520134f3 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/calc_plain.cpp @@ -0,0 +1,129 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ +//////////////////////////////////////////////////////////////////////////// +// +// Plain calculator example demostrating the grammar and semantic actions. +// This is discussed in the "Grammar" and "Semantic Actions" chapters in +// the Spirit User's Guide. +// +// [ JDG 5/10/2002 ] +// +//////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <iostream> +#include <string> + +//////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +//////////////////////////////////////////////////////////////////////////// +// +// Semantic actions +// +//////////////////////////////////////////////////////////////////////////// +namespace +{ + void do_int(char const* str, char const* end) + { + string s(str, end); + cout << "PUSH(" << s << ')' << endl; + } + + void do_add(char const*, char const*) { cout << "ADD\n"; } + void do_subt(char const*, char const*) { cout << "SUBTRACT\n"; } + void do_mult(char const*, char const*) { cout << "MULTIPLY\n"; } + void do_div(char const*, char const*) { cout << "DIVIDE\n"; } + void do_neg(char const*, char const*) { cout << "NEGATE\n"; } +} + +//////////////////////////////////////////////////////////////////////////// +// +// Our calculator grammar +// +//////////////////////////////////////////////////////////////////////////// +struct calculator : public grammar<calculator> +{ + template <typename ScannerT> + struct definition + { + definition(calculator const& /*self*/) + { + expression + = term + >> *( ('+' >> term)[&do_add] + | ('-' >> term)[&do_subt] + ) + ; + + term + = factor + >> *( ('*' >> factor)[&do_mult] + | ('/' >> factor)[&do_div] + ) + ; + + factor + = lexeme_d[(+digit_p)[&do_int]] + | '(' >> expression >> ')' + | ('-' >> factor)[&do_neg] + | ('+' >> factor) + ; + } + + rule<ScannerT> expression, term, factor; + + rule<ScannerT> const& + start() const { return expression; } + }; +}; + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tExpression parser...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type an expression...or [q or Q] to quit\n\n"; + + calculator calc; // Our parser + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + parse_info<> info = parse(str.c_str(), calc, space_p); + + if (info.full) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "stopped at: \": " << info.stop << "\"\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/comments.cpp b/src/boost/libs/spirit/classic/example/fundamental/comments.cpp new file mode 100644 index 00000000..9ffb4168 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/comments.cpp @@ -0,0 +1,232 @@ +/*============================================================================= + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// This example shows: +// 1. Parsing of different comment styles +// parsing C/C++-style comment +// parsing C++-style comment +// parsing PASCAL-style comment +// 2. Parsing tagged data with the help of the confix_parser +// 3. Parsing tagged data with the help of the confix_parser but the semantic +// action is directly attached to the body sequence parser +// +/////////////////////////////////////////////////////////////////////////////// + +#include <string> +#include <iostream> +#include <cassert> + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_confix.hpp> +#include <boost/spirit/include/classic_chset.hpp> + + +/////////////////////////////////////////////////////////////////////////////// +// used namespaces +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// actor called after successfully matching a single character +class actor_string +{ +public: + actor_string(std::string &rstr) : + matched(rstr) + { + } + + void operator() (const char *pbegin, const char *pend) const + { + matched += std::string(pbegin, pend-pbegin); + } + +private: + std::string &matched; +}; + +/////////////////////////////////////////////////////////////////////////////// +// actor called after successfully matching a C++-comment +void actor_cpp (const char *pfirst, const char *plast) +{ + cout << "Parsing C++-comment" <<endl; + cout << "Matched (" << plast-pfirst << ") characters: "; + cout << "\"" << std::string(pfirst, plast) << "\"" << endl; +} + +/////////////////////////////////////////////////////////////////////////////// +// main entry point +int main () +{ + +/////////////////////////////////////////////////////////////////////////////// +// +// 1. Parsing different comment styles +// parsing C/C++-style comments (non-nested!) +// +/////////////////////////////////////////////////////////////////////////////// + + char const* pCComment = "/* This is a /* nested */ C-comment */"; + + rule<> cpp_comment; + + cpp_comment = + comment_p("/*", "*/") // rule for C-comments + | comment_p("//") // rule for C++ comments + ; + + std::string comment_c; + parse_info<> result; + + result = parse (pCComment, cpp_comment[actor_string(comment_c)]); + if (result.hit) + { + cout << "Parsed C-comment successfully!" << endl; + cout << "Matched (" << (int)comment_c.size() << ") characters: "; + cout << "\"" << comment_c << "\"" << endl; + } + else + { + cout << "Failed to parse C/C++-comment!" << endl; + } + cout << endl; + + // parsing C++-style comment + char const* pCPPComment = "// This is a C++-comment\n"; + std::string comment_cpp; + + result = parse (pCPPComment, cpp_comment[&actor_cpp]); + if (result.hit) + cout << "Parsed C++-comment successfully!" << endl; + else + cout << "Failed to parse C++-comment!" << endl; + + cout << endl; + + + // parsing PASCAL-style comment (nested!) + char const* pPComment = "{ This is a (* nested *) PASCAL-comment }"; + + rule<> pascal_comment; + + pascal_comment = // in PASCAL we have two comment styles + comment_nest_p('{', '}') // both may be nested + | comment_nest_p("(*", "*)") + ; + + std::string comment_pascal; + + result = parse (pPComment, pascal_comment[actor_string(comment_pascal)]); + if (result.hit) + { + cout << "Parsed PASCAL-comment successfully!" << endl; + cout << "Matched (" << (int)comment_pascal.size() << ") characters: "; + cout << "\"" << comment_pascal << "\"" << endl; + } + else + { + cout << "Failed to parse PASCAL-comment!" << endl; + } + cout << endl; + +/////////////////////////////////////////////////////////////////////////////// +// +// 2. Parsing tagged data with the help of the confix parser +// +/////////////////////////////////////////////////////////////////////////////// + + std::string body; + rule<> open_tag, html_tag, close_tag, body_text; + + open_tag = + str_p("<b>") + ; + + body_text = + anychar_p + ; + + close_tag = + str_p("</b>") + ; + + html_tag = + confix_p (open_tag, (*body_text)[actor_string(body)], close_tag) + ; + + char const* pTag = "<b>Body text</b>"; + + result = parse (pTag, html_tag); + if (result.hit) + { + cout << "Parsed HTML snippet \"<b>Body text</b>\" successfully " + "(with re-attached actor)!" << endl; + cout << "Found body (" << (int)body.size() << " characters): "; + cout << "\"" << body << "\"" << endl; + } + else + { + cout << "Failed to parse HTML snippet (with re-attached actor)!" + << endl; + } + cout << endl; + +/////////////////////////////////////////////////////////////////////////////// +// +// 3. Parsing tagged data with the help of the confix_parser but the +// semantic action is directly attached to the body sequence parser +// (see comment in confix.hpp) and out of the usage of the 'direct()' +// construction function no automatic refactoring takes place. +// +// As you can see, for successful parsing it is required to refactor the +// confix parser by hand. To see, how it fails, you can try the following: +// +// html_tag_direct = +// confix_p.direct( +// str_p("<b>"), +// (*body_text)[actor_string(bodydirect)], +// str_p("</b>") +// ) +// ; +// +// Here the *body_text parser eats up all the input up to the end of the +// input sequence. +// +/////////////////////////////////////////////////////////////////////////////// + + rule<> html_tag_direct; + std::string bodydirect; + + html_tag_direct = + confix_p.direct( + str_p("<b>"), + (*(body_text - str_p("</b>")))[actor_string(bodydirect)], + str_p("</b>") + ) + ; + + char const* pTagDirect = "<b>Body text</b>"; + + result = parse (pTagDirect, html_tag_direct); + if (result.hit) + { + cout << "Parsed HTML snippet \"<b>Body text</b>\" successfully " + "(with direct actor)!" << endl; + cout << "Found body (" << (int)bodydirect.size() << " characters): "; + cout << "\"" << bodydirect << "\"" << endl; + } + else + { + cout << "Failed to parse HTML snippet (with direct actor)!" << endl; + } + cout << endl; + + return 0; +} diff --git a/src/boost/libs/spirit/classic/example/fundamental/complex_number.cpp b/src/boost/libs/spirit/classic/example/fundamental/complex_number.cpp new file mode 100644 index 00000000..3cb8d807 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/complex_number.cpp @@ -0,0 +1,103 @@ +/*============================================================================= + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A complex number micro parser (using subrules) +// +// [ JDG 5/10/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <iostream> +#include <complex> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Our complex number micro parser +// +/////////////////////////////////////////////////////////////////////////////// +bool +parse_complex(char const* str, complex<double>& c) +{ + double rN = 0.0; + double iN = 0.0; + + subrule<0> first; + subrule<1> r; + subrule<2> i; + + if (parse(str, + + // Begin grammar + ( + first = '(' >> r >> !(',' >> i) >> ')' | r, + r = real_p[assign(rN)], + i = real_p[assign(iN)] + ) + , + // End grammar + + space_p).full) + { + c = complex<double>(rN, iN); + return true; + } + else + { + return false; + } +} + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tA complex number micro parser for Spirit...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + + cout << "Give me a complex number of the form r or (r) or (r,i) \n"; + cout << "Type [q or Q] to quit\n\n"; + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + complex<double> c; + if (parse_complex(str.c_str(), c)) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << str << " Parses OK: " << c << endl; + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/distinct/distinct_parser.cpp b/src/boost/libs/spirit/classic/example/fundamental/distinct/distinct_parser.cpp new file mode 100644 index 00000000..6b4506d6 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/distinct/distinct_parser.cpp @@ -0,0 +1,68 @@ +/*============================================================================= + 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/assert.hpp> +#include <iostream> +#include <boost/cstdlib.hpp> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_distinct.hpp> + +using namespace std; +using namespace boost; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +// keyword_p for C++ +// (for basic usage instead of std_p) +const distinct_parser<> keyword_p("0-9a-zA-Z_"); + +// keyword_d for C++ +// (for mor intricate usage, for example together with symbol tables) +const distinct_directive<> keyword_d("0-9a-zA-Z_"); + +struct my_grammar: public grammar<my_grammar> +{ + template <typename ScannerT> + struct definition + { + typedef rule<ScannerT> rule_t; + + definition(my_grammar const& self) + { + top + = + keyword_p("declare") // use keyword_p instead of std_p + >> !ch_p(':') + >> keyword_d[str_p("ident")] // use keyword_d + ; + } + + rule_t top; + + rule_t const& start() const + { + return top; + } + }; +}; + +int main() +{ + my_grammar gram; + parse_info<> info; + + info = parse("declare ident", gram, space_p); + BOOST_ASSERT(info.full); // valid input + + info = parse("declare: ident", gram, space_p); + BOOST_ASSERT(info.full); // valid input + + info = parse("declareident", gram, space_p); + BOOST_ASSERT(!info.hit); // invalid input + + return exit_success; +} diff --git a/src/boost/libs/spirit/classic/example/fundamental/distinct/distinct_parser_dynamic.cpp b/src/boost/libs/spirit/classic/example/fundamental/distinct/distinct_parser_dynamic.cpp new file mode 100644 index 00000000..8e64fd64 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/distinct/distinct_parser_dynamic.cpp @@ -0,0 +1,64 @@ +/*============================================================================= + 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/assert.hpp> +#include <iostream> +#include <boost/cstdlib.hpp> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_distinct.hpp> + +using namespace std; +using namespace boost; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +struct my_grammar: public grammar<my_grammar> +{ + template <typename ScannerT> + struct definition + { + typedef rule<ScannerT> rule_t; + + // keyword_p for ASN.1 + dynamic_distinct_parser<ScannerT> keyword_p; + + definition(my_grammar const& self) + : keyword_p(alnum_p | ('-' >> ~ch_p('-'))) // ASN.1 has quite complex naming rules + { + top + = + keyword_p("asn-declare") // use keyword_p instead of std_p + >> !str_p("--") + >> keyword_p("ident") + ; + } + + rule_t top; + + rule_t const& start() const + { + return top; + } + }; +}; + +int main() +{ + my_grammar gram; + parse_info<> info; + + info = parse("asn-declare ident", gram, space_p); + BOOST_ASSERT(info.full); // valid input + + info = parse("asn-declare--ident", gram, space_p); + BOOST_ASSERT(info.full); // valid input + + info = parse("asn-declare-ident", gram, space_p); + BOOST_ASSERT(!info.hit); // invalid input + + return exit_success; +} diff --git a/src/boost/libs/spirit/classic/example/fundamental/error_handling.cpp b/src/boost/libs/spirit/classic/example/fundamental/error_handling.cpp new file mode 100644 index 00000000..f2efcc24 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/error_handling.cpp @@ -0,0 +1,55 @@ +/*============================================================================= + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// This sample demonstrates error handling as seen in the +// Error Handling" chapter in the User's Guide. +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_exceptions.hpp> +#include <iostream> +#include <boost/assert.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; + + rule<> start = + my_guard(ch_p('a') >> 'b' >> 'c' >> expect( ch_p('d') )) + [ + handler() + ]; + + bool r = parse("abcx", start).full; + + BOOST_ASSERT(!r); + return 0; +} + diff --git a/src/boost/libs/spirit/classic/example/fundamental/error_reporting.cpp b/src/boost/libs/spirit/classic/example/fundamental/error_reporting.cpp new file mode 100644 index 00000000..4b18781f --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/error_reporting.cpp @@ -0,0 +1,114 @@ +/*============================================================================= + Copyright (c) 2003 Pavel Baranov + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// An alternate error-handling scheme where the parser will +// complain (but not stop) if input doesn't match. +// +// [ Pavel Baranov 8/27/2003 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_functor_parser.hpp> +#include <iostream> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +static short errcount = 0; + +/////////////////////////////////////////////////////////////////////////////// +// +// Error reporting parser +// +/////////////////////////////////////////////////////////////////////////////// +struct error_report_parser { + + error_report_parser(const char *msg) : _msg(msg) {} + + typedef nil_t result_t; + + template <typename ScannerT> + int operator()(ScannerT const& scan, result_t& /*result*/) const + { + errcount++; + cerr << _msg << endl; + return 0; + } + +private: + string _msg; +}; + +typedef functor_parser<error_report_parser> error_report_p; + +/////////////////////////////////////////////////////////////////////////////// +// +// My grammar +// +/////////////////////////////////////////////////////////////////////////////// +struct my_grammar : public grammar<my_grammar> +{ + static error_report_p error_missing_semicolon; + static error_report_p error_missing_letter; + + template <typename ScannerT> + struct definition + { + definition(my_grammar const& self) : + SEMICOLON(';') + { + my_rule + = *(eps_p(alpha_p|SEMICOLON) >> + (alpha_p|error_missing_letter) >> + (SEMICOLON|error_missing_semicolon)) + ; + } + + chlit<> + SEMICOLON; + + rule<ScannerT> my_rule; + + rule<ScannerT> const& + start() const { return my_rule; } + }; +}; + +error_report_p my_grammar::error_missing_semicolon("missing semicolon"); +error_report_p my_grammar::error_missing_letter("missing letter"); + +/////////////////////////////////////////////////////////////////////////////// +// +// Main program +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << " Error handling demo\n\n"; + cout << " The parser expects a sequence of letter/semicolon pairs\n"; + cout << " and will complain (but not stop) if input doesn't match.\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + + my_grammar g; + + string str( "a;;b;cd;e;fg;" ); + cout << "input: " << str << "\n\n"; + + if( parse(str.c_str(), g, space_p).full && !errcount ) + cout << "\nparsing succeeded\n"; + else + cout << "\nparsing failed\n"; + + return 0; +} diff --git a/src/boost/libs/spirit/classic/example/fundamental/file_parser.cpp b/src/boost/libs/spirit/classic/example/fundamental/file_parser.cpp new file mode 100644 index 00000000..cd4036b1 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/file_parser.cpp @@ -0,0 +1,89 @@ +/*============================================================================= + Copyright (c) 2002 Jeff Westfahl + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A parser that echoes a file +// See the "File Iterator" chapter in the User's Guide. +// +// [ JMW 8/05/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_file_iterator.hpp> +#include <iostream> + +/////////////////////////////////////////////////////////////////////////////// +using namespace BOOST_SPIRIT_CLASSIC_NS; + +//////////////////////////////////////////////////////////////////////////// +// +// Types +// +//////////////////////////////////////////////////////////////////////////// +typedef char char_t; +typedef file_iterator<char_t> iterator_t; +typedef scanner<iterator_t> scanner_t; +typedef rule<scanner_t> rule_t; + +//////////////////////////////////////////////////////////////////////////// +// +// Actions +// +//////////////////////////////////////////////////////////////////////////// +void echo(iterator_t first, iterator_t const& last) +{ + while (first != last) + std::cout << *first++; +} + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main(int argc, char* argv[]) +{ + if (2 > argc) + { + std::cout << "Must specify a filename!\n"; + return -1; + } + + // Create a file iterator for this file + iterator_t first(argv[1]); + + if (!first) + { + std::cout << "Unable to open file!\n"; + return -1; + } + + // Create an EOF iterator + iterator_t last = first.make_end(); + + // A simple rule + rule_t r = *(anychar_p); + + // Parse + parse_info <iterator_t> info = parse( + first, + last, + r[&echo] + ); + + // This really shouldn't fail... + if (info.full) + std::cout << "Parse succeeded!\n"; + else + std::cout << "Parse failed!\n"; + + return 0; +} diff --git a/src/boost/libs/spirit/classic/example/fundamental/full_calc.cpp b/src/boost/libs/spirit/classic/example/fundamental/full_calc.cpp new file mode 100644 index 00000000..e1184d05 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/full_calc.cpp @@ -0,0 +1,188 @@ +/*============================================================================= + Copyright (c) 2001-2003 Dan Nuffer + Copyright (c) 2002-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) +=============================================================================*/ +//////////////////////////////////////////////////////////////////////////// +// +// Full calculator example using STL functors +// This is discussed in the "Functional" chapter in the Spirit User's Guide. +// +// Ported to Spirit v1.5 from v1.2/1.3 example by Dan Nuffer +// [ JDG 9/18/2002 ] +// +//////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <iostream> +#include <stack> +#include <functional> +#include <string> + +//////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +//////////////////////////////////////////////////////////////////////////// +// +// Semantic actions +// +//////////////////////////////////////////////////////////////////////////// +struct push_int +{ + push_int(stack<long>& eval_) + : eval(eval_) {} + + void operator()(char const* str, char const* /*end*/) const + { + long n = strtol(str, 0, 10); + eval.push(n); + cout << "push\t" << long(n) << endl; + } + + stack<long>& eval; +}; + +template <typename op> +struct do_op +{ + do_op(op const& the_op, stack<long>& eval_) + : m_op(the_op), eval(eval_) {} + + void operator()(char const*, char const*) const + { + long rhs = eval.top(); + eval.pop(); + long lhs = eval.top(); + eval.pop(); + + cout << "popped " << lhs << " and " << rhs << " from the stack. "; + cout << "pushing " << m_op(lhs, rhs) << " onto the stack.\n"; + eval.push(m_op(lhs, rhs)); + } + + op m_op; + stack<long>& eval; +}; + +template <class op> +do_op<op> +make_op(op const& the_op, stack<long>& eval) +{ + return do_op<op>(the_op, eval); +} + +struct do_negate +{ + do_negate(stack<long>& eval_) + : eval(eval_) {} + + void operator()(char const*, char const*) const + { + long lhs = eval.top(); + eval.pop(); + + cout << "popped " << lhs << " from the stack. "; + cout << "pushing " << -lhs << " onto the stack.\n"; + eval.push(-lhs); + } + + stack<long>& eval; +}; + +//////////////////////////////////////////////////////////////////////////// +// +// Our calculator grammar +// +//////////////////////////////////////////////////////////////////////////// +struct calculator : public grammar<calculator> +{ + calculator(stack<long>& eval_) + : eval(eval_) {} + + template <typename ScannerT> + struct definition + { + definition(calculator const& self) + { + integer = + lexeme_d[ (+digit_p)[push_int(self.eval)] ] + ; + + factor = + integer + | '(' >> expression >> ')' + | ('-' >> factor)[do_negate(self.eval)] + | ('+' >> factor) + ; + + term = + factor + >> *( ('*' >> factor)[make_op(multiplies<long>(), self.eval)] + | ('/' >> factor)[make_op(divides<long>(), self.eval)] + ) + ; + + expression = + term + >> *( ('+' >> term)[make_op(plus<long>(), self.eval)] + | ('-' >> term)[make_op(minus<long>(), self.eval)] + ) + ; + } + + rule<ScannerT> expression, term, factor, integer; + rule<ScannerT> const& + start() const { return expression; } + }; + + stack<long>& eval; +}; + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tThe simplest working calculator...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type an expression...or [q or Q] to quit\n\n"; + + stack<long> eval; + calculator calc(eval); // Our parser + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + parse_info<> info = parse(str.c_str(), calc, space_p); + + if (info.full) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "stopped at: \": " << info.stop << "\"\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/functor_parser.cpp b/src/boost/libs/spirit/classic/example/fundamental/functor_parser.cpp new file mode 100644 index 00000000..e9a52f31 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/functor_parser.cpp @@ -0,0 +1,160 @@ +/*============================================================================= + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002 Juan Carlos Arevalo-Baeza + 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_functor_parser.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> +#include <iostream> +#include <vector> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +// +// Demonstrates the functor_parser. This is discussed in the +// "Functor Parser" chapter in the Spirit User's Guide. +// +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Our parser functor +// +/////////////////////////////////////////////////////////////////////////////// +struct number_parser +{ + typedef int result_t; + template <typename ScannerT> + int + operator()(ScannerT const& scan, result_t& result) const + { + if (scan.at_end()) + return -1; + + char ch = *scan; + if (ch < '0' || ch > '9') + return -1; + + result = 0; + int len = 0; + + do + { + result = result*10 + int(ch - '0'); + ++len; + ++scan; + } while (!scan.at_end() && (ch = *scan, ch >= '0' && ch <= '9')); + + return len; + } +}; + +functor_parser<number_parser> number_parser_p; + +/////////////////////////////////////////////////////////////////////////////// +// +// Our number parser functions +// +/////////////////////////////////////////////////////////////////////////////// +bool +parse_number(char const* str, int& n) +{ + return parse(str, lexeme_d[number_parser_p[assign_a(n)]], space_p).full; +} + +bool +parse_numbers(char const* str, std::vector<int>& n) +{ + return + parse( + str, + lexeme_d[number_parser_p[push_back_a(n)]] + >> *(',' >> lexeme_d[number_parser_p[push_back_a(n)]]), + space_p + ).full; +} + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tA number parser implemented as a functor for Spirit...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + + cout << "Give me an integer number command\n"; + cout << "Commands:\n"; + cout << " A <num> --> parses a single number\n"; + cout << " B <num>, <num>, ... --> parses a series of numbers "; + cout << "separated by commas\n"; + cout << " Q --> quit\n\n"; + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + else if (str[0] == 'a' || str[0] == 'A') + { + int n; + if (parse_number(str.c_str()+1, n)) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << str << " Parses OK: " << n << endl; + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "-------------------------\n"; + } + } + + else if (str[0] == 'b' || str[0] == 'B') + { + std::vector<int> n; + if (parse_numbers(str.c_str()+1, n)) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + int size = n.size(); + cout << str << " Parses OK: " << size << " number(s): " << n[0]; + for (int i = 1; i < size; ++i) { + cout << ", " << n[i]; + } + cout << endl; + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "-------------------------\n"; + } + } + + else + { + cout << "-------------------------\n"; + cout << "Unrecognized command!!"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} diff --git a/src/boost/libs/spirit/classic/example/fundamental/list_parser.cpp b/src/boost/libs/spirit/classic/example/fundamental/list_parser.cpp new file mode 100644 index 00000000..922fb5d0 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/list_parser.cpp @@ -0,0 +1,233 @@ +/*============================================================================= + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// This sample shows the usage of the list_p utility parser +// 1. parsing a simple ',' delimited list w/o item formatting +// 2. parsing a CSV list (comma separated values - strings, integers or reals) +// 3. parsing a token list (token separated values - strings, integers or +// reals) +// with an action parser directly attached to the item part of the list_p +// generated parser + +#include <string> +#include <iostream> +#include <cassert> +#include <vector> + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_confix.hpp> +#include <boost/spirit/include/classic_lists.hpp> +#include <boost/spirit/include/classic_escape_char.hpp> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// actor, attached to the list_p parser +class list_actor +{ +public: + list_actor (std::vector<std::string> &vec_) : vec(vec_) {} + + // The following operator() is called by the action parser generated by + // attaching this actor to a list_p generated list parser. + + template <typename ActionIterT> + void operator() (ActionIterT const &first, ActionIterT const &last) const + { + vec.push_back(std::string(first, last-first)); + } + +private: + std::vector<std::string> &vec; +}; + +/////////////////////////////////////////////////////////////////////////////// +// main entry point +int main () +{ + // 1. parsing a simple ',' delimited list w/o item formatting + char const* plist_wo_item = "element1,element2,element3"; + rule<> list_wo_item; + std::vector<std::string> vec_list; + + list_wo_item = + list_p[push_back_a(vec_list)] + ; + + parse_info<> result = parse (plist_wo_item, list_wo_item); + + cout << "-----------------------------------------------------------------" + << endl; + + if (result.hit) + { + cout + << "Parsing simple list" << endl + << "\t" << plist_wo_item << endl + << "Parsed successfully!" << endl << endl; + + cout + << "Actor was called " << (int)vec_list.size() + << " times: " << endl; + + cout + << "Results got from the list parser:" << endl; + for (std::vector<std::string>::iterator it = vec_list.begin(); + it != vec_list.end(); ++it) + { + cout << *it << endl; + } + } + else + { + cout << "Failed to parse simple list!" << endl; + } + + cout << endl; + + // 2. parsing a CSV list (comma separated values - strings, integers or + // reals) + char const *plist_csv = "\"string\",\"string with an embedded \\\"\"," + "12345,0.12345e4,,2"; + rule<> list_csv, list_csv_item; + std::vector<std::string> vec_item; + + vec_list.clear(); + + list_csv_item = + !( + confix_p('\"', *c_escape_ch_p, '\"') + | longest_d[real_p | int_p] + ); + + list_csv = + list_p( + list_csv_item[push_back_a(vec_item)], + ',' + )[push_back_a(vec_list)] + ; + + result = parse (plist_csv, list_csv); + + cout << "-----------------------------------------------------------------" + << endl; + if (result.hit) + { + cout + << "Parsing CSV list (comma separated values) " << endl + << "\t" << plist_csv << endl + << "Parsed successfully!" << endl << endl; + + if (result.full) + { + cout << "Matched " << (int)vec_list.size() << + " list elements (full list): " << endl; + } + else + { + cout << "Matched " << (int)vec_list.size() << + " list elements: " << endl; + } + + cout << "The list parser matched:" << endl; + for (std::vector<std::string>::iterator itl = vec_list.begin(); + itl != vec_list.end(); ++itl) + { + cout << *itl << endl; + } + + cout << endl << "Item(s) got directly from the item parser:" << endl; + for (std::vector<std::string>::iterator it = vec_item.begin(); + it != vec_item.end(); ++it) + { + cout << *it << endl; + } + + } + else + { + cout << "Failed to parse CSV list!" << endl; + } + + cout << endl; + + // 3. parsing a token list (token separated values - strings, integers or + // reals) with an action parser directly attached to the item part of the + // list_p generated parser + char const *plist_csv_direct = "\"string\"<par>\"string with an embedded " + "\\\"\"<par>12345<par>0.12345e4"; + rule<> list_csv_direct, list_csv_direct_item; + + vec_list.clear(); + vec_item.clear(); + + // Note: the list parser is here generated through the list_p.direct() + // generator function. This inhibits re-attachment of the item_actor_direct + // during parser construction (see: comment in utility/lists.hpp) + list_csv_direct_item = + confix_p('\"', *c_escape_ch_p, '\"') + | longest_d[real_p | int_p] + ; + + list_csv_direct = + list_p.direct( + (*list_csv_direct_item)[list_actor(vec_item)], + "<par>" + )[list_actor(vec_list)] + ; + + result = parse (plist_csv_direct, list_csv_direct); + + cout << "-----------------------------------------------------------------" + << endl; + if (result.hit) + { + cout + << "Parsing CSV list (comma separated values)" << endl + << "The list parser was generated with 'list_p.direct()'" << endl + << "\t" << plist_csv_direct << endl + << "Parsed successfully!" << endl << endl; + + if (result.full) + { + cout << "Matched " << vec_list.size() << + " list elements (full list): " << endl; + } + else + { + cout << "Matched " << vec_list.size() << + " list elements: " << endl; + } + + cout << "The list parser matched:" << endl; + for (std::vector<std::string>::iterator itl = vec_list.begin(); + itl != vec_list.end(); ++itl) + { + cout << *itl << endl; + } + + cout << endl << "Items got directly from the item parser:" << endl; + for (std::vector<std::string>::iterator it = vec_item.begin(); + it != vec_item.end(); ++it) + { + cout << *it << endl; + } + + } + else + { + cout << "Failed to parse CSV list!" << endl; + } + + cout << endl; + + return 0; +} diff --git a/src/boost/libs/spirit/classic/example/fundamental/matching_tags.cpp b/src/boost/libs/spirit/classic/example/fundamental/matching_tags.cpp new file mode 100644 index 00000000..14581ff5 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/matching_tags.cpp @@ -0,0 +1,115 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ +//////////////////////////////////////////////////////////////////////////// +// +// HTML/XML like tag matching grammar +// Demonstrates phoenix and closures and parametric parsers +// This is discussed in the "Closures" chapter in the Spirit User's Guide. +// +// [ JDG 6/30/2002 ] +// +//////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_attribute.hpp> +#include <iostream> +#include <string> + +//////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +//////////////////////////////////////////////////////////////////////////// +// +// HTML/XML like tag matching grammar +// +//////////////////////////////////////////////////////////////////////////// +struct tags_closure : BOOST_SPIRIT_CLASSIC_NS::closure<tags_closure, string> +{ + member1 tag; +}; + +struct tags : public grammar<tags> +{ + template <typename ScannerT> + struct definition { + + definition(tags const& /*self*/) + { + element = start_tag >> *element >> end_tag; + + start_tag = + '<' + >> lexeme_d + [ + (+alpha_p) + [ + // construct string from arg1 and arg2 lazily + // and assign to element.tag + + element.tag = construct_<string>(arg1, arg2) + ] + ] + >> '>'; + + end_tag = "</" >> f_str_p(element.tag) >> '>'; + } + + rule<ScannerT, tags_closure::context_t> element; + rule<ScannerT> start_tag, end_tag; + + rule<ScannerT, tags_closure::context_t> const& + start() const { return element; } + }; +}; + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tHTML/XML like tag matching parser demo \n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type an HTML/XML like nested tag input...or [q or Q] to quit\n\n"; + cout << "Example: <html><head></head><body></body></html>\n\n"; + + tags p; // Our parser + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + parse_info<> info = parse(str.c_str(), p, space_p); + + if (info.full) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "stopped at: \": " << info.stop << "\"\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/more_calculators/ast_calc2.cpp b/src/boost/libs/spirit/classic/example/fundamental/more_calculators/ast_calc2.cpp new file mode 100644 index 00000000..a017b65f --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/more_calculators/ast_calc2.cpp @@ -0,0 +1,180 @@ +/*============================================================================= + 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_core.hpp> +#include <boost/spirit/include/classic_ast.hpp> +#include <boost/assert.hpp> + +#include <iostream> +#include <stack> +#include <functional> +#include <string> + +// This example shows how to use an AST and tree_iter_node instead of +// tree_val_node +//////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +typedef char const* iterator_t; +typedef tree_match<iterator_t, node_iter_data_factory<> > + parse_tree_match_t; + +typedef parse_tree_match_t::tree_iterator iter_t; + +typedef ast_match_policy<iterator_t, node_iter_data_factory<> > match_policy_t; +typedef scanner<iterator_t, scanner_policies<iter_policy_t, match_policy_t> > scanner_t; +typedef rule<scanner_t> rule_t; + + +// grammar rules +rule_t expression, term, factor, integer; + +//////////////////////////////////////////////////////////////////////////// +long evaluate(parse_tree_match_t hit); +long eval_expression(iter_t const& i); +long eval_term(iter_t const& i); +long eval_factor(iter_t const& i); +long eval_integer(iter_t const& i); + +long evaluate(parse_tree_match_t hit) +{ + return eval_expression(hit.trees.begin()); +} + +long eval_expression(iter_t const& i) +{ + cout << "In eval_expression. i->value = " << + string(i->value.begin(), i->value.end()) << + " i->children.size() = " << i->children.size() << endl; + + cout << "ID: " << i->value.id().to_long() << endl; + + if (i->value.id() == integer.id()) + { + BOOST_ASSERT(i->children.size() == 0); + return strtol(i->value.begin(), 0, 10); + } + else if (i->value.id() == factor.id()) + { + // factor can only be unary minus + BOOST_ASSERT(*i->value.begin() == '-'); + return - eval_expression(i->children.begin()); + } + else if (i->value.id() == term.id()) + { + if (*i->value.begin() == '*') + { + BOOST_ASSERT(i->children.size() == 2); + return eval_expression(i->children.begin()) * + eval_expression(i->children.begin()+1); + } + else if (*i->value.begin() == '/') + { + BOOST_ASSERT(i->children.size() == 2); + return eval_expression(i->children.begin()) / + eval_expression(i->children.begin()+1); + } + else + BOOST_ASSERT(0); + } + else if (i->value.id() == expression.id()) + { + if (*i->value.begin() == '+') + { + BOOST_ASSERT(i->children.size() == 2); + return eval_expression(i->children.begin()) + + eval_expression(i->children.begin()+1); + } + else if (*i->value.begin() == '-') + { + BOOST_ASSERT(i->children.size() == 2); + return eval_expression(i->children.begin()) - + eval_expression(i->children.begin()+1); + } + else + BOOST_ASSERT(0); + } + else + BOOST_ASSERT(0); // error + + return 0; +} + +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + BOOST_SPIRIT_DEBUG_RULE(integer); + BOOST_SPIRIT_DEBUG_RULE(factor); + BOOST_SPIRIT_DEBUG_RULE(term); + BOOST_SPIRIT_DEBUG_RULE(expression); + // 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 + + + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tThe simplest working calculator...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type an expression...or [q or Q] to quit\n\n"; + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + const char* str_begin = str.c_str(); + const char* str_end = str.c_str(); + while (*str_end) + ++str_end; + + scanner_t scan(str_begin, str_end); + + parse_tree_match_t hit = expression.parse(scan); + + + if (hit && str_begin == str_end) + { +#if defined(BOOST_SPIRIT_DUMP_PARSETREE_AS_XML) + // dump parse tree as XML + std::map<rule_id, std::string> rule_names; + rule_names[&integer] = "integer"; + rule_names[&factor] = "factor"; + rule_names[&term] = "term"; + rule_names[&expression] = "expression"; + tree_to_xml(cout, hit.trees, str.c_str(), rule_names); +#endif + + // print the result + cout << "parsing succeeded\n"; + cout << "result = " << evaluate(hit) << "\n\n"; + } + else + { + cout << "parsing failed\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/more_calculators/calc_with_variables.cpp b/src/boost/libs/spirit/classic/example/fundamental/more_calculators/calc_with_variables.cpp new file mode 100644 index 00000000..5e43a7fc --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/more_calculators/calc_with_variables.cpp @@ -0,0 +1,261 @@ +/*============================================================================= + Copyright (c) 2001-2003 Dan Nuffer + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// Full calculator example with variables +// [ JDG 9/18/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_symbols.hpp> +#include <iostream> +#include <stack> +#include <functional> +#include <string> + +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Semantic actions +// +/////////////////////////////////////////////////////////////////////////////// +struct push_num +{ + push_num(stack<double>& eval_) + : eval(eval_) {} + + void operator()(double n) const + { + eval.push(n); + cout << "push\t" << n << endl; + } + + stack<double>& eval; +}; + +template <typename op> +struct do_op +{ + do_op(op const& the_op, stack<double>& eval_) + : m_op(the_op), eval(eval_) {} + + void operator()(char const*, char const*) const + { + double rhs = eval.top(); + eval.pop(); + double lhs = eval.top(); + eval.pop(); + + cout << "popped " << lhs << " and " << rhs << " from the stack. "; + cout << "pushing " << m_op(lhs, rhs) << " onto the stack.\n"; + eval.push(m_op(lhs, rhs)); + } + + op m_op; + stack<double>& eval; +}; + +template <class op> +do_op<op> +make_op(op const& the_op, stack<double>& eval) +{ + return do_op<op>(the_op, eval); +} + +struct do_negate +{ + do_negate(stack<double>& eval_) + : eval(eval_) {} + + void operator()(char const*, char const*) const + { + double lhs = eval.top(); + eval.pop(); + + cout << "popped " << lhs << " from the stack. "; + cout << "pushing " << -lhs << " onto the stack.\n"; + eval.push(-lhs); + } + + stack<double>& eval; +}; + +struct get_var +{ + get_var(stack<double>& eval_) + : eval(eval_) {} + + void operator()(double n) const + { + eval.push(n); + cout << "push\t" << n << endl; + } + + stack<double>& eval; +}; + +struct set_var +{ + set_var(double*& var_) + : var(var_) {} + + void operator()(double& n) const + { + var = &n; + } + + double*& var; +}; + +struct redecl_var +{ + void operator()(double& /*n*/) const + { + cout << "Warning. You are attempting to re-declare a var.\n"; + } +}; + +struct do_assign +{ + do_assign(double*& var_, stack<double>& eval_) + : var(var_), eval(eval_) {} + + void operator()(char const*, char const*) const + { + if (var != 0) + { + *var = eval.top(); + cout << "assigning\n"; + } + } + + double*& var; + stack<double>& eval; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Our calculator grammar +// +/////////////////////////////////////////////////////////////////////////////// +struct calculator : public grammar<calculator> +{ + calculator(stack<double>& eval_) + : eval(eval_) {} + + template <typename ScannerT> + struct definition + { + definition(calculator const& self) + { + factor = + real_p[push_num(self.eval)] + | vars[get_var(self.eval)] + | '(' >> expression >> ')' + | ('-' >> factor)[do_negate(self.eval)] + ; + + term = + factor + >> *( ('*' >> factor)[make_op(multiplies<double>(), self.eval)] + | ('/' >> factor)[make_op(divides<double>(), self.eval)] + ) + ; + + expression = + term + >> *( ('+' >> term)[make_op(plus<double>(), self.eval)] + | ('-' >> term)[make_op(minus<double>(), self.eval)] + ) + ; + + assignment = + vars[set_var(self.var)] + >> '=' >> expression[do_assign(self.var, self.eval)] + ; + + var_decl = + lexeme_d + [ + ((alpha_p >> *(alnum_p | '_')) + - vars[redecl_var()])[vars.add] + ] + ; + + declaration = + lexeme_d["var" >> space_p] >> var_decl >> *(',' >> var_decl) + ; + + statement = + declaration | assignment | '?' >> expression + ; + } + + symbols<double> vars; + rule<ScannerT> statement, declaration, var_decl, + assignment, expression, term, factor; + + rule<ScannerT> const& + start() const { return statement; } + }; + + mutable double* var; + stack<double>& eval; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Main program +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tThe calculator with variables...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type a statement...or [q or Q] to quit\n\n"; + cout << "Variables may be declared:\t\tExample: var i, j, k\n"; + cout << "Assigning to a variable:\t\tExample: i = 10 * j\n"; + cout << "To evaluate an expression:\t\tExample: ? i * 3.33E-3\n\n"; + + stack<double> eval; + calculator calc(eval); // Our parser + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + parse_info<> info = parse(str.c_str(), calc, space_p); + + if (info.full) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "stopped at: \": " << info.stop << "\"\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/more_calculators/phoenix_subrule_calc.cpp b/src/boost/libs/spirit/classic/example/fundamental/more_calculators/phoenix_subrule_calc.cpp new file mode 100644 index 00000000..9cdfdd04 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/more_calculators/phoenix_subrule_calc.cpp @@ -0,0 +1,142 @@ +/*============================================================================= + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// Full calculator example +// [ demonstrating phoenix and subrules ] +// +// [ Hartmut Kaiser 10/8/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// + +//#define BOOST_SPIRIT_DEBUG // define this for debug output + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_attribute.hpp> +#include <iostream> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +/////////////////////////////////////////////////////////////////////////////// +// +// Our calculator grammar using phoenix to do the semantics and subrule's +// as it's working horses +// +// Note: The top rule propagates the expression result (value) upwards +// to the calculator grammar self.val closure member which is +// then visible outside the grammar (i.e. since self.val is the +// member1 of the closure, it becomes the attribute passed by +// the calculator to an attached semantic action. See the +// driver code that uses the calculator below). +// +/////////////////////////////////////////////////////////////////////////////// +struct calc_closure : BOOST_SPIRIT_CLASSIC_NS::closure<calc_closure, double> +{ + member1 val; +}; + +struct calculator : public grammar<calculator, calc_closure::context_t> +{ + template <typename ScannerT> + struct definition + { + definition(calculator const& self) + { + top = ( + expression = + term[self.val = arg1] + >> *( ('+' >> term[self.val += arg1]) + | ('-' >> term[self.val -= arg1]) + ) + , + + term = + factor[term.val = arg1] + >> *( ('*' >> factor[term.val *= arg1]) + | ('/' >> factor[term.val /= arg1]) + ) + , + + factor + = ureal_p[factor.val = arg1] + | '(' >> expression[factor.val = arg1] >> ')' + | ('-' >> factor[factor.val = -arg1]) + | ('+' >> factor[factor.val = arg1]) + ); + + BOOST_SPIRIT_DEBUG_NODE(top); + BOOST_SPIRIT_DEBUG_NODE(expression); + BOOST_SPIRIT_DEBUG_NODE(term); + BOOST_SPIRIT_DEBUG_NODE(factor); + } + + subrule<0, calc_closure::context_t> expression; + subrule<1, calc_closure::context_t> term; + subrule<2, calc_closure::context_t> factor; + + rule<ScannerT> top; + + rule<ScannerT> const& + start() const { return top; } + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Main program +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tExpression parser using Phoenix...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type an expression...or [q or Q] to quit\n\n"; + + calculator calc; // Our parser + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + double n = 0; + parse_info<> info = parse(str.c_str(), calc[var(n) = arg1], space_p); + + // calc[var(n) = arg1] invokes the calculator and extracts + // the result of the computation. See calculator grammar + // note above. + + if (info.full) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << "result = " << n << endl; + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "stopped at: \": " << info.stop << "\"\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/more_calculators/primitive_calc.cpp b/src/boost/libs/spirit/classic/example/fundamental/more_calculators/primitive_calc.cpp new file mode 100644 index 00000000..22babb52 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/more_calculators/primitive_calc.cpp @@ -0,0 +1,96 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A primitive calculator that knows how to add and subtract. +// [ demonstrating phoenix ] +// +// [ JDG 6/28/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <iostream> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +/////////////////////////////////////////////////////////////////////////////// +// +// Our primitive calculator +// +/////////////////////////////////////////////////////////////////////////////// +template <typename IteratorT> +bool primitive_calc(IteratorT first, IteratorT last, double& n) +{ + return parse(first, last, + + // Begin grammar + ( + real_p[var(n) = arg1] + >> *( ('+' >> real_p[var(n) += arg1]) + | ('-' >> real_p[var(n) -= arg1]) + ) + ) + , + // End grammar + + space_p).full; +} + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tA primitive calculator...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + + cout << "Give me a list of numbers to be added or subtracted.\n"; + cout << "Example: 1 + 10 + 3 - 4 + 9\n"; + cout << "The result is computed using Phoenix.\n"; + cout << "Type [q or Q] to quit\n\n"; + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + double n; + if (primitive_calc(str.begin(), str.end(), n)) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << str << " Parses OK: " << endl; + + cout << "result = " << n; + cout << "\n-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/more_calculators/rpn_calc.cpp b/src/boost/libs/spirit/classic/example/fundamental/more_calculators/rpn_calc.cpp new file mode 100644 index 00000000..844a7915 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/more_calculators/rpn_calc.cpp @@ -0,0 +1,163 @@ +/*============================================================================= + Copyright (c) 2001-2003 Hartmut Kaiser + Copyright (c) 2002-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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// This sample shows, how to use Phoenix for implementing a +// simple (RPN style) calculator [ demonstrating phoenix ] +// +// [ HKaiser 2001 ] +// [ JDG 6/29/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_attribute.hpp> +#include <boost/spirit/include/phoenix1_functions.hpp> +#include <iostream> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +/////////////////////////////////////////////////////////////////////////////// +// +// Our RPN calculator grammar using phoenix to do the semantics +// The class 'RPNCalculator' implements a polish reverse notation +// calculator which is equivalent to the following YACC description. +// +// exp: +// NUM { $$ = $1; } +// | exp exp '+' { $$ = $1 + $2; } +// | exp exp '-' { $$ = $1 - $2; } +// | exp exp '*' { $$ = $1 * $2; } +// | exp exp '/' { $$ = $1 / $2; } +// | exp exp '^' { $$ = pow ($1, $2); } /* Exponentiation */ +// | exp 'n' { $$ = -$1; } /* Unary minus */ +// ; +// +// The different notation results from the requirement of LL parsers not to +// allow left recursion in their grammar (would lead to endless recursion). +// Therefore the left recursion in the YACC script before is transformated +// into iteration. To some, this is less intuitive, but once you get used +// to it, it's very easy to follow. +// +// Note: The top rule propagates the expression result (value) upwards +// to the calculator grammar self.val closure member which is +// then visible outside the grammar (i.e. since self.val is the +// member1 of the closure, it becomes the attribute passed by +// the calculator to an attached semantic action. See the +// driver code that uses the calculator below). +// +/////////////////////////////////////////////////////////////////////////////// +struct pow_ +{ + template <typename X, typename Y> + struct result { typedef X type; }; + + template <typename X, typename Y> + X operator()(X x, Y y) const + { + using namespace std; + return pow(x, y); + } +}; + +// Notice how power(x, y) is lazily implemented using Phoenix function. +function<pow_> power; + +struct calc_closure : BOOST_SPIRIT_CLASSIC_NS::closure<calc_closure, double, double> +{ + member1 x; + member2 y; +}; + +struct calculator : public grammar<calculator, calc_closure::context_t> +{ + template <typename ScannerT> + struct definition { + + definition(calculator const& self) + { + top = expr [self.x = arg1]; + expr = + real_p [expr.x = arg1] + >> *( + expr [expr.y = arg1] + >> ( + ch_p('+') [expr.x += expr.y] + | ch_p('-') [expr.x -= expr.y] + | ch_p('*') [expr.x *= expr.y] + | ch_p('/') [expr.x /= expr.y] + | ch_p('^') [expr.x = power(expr.x, expr.y)] + ) + | ch_p('n') [expr.x = -expr.x] + ) + ; + } + + typedef rule<ScannerT, calc_closure::context_t> rule_t; + rule_t expr; + rule<ScannerT> top; + + rule<ScannerT> const& + start() const { return top; } + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Main program +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tExpression parser using Phoenix...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type an expression...or [q or Q] to quit\n\n"; + + calculator calc; // Our parser + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + double n = 0; + parse_info<> info = parse(str.c_str(), calc[var(n) = arg1], space_p); + + // calc[var(n) = arg1] invokes the calculator and extracts + // the result of the computation. See calculator grammar + // note above. + + if (info.full) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << "result = " << n << endl; + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "stopped at: \": " << info.stop << "\"\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/more_calculators/vmachine_calc.cpp b/src/boost/libs/spirit/classic/example/fundamental/more_calculators/vmachine_calc.cpp new file mode 100644 index 00000000..bbcb52df --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/more_calculators/vmachine_calc.cpp @@ -0,0 +1,275 @@ +/*============================================================================= + 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) +=============================================================================*/ +//////////////////////////////////////////////////////////////////////////// +// +// The calculator using a simple virtual machine and compiler. +// +// Ported to v1.5 from the original v1.0 code by JDG +// [ JDG 9/18/2002 ] +// +//////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <iostream> +#include <vector> +#include <string> + +//////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// The VMachine +// +/////////////////////////////////////////////////////////////////////////////// +enum ByteCodes +{ + OP_NEG, // negate the top stack entry + OP_ADD, // add top two stack entries + OP_SUB, // subtract top two stack entries + OP_MUL, // multiply top two stack entries + OP_DIV, // divide top two stack entries + OP_INT, // push constant integer into the stack + OP_RET // return from the interpreter +}; + +class vmachine +{ +public: + vmachine(unsigned stackSize = 1024) + : stack(new int[stackSize]), + stackPtr(stack) {} + ~vmachine() { delete [] stack; } + int top() const { return stackPtr[-1]; }; + void execute(int code[]); + +private: + + int* stack; + int* stackPtr; +}; + +void +vmachine::execute(int code[]) +{ + int const* pc = code; + bool running = true; + stackPtr = stack; + + while (running) + { + switch (*pc++) + { + case OP_NEG: + stackPtr[-1] = -stackPtr[-1]; + break; + + case OP_ADD: + stackPtr--; + stackPtr[-1] += stackPtr[0]; + break; + + case OP_SUB: + stackPtr--; + stackPtr[-1] -= stackPtr[0]; + break; + + case OP_MUL: + stackPtr--; + stackPtr[-1] *= stackPtr[0]; + break; + + case OP_DIV: + stackPtr--; + stackPtr[-1] /= stackPtr[0]; + break; + + case OP_INT: + // Check stack overflow here! + *stackPtr++ = *pc++; + break; + + case OP_RET: + running = false; + break; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// The Compiler +// +/////////////////////////////////////////////////////////////////////////////// +struct push_int +{ + push_int(vector<int>& code_) + : code(code_) {} + + void operator()(char const* str, char const* /*end*/) const + { + using namespace std; + int n = strtol(str, 0, 10); + code.push_back(OP_INT); + code.push_back(n); + cout << "push\t" << int(n) << endl; + } + + vector<int>& code; +}; + +struct push_op +{ + push_op(int op_, vector<int>& code_) + : op(op_), code(code_) {} + + void operator()(char const*, char const*) const + { + code.push_back(op); + + switch (op) { + + case OP_NEG: + cout << "neg\n"; + break; + + case OP_ADD: + cout << "add\n"; + break; + + case OP_SUB: + cout << "sub\n"; + break; + + case OP_MUL: + cout << "mul\n"; + break; + + case OP_DIV: + cout << "div\n"; + break; + } + } + + int op; + vector<int>& code; +}; + +template <typename GrammarT> +static bool +compile(GrammarT const& calc, char const* expr) +{ + cout << "\n/////////////////////////////////////////////////////////\n\n"; + + parse_info<char const*> + result = parse(expr, calc, space_p); + + if (result.full) + { + cout << "\t\t" << expr << " Parses OK\n\n\n"; + calc.code.push_back(OP_RET); + return true; + } + else + { + cout << "\t\t" << expr << " Fails parsing\n"; + cout << "\t\t"; + for (int i = 0; i < (result.stop - expr); i++) + cout << " "; + cout << "^--Here\n\n\n"; + return false; + } +} + +//////////////////////////////////////////////////////////////////////////// +// +// Our calculator grammar +// +//////////////////////////////////////////////////////////////////////////// +struct calculator : public grammar<calculator> +{ + calculator(vector<int>& code_) + : code(code_) {} + + template <typename ScannerT> + struct definition + { + definition(calculator const& self) + { + integer = + lexeme_d[ (+digit_p)[push_int(self.code)] ] + ; + + factor = + integer + | '(' >> expression >> ')' + | ('-' >> factor)[push_op(OP_NEG, self.code)] + | ('+' >> factor) + ; + + term = + factor + >> *( ('*' >> factor)[push_op(OP_MUL, self.code)] + | ('/' >> factor)[push_op(OP_DIV, self.code)] + ) + ; + + expression = + term + >> *( ('+' >> term)[push_op(OP_ADD, self.code)] + | ('-' >> term)[push_op(OP_SUB, self.code)] + ) + ; + } + + rule<ScannerT> expression, term, factor, integer; + + rule<ScannerT> const& + start() const { return expression; } + }; + + vector<int>& code; +}; + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tA simple virtual machine...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type an expression...or [q or Q] to quit\n\n"; + + vmachine mach; // Our virtual machine + vector<int> code; // Our VM code + calculator calc(code); // Our parser + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + code.clear(); + if (compile(calc, str.c_str())) + { + mach.execute(&*code.begin()); + cout << "\n\nresult = " << mach.top() << "\n\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/no_actions.cpp b/src/boost/libs/spirit/classic/example/fundamental/no_actions.cpp new file mode 100644 index 00000000..a57b6e17 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/no_actions.cpp @@ -0,0 +1,56 @@ +/*============================================================================= + 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) +=============================================================================*/ +// +// This example demonstrates no_actions_d directive. +// +// The no_actions_d directive ensures, that semantic actions of the inner +// parser would NOT be invoked. See the no_actions_scanner in the Scanner +// and Parsing chapter in the User's Guide. +// +//----------------------------------------------------------------------------- + +#include <boost/assert.hpp> +#include <iostream> +#include <boost/cstdlib.hpp> +#include <boost/spirit/include/classic_core.hpp> + +using namespace std; +using namespace boost; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +//----------------------------------------------------------------------------- + +int main() +{ + // To use the rule in the no_action_d directive we must declare it with + // the no_actions_scanner scanner + rule<no_actions_scanner<>::type> r; + + int i(0); + + // r is the rule with the semantic action + r = int_p[assign_a(i)]; + + parse_info<> info = parse( + "1", + + no_actions_d + [ + r + ] + ); + + BOOST_ASSERT(info.full); + // Check, that the action hasn't been invoked + BOOST_ASSERT(i == 0); + + return exit_success; +} + +//----------------------------------------------------------------------------- diff --git a/src/boost/libs/spirit/classic/example/fundamental/number_list.cpp b/src/boost/libs/spirit/classic/example/fundamental/number_list.cpp new file mode 100644 index 00000000..1756f118 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/number_list.cpp @@ -0,0 +1,93 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// This sample demontrates a parser for a comma separated list of numbers +// This is discussed in the "Quick Start" chapter in the Spirit User's Guide. +// +// [ JDG 5/10/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_push_back_actor.hpp> +#include <iostream> +#include <vector> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Our comma separated list parser +// +/////////////////////////////////////////////////////////////////////////////// +bool +parse_numbers(char const* str, vector<double>& v) +{ + return parse(str, + + // Begin grammar + ( + real_p[push_back_a(v)] >> *(',' >> real_p[push_back_a(v)]) + ) + , + // End grammar + + space_p).full; +} + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tA comma separated list parser for Spirit...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + + cout << "Give me a comma separated list of numbers.\n"; + cout << "The numbers will be inserted in a vector of numbers\n"; + cout << "Type [q or Q] to quit\n\n"; + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + vector<double> v; + if (parse_numbers(str.c_str(), v)) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << str << " Parses OK: " << endl; + + for (vector<double>::size_type i = 0; i < v.size(); ++i) + cout << i << ": " << v[i] << endl; + + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/parse_tree_calc1.cpp b/src/boost/libs/spirit/classic/example/fundamental/parse_tree_calc1.cpp new file mode 100644 index 00000000..755810e5 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/parse_tree_calc1.cpp @@ -0,0 +1,207 @@ +/*============================================================================= + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// Demonstrates parse trees. This is discussed in the +// "Trees" chapter in the Spirit User's Guide. +// +/////////////////////////////////////////////////////////////////////////////// +#define BOOST_SPIRIT_DUMP_PARSETREE_AS_XML + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_parse_tree.hpp> +#include <boost/assert.hpp> + +#include <iostream> +#include <stack> +#include <functional> +#include <string> + +#ifdef BOOST_SPIRIT_DUMP_PARSETREE_AS_XML +#include <boost/spirit/include/classic_tree_to_xml.hpp> +#include <map> +#endif + +//////////////////////////////////////////////////////////////////////////// +// This example shows how to use a parse tree +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +// Here's some typedefs to simplify things +typedef char const* iterator_t; +typedef tree_match<iterator_t> parse_tree_match_t; +typedef parse_tree_match_t::const_tree_iterator iter_t; + +typedef pt_match_policy<iterator_t> match_policy_t; +typedef scanner_policies<iteration_policy, match_policy_t, action_policy> scanner_policy_t; +typedef scanner<iterator_t, scanner_policy_t> scanner_t; +typedef rule<scanner_t> rule_t; + +// grammar rules +rule_t expression, term, factor, integer; + +//////////////////////////////////////////////////////////////////////////// +// Here's the function prototypes that we'll use. One function for each +// grammar rule. +long evaluate(const tree_parse_info<>& info); +long eval_expression(iter_t const& i); +long eval_term(iter_t const& i); +long eval_factor(iter_t const& i); +long eval_integer(iter_t const& i); + +long evaluate(const tree_parse_info<>& info) +{ + return eval_expression(info.trees.begin()); +} + +// i should be pointing to a node created by the expression rule +long eval_expression(iter_t const& i) +{ + parser_id id = i->value.id(); + BOOST_ASSERT(id == expression.id()); // check the id + + // first child points to a term, so call eval_term on it + iter_t chi = i->children.begin(); + long lhs = eval_term(chi); + for (++chi; chi != i->children.end(); ++chi) + { + // next node points to the operator. The text of the operator is + // stored in value (a vector<char>) + char op = *(chi->value.begin()); + ++chi; + long rhs = eval_term(chi); + if (op == '+') + lhs += rhs; + else if (op == '-') + lhs -= rhs; + else + BOOST_ASSERT(0); + } + return lhs; +} + +long eval_term(iter_t const& i) +{ + parser_id id = i->value.id(); + BOOST_ASSERT(id == term.id()); + + iter_t chi = i->children.begin(); + long lhs = eval_factor(chi); + for (++chi; chi != i->children.end(); ++chi) + { + char op = *(chi->value.begin()); + ++chi; + long rhs = eval_factor(chi); + if (op == '*') + lhs *= rhs; + else if (op == '/') + lhs /= rhs; + else + BOOST_ASSERT(0); + } + return lhs; +} + +long eval_factor(iter_t const& i) +{ + parser_id id = i->value.id(); + BOOST_ASSERT(id == factor.id()); + + iter_t chi = i->children.begin(); + id = chi->value.id(); + if (id == integer.id()) + return eval_integer(chi->children.begin()); + else if (*(chi->value.begin()) == '(') + { + ++chi; + return eval_expression(chi); + } + else if (*(chi->value.begin()) == '-') + { + ++chi; + return -eval_factor(chi); + } + else + { + BOOST_ASSERT(0); + return 0; + } +} + +long eval_integer(iter_t const& i) +{ + // extract integer (not always delimited by '\0') + string integer(i->value.begin(), i->value.end()); + + return strtol(integer.c_str(), 0, 10); +} + +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + + // Start grammar definition + integer = lexeme_d[ token_node_d[ (!ch_p('-') >> +digit_p) ] ]; + factor = integer + | '(' >> expression >> ')' + | ('-' >> factor); + term = factor >> + *( ('*' >> factor) + | ('/' >> factor) + ); + expression = term >> + *( ('+' >> term) + | ('-' >> term) + ); + // End grammar definition + + + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tThe simplest working calculator...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type an expression...or [q or Q] to quit\n\n"; + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + const char* first = str.c_str(); + + tree_parse_info<> info = pt_parse(first, expression); + + if (info.full) + { +#if defined(BOOST_SPIRIT_DUMP_PARSETREE_AS_XML) + // dump parse tree as XML + std::map<parser_id, std::string> rule_names; + rule_names[integer.id()] = "integer"; + rule_names[factor.id()] = "factor"; + rule_names[term.id()] = "term"; + rule_names[expression.id()] = "expression"; + tree_to_xml(cout, info.trees, first, rule_names); +#endif + + // print the result + cout << "parsing succeeded\n"; + cout << "result = " << evaluate(info) << "\n\n"; + } + else + { + cout << "parsing failed\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/parser_context.cpp b/src/boost/libs/spirit/classic/example/fundamental/parser_context.cpp new file mode 100644 index 00000000..d8ed32ba --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/parser_context.cpp @@ -0,0 +1,51 @@ +/*============================================================================= + 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) +=============================================================================*/ +// +// This example demonstrates usage of the parser_context template with +// an explicit argument to declare rules with match results different from +// nil_t. For better understanding, you should read the chapter "In-depth: +// The Parser Context" in the documentation. +// +// The default context of non-terminals is the parser_context. +// The parser_context is a template with one argument AttrT, which is the type +// of match attribute. +// +// In this example int_rule is declared as rule with int match attribute's +// type, so in int_rule variable we can hold any parser, which returns int +// value. For example int_p or bin_p. And the most important is that we can +// use returned value in the semantic action binded to the int_rule. +// +//----------------------------------------------------------------------------- +#include <iostream> +#include <boost/cstdlib.hpp> +#include <boost/spirit/include/phoenix1.hpp> +#include <boost/spirit/include/classic_core.hpp> + +using namespace std; +using namespace boost; +using namespace phoenix; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +//----------------------------------------------------------------------------- + +int main() +{ + rule<parser_context<int> > int_rule = int_p; + + parse( + "123", + // Using a returned value in the semantic action + int_rule[cout << arg1 << endl] + ); + + return exit_success; +} + +//----------------------------------------------------------------------------- + diff --git a/src/boost/libs/spirit/classic/example/fundamental/phoenix_calc.cpp b/src/boost/libs/spirit/classic/example/fundamental/phoenix_calc.cpp new file mode 100644 index 00000000..d4f816e6 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/phoenix_calc.cpp @@ -0,0 +1,132 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ +//////////////////////////////////////////////////////////////////////////// +// +// Full calculator example demonstrating Phoenix +// This is discussed in the "Closures" chapter in the Spirit User's Guide. +// +// [ JDG 6/29/2002 ] +// +//////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_attribute.hpp> +#include <iostream> +#include <string> + +//////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +//////////////////////////////////////////////////////////////////////////// +// +// Our calculator grammar using phoenix to do the semantics +// +// Note: The top rule propagates the expression result (value) upwards +// to the calculator grammar self.val closure member which is +// then visible outside the grammar (i.e. since self.val is the +// member1 of the closure, it becomes the attribute passed by +// the calculator to an attached semantic action. See the +// driver code that uses the calculator below). +// +//////////////////////////////////////////////////////////////////////////// +struct calc_closure : BOOST_SPIRIT_CLASSIC_NS::closure<calc_closure, double> +{ + member1 val; +}; + +struct calculator : public grammar<calculator, calc_closure::context_t> +{ + template <typename ScannerT> + struct definition + { + definition(calculator const& self) + { + top = expression[self.val = arg1]; + + expression + = term[expression.val = arg1] + >> *( ('+' >> term[expression.val += arg1]) + | ('-' >> term[expression.val -= arg1]) + ) + ; + + term + = factor[term.val = arg1] + >> *( ('*' >> factor[term.val *= arg1]) + | ('/' >> factor[term.val /= arg1]) + ) + ; + + factor + = ureal_p[factor.val = arg1] + | '(' >> expression[factor.val = arg1] >> ')' + | ('-' >> factor[factor.val = -arg1]) + | ('+' >> factor[factor.val = arg1]) + ; + } + + typedef rule<ScannerT, calc_closure::context_t> rule_t; + rule_t expression, term, factor; + rule<ScannerT> top; + + rule<ScannerT> const& + start() const { return top; } + }; +}; + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tExpression parser using Phoenix...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type an expression...or [q or Q] to quit\n\n"; + + calculator calc; // Our parser + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + double n = 0; + parse_info<> info = parse(str.c_str(), calc[var(n) = arg1], space_p); + + // calc[var(n) = arg1] invokes the calculator and extracts + // the result of the computation. See calculator grammar + // note above. + + if (info.full) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << "result = " << n << endl; + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "stopped at: \": " << info.stop << "\"\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.cpp b/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.cpp new file mode 100644 index 00000000..94975919 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.cpp @@ -0,0 +1,173 @@ +/*============================================================================= + Copyright (c) 2002 Juan Carlos Arevalo-Baeza + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A parser for a comma separated list of numbers, +// with positional error reporting +// See the "Position Iterator" chapter in the User's Guide. +// +// [ JCAB 9/28/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_position_iterator.hpp> +#include <boost/spirit/include/classic_functor_parser.hpp> +#include <iostream> +#include <fstream> +#include <vector> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Our error reporting parsers +// +/////////////////////////////////////////////////////////////////////////////// +std::ostream& operator<<(std::ostream& out, file_position const& lc) +{ + return out << + "\nFile:\t" << lc.file << + "\nLine:\t" << lc.line << + "\nCol:\t" << lc.column << endl; +} + +struct error_report_parser { + char const* eol_msg; + char const* msg; + + error_report_parser(char const* eol_msg_, char const* msg_): + eol_msg(eol_msg_), + msg (msg_) + {} + + typedef nil_t result_t; + + template <typename ScannerT> + int + operator()(ScannerT const& scan, result_t& /*result*/) const + { + if (scan.at_end()) { + if (eol_msg) { + file_position fpos = scan.first.get_position(); + cerr << fpos << eol_msg << endl; + } + } else { + if (msg) { + file_position fpos = scan.first.get_position(); + cerr << fpos << msg << endl; + } + } + + return -1; // Fail. + } + +}; +typedef functor_parser<error_report_parser> error_report_p; + +error_report_p +error_badnumber_or_eol = + error_report_parser( + "Expecting a number, but found the end of the file\n", + "Expecting a number, but found something else\n" + ); + +error_report_p +error_badnumber = + error_report_parser( + 0, + "Expecting a number, but found something else\n" + ); + +error_report_p +error_comma = + error_report_parser( + 0, + "Expecting a comma, but found something else\n" + ); + +/////////////////////////////////////////////////////////////////////////////// +// +// Our comma separated list parser +// +/////////////////////////////////////////////////////////////////////////////// +bool +parse_numbers(char const* filename, char const* str, vector<double>& v) +{ + typedef position_iterator<char const*> iterator_t; + iterator_t begin(str, str + strlen(str), filename); + iterator_t end; + begin.set_tabchars(8); + return parse(begin, end, + + // Begin grammar + ( + (real_p[push_back_a(v)] | error_badnumber) + >> *( + (',' | error_comma) + >> (real_p[push_back_a(v)] | error_badnumber_or_eol) + ) + ) + , + // End grammar + + space_p).full; +} + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main(int argc, char **argv) +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\tAn error-reporting parser for Spirit...\n\n"; + cout << "Parses a comma separated list of numbers from a file.\n"; + cout << "The numbers will be inserted in a vector of numbers\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + + char str[65536]; + char const* filename; + + if (argc > 1) { + filename = argv[1]; + ifstream file(filename); + file.get(str, sizeof(str), '\0'); + } else { + filename = "<cin>"; + cin.get(str, sizeof(str), '\0'); + } + + vector<double> v; + if (parse_numbers(filename, str, v)) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << str << " Parses OK: " << endl; + + for (vector<double>::size_type i = 0; i < v.size(); ++i) + cout << i << ": " << v[i] << endl; + + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "-------------------------\n"; + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.err1 b/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.err1 new file mode 100644 index 00000000..d6646b72 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.err1 @@ -0,0 +1,8 @@ +0, 1,2 , 3 a,4 +,5, +6 +, +7 + + +,08 diff --git a/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.err2 b/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.err2 new file mode 100644 index 00000000..012e2738 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.err2 @@ -0,0 +1,8 @@ +0, 1,2 , 3 ,4 +,5, +6 +, +7 + + +, diff --git a/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.err3 b/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.err3 new file mode 100644 index 00000000..8e011921 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.err3 @@ -0,0 +1,8 @@ +0, 1,2 , a3 ,4 +,5, +6 +, +7 + + +,08 diff --git a/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.ok b/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.ok new file mode 100644 index 00000000..9bf6f0d1 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/position_iterator/position_iterator.ok @@ -0,0 +1,8 @@ +0, 1,2 , 3 ,4 +,5, +6 +, +7 + + +,08 diff --git a/src/boost/libs/spirit/classic/example/fundamental/refactoring.cpp b/src/boost/libs/spirit/classic/example/fundamental/refactoring.cpp new file mode 100644 index 00000000..701fdbef --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/refactoring.cpp @@ -0,0 +1,214 @@ +/*============================================================================= + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// This example shows the usage of the refactoring parser family parsers +// See the "Refactoring Parsers" chapter in the User's Guide. + +#include <iostream> +#include <string> + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_refactoring.hpp> + +/////////////////////////////////////////////////////////////////////////////// +// used namespaces +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// actor, used by the refactor_action_p test +struct refactor_action_actor +{ + refactor_action_actor (std::string &str_) : str(str_) {} + + template <typename IteratorT> + void operator() (IteratorT const &first, IteratorT const &last) const + { + str = std::string(first, last-first); + } + + std::string &str; +}; + +/////////////////////////////////////////////////////////////////////////////// +// main entry point +int main() +{ + parse_info<> result; + char const *test_string = "Some string followed by a newline\n"; + +/////////////////////////////////////////////////////////////////////////////// +// +// 1. Testing the refactor_unary_d parser +// +// The following test should successfully parse the test string, because the +// +// refactor_unary_d[ +// *anychar_p - '\n' +// ] +// +// is refactored into +// +// *(anychar_p - '\n'). +// +/////////////////////////////////////////////////////////////////////////////// + + result = parse(test_string, refactor_unary_d[*anychar_p - '\n'] >> '\n'); + + if (result.full) + { + cout << "Successfully refactored an unary!" << endl; + } + else + { + cout << "Failed to refactor an unary!" << endl; + } + +// Parsing the same test string without refactoring fails, because the +// *anychar_p eats up all the input up to the end of the input string. + + result = parse(test_string, (*anychar_p - '\n') >> '\n'); + + if (result.full) + { + cout + << "Successfully parsed test string (should not happen)!" + << endl; + } + else + { + cout + << "Correctly failed parsing the test string (without refactoring)!" + << endl; + } + cout << endl; + +/////////////////////////////////////////////////////////////////////////////// +// +// 2. Testing the refactor_action_d parser +// +// The following test should successfully parse the test string, because the +// +// refactor_action_d[ +// (*(anychar_p - '$'))[refactor_action_actor(str)] >> '$' +// ] +// +// is refactored into +// +// (*(anychar_p - '$') >> '$')[refactor_action_actor(str)]. +// +/////////////////////////////////////////////////////////////////////////////// + + std::string str; + char const *test_string2 = "Some test string ending with a $"; + + result = + parse(test_string2, + refactor_action_d[ + (*(anychar_p - '$'))[refactor_action_actor(str)] >> '$' + ] + ); + + if (result.full && str == std::string(test_string2)) + { + cout << "Successfully refactored an action!" << endl; + cout << "Parsed: \"" << str << "\"" << endl; + } + else + { + cout << "Failed to refactor an action!" << endl; + } + +// Parsing the same test string without refactoring fails, because the +// the attached actor gets called only for the first part of the string +// (without the '$') + + result = + parse(test_string2, + (*(anychar_p - '$'))[refactor_action_actor(str)] >> '$' + ); + + if (result.full && str == std::string(test_string2)) + { + cout << "Successfully parsed test string!" << endl; + cout << "Parsed: \"" << str << "\"" << endl; + } + else + { + cout + << "Correctly failed parsing the test string (without refactoring)!" + << endl; + cout << "Parsed instead: \"" << str << "\"" << endl; + } + cout << endl; + +/////////////////////////////////////////////////////////////////////////////// +// +// 3. Testing the refactor_action_d parser with an embedded (nested) +// refactor_unary_p parser +// +// The following test should successfully parse the test string, because the +// +// refactor_action_unary_d[ +// ((*anychar_p)[refactor_action_actor(str)] - '$') +// ] >> '$' +// +// is refactored into +// +// (*(anychar_p - '$'))[refactor_action_actor(str)] >> '$'. +// +/////////////////////////////////////////////////////////////////////////////// + + const refactor_action_gen<refactor_unary_gen<> > refactor_action_unary_d = + refactor_action_gen<refactor_unary_gen<> >(refactor_unary_d); + + result = + parse(test_string2, + refactor_action_unary_d[ + ((*anychar_p)[refactor_action_actor(str)] - '$') + ] >> '$' + ); + + if (result.full) + { + cout + << "Successfully refactored an action attached to an unary!" + << endl; + cout << "Parsed: \"" << str << "\"" << endl; + } + else + { + cout << "Failed to refactor an action!" << endl; + } + +// Parsing the same test string without refactoring fails, because the +// anychar_p eats up all the input up to the end of the string + + result = + parse(test_string2, + ((*anychar_p)[refactor_action_actor(str)] - '$') >> '$' + ); + + if (result.full) + { + cout << "Successfully parsed test string!" << endl; + cout << "Parsed: \"" << str << "\"" << endl; + } + else + { + cout + << "Correctly failed parsing the test string (without refactoring)!" + << endl; + cout << "Parsed instead: \"" << str << "\"" << endl; + } + cout << endl; + + return 0; +} + diff --git a/src/boost/libs/spirit/classic/example/fundamental/regular_expression.cpp b/src/boost/libs/spirit/classic/example/fundamental/regular_expression.cpp new file mode 100644 index 00000000..48b33cea --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/regular_expression.cpp @@ -0,0 +1,110 @@ +/*============================================================================= + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// Demonstrate regular expression parser objects +// See the "Regular Expression Parser" chapter in the User's Guide. +// +// This sample requires an installed version of the boost regex library +// (http://www.boost.org) The sample was tested with boost V1.28.0 +// +/////////////////////////////////////////////////////////////////////////////// +#include <string> +#include <iostream> + +#include <boost/version.hpp> +#include <boost/spirit/include/classic_core.hpp> + +/////////////////////////////////////////////////////////////////////////////// +// +// The following header must be included, if regular expression support is +// required for Spirit. +// +// The BOOST_SPIRIT_NO_REGEX_LIB PP constant should be defined, if you're +// using the Boost.Regex library from one translation unit only. Otherwise +// you have to link with the Boost.Regex library as defined in the related +// documentation (see. http://www.boost.org). +// +// For Boost > V1.32.0 you'll always have to link against the Boost.Regex +// libraries. +// +/////////////////////////////////////////////////////////////////////////////// +#if BOOST_VERSION <= 103200 +#define BOOST_SPIRIT_NO_REGEX_LIB +#endif +#include <boost/spirit/include/classic_regex.hpp> + +/////////////////////////////////////////////////////////////////////////////// +// used namespaces +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// main entry point +int main() +{ + const char *ptest = "123 E 456"; + const char *prx = "[1-9]+[[:space:]]*E[[:space:]]*"; + + cout << "Parse " << ptest << " against regular expression: " << prx + << endl; + + // 1. direct use of rxlit<> + rxstrlit<> regexpr(prx); + parse_info<> result; + string str; + + result = parse (ptest, regexpr[assign(str)]); + if (result.hit) + { + cout << "Parsed regular expression successfully!" << endl; + cout << "Matched (" << (int)result.length << ") characters: "; + cout << "\"" << str << "\"" << endl; + } + else + { + cout << "Failed to parse regular expression!" << endl; + } + cout << endl; + + // 2. use of regex_p predefined parser object + str.empty(); + result = parse (ptest, regex_p(prx)[assign(str)]); + if (result.hit) + { + cout << "Parsed regular expression successfully!" << endl; + cout << "Matched (" << (int)result.length << ") characters: "; + cout << "\"" << str << "\"" << endl; + } + else + { + cout << "Failed to parse regular expression!" << endl; + } + cout << endl; + + // 3. test the regression reported by Grzegorz Marcin Koczyk (gkoczyk@echostar.pl) + string str1; + string str2; + char const *ptest1 = "Token whatever \nToken"; + + result = parse(ptest1, rxstrlit<>("Token")[assign(str1)] + >> rxstrlit<>("Token")[assign(str2)]); + + if (!result.hit) + cout << "Parsed regular expression successfully!" << endl; + else + cout << "Failed to parse regular expression!" << endl; + + cout << endl; + + return 0; +} + + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/roman_numerals.cpp b/src/boost/libs/spirit/classic/example/fundamental/roman_numerals.cpp new file mode 100644 index 00000000..32f26d9e --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/roman_numerals.cpp @@ -0,0 +1,189 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A Roman Numerals Parser (demonstrating the symbol table). This is +// discussed in the "Symbols" chapter in the Spirit User's Guide. +// +// [ JDG 8/22/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_symbols.hpp> +#include <iostream> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Parse roman hundreds (100..900) numerals using the symbol table. +// Notice that the data associated with each slot is passed +// to attached semantic actions. +// +/////////////////////////////////////////////////////////////////////////////// +struct hundreds : symbols<unsigned> +{ + hundreds() + { + add + ("C" , 100) + ("CC" , 200) + ("CCC" , 300) + ("CD" , 400) + ("D" , 500) + ("DC" , 600) + ("DCC" , 700) + ("DCCC" , 800) + ("CM" , 900) + ; + } + +} hundreds_p; + +/////////////////////////////////////////////////////////////////////////////// +// +// Parse roman tens (10..90) numerals using the symbol table. +// +/////////////////////////////////////////////////////////////////////////////// +struct tens : symbols<unsigned> +{ + tens() + { + add + ("X" , 10) + ("XX" , 20) + ("XXX" , 30) + ("XL" , 40) + ("L" , 50) + ("LX" , 60) + ("LXX" , 70) + ("LXXX" , 80) + ("XC" , 90) + ; + } + +} tens_p; + +/////////////////////////////////////////////////////////////////////////////// +// +// Parse roman ones (1..9) numerals using the symbol table. +// +/////////////////////////////////////////////////////////////////////////////// +struct ones : symbols<unsigned> +{ + ones() + { + add + ("I" , 1) + ("II" , 2) + ("III" , 3) + ("IV" , 4) + ("V" , 5) + ("VI" , 6) + ("VII" , 7) + ("VIII" , 8) + ("IX" , 9) + ; + } + +} ones_p; + +/////////////////////////////////////////////////////////////////////////////// +// +// Semantic actions +// +/////////////////////////////////////////////////////////////////////////////// +struct add_1000 +{ + add_1000(unsigned& r_) : r(r_) {} + void operator()(char) const { r += 1000; } + unsigned& r; +}; + +struct add_roman +{ + add_roman(unsigned& r_) : r(r_) {} + void operator()(unsigned n) const { r += n; } + unsigned& r; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// roman (numerals) grammar +// +/////////////////////////////////////////////////////////////////////////////// +struct roman : public grammar<roman> +{ + template <typename ScannerT> + struct definition + { + definition(roman const& self) + { + first + = +ch_p('M') [add_1000(self.r)] + || hundreds_p [add_roman(self.r)] + || tens_p [add_roman(self.r)] + || ones_p [add_roman(self.r)]; + + // Note the use of the || operator. The expression + // a || b reads match a or b and in sequence. Try + // defining the roman numerals grammar in YACC or + // PCCTS. Spirit rules! :-) + } + + rule<ScannerT> first; + rule<ScannerT> const& + start() const { return first; } + }; + + roman(unsigned& r_) : r(r_) {} + unsigned& r; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Main driver code +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tRoman Numerals Parser\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type a Roman Numeral ...or [q or Q] to quit\n\n"; + + // Start grammar definition + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + unsigned n = 0; + roman roman_p(n); + if (parse(str.c_str(), roman_p).full) + { + cout << "parsing succeeded\n"; + cout << "result = " << n << "\n\n"; + } + else + { + cout << "parsing failed\n\n"; + } + } + + cout << "Bye... :-) \n\n"; + + return 0; +} diff --git a/src/boost/libs/spirit/classic/example/fundamental/stuff_vector.cpp b/src/boost/libs/spirit/classic/example/fundamental/stuff_vector.cpp new file mode 100644 index 00000000..77f51b27 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/stuff_vector.cpp @@ -0,0 +1,114 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// This sample demontrates a parser for a comma separated list of numbers +// This is the phoenix version of number_list.cpp. +// This is discussed in the "Phoenix" chapter in the Spirit User's Guide. +// +// [ JDG 1/12/2004 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_operators.hpp> +#include <boost/spirit/include/phoenix1_functions.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <iostream> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +/////////////////////////////////////////////////////////////////////////////// +// +// Our comma separated list parser +// +/////////////////////////////////////////////////////////////////////////////// +struct push_back_impl +{ + template <typename Container, typename Item> + struct result + { + typedef void type; + }; + + template <typename Container, typename Item> + void operator()(Container& c, Item const& item) const + { + c.push_back(item); + } +}; + +function<push_back_impl> const push_back = push_back_impl(); + +bool +parse_numbers(char const* str, vector<double>& v) +{ + return parse(str, + + // Begin grammar + ( + real_p[push_back(var(v), arg1)] + >> *(',' >> real_p[push_back(var(v), arg1)]) + ) + , + // End grammar + + space_p).full; +} + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tA comma separated list parser for Spirit...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + + cout << "Give me a comma separated list of numbers.\n"; + cout << "The numbers will be inserted in a vector of numbers\n"; + cout << "Type [q or Q] to quit\n\n"; + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + vector<double> v; + if (parse_numbers(str.c_str(), v)) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << str << " Parses OK: " << endl; + + for (vector<double>::size_type i = 0; i < v.size(); ++i) + cout << i << ": " << v[i] << endl; + + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/stuff_vector2.cpp b/src/boost/libs/spirit/classic/example/fundamental/stuff_vector2.cpp new file mode 100644 index 00000000..a5a3232c --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/stuff_vector2.cpp @@ -0,0 +1,125 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// This sample demontrates a parser for a comma separated list of identifiers +// This is a variation of stuff_vector.cpp. +// This is discussed in the "Phoenix" chapter in the Spirit User's Guide. +// +// [ JDG 1/12/2004 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_operators.hpp> +#include <boost/spirit/include/phoenix1_functions.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_casts.hpp> +#include <iostream> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +/////////////////////////////////////////////////////////////////////////////// +// +// Our comma separated list parser +// +/////////////////////////////////////////////////////////////////////////////// +struct push_back_impl +{ + template <typename Container, typename Item> + struct result + { + typedef void type; + }; + + template <typename Container, typename Item> + void operator()(Container& c, Item const& item) const + { + c.push_back(item); + } +}; + +function<push_back_impl> const push_back = push_back_impl(); + +bool +parse_identifiers(char const* str, vector<std::string>& v) +{ + return parse(str, + + // Begin grammar + ( + (+alpha_p) + [ + push_back(var(v), construct_<std::string>(arg1, arg2)) + ] + >> + *(',' >> + (+alpha_p) + [ + push_back(var(v), construct_<std::string>(arg1, arg2)) + ] + ) + ) + , + // End grammar + + space_p).full; +} + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tA comma separated list parser for Spirit...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + + cout << "Give me a comma separated list of identifiers.\n"; + cout << "An identifier is comprised of one or more alphabetic characters.\n"; + cout << "The identifiers will be inserted in a vector of numbers\n"; + cout << "Type [q or Q] to quit\n\n"; + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + vector<std::string> v; + if (parse_identifiers(str.c_str(), v)) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << str << " Parses OK: " << endl; + + for (vector<std::string>::size_type i = 0; i < v.size(); ++i) + cout << i << ": " << v[i] << endl; + + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/subrule_calc.cpp b/src/boost/libs/spirit/classic/example/fundamental/subrule_calc.cpp new file mode 100644 index 00000000..238a1299 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/subrule_calc.cpp @@ -0,0 +1,140 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// This calculator example demontrates the use of subrules. +// This is discussed in the "Subrule" chapter in the Spirit User's Guide. +// +// [ JDG 4/11/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// + +//#define BOOST_SPIRIT_DEBUG // define this for debug output + +#include <boost/spirit/include/classic_core.hpp> +#include <iostream> +#include <string> + +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Semantic actions +// +/////////////////////////////////////////////////////////////////////////////// +namespace +{ + void do_int(char const* str, char const* end) + { + string s(str, end); + cout << "PUSH(" << s << ')' << endl; + } + + void do_add(char const*, char const*) { cout << "ADD\n"; } + void do_subt(char const*, char const*) { cout << "SUBTRACT\n"; } + void do_mult(char const*, char const*) { cout << "MULTIPLY\n"; } + void do_div(char const*, char const*) { cout << "DIVIDE\n"; } + void do_neg(char const*, char const*) { cout << "NEGATE\n"; } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Our calculator grammar (using subrules) +// +/////////////////////////////////////////////////////////////////////////////// +struct calculator : public grammar<calculator> +{ + template <typename ScannerT> + struct definition { + + definition(calculator const& /*self*/) + { + first = ( + + expression = + term + >> *( ('+' >> term)[&do_add] + | ('-' >> term)[&do_subt] + ) + , + + term = + factor + >> *( ('*' >> factor)[&do_mult] + | ('/' >> factor)[&do_div] + ) + , + + factor + = lexeme_d[(+digit_p)[&do_int]] + | '(' >> expression >> ')' + | ('-' >> factor)[&do_neg] + | ('+' >> factor) + ); + + BOOST_SPIRIT_DEBUG_NODE(first); + BOOST_SPIRIT_DEBUG_NODE(expression); + BOOST_SPIRIT_DEBUG_NODE(term); + BOOST_SPIRIT_DEBUG_NODE(factor); + } + + subrule<0> expression; + subrule<1> term; + subrule<2> factor; + + rule<ScannerT> first; + rule<ScannerT> const& + start() const { return first; } + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Main program +// +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tA calculator using subrules...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "Type an expression...or [q or Q] to quit\n\n"; + + calculator calc; // Our parser + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + parse_info<> info = parse(str.c_str(), calc, space_p); + + if (info.full) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "stopped at: \": " << info.stop << "\"\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/sum.cpp b/src/boost/libs/spirit/classic/example/fundamental/sum.cpp new file mode 100644 index 00000000..d6dd9c9d --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/sum.cpp @@ -0,0 +1,92 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A parser for summing a list of numbers. Demonstrating phoenix +// This is discussed in the "Phoenix" chapter in the Spirit User's Guide. +// +// [ JDG 6/28/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <iostream> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +/////////////////////////////////////////////////////////////////////////////// +// +// Our adder +// +/////////////////////////////////////////////////////////////////////////////// +template <typename IteratorT> +bool adder(IteratorT first, IteratorT last, double& n) +{ + return parse(first, last, + + // Begin grammar + ( + real_p[var(n) = arg1] >> *(',' >> real_p[var(n) += arg1]) + ) + , + // End grammar + + space_p).full; +} + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tA parser for summing a list of numbers...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + + cout << "Give me a comma separated list of numbers.\n"; + cout << "The numbers are added using Phoenix.\n"; + cout << "Type [q or Q] to quit\n\n"; + + string str; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + double n; + if (adder(str.begin(), str.end(), n)) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << str << " Parses OK: " << endl; + + cout << "sum = " << n; + cout << "\n-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/thousand_separated.cpp b/src/boost/libs/spirit/classic/example/fundamental/thousand_separated.cpp new file mode 100644 index 00000000..1b84e05b --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/thousand_separated.cpp @@ -0,0 +1,133 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A parser for a real number parser that parses thousands separated numbers +// with at most two decimal places and no exponent. This is discussed in the +// "Numerics" chapter in the Spirit User's Guide. +// +// [ JDG 12/16/2003 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_assign_actor.hpp> +#include <iostream> +#include <string> + +/////////////////////////////////////////////////////////////////////////////// +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; + + // Note: On erroneous input such as "123,45", the result should + // be a partial match "123". 'save' is used to makes sure that + // the scanner position is placed at the last *valid* parse + // position. + } + return scan.no_match(); + } +}; + +real_parser<double, ts_real_parser_policies<double> > const + ts_real_p = real_parser<double, ts_real_parser_policies<double> >(); + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + cout << "/////////////////////////////////////////////////////////\n\n"; + cout << "\t\tA real number parser that parses thousands separated\n"; + cout << "\t\tnumbers with at most two decimal places and no exponent...\n\n"; + cout << "/////////////////////////////////////////////////////////\n\n"; + + cout << "Give me a number.\n"; + cout << "Type [q or Q] to quit\n\n"; + + string str; + double n; + while (getline(cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + if (parse(str.c_str(), ts_real_p[assign_a(n)]).full) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + cout << str << " Parses OK: " << endl; + cout << "n=" << n << endl; + cout << "-------------------------\n"; + } + else + { + cout << "-------------------------\n"; + cout << "Parsing failed\n"; + cout << "-------------------------\n"; + } + } + + cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/fundamental/tree_calc_grammar.hpp b/src/boost/libs/spirit/classic/example/fundamental/tree_calc_grammar.hpp new file mode 100644 index 00000000..26e42261 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/fundamental/tree_calc_grammar.hpp @@ -0,0 +1,76 @@ +/*============================================================================= + 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) +=============================================================================*/ +#ifndef BOOST_SPIRIT_TREE_CALC_GRAMMAR_HPP_ +#define BOOST_SPIRIT_TREE_CALC_GRAMMAR_HPP_ + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +/////////////////////////////////////////////////////////////////////////////// +// +// Demonstrates the AST and parse trees. This is discussed in the +// "Trees" chapter in the Spirit User's Guide. +// +/////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////// +// +// 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[ 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; } + }; +}; + +#endif + diff --git a/src/boost/libs/spirit/classic/example/intermediate/ipv4.cpp b/src/boost/libs/spirit/classic/example/intermediate/ipv4.cpp new file mode 100644 index 00000000..93453bac --- /dev/null +++ b/src/boost/libs/spirit/classic/example/intermediate/ipv4.cpp @@ -0,0 +1,304 @@ +/*============================================================================= + Copyright (c) 2002-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_push_back_actor.hpp> +#include <boost/spirit/include/classic_if.hpp> +#include <boost/spirit/include/classic_for.hpp> +#include <boost/spirit/include/phoenix1.hpp> +#include <iostream> +#include <string> +#include <vector> +#include <algorithm> + +/////////////////////////////////////////////////////////////////////////////// +// +// Sample parser for binary data. This sample highlights the use of dynamic +// parsing where the result of actions direct the actual parsing behavior. +// We shall demonstrate 1) the use of phoenix to implement lambda (unnamed) +// functions, 2) dynamic looping using for_p, 3) the push_back_a actor for +// stuffing data into a vector, and 4) the if_p parser for choosing parser +// branches based on semantic conditions. +// +// << Sample idea by Florian Weimer >> +// +// For simplicity, we shall use bytes as atoms (and not 16-bit quantities +// in big-endian format or something similar, which would be more realistic) +// and PASCAL strings. +// +// A packet is the literal octet with value 255, followed by a variable +// octet N (denoting the total length of the packet), followed by N-2 octets +// (the payload). The payload contains a variable-length header, followed +// by zero or more elements. +// +// The header contains a single PASCAL string. +// +// An element is a PASCAL string (alternative: an element is an octet M, +// followed by [M/8] bytes, i.e. the necessary number of bytes to store M +// bits). +// +// (This data structure is inspired by the format of a BGP UPDATE message.) +// +// Packet layout: +// +// .-------------------. +// | 0xff | ^ +// +-------------------+ | +// | packet length | | +// +-------------------+ | number of bytes indicated by packet length +// : : | +// : payload : | +// | | v +// `-------------------' +// +// Payload layout: +// +// .-------------------. +// | header length | +// +-------------------+ +// | header octets | ^ +// : : | number of octets given by header length +// : : | +// : : v +// +-------------------+ +// | IPv4 prefix | ^ +// : : | IPv4 prefixes have variable length (see +// +-------------------+ | below). The number of prefixes is +// | IPv4 prefix | | determined by the packet length. +// : : | +// +-------------------+ | +// : : | +// : : v +// +// +// IPv4 prefix layout comes in five variants, depending on the first +// octet: +// +// .-------------------. +// | 0x00 | single octet, corresponds to 0.0.0.0/0 +// `-------------------' +// +// .-------------------. +// | 0x01 to 0x08 | two octets, prefix lengths up to /8. +// +-------------------+ +// | MSB of network | +// `-------------------' +// +// .-------------------. +// | 0x09 to 0x10 | three octets, prefix lengths up to /16. +// +-------------------+ +// | MSB of network | +// +-------------------+ +// | next octet | +// `-------------------' +// +// .-------------------. +// | 0x11 to 0x18 | four octets, prefix lengths up to /24. +// +-------------------+ +// | MSB of network | +// +-------------------+ +// | next octet | +// +-------------------+ +// | next octet | +// `-------------------' +// +// .-------------------. +// | 0x19 to 0x20 | five octets, prefix lengths up to /32. +// +-------------------+ +// | MSB of network | +// +-------------------+ +// | next octet | +// +-------------------+ +// | next octet | +// +-------------------+ +// | LSB of network | +// `-------------------' +// +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +struct ipv4_prefix_data +{ + char prefix_len, n0, n1, n2, n3; + + ipv4_prefix_data() + : prefix_len(0),n0(0),n1(0),n2(0),n3(0) {} +}; + +struct ipv4_data +{ + char packet_len, header_len; + std::string header; + std::vector<ipv4_prefix_data> prefixes; + + ipv4_data() + : packet_len(0),header_len(0){} + +}; + +struct ipv4 : public grammar<ipv4> +{ + template <typename ScannerT> + struct definition + { + definition(ipv4 const& self) + { + packet = + '\xff' + >> anychar_p[var(self.data.packet_len) = arg1] + >> payload + ; + + payload = + anychar_p[var(self.data.header_len) = arg1] + >> for_p(var(i) = 0, var(i) < var(self.data.header_len), ++var(i)) + [ + anychar_p[var(self.data.header) += arg1] + ] + >> *ipv4_prefix + ; + + ipv4_prefix = + anychar_p + [ + var(temp.prefix_len) = arg1, + var(temp.n0) = 0, + var(temp.n1) = 0, + var(temp.n2) = 0, + var(temp.n3) = 0 + ] + + >> if_p(var(temp.prefix_len) > 0x00) + [ + anychar_p[var(temp.n0) = arg1] + >> if_p(var(temp.prefix_len) > 0x08) + [ + anychar_p[var(temp.n1) = arg1] + >> if_p(var(temp.prefix_len) > 0x10) + [ + anychar_p[var(temp.n2) = arg1] + >> if_p(var(temp.prefix_len) > 0x18) + [ + anychar_p[var(temp.n3) = arg1] + ] + ] + ] + ] + [ + push_back_a(self.data.prefixes, temp) + ] + ; + } + + int i; + ipv4_prefix_data temp; + rule<ScannerT> packet, payload, ipv4_prefix; + rule<ScannerT> const& + start() const { return packet; } + }; + + ipv4(ipv4_data& data) + : data(data) {} + + ipv4_data& data; +}; + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +as_byte(char n) +{ + if (n < 0) + return n + 256; + return n; +} + +void +print_prefix(ipv4_prefix_data const& prefix) +{ + cout << "prefix length = " << as_byte(prefix.prefix_len) << endl; + cout << "n0 = " << as_byte(prefix.n0) << endl; + cout << "n1 = " << as_byte(prefix.n1) << endl; + cout << "n2 = " << as_byte(prefix.n2) << endl; + cout << "n3 = " << as_byte(prefix.n3) << endl; +} + +void +parse_ipv4(char const* str, unsigned len) +{ + ipv4_data data; + ipv4 g(data); + parse_info<> info = parse(str, str+len, g); + + if (info.full) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + + cout << "packet length = " << as_byte(data.packet_len) << endl; + cout << "header length = " << as_byte(data.header_len) << endl; + cout << "header = " << data.header << endl; + + for_each(data.prefixes.begin(), data.prefixes.end(), print_prefix); + cout << "-------------------------\n"; + } + else + { + cout << "Parsing failed\n"; + cout << "stopped at:"; + for (char const* s = info.stop; s != str+len; ++s) + cout << static_cast<int>(*s) << endl; + } +} + +// Test inputs: + +// The string in the header is "empty", the prefix list is empty. +char const i1[8] = +{ + 0xff,0x08,0x05, + 'e','m','p','t','y' +}; + +// The string in the header is "default route", the prefix list +// has just one element, 0.0.0.0/0. +char const i2[17] = +{ + 0xff,0x11,0x0d, + 'd','e','f','a','u','l','t',' ', + 'r','o','u','t','e', + 0x00 +}; + +// The string in the header is "private address space", the prefix list +// has the elements 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16. +char const i3[32] = +{ + 0xff,0x20,0x15, + 'p','r','i','v','a','t','e',' ', + 'a','d','d','r','e','s','s',' ', + 's','p','a','c','e', + 0x08,0x0a, + 0x0c,0xac,0x10, + 0x10,0xc0,0xa8 +}; + +int +main() +{ + parse_ipv4(i1, sizeof(i1)); + parse_ipv4(i2, sizeof(i2)); + parse_ipv4(i3, sizeof(i3)); + return 0; +} + diff --git a/src/boost/libs/spirit/classic/example/intermediate/ipv4_opt.cpp b/src/boost/libs/spirit/classic/example/intermediate/ipv4_opt.cpp new file mode 100644 index 00000000..ed5429fd --- /dev/null +++ b/src/boost/libs/spirit/classic/example/intermediate/ipv4_opt.cpp @@ -0,0 +1,213 @@ +/*============================================================================= + Copyright (c) 2002-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_push_back_actor.hpp> +#include <boost/spirit/include/classic_if.hpp> +#include <boost/spirit/include/classic_for.hpp> +#include <boost/spirit/include/phoenix1.hpp> +#include <iostream> +#include <string> +#include <vector> +#include <algorithm> + +/////////////////////////////////////////////////////////////////////////////// +// +// Please check it out ipv4.cpp sample first! +// << See ipv4.cpp sample for details >> +// +// This is a variation of the ipv4.cpp sample. The original ipv4.cpp code +// compiles to 36k on MSVC7.1. Not bad! Yet, we want to shave a little bit +// more. Is it possible? Yes! This time, we'll use subrules and just store +// the rules in a plain old struct. We are parsing at the char level anyway, +// so we know what type of rule we'll need: a plain rule<>. The result: we +// shaved off another 20k. Now the code compiles to 16k on MSVC7.1. +// +// Could we have done better? Yes, but only if only we had typeof! << See +// the techniques section of the User's guide >> ... Someday... :-) +// +/////////////////////////////////////////////////////////////////////////////// +using namespace std; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +struct ipv4_prefix_data +{ + char prefix_len, n0, n1, n2, n3; + + ipv4_prefix_data() + : prefix_len(0),n0(0),n1(0),n2(0),n3(0) {} +}; + +struct ipv4_data +{ + char packet_len, header_len; + std::string header; + std::vector<ipv4_prefix_data> prefixes; + + ipv4_data() + : packet_len(0),header_len(0){} + +}; + +struct ipv4 +{ + ipv4(ipv4_data& data) + : data(data) + { + start = + ( + packet = + '\xff' + >> anychar_p[var(data.packet_len) = arg1] + >> payload + , + + payload = + anychar_p[var(data.header_len) = arg1] + >> for_p(var(i) = 0, var(i) < var(data.header_len), ++var(i)) + [ + anychar_p[var(data.header) += arg1] + ] + >> *ipv4_prefix + , + + ipv4_prefix = + anychar_p + [ + var(temp.prefix_len) = arg1, + var(temp.n0) = 0, + var(temp.n1) = 0, + var(temp.n2) = 0, + var(temp.n3) = 0 + ] + + >> if_p(var(temp.prefix_len) > 0x00) + [ + anychar_p[var(temp.n0) = arg1] + >> if_p(var(temp.prefix_len) > 0x08) + [ + anychar_p[var(temp.n1) = arg1] + >> if_p(var(temp.prefix_len) > 0x10) + [ + anychar_p[var(temp.n2) = arg1] + >> if_p(var(temp.prefix_len) > 0x18) + [ + anychar_p[var(temp.n3) = arg1] + ] + ] + ] + ] + [ + push_back_a(data.prefixes, temp) + ] + ); + } + + int i; + ipv4_prefix_data temp; + + rule<> start; + subrule<0> packet; + subrule<1> payload; + subrule<2> ipv4_prefix; + ipv4_data& data; +}; + +//////////////////////////////////////////////////////////////////////////// +// +// Main program +// +//////////////////////////////////////////////////////////////////////////// +int +as_byte(char n) +{ + if (n < 0) + return n + 256; + return n; +} + +void +print_prefix(ipv4_prefix_data const& prefix) +{ + cout << "prefix length = " << as_byte(prefix.prefix_len) << endl; + cout << "n0 = " << as_byte(prefix.n0) << endl; + cout << "n1 = " << as_byte(prefix.n1) << endl; + cout << "n2 = " << as_byte(prefix.n2) << endl; + cout << "n3 = " << as_byte(prefix.n3) << endl; +} + +void +parse_ipv4(char const* str, unsigned len) +{ + ipv4_data data; + ipv4 g(data); + parse_info<> info = parse(str, str+len, g.start); + + if (info.full) + { + cout << "-------------------------\n"; + cout << "Parsing succeeded\n"; + + cout << "packet length = " << as_byte(data.packet_len) << endl; + cout << "header length = " << as_byte(data.header_len) << endl; + cout << "header = " << data.header << endl; + + for_each(data.prefixes.begin(), data.prefixes.end(), print_prefix); + cout << "-------------------------\n"; + } + else + { + cout << "Parsing failed\n"; + cout << "stopped at:"; + for (char const* s = info.stop; s != str+len; ++s) + cout << static_cast<int>(*s) << endl; + } +} + +// Test inputs: + +// The string in the header is "empty", the prefix list is empty. +char const i1[8] = +{ + 0xff,0x08,0x05, + 'e','m','p','t','y' +}; + +// The string in the header is "default route", the prefix list +// has just one element, 0.0.0.0/0. +char const i2[17] = +{ + 0xff,0x11,0x0d, + 'd','e','f','a','u','l','t',' ', + 'r','o','u','t','e', + 0x00 +}; + +// The string in the header is "private address space", the prefix list +// has the elements 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16. +char const i3[32] = +{ + 0xff,0x20,0x15, + 'p','r','i','v','a','t','e',' ', + 'a','d','d','r','e','s','s',' ', + 's','p','a','c','e', + 0x08,0x0a, + 0x0c,0xac,0x10, + 0x10,0xc0,0xa8 +}; + +int +main() +{ + parse_ipv4(i1, sizeof(i1)); + parse_ipv4(i2, sizeof(i2)); + parse_ipv4(i3, sizeof(i3)); + return 0; +} + diff --git a/src/boost/libs/spirit/classic/example/intermediate/lazy_parser.cpp b/src/boost/libs/spirit/classic/example/intermediate/lazy_parser.cpp new file mode 100644 index 00000000..6035fd80 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/intermediate/lazy_parser.cpp @@ -0,0 +1,126 @@ +/*============================================================================= + 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) +=============================================================================*/ +// +// This example demonstrates the lazy_p parser. You should read +// "The Lazy Parser" in the documentation. +// +// We want to parse nested blocks of numbers like this: +// +// dec { +// 1 2 3 +// bin { +// 1 10 11 +// } +// 4 5 6 +// } +// +// where the numbers in the "dec" block are wrote in the decimal system and +// the numbers in the "bin" block are wrote in the binary system. We want +// parser to return the overall sum. +// +// To achive this when base ("bin" or "dec") is parsed, in semantic action +// we store a pointer to the appropriate numeric parser in the closure +// variable block.int_rule. Than, when we need to parse a number we use lazy_p +// parser to invoke the parser stored in the block.int_rule pointer. +// +//----------------------------------------------------------------------------- +#include <boost/assert.hpp> +#include <boost/cstdlib.hpp> +#include <boost/spirit/include/phoenix1.hpp> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_symbols.hpp> +#include <boost/spirit/include/classic_attribute.hpp> +#include <boost/spirit/include/classic_dynamic.hpp> + +using namespace boost; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +//----------------------------------------------------------------------------- +// my grammar + +struct my_grammar + : public grammar<my_grammar, parser_context<int> > +{ + // grammar definition + template<typename ScannerT> + struct definition + { + typedef rule<ScannerT> rule_t; + typedef stored_rule<ScannerT, parser_context<int> > number_rule_t; + + struct block_closure; + typedef boost::spirit::classic::closure< + block_closure, + int, + typename number_rule_t::alias_t> + closure_base_t; + + struct block_closure : closure_base_t + { + typename closure_base_t::member1 sum; + typename closure_base_t::member2 int_rule; + }; + + // block rule type + typedef rule<ScannerT, typename block_closure::context_t> block_rule_t; + + block_rule_t block; + rule_t block_item; + symbols<number_rule_t> base; + + definition(my_grammar const& self) + { + block = + base[ + block.sum = 0, + // store a number rule in a closure member + block.int_rule = arg1 + ] + >> "{" + >> *block_item + >> "}" + ; + + block_item = + // use the stored rule + lazy_p(block.int_rule)[block.sum += arg1] + | block[block.sum += arg1] + ; + + // bind base keywords and number parsers + base.add + ("bin", bin_p) + ("dec", uint_p) + ; + } + + block_rule_t const& start() const + { + return block; + } + }; +}; + +//----------------------------------------------------------------------------- + +int main() +{ + my_grammar gram; + parse_info<> info; + + int result; + info = parse("bin{1 dec{1 2 3} 10}", gram[var(result) = arg1], space_p); + BOOST_ASSERT(info.full); + BOOST_ASSERT(result == 9); + + return exit_success; +} + +//----------------------------------------------------------------------------- diff --git a/src/boost/libs/spirit/classic/example/intermediate/parameters.cpp b/src/boost/libs/spirit/classic/example/intermediate/parameters.cpp new file mode 100644 index 00000000..b93fb0ec --- /dev/null +++ b/src/boost/libs/spirit/classic/example/intermediate/parameters.cpp @@ -0,0 +1,216 @@ +/*============================================================================= + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// This sample show the usage of parser parameters. +// +// Parser parameters are used to pass some values from the outer parsing scope +// to the next inner scope. They can be imagined as the opposite to the return +// value paradigm, which returns some value from the inner to the next outer +// scope. See the "Closures" chapter in the User's Guide. + +#include <string> +#include <iostream> +#include <cassert> + +#if defined(_MSC_VER) /*&& !defined(__COMO__)*/ +#pragma warning(disable: 4244) +#pragma warning(disable: 4355) +#endif // defined(_MSC_VER) && !defined(__COMO__) + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_symbols.hpp> +#include <boost/spirit/include/classic_closure.hpp> + +#include <boost/spirit/include/phoenix1_tuples.hpp> +#include <boost/spirit/include/phoenix1_tuple_helpers.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> + +/////////////////////////////////////////////////////////////////////////////// +// used namespaces +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; +using namespace std; + +/////////////////////////////////////////////////////////////////////////////// +// Helper class for encapsulation of the type for the parsed variable names +class declaration_type +{ +public: + enum vartype { + vartype_unknown = 0, // unknown variable type + vartype_int = 1, // 'int' + vartype_real = 2 // 'real' + }; + + declaration_type() : type(vartype_unknown) + { + } + template <typename ItT> + declaration_type(ItT const &first, ItT const &last) + { + init(string(first, last-first-1)); + } + declaration_type(declaration_type const &type_) : type(type_.type) + { + } + declaration_type(string const &type_) : type(vartype_unknown) + { + init(type_); + } + +// access to the variable type + operator vartype const &() const { return type; } + operator string () + { + switch(type) { + default: + case vartype_unknown: break; + case vartype_int: return string("int"); + case vartype_real: return string("real"); + } + return string ("unknown"); + } + + void swap(declaration_type &s) { std::swap(type, s.type); } + +protected: + void init (string const &type_) + { + if (type_ == "int") + type = vartype_int; + else if (type_ == "real") + type = vartype_real; + else + type = vartype_unknown; + } + +private: + vartype type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// used closure type +// +/////////////////////////////////////////////////////////////////////////////// +struct var_decl_closure : BOOST_SPIRIT_CLASSIC_NS::closure<var_decl_closure, declaration_type> +{ + member1 val; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// symbols_with_data +// +// Helper class for inserting an item with data into a symbol table +// +/////////////////////////////////////////////////////////////////////////////// +template <typename T, typename InitT> +class symbols_with_data +{ +public: + typedef + symbol_inserter<T, BOOST_SPIRIT_CLASSIC_NS::impl::tst<T, char> > + symbol_inserter_t; + + symbols_with_data(symbol_inserter_t const &add_, InitT const &data_) : + add(add_), data(as_actor<InitT>::convert(data_)) + { + } + + template <typename IteratorT> + symbol_inserter_t const & + operator()(IteratorT const &first_, IteratorT const &last) const + { + IteratorT first = first_; + return add(first, last, data()); + } + +private: + symbol_inserter_t const &add; + typename as_actor<InitT>::type data; +}; + +template <typename T, typename CharT, typename InitT> +inline +symbols_with_data<T, InitT> +symbols_gen(symbol_inserter<T, BOOST_SPIRIT_CLASSIC_NS::impl::tst<T, CharT> > const &add_, + InitT const &data_) +{ + return symbols_with_data<T, InitT>(add_, data_); +} + +/////////////////////////////////////////////////////////////////////////////// +// The var_decl_list grammar parses variable declaration list + +struct var_decl_list : + public grammar<var_decl_list, var_decl_closure::context_t> +{ + template <typename ScannerT> + struct definition + { + definition(var_decl_list const &self) + { + // pass variable type returned from 'type' to list closure member 0 + decl = type[self.val = arg1] >> +space_p >> list(self.val); + + // m0 to access arg 0 of list --> passing variable type down to ident + list = ident(list.val) >> *(',' >> ident(list.val)); + + // store identifier and type into the symbol table + ident = (*alnum_p)[symbols_gen(symtab.add, ident.val)]; + + // the type of the decl is returned in type's closure member 0 + type = + str_p("int")[type.val = construct_<string>(arg1, arg2)] + | str_p("real")[type.val = construct_<string>(arg1, arg2)] + ; + + BOOST_SPIRIT_DEBUG_RULE(decl); + BOOST_SPIRIT_DEBUG_RULE(list); + BOOST_SPIRIT_DEBUG_RULE(ident); + BOOST_SPIRIT_DEBUG_RULE(type); + } + + rule<ScannerT> const& + start() const { return decl; } + + private: + typedef rule<ScannerT, var_decl_closure::context_t> rule_t; + rule_t type; + rule_t list; + rule_t ident; + symbols<declaration_type> symtab; + + rule<ScannerT> decl; // start rule + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// main entry point +int main() +{ +var_decl_list decl; +declaration_type type; +char const *pbegin = "int var1"; + + if (parse (pbegin, decl[assign(type)]).full) { + cout << endl + << "Parsed variable declarations successfully!" << endl + << "Detected type: " << declaration_type::vartype(type) + << " (" << string(type) << ")" + << endl; + } else { + cout << endl + << "Parsing the input stream failed!" + << endl; + } + return 0; +} + diff --git a/src/boost/libs/spirit/classic/example/intermediate/regex_convert.cpp b/src/boost/libs/spirit/classic/example/intermediate/regex_convert.cpp new file mode 100644 index 00000000..e167c2e3 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/intermediate/regex_convert.cpp @@ -0,0 +1,177 @@ +/*============================================================================= + 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 +// +// Demonstrate regular expression parsers for match based text conversion +// +// This sample requires an installed version of the boost regex library +// (http://www.boost.org) The sample was tested with boost V1.29.0 +// +// Note: - there is no error handling in this example +// - this program isn't particularly useful +// +// This example shows one way build a kind of filter program. +// It reads input from std::cin and uses a grammar and actions +// to print out a modified version of the input. +// +// [ Martin Wille, 10/18/2002 ] +// +/////////////////////////////////////////////////////////////////////////////// + +#include <string> +#include <iostream> +#include <streambuf> +#include <sstream> +#include <deque> +#include <iterator> + +#include <boost/function.hpp> +#include <boost/spirit/include/classic_core.hpp> + +/////////////////////////////////////////////////////////////////////////////// +// +// The following header must be included, if regular expression support is +// required for Spirit. +// +// The BOOST_SPIRIT_NO_REGEX_LIB PP constant should be defined, if you're using the +// Boost.Regex library from one translation unit only. Otherwise you have to +// link with the Boost.Regex library as defined in the related documentation +// (see. http://www.boost.org). +// +/////////////////////////////////////////////////////////////////////////////// +#define BOOST_SPIRIT_NO_REGEX_LIB +#include <boost/spirit/include/classic_regex.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace std; + +namespace { + long triple(long val) + { + return 3*val; + } + /////////////////////////////////////////////////////////////////////////// + // + // actions + // + struct emit_constant + { + emit_constant(string const &text) + : msg(text) + {} + + template<typename Iterator> + void operator()(Iterator b, Iterator e) const + { + cout.rdbuf()->sputn(msg.data(), msg.size()); + } + + private: + + string msg; + }; + + void + copy_unmodified(char letter) + { + cout.rdbuf()->sputc(letter); + } + + struct emit_modified_subscript + { + emit_modified_subscript(boost::function<long (long)> const &f) + : modifier(f) + {} + + template<typename Iterator> + void operator()(Iterator b, Iterator e) const + { + string tmp(b+1,e-1); + long val = strtol(tmp.c_str(),0, 0); + ostringstream os; + os << modifier(val); + tmp = os.str(); + cout.rdbuf()->sputc('['); + cout.rdbuf()->sputn(tmp.c_str(), tmp.size()); + cout.rdbuf()->sputc(']'); + } + + private: + + boost::function<long (long)> modifier; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// The grammar 'conversion_grammar' serves as a working horse for match based +// text conversion. It does the following: +// +// - converts the word "class" into the word "struct" +// - multiplies any integer number enclosed in square brackets with 3 +// - any other input is simply copied to the output + +struct conversion_grammar + : grammar<conversion_grammar> +{ + template<class ScannerT> + struct definition + { + typedef ScannerT scanner_t; + + definition(conversion_grammar const &) + { + static const char expr[] = "\\[\\d+\\]"; + first = ( + ///////////////////////////////////////////////////////////// + // note that "fallback" is the last alternative here ! + top = *(class2struct || subscript || fallback), + ///////////////////////////////////////////////////////////// + // replace any occurrence of "class" by "struct" + class2struct = str_p("class") [emit_constant("struct")], + ///////////////////////////////////////////////////////////// + // if the input maches "[some_number]" + // "some_number" is multiplied by 3 before printing + subscript = regex_p(expr) [emit_modified_subscript(&triple)], + ///////////////////////////////////////////////////////////// + // if nothing else can be done with the input + // then it will be printed without modifications + fallback = anychar_p [©_unmodified] + ); + } + + rule<scanner_t> const & start() { return first; } + + private: + + subrule<0> top; + subrule<1> class2struct; + subrule<2> subscript; + subrule<3> fallback; + rule<scanner_t> first; + }; +}; + +int +main() +{ + // this would print "struct foo {}; foo bar[9];": + // parse("class foo {}; foo bar[3];", conversion_grammar()); + + // Note: the regular expression parser contained in the + // grammar requires a bidirectional iterator. Therefore, + // we cannot use sdt::istreambuf_iterator as one would + // do with other Spirit parsers. + istreambuf_iterator<char> input_iterator(cin); + std::deque<char> input(input_iterator, istreambuf_iterator<char>()); + + parse(input.begin(), input.end(), conversion_grammar()); + return 0; +} + diff --git a/src/boost/libs/spirit/classic/example/intermediate/simple_xml/actions.hpp b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/actions.hpp new file mode 100644 index 00000000..285edf21 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/actions.hpp @@ -0,0 +1,68 @@ +// Copyright (c) 2005 Carl Barron. 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) + +#ifndef ACTIONS_H +#define ACTIONS_H +#include <boost/spirit/include/phoenix1.hpp> +#include <boost/variant.hpp> +#include "tag.hpp" + +struct push_child_impl +{ + template <class T,class A> + struct result {typedef void type;}; + + template <class T,class A> + void operator () (T &list, const A &value) const + { + typename tag::variant_type p(value); + list.push_back(p); + } +}; + +struct store_in_map_impl +{ + template <class T,class A> + struct result{typedef void type;}; + + template <class T,class A> + void operator () (T &map,const A &value)const + { + typedef typename T::value_type value_type; + map.insert(value_type(value)); + } +}; + +struct push_back_impl +{ + template <class T,class A> + struct result {typedef void type;}; + + template <class T,class A> + void operator () (T &list,const A &value)const + { + list.push_back(value); + } +}; + +struct store_tag_impl +{ + template <class T,class A,class B,class C> + struct result {typedef void type;}; + + template <class T,class A,class B,class C> + void operator ()(T &t,const A &a,const B &b,const C &c)const + { + t.id = a; + t.attributes = b; + t.children = c; + } +}; + + +typedef phoenix::function<push_back_impl> push_back_f; +typedef phoenix::function<store_in_map_impl>store_in_map_f; +typedef phoenix::function<push_child_impl> push_child_f; +typedef phoenix::function<store_tag_impl> store_tag_f; +#endif diff --git a/src/boost/libs/spirit/classic/example/intermediate/simple_xml/driver.cpp b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/driver.cpp new file mode 100644 index 00000000..57ad6f20 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/driver.cpp @@ -0,0 +1,43 @@ +// Copyright (c) 2005 Carl Barron. 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 "xml_g.hpp" +#include <boost/spirit/include/classic_utility.hpp> +#include <iostream> + +namespace std +{ + std::ostream & operator << (std::ostream &os,std::pair<std::string,std::string> const &p) + { + return os << p.first << '=' << p.second; + } + + std::ostream & operator << (std::ostream &os,const tag &t) + { + return os << t.id; + } + +} + +int main() +{ + const char *test = + // "<A x=\"1\" y=\"2\"> test 1 </A>" + // "<B x=\"3\" y= \"4\" z = \"10\"> test 3 </B>" + // "<C><A></A><V><W></W></V></C>" + // "<D x=\"4\"/>" + "<E>xxx<F>yyy</F>zzz</E>" + ; + std::list<tag> tags; + xml_g g(tags); + + if(SP::parse(test,g,SP::comment_p("<---","--->")).full) + { + std::for_each(tags.begin(),tags.end(),walk_data()); + } + else + { + std::cout << "parse failed\n"; + } +} diff --git a/src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.cpp b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.cpp new file mode 100644 index 00000000..088f3a00 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.cpp @@ -0,0 +1,46 @@ +// Copyright (c) 2005 Carl Barron. 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 "tag.hpp" +#include <iostream> +#include <algorithm> + +namespace +{ + struct print_pair + { + template <class P> + void operator () (const P &x) + { + std::cout << '\t' << x.first << ':' << x.second <<'\n'; + } + }; + +} + +void walk_data::operator () (const std::string &x) +{ + std::cout << "String:" << x <<'\n'; +} + +void walk_data::operator () (const tag &t) +{ + std::cout << "Tag:" << t.id << '\n'; + std::cout << "Attributes\n"; + + std::for_each + ( + t.attributes.begin(), + t.attributes.end(), + print_pair() + ); + std::cout << "Children:\n"; + std::for_each + ( + t.children.begin(), + t.children.end(), + boost::apply_visitor(*this) + ); + std::cout << "End of tag:" << t.id << '\n'; +} diff --git a/src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.hpp b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.hpp new file mode 100644 index 00000000..15f97593 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2005 Carl Barron. 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) + +#ifndef SIMPLE_XML_TAG_H +#define SIMPLE_XML_TAG_H + +#include <boost/variant.hpp> +#include <list> +#include <map> +#include <string> + +struct tag +{ + std::string id; + std::map<std::string,std::string> attributes; + typedef boost::variant< + std::string, + boost::recursive_wrapper<tag> + > + variant_type; + std::list<variant_type> children; +}; + + +struct walk_data +{ + typedef void result_type; + void operator () (const std::string &x); + void operator () (const tag &t); +}; + +#endif diff --git a/src/boost/libs/spirit/classic/example/intermediate/simple_xml/xml_g.hpp b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/xml_g.hpp new file mode 100644 index 00000000..fb0a4c61 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/xml_g.hpp @@ -0,0 +1,186 @@ +// Copyright (c) 2005 Carl Barron. 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) + +#ifndef XML_G_H +#define XML_G_H +#define BOOST_SPIRIT_DEBUG +#ifndef BOOST_SPIRIT_CLOSURE_LIMIT +#define BOOST_SPIRIT_CLOSURE_LIMIT 10 +#endif + +#ifndef PHOENIX_LIMIT +#define PHOENIX_LIMIT 10 +#endif + +#if BOOST_SPIRIT_CLOSURE_LIMIT < 6 +#undef BOOST_SPIRIT_CLOSURE_LIMIT +#define BOOST_SPIRIT_CLOSURE_LIMIT 6 +#endif + +#if PHOENIX_LIMIT < BOOST_SPIRIT_CLOSURE_LIMIT +#undef PHOENIX_LIMIT +#define PHOENIX_LIMIT BOOST_SPIRIT_CLOSURE_LIMIT +#endif + +#if 0 +#ifdef BOOST_SPIRIT_DEBUG_FLAGS +#undef BOOST_SPIRIT_DEBUG_FLAGS +#endif +#define BOOST_SPIRIT_DEBUG_FLAGS (BOOST_SPIRIT_DEBUG_FLAGS_MAX - BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES) +#endif + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_attribute.hpp> +#include <boost/spirit/include/phoenix1.hpp> +#include "tag.hpp" +#include "actions.hpp" +#include <boost/variant.hpp> + +#include <string> +#include <utility> + +namespace SP = BOOST_SPIRIT_CLASSIC_NS; +using phoenix::arg1; +using phoenix::arg2; +using phoenix::construct_; +using phoenix::var; + +struct str_cls:SP::closure<str_cls,std::string> +{ member1 value;}; + +struct attrib_cls:SP::closure +< + attrib_cls, + std::pair<std::string,std::string>, + std::string, + std::string +> +{ + member1 value; + member2 first; + member3 second; +}; + +struct tagged_cls:SP::closure +< + tagged_cls, + tag, + std::string, + std::map<std::string,std::string>, + std::list<typename tag::variant_type> +> +{ + member1 value; + member2 ID; + member3 attribs; + member4 children; +}; + +struct xml_g:SP::grammar<xml_g> +{ + std::list<tag> &tags; + xml_g(std::list<tag> &a):tags(a){} + template <class Scan> + struct definition + { + definition(const xml_g &s) + { + white = +SP::space_p + ; + + tagged = (start_tag + >> *inner + >> end_tag + | simple_start_tag + ) + [store_tag(tagged.value,tagged.ID,tagged.attribs, + tagged.children)] + ; + + end_tag = SP::str_p("</") + >> SP::f_str_p(tagged.ID) + >> '>' + ; + + inner = (tagged + | str) [push_child(tagged.children,arg1)] + ; + + str = SP::lexeme_d[+(SP::anychar_p - '<')] + [str.value=construct_<std::string>(arg1,arg2)] + ; + + top = +tagged + [push_back(var(s.tags),arg1)] + ; + + starter = SP::ch_p('<') + >> SP::lexeme_d[+SP::alpha_p] + [tagged.ID = construct_<std::string>(arg1,arg2)] + >> *attrib + [store_in_map(tagged.attribs,arg1)] + >> !white + ; + start_tag = starter + >> '>' + ; + + simple_start_tag = starter + >> "/>" + ; + + attrib = white + >>SP::lexeme_d[+SP::alpha_p] + [attrib.first = construct_<std::string>(arg1,arg2)] + >> !white + >> '=' + >> !white + >> '"' + >> SP::lexeme_d[+(SP::anychar_p - '"')] + [attrib.second = construct_<std::string>(arg1,arg2)] + >> SP::ch_p('"') + [attrib.value = construct_ + < + std::pair + < + std::string, + std::string + > + >(attrib.first,attrib.second)] + ; + BOOST_SPIRIT_DEBUG_RULE(tagged); + BOOST_SPIRIT_DEBUG_RULE(end_tag); + BOOST_SPIRIT_DEBUG_RULE(inner); + BOOST_SPIRIT_DEBUG_RULE(str); + BOOST_SPIRIT_DEBUG_RULE(top); + BOOST_SPIRIT_DEBUG_RULE(start_tag); + BOOST_SPIRIT_DEBUG_RULE(attrib); + BOOST_SPIRIT_DEBUG_RULE(white); + BOOST_SPIRIT_DEBUG_RULE(starter); + BOOST_SPIRIT_DEBUG_RULE(simple_start_tag); + } + + // actions + push_back_f push_back; + push_child_f push_child; + store_in_map_f store_in_map; + store_tag_f store_tag; + // rules + SP::rule<Scan,tagged_cls::context_t> tagged; + SP::rule<Scan> end_tag; + SP::rule<Scan> inner; + SP::rule<Scan,str_cls::context_t> str; + SP::rule<Scan> top; + SP::rule<Scan> starter; + SP::rule<Scan> simple_start_tag; + SP::rule<Scan> start_tag; + SP::rule<Scan> white; + SP::rule<Scan,attrib_cls::context_t> attrib; + SP::rule<Scan> const &start() const + { return top;} + }; +}; + +#endif + diff --git a/src/boost/libs/spirit/classic/example/techniques/dynamic_rule.cpp b/src/boost/libs/spirit/classic/example/techniques/dynamic_rule.cpp new file mode 100644 index 00000000..d3e1a086 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/dynamic_rule.cpp @@ -0,0 +1,58 @@ +/*============================================================================= + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// This example shows how the assign operator can be used to modify +// rules with semantic actions +// +// First we show the basic spirit without (without any dynamic feature), +// then we show how to use assign_a to make it dynamic, +// +// the grammar has to parse abcabc... sequences +/////////////////////////////////////////////////////////////////////////////// +#include <iostream> + +#define BOOST_SPIRIT_DEBUG +#include <boost/spirit.hpp> + +#include <boost/spirit/include/classic_assign_actor.hpp> + +int main() +{ + using namespace BOOST_SPIRIT_CLASSIC_NS; + using namespace std; + + rule<> a,b,c,next; + const char* str="abcabc"; + parse_info<> hit; + BOOST_SPIRIT_DEBUG_NODE(next); + BOOST_SPIRIT_DEBUG_NODE(a); + BOOST_SPIRIT_DEBUG_NODE(b); + BOOST_SPIRIT_DEBUG_NODE(c); + + // basic spirit gram + a = ch_p('a') >> !b; + b = ch_p('b') >> !c; + c = ch_p('c') >> !a; + + hit = parse(str, a); + cout<<"hit :"<<( hit.hit ? "yes" : "no")<<", " + <<(hit.full ? "full": "not full") + <<endl; + + // using assign_a + a = ch_p('a')[ assign_a( next, b)] >> !next; + b = ch_p('b')[ assign_a( next, c)] >> !next; + c = ch_p('c')[ assign_a( next, a)] >> !next; + hit = parse(str, a); + cout<<"hit :"<<( hit.hit ? "yes" : "no")<<", " + <<(hit.full ? "full": "not full") + <<endl; + + return 0; +} diff --git a/src/boost/libs/spirit/classic/example/techniques/epsilon.cpp b/src/boost/libs/spirit/classic/example/techniques/epsilon.cpp new file mode 100644 index 00000000..b331774d --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/epsilon.cpp @@ -0,0 +1,68 @@ +/*============================================================================= + 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) +=============================================================================*/ +// +// This example demonstrates the behaviour of epsilon_p when used as parser +// generator. +// +// The "r" is the rule, which is passed as a subject to the epsilon_p parser +// generator. The "r" is the rule with binded semantic actions. But epsilon_p +// parser generator is intended for looking forward and we don't want to +// invoke semantic actions of subject parser. Hence the epsilon_p uses +// the no_actions policy. +// +// Because we want to use the "r" rule both in the epsilon_p and outside of it +// we need the "r" to support two differant scanners, one with no_actions +// action policy and one with the default action policy. To achieve this +// we declare the "r" with the no_actions_scanner_list scanner type. +// +//----------------------------------------------------------------------------- +#define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 2 + +#include <boost/assert.hpp> +#include <iostream> +#include <boost/cstdlib.hpp> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/phoenix1.hpp> + +using namespace std; +using namespace boost; +using namespace BOOST_SPIRIT_CLASSIC_NS; +using namespace phoenix; + +//----------------------------------------------------------------------------- + +int main() +{ + rule< + // Support both the default phrase_scanner_t and the modified version + // with no_actions action_policy + no_actions_scanner_list<phrase_scanner_t>::type + > r; + + int i(0); + + r = int_p[var(i) += arg1]; + + parse_info<> info = parse( + "1", + + // r rule is used twice but the semantic action is invoked only once + epsilon_p(r) >> r, + + space_p + ); + + BOOST_ASSERT(info.full); + // Check, that the semantic action was invoked only once + BOOST_ASSERT(i == 1); + + return exit_success; +} + +//----------------------------------------------------------------------------- diff --git a/src/boost/libs/spirit/classic/example/techniques/multiple_scanners.cpp b/src/boost/libs/spirit/classic/example/techniques/multiple_scanners.cpp new file mode 100644 index 00000000..c7d48215 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/multiple_scanners.cpp @@ -0,0 +1,53 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ + +// *** See the section "Rule With Multiple Scanners" in +// *** chapter "Techniques" of the Spirit documentation +// *** for information regarding this snippet + +#define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 3 + +#include <iostream> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/assert.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +struct my_grammar : 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; } + }; +}; + +int +main() +{ + my_grammar g; + bool success = parse("abcdef aBc d e f aBc d E f", g, space_p).full; + BOOST_ASSERT(success); + std::cout << "SUCCESS!!!\n"; + return 0; +} diff --git a/src/boost/libs/spirit/classic/example/techniques/nabialek.cpp b/src/boost/libs/spirit/classic/example/techniques/nabialek.cpp new file mode 100644 index 00000000..c2fbd1a0 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/nabialek.cpp @@ -0,0 +1,94 @@ +/*============================================================================= + Copyright (c) 2003 Sam Nabialek + Copyright (c) 2003-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> + +#define BOOST_SPIRIT_DEBUG + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_error_handling.hpp> +#include <boost/spirit/include/classic_iterator.hpp> +#include <boost/spirit/include/classic_symbols.hpp> +#include <boost/spirit/include/classic_utility.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +template <typename Rule> +struct SetRest +{ + SetRest(Rule& the_rule) + : m_the_rule(the_rule) + { + } + + void operator()(Rule* new_rule) const + { + m_the_rule = *new_rule; + } + +private: + + Rule& m_the_rule; +}; + + +struct nabialek_trick : public grammar<nabialek_trick> +{ + template <typename ScannerT> + struct definition + { + typedef rule<ScannerT> rule_t; + + rule_t name; + rule_t line; + rule_t rest; + rule_t main; + rule_t one; + rule_t two; + + symbols<rule_t*> continuations; + + definition(nabialek_trick const& self) + { + name = lexeme_d[repeat_p(1,20)[alnum_p | '_']]; + + one = name; + two = name >> ',' >> name; + + continuations.add + ("one", &one) + ("two", &two) + ; + + line = continuations[SetRest<rule_t>(rest)] >> rest; + main = *line; + + BOOST_SPIRIT_DEBUG_RULE(name); + BOOST_SPIRIT_DEBUG_RULE(line); + BOOST_SPIRIT_DEBUG_RULE(rest); + BOOST_SPIRIT_DEBUG_RULE(main); + BOOST_SPIRIT_DEBUG_RULE(one); + BOOST_SPIRIT_DEBUG_RULE(two); + } + + rule_t const& + start() const + { + return main; + } + }; +}; + +int +main() +{ + nabialek_trick g; + parse("one only\none again\ntwo first,second", g, space_p); + return 0; +} diff --git a/src/boost/libs/spirit/classic/example/techniques/no_rules/no_rule1.cpp b/src/boost/libs/spirit/classic/example/techniques/no_rules/no_rule1.cpp new file mode 100644 index 00000000..547ee978 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/no_rules/no_rule1.cpp @@ -0,0 +1,51 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ + +// *** See the section "Look Ma' No Rules" in +// *** chapter "Techniques" of the Spirit documentation +// *** for information regarding this snippet + +#include <iostream> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/assert.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + + struct skip_grammar : grammar<skip_grammar> + { + template <typename ScannerT> + struct definition + { + definition(skip_grammar const& /*self*/) + { + skip + = space_p + | "//" >> *(anychar_p - '\n') >> '\n' + | "/*" >> *(anychar_p - "*/") >> "*/" + ; + } + + rule<ScannerT> skip; + + rule<ScannerT> const& + start() const { return skip; } + }; + }; + +int +main() +{ + skip_grammar g; + bool success = parse( + "/*this is a comment*/\n//this is a c++ comment\n\n", + *g).full; + BOOST_ASSERT(success); + std::cout << "SUCCESS!!!\n"; + return 0; +} diff --git a/src/boost/libs/spirit/classic/example/techniques/no_rules/no_rule2.cpp b/src/boost/libs/spirit/classic/example/techniques/no_rules/no_rule2.cpp new file mode 100644 index 00000000..ddd37d50 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/no_rules/no_rule2.cpp @@ -0,0 +1,58 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ + +// *** See the section "Look Ma' No Rules" in +// *** chapter "Techniques" of the Spirit documentation +// *** for information regarding this snippet + +#include <iostream> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/assert.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +struct skip_grammar : grammar<skip_grammar> +{ + template <typename ScannerT> + struct definition + { + definition(skip_grammar const& /*self*/) + : skip + ( space_p + | "//" >> *(anychar_p - '\n') >> '\n' + | "/*" >> *(anychar_p - "*/") >> "*/" + ) + { + } + + typedef + alternative<alternative<space_parser, sequence<sequence< + strlit<const char*>, kleene_star<difference<anychar_parser, + chlit<char> > > >, chlit<char> > >, sequence<sequence< + strlit<const char*>, kleene_star<difference<anychar_parser, + strlit<const char*> > > >, strlit<const char*> > > + skip_t; + skip_t skip; + + skip_t const& + start() const { return skip; } + }; +}; + +int +main() +{ + skip_grammar g; + bool success = parse( + "/*this is a comment*/\n//this is a c++ comment\n\n", + *g).full; + BOOST_ASSERT(success); + std::cout << "SUCCESS!!!\n"; + return 0; +} diff --git a/src/boost/libs/spirit/classic/example/techniques/no_rules/no_rule3.cpp b/src/boost/libs/spirit/classic/example/techniques/no_rules/no_rule3.cpp new file mode 100644 index 00000000..bbdde085 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/no_rules/no_rule3.cpp @@ -0,0 +1,86 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ + +// *** See the section "Look Ma' No Rules" in +// *** chapter "Techniques" of the Spirit documentation +// *** for information regarding this snippet + +#include <iostream> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/assert.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +namespace boost { namespace spirit +{ + template <typename DerivedT> + struct sub_grammar : parser<DerivedT> + { + typedef sub_grammar self_t; + typedef DerivedT const& embed_t; + + template <typename ScannerT> + struct result + { + typedef typename parser_result< + typename DerivedT::start_t, ScannerT>::type + type; + }; + + DerivedT const& derived() const + { return *static_cast<DerivedT const*>(this); } + + template <typename ScannerT> + typename parser_result<self_t, ScannerT>::type + parse(ScannerT const& scan) const + { + return derived().start.parse(scan); + } + }; +}} + +/////////////////////////////////////////////////////////////////////////////// +// +// Client code +// +/////////////////////////////////////////////////////////////////////////////// +struct skip_grammar : boost::spirit::sub_grammar<skip_grammar> +{ + typedef + alternative<alternative<space_parser, sequence<sequence< + strlit<const char*>, kleene_star<difference<anychar_parser, + chlit<char> > > >, chlit<char> > >, sequence<sequence< + strlit<const char*>, kleene_star<difference<anychar_parser, + strlit<const char*> > > >, strlit<const char*> > > + start_t; + + skip_grammar() + : start + ( + space_p + | "//" >> *(anychar_p - '\n') >> '\n' + | "/*" >> *(anychar_p - "*/") >> "*/" + ) + {} + + start_t start; +}; + +int +main() +{ + skip_grammar g; + + bool success = parse( + "/*this is a comment*/\n//this is a c++ comment\n\n", + *g).full; + BOOST_ASSERT(success); + std::cout << "SUCCESS!!!\n"; + return 0; +} diff --git a/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/opaque_rule_parser.cpp b/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/opaque_rule_parser.cpp new file mode 100644 index 00000000..7525bd95 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/opaque_rule_parser.cpp @@ -0,0 +1,67 @@ +/*============================================================================== + 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) +==============================================================================*/ +//------------------------------------------------------------------------------ +// This example demonstrates the opaque rule parser. +// See boost/spirit/include/rule_parser.hpp for details. +//------------------------------------------------------------------------------ +#include <iostream> + +#include <boost/typeof/typeof.hpp> + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_typeof.hpp> + +#include <boost/spirit/include/classic_rule_parser.hpp> + +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + +namespace my_project { namespace my_grammar { + + using namespace BOOST_SPIRIT_CLASSIC_NS; + + #define BOOST_SPIRIT__NAMESPACE (2,(my_project,my_grammar)) + + BOOST_SPIRIT_OPAQUE_RULE_PARSER(word, + (1,( ((char const *),str) )), + -, + + lexeme_d[ str >> +space_p ] + ) + + BOOST_SPIRIT_OPAQUE_RULE_PARSER(main, + -,-, + + *( word("dup") | word("swap") | word("drop") | word("rot") | word("tuck") ) + ) + + #undef BOOST_SPIRIT__NAMESPACE + +} } // namespace my_project::my_grammar + + + +int main() +{ + std::string str; + while (std::getline(std::cin, str)) + { + if (str.empty()) + break; + + str += '\n'; + + if (BOOST_SPIRIT_CLASSIC_NS::parse(str.c_str(), my_project::my_grammar::main).full) + std::cout << "\nOK." << std::endl; + else + std::cout << "\nERROR." << std::endl; + } + return 0; +} + + diff --git a/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/rule_parser_1_1.cpp b/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/rule_parser_1_1.cpp new file mode 100644 index 00000000..54d1a5d6 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/rule_parser_1_1.cpp @@ -0,0 +1,103 @@ +/*============================================================================== + 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) +==============================================================================*/ +//------------------------------------------------------------------------------ +// This example uses typeof to build a nonrecursive grammar. +// See boost/spirit/include/rule_parser.hpp for details. +//------------------------------------------------------------------------------ +#include <string> +#include <iostream> + +#include <boost/typeof/typeof.hpp> + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_typeof.hpp> + +#include <boost/spirit/include/classic_confix.hpp> +#include <boost/spirit/include/classic_typeof.hpp> + +#include <boost/spirit/include/classic_rule_parser.hpp> + +// It's important to create an own registration group, even if there are no +// manual Typeof registrations like in this case. +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + + +namespace my_project { namespace my_module { + + using namespace BOOST_SPIRIT_CLASSIC_NS; + + + // A semantic action. + void echo_uint(unsigned i) { std::cout << "- " << i << std::endl; } + + + #define BOOST_SPIRIT__NAMESPACE (2,(my_project,my_module)) + + // C/C++ comment and whitespace skip parser.. + BOOST_SPIRIT_RULE_PARSER(skipper, + -,-,-, + + ( confix_p("//",*anychar_p,eol_p) + | confix_p("/*",*anychar_p,"*/") + | space_p + ) + ) + + // Parser for unsigned decimal, hexadecimal and binary literals. + BOOST_SPIRIT_RULE_PARSER(uint_literal, + -,-,-, + + "0x" >> hex_p[ & echo_uint ] + | "0b" >> bin_p[ & echo_uint ] + | uint_p[ & echo_uint ] + ) + + // A generic list parser (in some ways similar to Spirit's list_p utility or + // the % operator) with two parameters. + BOOST_SPIRIT_RULE_PARSER(enumeration_parser, + (2,( element_parser, delimiter_parser )),-,-, + + element_parser >> *(delimiter_parser >> element_parser) + ) + + // Parse an optional, comma separated list of uints with explicit post-skip. + BOOST_SPIRIT_RULE_PARSER(line, + -,-,-, + ! enumeration_parser(uint_literal,',') + >> lexeme_d[ !skipper ] + ) + + bool parse_line(char const * str) + { + return BOOST_SPIRIT_CLASSIC_NS::parse(str,line,skipper).full; + } + + #undef BOOST_SPIRIT__NAMESPACE + +} } // namespace ::my_project::my_module + + +int main() +{ + std::string str; + while (std::getline(std::cin, str)) + { + if (str.empty()) + break; + + str += '\n'; + + if (my_project::my_module::parse_line(str.c_str())) + std::cout << "\nOK." << std::endl; + else + std::cout << "\nERROR." << std::endl; + } + return 0; +} + diff --git a/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/rule_parser_1_2.cpp b/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/rule_parser_1_2.cpp new file mode 100644 index 00000000..c80e49fc --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/rule_parser_1_2.cpp @@ -0,0 +1,100 @@ +/*============================================================================== + 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) +==============================================================================*/ +//------------------------------------------------------------------------------ +// This example uses typeof to build a nonrecursive grammar. +// See boost/spirit/include/rule_parser.hpp for details. +//------------------------------------------------------------------------------ +#include <string> +#include <iostream> + +#include <boost/typeof/typeof.hpp> + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_typeof.hpp> + +#include <boost/spirit/include/classic_confix.hpp> +#include <boost/spirit/include/classic_typeof.hpp> + +#include <boost/spirit/include/classic_rule_parser.hpp> + +// It's important to create an own registration group, even if there are no +// manual Typeof registrations like in this case. +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +namespace my_project { namespace my_module { + + // Semantic actions. + void echo_uint(unsigned i) { std::cout << i; } + void comma(unsigned) { std::cout << ','; } + + #define BOOST_SPIRIT__NAMESPACE (2,(my_project,my_module)) + + // Define the action placeholders we use. + BOOST_SPIRIT_ACTION_PLACEHOLDER(uint_action) + BOOST_SPIRIT_ACTION_PLACEHOLDER(next_action) + + // Parser for unsigned decimal, hexadecimal and binary literals. + // Takes a function pointer as its parameter. + BOOST_SPIRIT_RULE_PARSER(uint_literal + ,-,(1,( uint_action )),-, + + str_p("0x") >> hex_p[ uint_action ] + | str_p("0b") >> bin_p[ uint_action ] + | uint_p[ uint_action ] + ) + + // Parser for a list of (dec/hex/bin) uints. + BOOST_SPIRIT_RULE_PARSER(uint_list, + -,(2,( uint_action, next_action )),-, + + uint_literal[uint_action] >> *(',' >> uint_literal[next_action][uint_action]) + ) + + // Parse an optional, comma separated list of uints with explicit post-skip. + // Note that we have to put the rule into parentheses here, because it + // contains an unparenthesized comma. + BOOST_SPIRIT_RULE_PARSER(line, + -,-,-, + + ( + ! uint_list[ (uint_action = & echo_uint), (next_action = & comma) ] + >> lexeme_d[ !space_p ] + ) + ) + + bool parse_line(char const * str) + { + return BOOST_SPIRIT_CLASSIC_NS::parse(str,line,space_p).full; + } + + #undef BOOST_SPIRIT__NAMESPACE + +} } // namespace ::my_project::my_module + + +int main() +{ + std::string str; + while (std::getline(std::cin, str)) + { + if (str.empty()) + break; + + str += '\n'; + + if (my_project::my_module::parse_line(str.c_str())) + std::cout << "\nOK." << std::endl; + else + std::cout << "\nERROR." << std::endl; + } + return 0; +} + diff --git a/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/rule_parser_2_1.cpp b/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/rule_parser_2_1.cpp new file mode 100644 index 00000000..356bc505 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/rule_parser_2_1.cpp @@ -0,0 +1,107 @@ +/*============================================================================== + Copyright (c) 2002-2003 Joel de Guzman + 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) +==============================================================================*/ +//------------------------------------------------------------------------------ +// This example shows a recursive grammar built using subrules and typeof. +// See boost/spirit/include/rule_parser.hpp for details. +// This example is based on subrule_calc.cpp. +//------------------------------------------------------------------------------ +#include <string> +#include <iostream> + +#include <boost/typeof/typeof.hpp> + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_typeof.hpp> + +#include <boost/spirit/include/classic_rule_parser.hpp> + +// Don't forget to +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +// Semantic actions +namespace +{ + void do_int(int v) { std::cout << "PUSH(" << v << ')' << std::endl; } + void do_add(char const*, char const*) { std::cout << "ADD" << std::endl; } + void do_sub(char const*, char const*) { std::cout << "SUB" << std::endl; } + void do_mul(char const*, char const*) { std::cout << "MUL" << std::endl; } + void do_div(char const*, char const*) { std::cout << "DIV" << std::endl; } + void do_neg(char const*, char const*) { std::cout << "NEG" << std::endl; } +} + +// Operating at root namespace... +#define BOOST_SPIRIT__NAMESPACE - + + +// Our calculator grammar using subrules in a rule parser. +BOOST_SPIRIT_RULE_PARSER( calc, + -, + -, + (3,( ((subrule<0>),expression,()), + ((subrule<1>),term,()), + ((subrule<2>),factor,() )) ), + ( + expression = + term + >> *( ('+' >> term)[&do_add] + | ('-' >> term)[&do_sub] + ) + , + + term = + factor + >> *( ('*' >> factor)[&do_mul] + | ('/' >> factor)[&do_div] + ) + , + + factor = + int_p[&do_int] + | ('(' >> expression >> ')') + | ('-' >> factor)[&do_neg] + | ('+' >> factor) + ) +) + +#undef BOOST_SPIRIT__NAMESPACE + + +// Main program +int main() +{ + std::cout + << "/////////////////////////////////////////////////////////\n" + << "\t\tA ruleless calculator using subrules...\n" + << "/////////////////////////////////////////////////////////\n" + << "Type an expression...or an empty line to quit\n" + << std::endl; + + std::string str; + while (std::getline(std::cin, str)) + { + if (str.empty()) break; + + parse_info<> info = parse(str.c_str(), calc, space_p); + + if (info.full) + std::cout + << "OK." + << std::endl; + else + std::cout + << "ERROR.\n" + << "Stopped at: \": " << info.stop << "\".\n" + << std::endl; + } + return 0; +} + diff --git a/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/rule_parser_2_2.cpp b/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/rule_parser_2_2.cpp new file mode 100644 index 00000000..3ae9738a --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/no_rules_with_typeof/rule_parser_2_2.cpp @@ -0,0 +1,142 @@ +/*============================================================================== + Copyright (c) 2002-2003 Joel de Guzman + 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) +==============================================================================*/ +//------------------------------------------------------------------------------ +// This example demonstrates how to make recursive grammars scale with typeof. +// It uses a rule parser with member variables and the parser_reference utility. +// See boost/spirit/include/rule_parser.hpp for details. +// This example is based on subrule_calc.cpp. +//------------------------------------------------------------------------------ +#include <string> +#include <iostream> + +#include <boost/config.hpp> + +#if defined(BOOST_MSVC) +// Disable MSVC's "'this' used in base/member initializer" warning. +// It's perfectly safe to use 'this' in a base/member initializer [ 12.6.2-7 ]. +// The warning tries to prevent undefined behaviour when the 'this'-pointer is +// used to do illegal things during construction [ 12.6.2-8 ] -- we don't. +# pragma warning(disable:4355) +#endif + +#include <boost/typeof/typeof.hpp> + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_typeof.hpp> + +#include <boost/spirit/include/classic_rule_parser.hpp> + + +// Don't forget to +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +// Semantic actions +namespace +{ + void do_int(int v) { std::cout << "PUSH(" << v << ')' << std::endl; } + void do_add(char const*, char const*) { std::cout << "ADD" << std::endl; } + void do_sub(char const*, char const*) { std::cout << "SUB" << std::endl; } + void do_mul(char const*, char const*) { std::cout << "MUL" << std::endl; } + void do_div(char const*, char const*) { std::cout << "DIV" << std::endl; } + void do_neg(char const*, char const*) { std::cout << "NEG" << std::endl; } +} + +// Operating at root namespace... +#define BOOST_SPIRIT__NAMESPACE - + +// Our calculator grammar using paramterized rule parsers. +// Subrules are passed to the rule parsers as arguments to allow recursion. + +BOOST_SPIRIT_RULE_PARSER(expression, + (1,(term)), + -, + -, + + term + >> *( ('+' >> term)[ &do_add ] + | ('-' >> term)[ &do_sub ] + ) +) + +BOOST_SPIRIT_RULE_PARSER(term, + (1,(factor)), + -, + -, + + factor + >> *( ('*' >> factor)[ &do_mul ] + | ('/' >> factor)[ &do_div ] + ) +) + +// This rule parser uses the 'parser_reference' utility to refer to itself. +// Note that here is another recursive loop, however, the self-reference, unlike +// a subrule, cannot be passed to contained parsers because we would end up with +// an endless loop at compile time finding the type. +BOOST_SPIRIT_RULE_PARSER(factor, + (1,(expression)), + -, + (1,( ((parser_reference<factor_t>),factor,(*this)) )), + + ( int_p[& do_int] + | ('(' >> expression >> ')') + | ('-' >> factor)[&do_neg] + | ('+' >> factor) + ) +) + + +// This rule parser implements recursion between the other ones. +BOOST_SPIRIT_RULE_PARSER( calc, + -, + -, + (3,( ((subrule<0>),sr_expression,()), + ((subrule<1>),sr_term,()), + ((subrule<2>),sr_factor,() )) ), + + ( + sr_expression = expression(sr_term), + sr_term = term(sr_factor), + sr_factor = factor(sr_expression) + ) +) + +// Main program +int main() +{ + std::cout + << "/////////////////////////////////////////////////////////////\n" + << "\t\tA ruleless calculator using rule parsers and subrules...\n" + << "/////////////////////////////////////////////////////////////\n" + << "Type an expression...or an empty line to quit\n" + << std::endl; + + std::string str; + while (std::getline(std::cin, str)) + { + if (str.empty()) break; + + parse_info<> info = parse(str.c_str(), calc, space_p); + + if (info.full) + std::cout + << "OK." + << std::endl; + else + std::cout + << "ERROR.\n" + << "Stopped at: \": " << info.stop << "\".\n" + << std::endl; + } + return 0; +} + diff --git a/src/boost/libs/spirit/classic/example/techniques/right_recursion.cpp b/src/boost/libs/spirit/classic/example/techniques/right_recursion.cpp new file mode 100644 index 00000000..132b0dc5 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/right_recursion.cpp @@ -0,0 +1,90 @@ +/*============================================================================= + Copyright (c) 2005 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> + +#define BOOST_SPIRIT_DEBUG +#include <boost/spirit/include/classic_core.hpp> +#include <boost/assert.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +struct non_greedy_kleene : public grammar<non_greedy_kleene> +{ + template <typename ScannerT> + struct definition + { + typedef rule<ScannerT> rule_t; + rule_t r; + + definition(non_greedy_kleene const& self) + { + r = (alnum_p >> r) | digit_p; + BOOST_SPIRIT_DEBUG_RULE(r); + } + + rule_t const& + start() const + { + return r; + } + }; +}; + +struct non_greedy_plus : public grammar<non_greedy_plus> +{ + template <typename ScannerT> + struct definition + { + typedef rule<ScannerT> rule_t; + rule_t r; + + definition(non_greedy_plus const& self) + { + r = alnum_p >> (r | digit_p); + BOOST_SPIRIT_DEBUG_RULE(r); + } + + rule_t const& + start() const + { + return r; + } + }; +}; +int +main() +{ + bool success; + { + non_greedy_kleene k; + success = parse("3", k).full; + BOOST_ASSERT(success); + success = parse("abcdef3", k).full; + BOOST_ASSERT(success); + success = parse("abc2def3", k).full; + BOOST_ASSERT(success); + success = parse("abc", k).full; + BOOST_ASSERT(!success); + } + + { + non_greedy_plus p; + success = parse("3", p).full; + BOOST_ASSERT(!success); + success = parse("abcdef3", p).full; + BOOST_ASSERT(success); + success = parse("abc2def3", p).full; + BOOST_ASSERT(success); + success = parse("abc", p).full; + BOOST_ASSERT(!success); + } + + std::cout << "SUCCESS!!!\n"; + return 0; +} diff --git a/src/boost/libs/spirit/classic/example/techniques/typeof.cpp b/src/boost/libs/spirit/classic/example/techniques/typeof.cpp new file mode 100644 index 00000000..5aacd758 --- /dev/null +++ b/src/boost/libs/spirit/classic/example/techniques/typeof.cpp @@ -0,0 +1,41 @@ +/*============================================================================= + Copyright (c) 2002-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) +=============================================================================*/ + +// *** See the section "typeof" in chapter "Techniques" of +// *** the Spirit documentation for information regarding +// *** this snippet. + +#include <iostream> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/typeof/typeof.hpp> +#include <boost/assert.hpp> + +using namespace BOOST_SPIRIT_CLASSIC_NS; + +#define RULE(name, definition) BOOST_TYPEOF(definition) name = definition + +int +main() +{ + RULE( + skipper, + ( space_p + | "//" >> *(anychar_p - '\n') >> '\n' + | "/*" >> *(anychar_p - "*/") >> "*/" + ) + ); + + bool success = parse( + "/*this is a comment*/\n//this is a c++ comment\n\n", + *skipper).full; + BOOST_ASSERT(success); + std::cout << "SUCCESS!!!\n"; + return 0; +} + diff --git a/src/boost/libs/spirit/classic/index.html b/src/boost/libs/spirit/classic/index.html new file mode 100644 index 00000000..d789969b --- /dev/null +++ b/src/boost/libs/spirit/classic/index.html @@ -0,0 +1,263 @@ +<html> +<head> +<title>Spirit User's Guide</title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<link rel="stylesheet" href="doc/theme/style.css" type="text/css"> +</head> + +<body> +<table width="100%" border="0" background="doc/theme/bkd2.gif" cellspacing="2"> + <tr> + <td width="10"> + <h1></h1> + </td> + <td width="85%"> <font face="Verdana, Arial, Helvetica, sans-serif"><b><font size="6">Spirit + User's Guide</font></b></font></td> + <td width="112"><a href="http://spirit.sf.net"><img src="doc/theme/spirit.gif" width="112" height="48" align="right" border="0"></a></td> + </tr> +</table> +<br> +<table width="75%" border="0" align="center"> + <tr> + <td class="table_title">Table of Contents</td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/preface.html">Preface</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/introduction.html">Introduction</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/quick_start.html">Quick Start</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/basic_concepts.html">Basic Concepts</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/organization.html">Organization</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="change_log.html">What's New </a></td> + </tr> + <tr> + <td class="toc_cells_L0"><b><font face="Geneva, Arial, Helvetica, san-serif">Core</font></b></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/primitives.html">Primitives</a> </td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/operators.html">Operators</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/numerics.html">Numerics</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/rule.html">The Rule</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/epsilon.html">Epsilon</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/directives.html">Directives</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/scanner.html">The Scanner and Parsing</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/grammar.html">The Grammar</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/subrules.html">Subrules</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/semantic_actions.html">Semantic Actions</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/indepth_the_parser.html">In-depth: The + Parser</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/indepth_the_scanner.html">In-depth: + The Scanner</a> </td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/indepth_the_parser_context.html">In-depth: + The Parser Context</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><strong>Actors</strong></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/predefined_actors.html">Predefined Actions</a> + </td> + </tr> + <tr> + <td class="toc_cells_L0"><b>Attribute</b></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/parametric_parsers.html">Parametric + Parsers</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/functional.html">Functional</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/phoenix.html">Phoenix</a><a href="doc/parametric_parsers.html"></a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/closures.html">Closures</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><strong>Dynamic</strong></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/dynamic_parsers.html">Dynamic Parsers</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/stored_rule.html">Storable Rules</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/the_lazy_parser.html">The Lazy Parser</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/select_parser.html">The Select Parser</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/switch_parser.html">The Switch Parser</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><b>Utility</b></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/escape_char_parser.html">Escape Character + Parsers</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/loops.html">Loop Parsers</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/character_sets.html">Character Set Parser</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/confix.html">Confix and Comment Parsers</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/list_parsers.html">List Parsers</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/functor_parser.html">Functor Parser</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/refactoring.html">Refactoring Parsers</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/regular_expression_parser.html">Regular + Expression Parser</a> </td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/scoped_lock.html">Scoped Lock</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/distinct.html">Distinct Parser </a></td> + </tr> + <tr> + <td class="toc_cells_L0"><b>Symbols</b></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/symbols.html">The Symbol Table</a></td> + </tr> + <tr> + <td class="table_cells"><b>Trees</b></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/trees.html">Parse Trees and ASTs</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><b>Iterator</b></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/multi_pass.html">Multi Pass </a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/file_iterator.html">File Iterator</a></td> + </tr> + <tr> + <td class="toc_cells_L1"><a href="doc/position_iterator.html">Position Iterator + </a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/debugging.html">Debugging</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/error_handling.html">Error Handling</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/quickref.html">Quick Reference</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/includes.html">Includes</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/portability.html">Portability</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/style_guide.html">Style Guide</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/techniques.html">Techniques</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/faq.html">FAQ</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/rationale.html">Rationale</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/acknowledgments.html">Acknowledgments</a></td> + </tr> + <tr> + <td class="toc_cells_L0"><a href="doc/references.html">References</a></td> + </tr> +</table> +<br> +<table width="50%" border="0" align="center"> + <tr> + <td> + <div align="center"><font size="2" color="#666666">Copyright © 1998-2003 + Joel de Guzman</font><font size="2"><br> + <br> + Portions of this document: <br> + <font color="#666666">Copyright © 2001-2003 Hartmut Kaiser<br> + Copyright © 2001-2002 Daniel C. Nuffer<br> + Copyright © 2002 Chris Uzdavinis<br> + Copyright © 2002 Jeff Westfahl<br> + Copyright © 2002 Juan Carlos Arevalo-Baeza<br> + </font><font size="2"><font color="#666666">Copyright © 2003 Martin + Wille <br> + Copyright © 2003 Ross Smith<br> + <font size="2"><font size="2">Copyright © 2003</font></font></font> + <font color="#666666">Jonathan de Halleux </font></font></font></div> + <p><font size="2"> <font color="#666666"> 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) + </font> </font></p> + </td> + </tr> +</table> +<br> +<table width="35%" border="0" align="center"> + <tr> + <td> + <div align="center"><font size="2">Spirit is hosted by <a href="http://sourceforge.net">SourceForge</a></font><br> + <font size="2"><a href="http://spirit.sourceforge.net/">http://spirit.sourceforge.net/ + </a></font> <br> + <br> + <a href="http://sourceforge.net"><img src="http://sourceforge.net/sflogo.php?group_id=28447" width="88" height="31" border="0" alt="SourceForge Logo"></a></div> + </td> + </tr> +</table> +<br> +<p> </p> +</body> +</html> diff --git a/src/boost/libs/spirit/classic/meta/libraries.json b/src/boost/libs/spirit/classic/meta/libraries.json new file mode 100644 index 00000000..8c1f7abd --- /dev/null +++ b/src/boost/libs/spirit/classic/meta/libraries.json @@ -0,0 +1,18 @@ +{ + "key": "spirit/classic", + "name": "Spirit Classic", + "authors": [ + "Joel de Guzman", + "Hartmut Kaiser", + "Dan Nuffer" + ], + "description": "LL parser framework represents parsers directly as EBNF grammars in inlined C++.", + "category": [ + "Parsing", + "String" + ], + "maintainers": [ + "Joel de Guzman <joel -at- boost-consulting.com>", + "Hartmut Kaiser <hartmut.kaiser -at- gmail.com>" + ] +} diff --git a/src/boost/libs/spirit/classic/phoenix/example/Jamfile b/src/boost/libs/spirit/classic/phoenix/example/Jamfile new file mode 100644 index 00000000..1790816f --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/example/Jamfile @@ -0,0 +1,79 @@ +#============================================================================== +# Copyright (c) 2002 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) +#============================================================================== +# +# Phoenix examples boost-jam file +# Joel de Guzman [Sept 27, 2002] +# + +#unit-test sample1 +# : fundamental/sample1.cpp +# : +# : +# ; + +unit-test sample2 + : fundamental/sample2.cpp + : + : + ; + +unit-test sample3 + : fundamental/sample3.cpp + : + : + ; + +unit-test sample4 + : fundamental/sample4.cpp + : + : + ; + +unit-test sample5 + : fundamental/sample5.cpp + : + : + ; + +unit-test sample6 + : fundamental/sample6.cpp + : + : + ; + +unit-test sample7 + : fundamental/sample7.cpp + : + : + ; + +unit-test sample8 + : fundamental/sample8.cpp + : + : + ; + +unit-test sample9 + : fundamental/sample9.cpp + : + : + ; + +unit-test sample10 + : fundamental/sample10.cpp + : + : + ; + +unit-test closures + : fundamental/closures.cpp + : + : + ; + diff --git a/src/boost/libs/spirit/classic/phoenix/example/fundamental/closures.cpp b/src/boost/libs/spirit/classic/phoenix/example/fundamental/closures.cpp new file mode 100644 index 00000000..1255ab6b --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/example/fundamental/closures.cpp @@ -0,0 +1,66 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <vector> +#include <algorithm> +#include <iostream> +#include <cassert> + +#define PHOENIX_LIMIT 15 +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_composite.hpp> +#include <boost/spirit/include/phoenix1_special_ops.hpp> +#include <boost/spirit/include/phoenix1_statements.hpp> +#include <boost/spirit/include/phoenix1_functions.hpp> +#include <boost/spirit/include/phoenix1_closures.hpp> + +////////////////////////////////// +using namespace phoenix; + +////////////////////////////////// +int +main() +{ + struct my_closure : closure<int, std::string, double> { + + member1 num; + member2 message; + member3 real; + }; + + my_closure clos; + + { // First stack frame + closure_frame<my_closure::self_t> frame(clos); + (clos.num = 123)(); + (clos.num += 456)(); + (clos.real = clos.num / 56.5)(); + (clos.message = "Hello " + std::string("World "))(); + + { // Second stack frame + closure_frame<my_closure::self_t> frame(clos); + (clos.num = 987)(); + (clos.message = "Abracadabra ")(); + (clos.real = clos.num * 1e30)(); + + { // Third stack frame + tuple<int, char const*, double> init(-1, "Direct Init ", 3.14); + closure_frame<my_closure::self_t> frame(clos, init); + + (std::cout << clos.message << clos.num << ", " << clos.real << '\n')(); + } + + (std::cout << clos.message << clos.num << ", " << clos.real << '\n')(); + } + + (std::cout << clos.message << clos.num << ", " << clos.real << '\n')(); + } + + return 0; +} diff --git a/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample10.cpp b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample10.cpp new file mode 100644 index 00000000..ae59adf1 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample10.cpp @@ -0,0 +1,525 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <vector> +#include <algorithm> +#include <iostream> + +#define PHOENIX_LIMIT 5 +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_composite.hpp> +#include <boost/spirit/include/phoenix1_special_ops.hpp> +#include <boost/spirit/include/phoenix1_statements.hpp> +#include <boost/spirit/include/phoenix1_functions.hpp> + +namespace phoenix { + +/////////////////////////////////////////////////////////////////////////////// +// +// local_tuple +// +// This *is a* tuple like the one we see in TupleT in any actor +// base class' eval member function. local_tuple should look and +// feel the same as a tupled-args, that's why it is derived from +// TupleArgsT. It has an added member, locs which is another tuple +// where the local variables will be stored. locs is mutable to +// allow read-write access to our locals regardless of +// local_tuple's constness (The eval member function accepts it as +// a const argument). +// +/////////////////////////////////////////////////////////////////////////////// +template <typename TupleArgsT, typename TupleLocsT> +struct local_tuple : public TupleArgsT { + + local_tuple(TupleArgsT const& args, TupleLocsT const& locs_) + : TupleArgsT(args), locs(locs_) {} + + mutable TupleLocsT locs; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// local_var_result +// +// This is a return type computer. Given a constant integer N, a +// parent index and a tuple, get the Nth local variable type. The +// parent index is an integer specifying which parent scope to +// access; 0==current scope, 1==parent scope, 2==parent's parent +// scope etc. +// +// This is a metaprogram with partial specializations. There is a +// general case, a special case for local_tuples and a terminating +// special case for local_tuples. +// +// General case: If TupleT is not really a local_tuple, we just return nil_t. +// +// local_tuples case: +// Parent index is 0: We get the Nth local variable. +// Otherwise: We subclass from local_tuples<N, Parent-1, TupleArgsT> +// +/////////////////////////////////////////////////////////////////////////////// +template <int N, int Parent, typename TupleT> +struct local_var_result { + + typedef nil_t type; +}; + +////////////////////////////////// +template <int N, int Parent, typename TupleArgsT, typename TupleLocsT> +struct local_var_result<N, Parent, local_tuple<TupleArgsT, TupleLocsT> > +: public local_var_result<N, Parent-1, TupleArgsT> {}; + +////////////////////////////////// +template <int N, typename TupleArgsT, typename TupleLocsT> +struct local_var_result<N, 0, local_tuple<TupleArgsT, TupleLocsT> > { + + typedef typename tuple_element<N, TupleLocsT>::type& type; + + static type get(local_tuple<TupleArgsT, TupleLocsT> const& tuple) + { return tuple.locs[tuple_index<N>()]; } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// local_var +// +// This class looks so curiously like the argument class. local_var +// provides access to the Nth local variable packed in the tuple +// duo local_tuple above. Parent specifies the Nth parent scope. +// 0==current scope, 1==parent scope, 2==parent's parent scope etc. +// The member function parent<N>() may be called to provide access +// to outer scopes. +// +// Note that the member function eval expects a local_tuple +// argument. Otherwise there will be acompile-time error. local_var +// primitives only work within the context of a context_composite +// (see below). +// +// Provided are some predefined local_var actors for 0..N local +// variable access: lvar1..locN. +// +/////////////////////////////////////////////////////////////////////////////// +template <int N, int Parent = 0> +struct local_var { + + typedef local_var<N, Parent> self_t; + + template <typename TupleT> + struct result { + + typedef typename local_var_result<N, Parent, TupleT>::type type; + }; + + template <typename TupleT> + typename actor_result<self_t, TupleT>::type + eval(TupleT const& tuple) const + { + return local_var_result<N, Parent, TupleT>::get(tuple); + } + + template <int PIndex> + actor<local_var<N, Parent+PIndex> > + parent() const + { + return local_var<N, Parent+PIndex>(); + } +}; + +////////////////////////////////// +namespace locals { + + actor<local_var<0> > const result = local_var<0>(); + actor<local_var<1> > const lvar1 = local_var<1>(); + actor<local_var<2> > const lvar2 = local_var<2>(); + actor<local_var<3> > const lvar3 = local_var<3>(); + actor<local_var<4> > const lvar4 = local_var<4>(); +} + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////// +template <int N, int Parent, typename TupleT> +struct local_func_result { + + typedef nil_t type; +}; + +////////////////////////////////// +template <int N, int Parent, typename TupleArgsT, typename TupleLocsT> +struct local_func_result<N, Parent, local_tuple<TupleArgsT, TupleLocsT> > +: public local_func_result<N, Parent-1, TupleArgsT> {}; + +////////////////////////////////// +template <int N, typename TupleArgsT, typename TupleLocsT> +struct local_func_result<N, 0, local_tuple<TupleArgsT, TupleLocsT> > { + + typedef typename actor_result< + typename tuple_element<N, TupleLocsT>::type, + local_tuple<TupleArgsT, TupleLocsT> + >::type type; + + template <typename ArgsT> + static type eval(local_tuple<ArgsT, TupleLocsT> const& tuple) + { return tuple.locs[tuple_index<N>()].eval(tuple); } +}; + + + + + + + + +template < + int N, int Parent, + typename A0 = nil_t, + typename A1 = nil_t, + typename A2 = nil_t, + typename A3 = nil_t, + typename A4 = nil_t +> +struct local_function_actor; + +////////////////////////////////// +template <int N, int Parent> +struct local_function_base { + + template <typename TupleT> + struct result { + + typedef typename local_func_result<N, Parent, TupleT>::type type; + }; +}; + +////////////////////////////////// +template <int N, int Parent> +struct local_function_actor<N, Parent, nil_t, nil_t, nil_t, nil_t, nil_t> +: public local_function_base<N, Parent> { + + template <typename TupleArgsT, typename TupleLocsT> + typename local_func_result< + N, Parent, local_tuple<TupleArgsT, TupleLocsT> >::type + eval(local_tuple<TupleArgsT, TupleLocsT> const& args) const + { + typedef local_tuple<TupleArgsT, TupleLocsT> local_tuple_t; + typedef tuple<> tuple_t; + tuple_t local_args; + + local_tuple<tuple_t, TupleLocsT> local_context(local_args, args.locs); + return local_func_result< + N, Parent, local_tuple_t> + ::eval(local_context); + } +}; + +////////////////////////////////// +template <int N, int Parent, + typename A0> +struct local_function_actor<N, Parent, A0, nil_t, nil_t, nil_t, nil_t> +: public local_function_base<N, Parent> { + + local_function_actor( + A0 const& _0) + : a0(_0) {} + + template <typename TupleArgsT, typename TupleLocsT> + typename local_func_result< + N, Parent, local_tuple<TupleArgsT, TupleLocsT> >::type + eval(local_tuple<TupleArgsT, TupleLocsT> const& args) const + { + typedef local_tuple<TupleArgsT, TupleLocsT> local_tuple_t; + typename actor_result<A0, local_tuple_t>::type r0 = a0.eval(args); + + typedef tuple< + typename actor_result<A0, local_tuple_t>::type + > tuple_t; + tuple_t local_args(r0); + + local_tuple<tuple_t, TupleLocsT> local_context(local_args, args.locs); + return local_func_result< + N, Parent, local_tuple_t> + ::eval(local_context); + } + + A0 a0; // actors +}; + +namespace impl { + + template < + int N, int Parent, + typename T0 = nil_t, + typename T1 = nil_t, + typename T2 = nil_t, + typename T3 = nil_t, + typename T4 = nil_t + > + struct make_local_function_actor { + + typedef local_function_actor< + N, Parent, + typename as_actor<T0>::type, + typename as_actor<T1>::type, + typename as_actor<T2>::type, + typename as_actor<T3>::type, + typename as_actor<T4>::type + > composite_type; + + typedef actor<composite_type> type; + }; +} + + + +template <int N, int Parent = 0> +struct local_function { + + actor<local_function_actor<N, Parent> > + operator()() const + { + return local_function_actor<N, Parent>(); + } + + template <typename T0> + typename impl::make_local_function_actor<N, Parent, T0>::type + operator()(T0 const& _0) const + { + return impl::make_local_function_actor<N, Parent, T0>::composite_type(_0); + } + + template <int PIndex> + local_function<N, Parent+PIndex> + parent() const + { + return local_function<N, Parent+PIndex>(); + } +}; + +////////////////////////////////// +namespace locals { + + local_function<1> const lfun1 = local_function<1>(); + local_function<2> const lfun2 = local_function<2>(); + local_function<3> const lfun3 = local_function<3>(); + local_function<4> const lfun4 = local_function<4>(); +} + + + + + + +/////////////////////////////////////////////////////////////////////////////// +// +// context_composite +// +// This class encapsulates an actor and some local variable +// initializers packed in a tuple. +// +// context_composite is just like a proxy and delegates the actual +// evaluation to the actor. The actor does the actual work. In the +// eval member function, before invoking the embedded actor's eval +// member function, we first stuff an instance of our locals and +// bundle both 'args' and 'locals' in a local_tuple. This +// local_tuple instance is created in the stack initializing it +// with our locals member. We then pass this local_tuple instance +// as an argument to the actor's eval member function. +// +/////////////////////////////////////////////////////////////////////////////// +template <typename ActorT, typename LocsT> +struct context_composite { + + typedef context_composite<ActorT, LocsT> self_t; + + template <typename TupleT> + struct result { typedef typename tuple_element<0, LocsT>::type type; }; + + context_composite(ActorT const& actor_, LocsT const& locals_) + : actor(actor_), locals(locals_) {} + + template <typename TupleT> + typename tuple_element<0, LocsT>::type + eval(TupleT const& args) const + { + local_tuple<TupleT, LocsT> local_context(args, locals); + actor.eval(local_context); + return local_context.locs[tuple_index<0>()]; + } + + ActorT actor; + LocsT locals; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// context_gen +// +// At construction time, this class is given some local var- +// initializers packed in a tuple. We just store this for later. +// The operator[] of this class creates the actual context_composite +// given an actor. This is responsible for the construct +// context<types>[actor]. +// +/////////////////////////////////////////////////////////////////////////////// +template <typename LocsT> +struct context_gen { + + context_gen(LocsT const& locals_) + : locals(locals_) {} + + template <typename ActorT> + actor<context_composite<typename as_actor<ActorT>::type, LocsT> > + operator[](ActorT const& actor) + { + return context_composite<typename as_actor<ActorT>::type, LocsT> + (as_actor<ActorT>::convert(actor), locals); + } + + LocsT locals; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Front end generator functions. These generators are overloaded for +// 1..N local variables. context<T0,... TN>(i0,...iN) generate +// context_gen objects (see above). +// +/////////////////////////////////////////////////////////////////////////////// +template <typename T0> +inline context_gen<tuple<T0> > +context() +{ + typedef tuple<T0> tuple_t; + return context_gen<tuple_t>(tuple_t(T0())); +} + +////////////////////////////////// +template <typename T0, typename T1> +inline context_gen<tuple<T0, T1> > +context( + T1 const& _1 = T1() +) +{ + typedef tuple<T0, T1> tuple_t; + return context_gen<tuple_t>(tuple_t(T0(), _1)); +} + +////////////////////////////////// +template <typename T0, typename T1, typename T2> +inline context_gen<tuple<T0, T1, T2> > +context( + T1 const& _1 = T1(), + T2 const& _2 = T2() +) +{ + typedef tuple<T0, T1, T2> tuple_t; + return context_gen<tuple_t>(tuple_t(T0(), _1, _2)); +} + +////////////////////////////////// +template <typename T0, typename T1, typename T2, typename T3> +inline context_gen<tuple<T0, T1, T2, T3> > +context( + T1 const& _1 = T1(), + T2 const& _2 = T2(), + T3 const& _3 = T3() +) +{ + typedef tuple<T0, T1, T2, T3> tuple_t; + return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3)); +} + +////////////////////////////////// +template <typename T0, typename T1, typename T2, typename T3, typename T4> +inline context_gen<tuple<T0, T1, T2, T3, T4> > +context( + T1 const& _1 = T1(), + T2 const& _2 = T2(), + T3 const& _3 = T3(), + T4 const& _4 = T4() +) +{ + typedef tuple<T0, T1, T2, T3, T4> tuple_t; + return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3, _4)); +} + + + + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////// +} + +////////////////////////////////// +using namespace std; +using namespace phoenix; +using namespace phoenix::locals; + +////////////////////////////////// +int +main() +{ + int _10 = 10; + +#ifndef __BORLANDC__ + + context<nil_t> + ( + 1000, // lvar1: local int variable + cout << arg1 << '\n', // lfun2: local function w/ 1 argument (arg1) + lvar1 * 2, // lfun3: local function that accesses local variable lvar1 + lfun2(2 * arg1) // lfun4: local function that calls local function lfun2 + ) + [ + lfun2(arg1 + 2000), + lfun2(val(5000) * 2), + lfun2(lvar1 + lfun3()), + lfun4(val(55)), + cout << lvar1 << '\n', + cout << lfun3() << '\n', + cout << val("bye bye\n") + ] + + (_10); + +#else // Borland does not like local variables w/ local functions + // we can have local variables (see sample 7..9) *OR* + // local functions (this: sample 10) but not both + // Sigh... Borland :-{ + + context<nil_t> + ( + 12345, + cout << arg1 << '\n' + ) + [ + lfun2(arg1 + 687), + lfun2(val(9999) * 2), + cout << val("bye bye\n") + ] + + (_10); + +#endif + + return 0; +} diff --git a/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample2.cpp b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample2.cpp new file mode 100644 index 00000000..d8dc195d --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample2.cpp @@ -0,0 +1,31 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <vector> +#include <algorithm> +#include <iostream> +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> + +using namespace std; +using namespace phoenix; + +int +main() +{ + int init[] = { 2, 10, 4, 5, 1, 6, 8, 3, 9, 7 }; + vector<int> c(init, init + 10); + typedef vector<int>::iterator iterator; + + // Find the first odd number in container c + iterator it = find_if(c.begin(), c.end(), arg1 % 2 == 1); + + if (it != c.end()) + cout << *it; // if found, print the result + return 0; +} diff --git a/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample3.cpp b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample3.cpp new file mode 100644 index 00000000..49ff8628 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample3.cpp @@ -0,0 +1,43 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <vector> +#include <algorithm> +#include <iostream> +#include <boost/spirit/include/phoenix1_functions.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> + +using namespace std; +using namespace phoenix; + +struct is_odd_ { + + template <typename ArgT> + struct result { typedef bool type; }; + + template <typename ArgT> + bool operator()(ArgT arg1) const + { return arg1 % 2 == 1; } +}; + +function<is_odd_> is_odd; + +int +main() +{ + int init[] = { 2, 10, 4, 5, 1, 6, 8, 3, 9, 7 }; + vector<int> c(init, init + 10); + typedef vector<int>::iterator iterator; + + // Find the first odd number in container c + iterator it = find_if(c.begin(), c.end(), is_odd(arg1)); + + if (it != c.end()) + cout << *it; // if found, print the result + return 0; +} diff --git a/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample4.cpp b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample4.cpp new file mode 100644 index 00000000..27fa7720 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample4.cpp @@ -0,0 +1,36 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <vector> +#include <algorithm> +#include <iostream> +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_statements.hpp> +#include <boost/spirit/include/phoenix1_special_ops.hpp> + +using namespace std; +using namespace phoenix; + +int +main() +{ + int init[] = { 2, 10, 4, 5, 1, 6, 8, 3, 9, 7 }; + vector<int> c(init, init + 10); + typedef vector<int>::iterator iterator; + + // Print all odd contents of an stl container c + for_each(c.begin(), c.end(), + if_(arg1 % 2 == 1) + [ + cout << arg1 << ' ' + ] + ); + + return 0; +} diff --git a/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample5.cpp b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample5.cpp new file mode 100644 index 00000000..ed2b4ae7 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample5.cpp @@ -0,0 +1,43 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <vector> +#include <algorithm> +#include <iostream> +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> + +using namespace std; +using namespace phoenix; + +////////////////////////////////// +template <int N> +struct static_int { + + template <typename TupleT> + struct result { typedef int type; }; + + template <typename TupleT> + int eval(TupleT const&) const { return N; } +}; + +////////////////////////////////// +template <int N> +phoenix::actor<static_int<N> > +int_const() +{ + return static_int<N>(); +} + +////////////////////////////////// +int +main() +{ + cout << (int_const<5>() + int_const<6>())() << endl; + return 0; +} diff --git a/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample6.cpp b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample6.cpp new file mode 100644 index 00000000..1c1f7fd4 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample6.cpp @@ -0,0 +1,88 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <vector> +#include <algorithm> +#include <iostream> +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_composite.hpp> +#include <boost/spirit/include/phoenix1_special_ops.hpp> + +using namespace std; +using namespace phoenix; + +////////////////////////////////// +template <typename CondT, typename TrueT, typename FalseT> +struct if_else_composite { + + typedef if_else_composite<CondT, TrueT, FalseT> self_t; + + template <typename TupleT> + struct result { + + typedef typename higher_rank< + typename actor_result<TrueT, TupleT>::plain_type, + typename actor_result<FalseT, TupleT>::plain_type + >::type type; + }; + + if_else_composite( + CondT const& cond_, TrueT const& true__, FalseT const& false__) + : cond(cond_), true_(true__), false_(false__) {} + + template <typename TupleT> + typename actor_result<self_t, TupleT>::type + eval(TupleT const& args) const + { + return cond.eval(args) ? true_.eval(args) : false_.eval(args); + } + + CondT cond; TrueT true_; FalseT false_; // actors +}; + +////////////////////////////////// +template <typename CondT, typename TrueT, typename FalseT> +inline actor<if_else_composite< + typename as_actor<CondT>::type, + typename as_actor<TrueT>::type, + typename as_actor<FalseT>::type> > +if_else_(CondT const& cond, TrueT const& true_, FalseT const& false_) +{ + typedef if_else_composite< + typename as_actor<CondT>::type, + typename as_actor<TrueT>::type, + typename as_actor<FalseT>::type> + result; + + return result( + as_actor<CondT>::convert(cond), + as_actor<TrueT>::convert(true_), + as_actor<FalseT>::convert(false_)); +} + +////////////////////////////////// +int +main() +{ + int init[] = { 2, 10, 4, 5, 1, 6, 8, 3, 9, 7 }; + vector<int> c(init, init + 10); + typedef vector<int>::iterator iterator; + + // Print all contents of an stl container c and + // prefix " is odd" or " is even" appropriately. + + for_each(c.begin(), c.end(), + cout + << arg1 + << if_else_(arg1 % 2 == 1, " is odd", " is even") + << val('\n') + ); + + return 0; +} diff --git a/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample7.cpp b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample7.cpp new file mode 100644 index 00000000..713121f3 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample7.cpp @@ -0,0 +1,275 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <vector> +#include <algorithm> +#include <iostream> + +#define PHOENIX_LIMIT 5 +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_composite.hpp> +#include <boost/spirit/include/phoenix1_special_ops.hpp> +#include <boost/spirit/include/phoenix1_statements.hpp> + +namespace phoenix { + +/////////////////////////////////////////////////////////////////////////////// +// +// local_tuple +// +// This *is a* tuple like the one we see in TupleT in any actor +// base class' eval member function. local_tuple should look and +// feel the same as a tupled-args, that's why it is derived from +// TupleArgsT. It has an added member, locs which is another tuple +// where the local variables will be stored. locs is mutable to +// allow read-write access to our locals regardless of +// local_tuple's constness (The eval member function accepts it as +// a const argument). +// +/////////////////////////////////////////////////////////////////////////////// +template <typename TupleArgsT, typename TupleLocsT> +struct local_tuple : public TupleArgsT { + + typedef TupleLocsT local_vars_t; + + local_tuple(TupleArgsT const& args, TupleLocsT const& locs_) + : TupleArgsT(args), locs(locs_) {} + + mutable TupleLocsT locs; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// local_var_result +// +// This is a return type computer. Given a constant integer N and a +// tuple, get the Nth local variable type. If TupleT is not really +// a local_tuple, we just return nil_t. Otherwise we get the Nth +// local variable type. +// +/////////////////////////////////////////////////////////////////////////////// +template <int N, typename TupleT> +struct local_var_result { + + typedef nil_t type; +}; + +////////////////////////////////// +template <int N, typename TupleArgsT, typename TupleLocsT> +struct local_var_result<N, local_tuple<TupleArgsT, TupleLocsT> > { + + typedef typename tuple_element<N, TupleLocsT>::type& type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// local_var +// +// This class looks so curiously like the argument class. local_var +// provides access to the Nth local variable packed in the tuple +// duo local_tuple above. Note that the member function eval +// expects a local_tuple argument. Otherwise the expression +// 'tuple.locs' will fail (compile-time error). local_var +// primitives only work within the context of a locals_composite +// (see below). +// +// Provided are some predefined local_var actors for 0..N local +// variable access: loc1..locN. +// +/////////////////////////////////////////////////////////////////////////////// +template <int N> +struct local_var { + + template <typename TupleT> + struct result { + + typedef typename local_var_result<N, TupleT>::type type; + }; + + template <typename TupleT> + typename local_var_result<N, TupleT>::type + eval(TupleT const& tuple) const + { + return tuple.locs[tuple_index<N>()]; + } +}; + +////////////////////////////////// +actor<local_var<0> > const loc1 = local_var<0>(); +actor<local_var<1> > const loc2 = local_var<1>(); +actor<local_var<2> > const loc3 = local_var<2>(); +actor<local_var<3> > const loc4 = local_var<3>(); +actor<local_var<4> > const loc5 = local_var<4>(); + +/////////////////////////////////////////////////////////////////////////////// +// +// locals_composite +// +// This class encapsulates an actor and some local variable +// initializers packed in a tuple. +// +// locals_composite is just like a proxy and delegates the actual +// evaluation to the actor. The actor does the actual work. In the +// eval member function, before invoking the embedded actor's eval +// member function, we first stuff an instance of our locals and +// bundle both 'args' and 'locals' in a local_tuple. This +// local_tuple instance is created in the stack initializing it +// with our locals member. We then pass this local_tuple instance +// as an argument to the actor's eval member function. +// +/////////////////////////////////////////////////////////////////////////////// +template <typename ActorT, typename LocsT> +struct locals_composite { + + typedef locals_composite<ActorT, LocsT> self_t; + + template <typename TupleT> + struct result { typedef typename actor_result<ActorT, TupleT>::type type; }; + + locals_composite(ActorT const& actor_, LocsT const& locals_) + : actor(actor_), locals(locals_) {} + + template <typename TupleT> + typename actor_result<ActorT, TupleT>::type + eval(TupleT const& args) const + { + actor.eval(local_tuple<TupleT, LocsT>(args, locals)); + } + + ActorT actor; + LocsT locals; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// locals_gen +// +// At construction time, this class is given some local var- +// initializers packed in a tuple. We just store this for later. +// The operator[] of this class creates the actual locals_composite +// given an actor. This is responsible for the construct +// locals<types>[actor]. +// +/////////////////////////////////////////////////////////////////////////////// +template <typename LocsT> +struct locals_gen { + + locals_gen(LocsT const& locals_) + : locals(locals_) {} + + template <typename ActorT> + actor<locals_composite<typename as_actor<ActorT>::type, LocsT> > + operator[](ActorT const& actor) + { + return locals_composite<typename as_actor<ActorT>::type, LocsT> + (as_actor<ActorT>::convert(actor), locals); + } + + LocsT locals; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Front end generator functions. These generators are overloaded for +// 1..N local variables. locals<T0,... TN>(i0,...iN) generate locals_gen +// objects (see above). +// +/////////////////////////////////////////////////////////////////////////////// +template <typename T0> +inline locals_gen<tuple<T0> > +locals( + T0 const& _0 = T0() +) +{ + typedef tuple<T0> tuple_t; + return locals_gen<tuple_t>(tuple_t(_0)); +} + +////////////////////////////////// +template <typename T0, typename T1> +inline locals_gen<tuple<T0, T1> > +locals( + T0 const& _0 = T0(), + T1 const& _1 = T1() +) +{ + typedef tuple<T0, T1> tuple_t; + return locals_gen<tuple_t>(tuple_t(_0, _1)); +} + +////////////////////////////////// +template <typename T0, typename T1, typename T2> +inline locals_gen<tuple<T0, T1, T2> > +locals( + T0 const& _0 = T0(), + T1 const& _1 = T1(), + T2 const& _2 = T2() +) +{ + typedef tuple<T0, T1, T2> tuple_t; + return locals_gen<tuple_t>(tuple_t(_0, _1, _2)); +} + +////////////////////////////////// +template <typename T0, typename T1, typename T2, typename T3> +inline locals_gen<tuple<T0, T1, T2, T3> > +locals( + T0 const& _0 = T0(), + T1 const& _1 = T1(), + T2 const& _2 = T2(), + T3 const& _3 = T3() +) +{ + typedef tuple<T0, T1, T2, T3> tuple_t; + return locals_gen<tuple_t>(tuple_t(_0, _1, _2, _3)); +} + +////////////////////////////////// +template <typename T0, typename T1, typename T2, typename T3, typename T4> +inline locals_gen<tuple<T0, T1, T2, T3, T4> > +locals( + T0 const& _0 = T0(), + T1 const& _1 = T1(), + T2 const& _2 = T2(), + T3 const& _3 = T3(), + T4 const& _4 = T4() +) +{ + typedef tuple<T0, T1, T2, T3> tuple_t; + return locals_gen<tuple_t>(tuple_t(_0, _1, _2, _3, _4)); +} + +/////////////////////////////////////////////////////////////////////////////// +} + +////////////////////////////////// +using namespace std; +using namespace phoenix; + +////////////////////////////////// +int +main() +{ + int init[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + vector<int> c(init, init + 10); + typedef vector<int>::iterator iterator; + + for_each(c.begin(), c.end(), + locals<int, char const*>(0, "...That's all\n") + [ + for_(loc1 = 0, loc1 < arg1, ++loc1) + [ + cout << loc1 << ", " + ], + cout << loc2 + ] + ); + + return 0; +} diff --git a/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample8.cpp b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample8.cpp new file mode 100644 index 00000000..eef462d3 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample8.cpp @@ -0,0 +1,284 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <vector> +#include <algorithm> +#include <iostream> + +#define PHOENIX_LIMIT 5 +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_composite.hpp> +#include <boost/spirit/include/phoenix1_special_ops.hpp> +#include <boost/spirit/include/phoenix1_statements.hpp> + +namespace phoenix { + +/////////////////////////////////////////////////////////////////////////////// +// +// local_tuple +// +// This *is a* tuple like the one we see in TupleT in any actor +// base class' eval member function. local_tuple should look and +// feel the same as a tupled-args, that's why it is derived from +// TupleArgsT. It has an added member, locs which is another tuple +// where the local variables will be stored. locs is mutable to +// allow read-write access to our locals regardless of +// local_tuple's constness (The eval member function accepts it as +// a const argument). +// +/////////////////////////////////////////////////////////////////////////////// +template <typename TupleArgsT, typename TupleLocsT> +struct local_tuple : public TupleArgsT { + + typedef TupleLocsT local_vars_t; + + local_tuple(TupleArgsT const& args, TupleLocsT const& locs_) + : TupleArgsT(args), locs(locs_) {} + + mutable TupleLocsT locs; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// local_var_result +// +// This is a return type computer. Given a constant integer N and a +// tuple, get the Nth local variable type. If TupleT is not really +// a local_tuple, we just return nil_t. Otherwise we get the Nth +// local variable type. +// +/////////////////////////////////////////////////////////////////////////////// +template <int N, typename TupleT> +struct local_var_result { + + typedef nil_t type; +}; + +////////////////////////////////// +template <int N, typename TupleArgsT, typename TupleLocsT> +struct local_var_result<N, local_tuple<TupleArgsT, TupleLocsT> > { + + typedef typename tuple_element<N, TupleLocsT>::type& type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// local_var +// +// This class looks so curiously like the argument class. local_var +// provides access to the Nth local variable packed in the tuple +// duo local_tuple above. Note that the member function eval +// expects a local_tuple argument. Otherwise the expression +// 'tuple.locs' will fail (compile-time error). local_var +// primitives only work within the context of a context_composite +// (see below). +// +// Provided are some predefined local_var actors for 0..N local +// variable access: loc1..locN. +// +/////////////////////////////////////////////////////////////////////////////// +template <int N> +struct local_var { + + template <typename TupleT> + struct result { + + typedef typename local_var_result<N, TupleT>::type type; + }; + + template <typename TupleT> + typename local_var_result<N, TupleT>::type + eval(TupleT const& tuple) const + { + return tuple.locs[tuple_index<N>()]; + } +}; + +////////////////////////////////// +namespace locals { + + actor<local_var<0> > const result = local_var<0>(); + actor<local_var<1> > const loc1 = local_var<1>(); + actor<local_var<2> > const loc2 = local_var<2>(); + actor<local_var<3> > const loc3 = local_var<3>(); + actor<local_var<4> > const loc4 = local_var<4>(); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// context_composite +// +// This class encapsulates an actor and some local variable +// initializers packed in a tuple. +// +// context_composite is just like a proxy and delegates the actual +// evaluation to the actor. The actor does the actual work. In the +// eval member function, before invoking the embedded actor's eval +// member function, we first stuff an instance of our locals and +// bundle both 'args' and 'locals' in a local_tuple. This +// local_tuple instance is created in the stack initializing it +// with our locals member. We then pass this local_tuple instance +// as an argument to the actor's eval member function. +// +/////////////////////////////////////////////////////////////////////////////// +template <typename ActorT, typename LocsT> +struct context_composite { + + typedef context_composite<ActorT, LocsT> self_t; + + template <typename TupleT> + struct result { typedef typename tuple_element<0, LocsT>::type type; }; + + context_composite(ActorT const& actor_, LocsT const& locals_) + : actor(actor_), locals(locals_) {} + + template <typename TupleT> + typename tuple_element<0, LocsT>::type + eval(TupleT const& args) const + { + local_tuple<TupleT, LocsT> local_context(args, locals); + actor.eval(local_context); + return local_context.locs[tuple_index<0>()]; + } + + ActorT actor; + LocsT locals; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// context_gen +// +// At construction time, this class is given some local var- +// initializers packed in a tuple. We just store this for later. +// The operator[] of this class creates the actual context_composite +// given an actor. This is responsible for the construct +// context<types>[actor]. +// +/////////////////////////////////////////////////////////////////////////////// +template <typename LocsT> +struct context_gen { + + context_gen(LocsT const& locals_) + : locals(locals_) {} + + template <typename ActorT> + actor<context_composite<typename as_actor<ActorT>::type, LocsT> > + operator[](ActorT const& actor) + { + return context_composite<typename as_actor<ActorT>::type, LocsT> + (as_actor<ActorT>::convert(actor), locals); + } + + LocsT locals; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Front end generator functions. These generators are overloaded for +// 1..N local variables. context<T0,... TN>(i0,...iN) generate context_gen +// objects (see above). +// +/////////////////////////////////////////////////////////////////////////////// +template <typename T0> +inline context_gen<tuple<T0> > +context() +{ + typedef tuple<T0> tuple_t; + return context_gen<tuple_t>(tuple_t(T0())); +} + +////////////////////////////////// +template <typename T0, typename T1> +inline context_gen<tuple<T0, T1> > +context( + T1 const& _1 = T1() +) +{ + typedef tuple<T0, T1> tuple_t; + return context_gen<tuple_t>(tuple_t(T0(), _1)); +} + +////////////////////////////////// +template <typename T0, typename T1, typename T2> +inline context_gen<tuple<T0, T1, T2> > +context( + T1 const& _1 = T1(), + T2 const& _2 = T2() +) +{ + typedef tuple<T0, T1, T2> tuple_t; + return context_gen<tuple_t>(tuple_t(T0(), _1, _2)); +} + +////////////////////////////////// +template <typename T0, typename T1, typename T2, typename T3> +inline context_gen<tuple<T0, T1, T2, T3> > +context( + T1 const& _1 = T1(), + T2 const& _2 = T2(), + T3 const& _3 = T3() +) +{ + typedef tuple<T0, T1, T2, T3> tuple_t; + return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3)); +} + +////////////////////////////////// +template <typename T0, typename T1, typename T2, typename T3, typename T4> +inline context_gen<tuple<T0, T1, T2, T3, T4> > +context( + T1 const& _1 = T1(), + T2 const& _2 = T2(), + T3 const& _3 = T3(), + T4 const& _4 = T4() +) +{ + typedef tuple<T0, T1, T2, T3> tuple_t; + return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3, _4)); +} + +/////////////////////////////////////////////////////////////////////////////// +} + +////////////////////////////////// +using namespace std; +using namespace phoenix; +using namespace phoenix::locals; + +////////////////////////////////// +int +main() +{ + int init[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + vector<int> c(init, init + 10); + typedef vector<int>::iterator iterator; + + // find the first element > 5, print each element + // as we traverse the container c. Print the result + // if one is found. + + find_if(c.begin(), c.end(), + context<bool>() + [ + cout << arg1, + result = arg1 > 5, + if_(!result) + [ + cout << val(", ") + ] + .else_ + [ + cout << val(" found result == ") << arg1 + ] + ] + ); + + return 0; +} diff --git a/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample9.cpp b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample9.cpp new file mode 100644 index 00000000..f67a6d04 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample9.cpp @@ -0,0 +1,311 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <vector> +#include <algorithm> +#include <iostream> + +#define PHOENIX_LIMIT 5 +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_composite.hpp> +#include <boost/spirit/include/phoenix1_special_ops.hpp> +#include <boost/spirit/include/phoenix1_statements.hpp> + +namespace phoenix { + +/////////////////////////////////////////////////////////////////////////////// +// +// local_tuple +// +// This *is a* tuple like the one we see in TupleT in any actor +// base class' eval member function. local_tuple should look and +// feel the same as a tupled-args, that's why it is derived from +// TupleArgsT. It has an added member, locs which is another tuple +// where the local variables will be stored. locs is mutable to +// allow read-write access to our locals regardless of +// local_tuple's constness (The eval member function accepts it as +// a const argument). +// +/////////////////////////////////////////////////////////////////////////////// +template <typename TupleArgsT, typename TupleLocsT> +struct local_tuple : public TupleArgsT { + + typedef TupleLocsT local_vars_t; + typedef TupleArgsT parent_t; + + local_tuple(TupleArgsT const& args, TupleLocsT const& locs_) + : TupleArgsT(args), locs(locs_) {} + + TupleArgsT& parent() { return *this; } + TupleArgsT const& parent() const { return *this; } + + mutable TupleLocsT locs; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// local_var_result +// +// This is a return type computer. Given a constant integer N, a +// parent index and a tuple, get the Nth local variable type. The +// parent index is an integer specifying which parent scope to +// access; 0==current scope, 1==parent scope, 2==parent's parent +// scope. +// +// This is a metaprogram with partial specializations. There is a +// general case, a special case for local_tuples and a terminating +// special case for local_tuples. +// +// General case: If TupleT is not really a local_tuple, we just return nil_t. +// +// local_tuples case: +// Parent index is 0: We get the Nth local variable. +// Otherwise: We subclass from local_tuples<N, Parent-1, TupleArgsT> +// +/////////////////////////////////////////////////////////////////////////////// +template <int N, int Parent, typename TupleT> +struct local_var_result { + + typedef nil_t type; +}; + +////////////////////////////////// +template <int N, int Parent, typename TupleArgsT, typename TupleLocsT> +struct local_var_result<N, Parent, local_tuple<TupleArgsT, TupleLocsT> > +: public local_var_result<N, Parent-1, TupleArgsT> {}; + +////////////////////////////////// +template <int N, typename TupleArgsT, typename TupleLocsT> +struct local_var_result<N, 0, local_tuple<TupleArgsT, TupleLocsT> > { + + typedef typename tuple_element< + N, TupleLocsT + >::type& type; + + static type get(local_tuple<TupleArgsT, TupleLocsT> const& tuple) + { return tuple.locs[tuple_index<N>()]; } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// local_var +// +// This class looks so curiously like the argument class. local_var +// provides access to the Nth local variable packed in the tuple +// duo local_tuple above. Parent specifies the Nth parent scope. +// 0==current scope, 1==parent scope, 2==parent's parent scope. The +// member function parent<N>() may be called to provide access to +// outer scopes. +// +// Note that the member function eval expects a local_tuple +// argument. Otherwise there will be acompile-time error. local_var +// primitives only work within the context of a context_composite +// (see below). +// +// Provided are some predefined local_var actors for 0..N local +// variable access: loc1..locN. +// +/////////////////////////////////////////////////////////////////////////////// +template <int N, int Parent = 0> +struct local_var { + + template <typename TupleT> + struct result { + + typedef typename local_var_result<N, Parent, TupleT>::type type; + }; + + template <typename TupleT> + typename local_var_result<N, Parent, TupleT>::type + eval(TupleT const& tuple) const + { + return local_var_result<N, Parent, TupleT>::get(tuple); + } + + template <int PIndex> + actor<local_var<N, Parent+PIndex> > + parent() const + { + return local_var<N, Parent+PIndex>(); + } +}; + +////////////////////////////////// +namespace locals { + + actor<local_var<0> > const result = local_var<0>(); + actor<local_var<1> > const loc1 = local_var<1>(); + actor<local_var<2> > const loc2 = local_var<2>(); + actor<local_var<3> > const loc3 = local_var<3>(); + actor<local_var<4> > const loc4 = local_var<4>(); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// context_composite +// +// This class encapsulates an actor and some local variable +// initializers packed in a tuple. +// +// context_composite is just like a proxy and delegates the actual +// evaluation to the actor. The actor does the actual work. In the +// eval member function, before invoking the embedded actor's eval +// member function, we first stuff an instance of our locals and +// bundle both 'args' and 'locals' in a local_tuple. This +// local_tuple instance is created in the stack initializing it +// with our locals member. We then pass this local_tuple instance +// as an argument to the actor's eval member function. +// +/////////////////////////////////////////////////////////////////////////////// +template <typename ActorT, typename LocsT> +struct context_composite { + + typedef context_composite<ActorT, LocsT> self_t; + + template <typename TupleT> + struct result { typedef typename tuple_element<0, LocsT>::type type; }; + + context_composite(ActorT const& actor_, LocsT const& locals_) + : actor(actor_), locals(locals_) {} + + template <typename TupleT> + typename tuple_element<0, LocsT>::type + eval(TupleT const& args) const + { + local_tuple<TupleT, LocsT> local_context(args, locals); + actor.eval(local_context); + return local_context.locs[tuple_index<0>()]; + } + + ActorT actor; + LocsT locals; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// context_gen +// +// At construction time, this class is given some local var- +// initializers packed in a tuple. We just store this for later. +// The operator[] of this class creates the actual context_composite +// given an actor. This is responsible for the construct +// context<types>[actor]. +// +/////////////////////////////////////////////////////////////////////////////// +template <typename LocsT> +struct context_gen { + + context_gen(LocsT const& locals_) + : locals(locals_) {} + + template <typename ActorT> + actor<context_composite<typename as_actor<ActorT>::type, LocsT> > + operator[](ActorT const& actor) + { + return context_composite<typename as_actor<ActorT>::type, LocsT> + (as_actor<ActorT>::convert(actor), locals); + } + + LocsT locals; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Front end generator functions. These generators are overloaded for +// 1..N local variables. context<T0,... TN>(i0,...iN) generate context_gen +// objects (see above). +// +/////////////////////////////////////////////////////////////////////////////// +template <typename T0> +inline context_gen<tuple<T0> > +context() +{ + typedef tuple<T0> tuple_t; + return context_gen<tuple_t>(tuple_t(T0())); +} + +////////////////////////////////// +template <typename T0, typename T1> +inline context_gen<tuple<T0, T1> > +context( + T1 const& _1 = T1() +) +{ + typedef tuple<T0, T1> tuple_t; + return context_gen<tuple_t>(tuple_t(T0(), _1)); +} + +////////////////////////////////// +template <typename T0, typename T1, typename T2> +inline context_gen<tuple<T0, T1, T2> > +context( + T1 const& _1 = T1(), + T2 const& _2 = T2() +) +{ + typedef tuple<T0, T1, T2> tuple_t; + return context_gen<tuple_t>(tuple_t(T0(), _1, _2)); +} + +////////////////////////////////// +template <typename T0, typename T1, typename T2, typename T3> +inline context_gen<tuple<T0, T1, T2, T3> > +context( + T1 const& _1 = T1(), + T2 const& _2 = T2(), + T3 const& _3 = T3() +) +{ + typedef tuple<T0, T1, T2, T3> tuple_t; + return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3)); +} + +////////////////////////////////// +template <typename T0, typename T1, typename T2, typename T3, typename T4> +inline context_gen<tuple<T0, T1, T2, T3, T4> > +context( + T1 const& _1 = T1(), + T2 const& _2 = T2(), + T3 const& _3 = T3(), + T4 const& _4 = T4() +) +{ + typedef tuple<T0, T1, T2, T3> tuple_t; + return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3, _4)); +} + +/////////////////////////////////////////////////////////////////////////////// +} + +////////////////////////////////// +using namespace std; +using namespace phoenix; +using namespace phoenix::locals; + +////////////////////////////////// +int +main() +{ + context<nil_t>(1) + [ + cout << loc1 << '\n', + context<nil_t>(2) + [ + cout << loc1.parent<1>() << ' ' << loc1 << '\n', + context<nil_t>(3) + [ + cout << loc1.parent<2>() << ' ' << loc1.parent<1>() << ' ' << loc1 << '\n' + ] + ] + ] + + (); + + return 0; +} diff --git a/src/boost/libs/spirit/classic/phoenix/index.html b/src/boost/libs/spirit/classic/phoenix/index.html new file mode 100644 index 00000000..0f556ec5 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/index.html @@ -0,0 +1,180 @@ +<html> +<head> +<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc --> +<title>Phoenix V1.2.1</title> +<link rel="stylesheet" href="doc/theme/style.css" type="text/css"> +<link rel="next" href="doc/preface.html"> +</head> +<body> +<table width="100%" height="48" border="0" background="doc/theme/bkd2.gif" cellspacing="2"> + <tr> + <td width="10"> + </td> + <td width="85%"> <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Phoenix + v1.2.1</b></font> </td> + <td width="112"><a href="http://spirit.sf.net"><img src="doc/theme/spirit.gif" align="right" border="0"></a></td> + </tr> +</table> +<br> +<table width="80%" border="0" align="center"> + <tr> + <td class="toc_title">Table of contents</td> + </tr> + <tr> + <td class="toc_cells_L0"> + <a href="doc/preface.html">Preface</a> + </td> + </tr> + <tr> + <td class="toc_cells_L0"> + <a href="doc/introduction.html">Introduction</a> + </td> + </tr> + <tr> + <td class="toc_cells_L0"> + <a href="doc/quick_start.html">Quick start</a> + </td> + </tr> + <tr> + <td class="toc_cells_L0"> + <a href="doc/basic_concepts.html">Basic Concepts</a> + </td> + </tr> + <tr> + <td class="toc_cells_L0"> + <a href="doc/architecture.html">Architecture</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/lazy_functions.html">Lazy functions</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/place_holders.html">Place holders</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/polymorphic_functions.html">Polymorphic functions</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/organization.html">Organization</a> + </td> + </tr> + <tr> + <td class="toc_cells_L0"> + <a href="doc/actors.html">Actors</a> + </td> + </tr> + <tr> + <td class="toc_cells_L0"> + <a href="doc/primitives.html">Primitives</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/arguments.html">Arguments</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/values.html">Values</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/variables.html">Variables</a> + </td> + </tr> + <tr> + <td class="toc_cells_L0"> + <a href="doc/composites.html">Composites</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/functions.html">Functions</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/operators.html">Operators</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/statements.html">Statements</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/binders.html">Binders</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/adaptable_closures.html">Adaptable closures</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/lazy_construction.html">Lazy Construction and Conversions</a> + </td> + </tr> + <tr> + <td class="toc_cells_L0"> + <a href="doc/efficiency.html">Efficiency</a> + </td> + </tr> + <tr> + <td class="toc_cells_L0"> + <a href="doc/inside_phoenix.html">Inside Phoenix</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/tuples.html">Tuples</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/actors_revisited.html">Actors revisited</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/composites_revisited.html">Composites revisited</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/operators_revisited.html">Operators revisited</a> + </td> + </tr> + <tr> + <td class="toc_cells_L1"> + <a href="doc/interfacing.html">Interfacing</a> + </td> + </tr> + <tr> + <td class="toc_cells_L0"> + <a href="doc/wrap_up.html">Wrap up</a> + </td> + </tr> + <tr> + <td class="toc_cells_L0"> + <a href="doc/references.html">References</a> + </td> + </tr> +</table> +<br> +<hr size="1"><p class="copyright">Copyright © 2001-2002 Joel de Guzman<br><br> +<font size="2">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) </font> </p> +</body> +</html> diff --git a/src/boost/libs/spirit/classic/phoenix/test/Jamfile b/src/boost/libs/spirit/classic/phoenix/test/Jamfile new file mode 100644 index 00000000..cfc1b0cd --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/Jamfile @@ -0,0 +1,81 @@ +#============================================================================== +# Copyright (c) 2002 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) +#============================================================================== +# +# Phoenix examples boost-jam file +# Joel de Guzman [Sept 27, 2002] +# + +unit-test binary_tests + : binary_tests.cpp + : + ; + +unit-test binders_tests + : binders_tests.cpp + : + ; + +unit-test functors_tests + : functors_tests.cpp + : + ; + +unit-test iostream_tests + : iostream_tests.cpp + : + ; + + +unit-test mixed_binary_tests + : mixed_binary_tests.cpp + : + ; + + +unit-test more_expressions_tests + : more_expressions_tests.cpp + : + ; + + +unit-test primitives_tests + : primitives_tests.cpp + : + ; + + +unit-test statements_tests + : statements_tests.cpp + : + ; + + +unit-test stl_tests + : stl_tests.cpp + : + ; + + +unit-test tuples_tests + : tuples_tests.cpp + : + ; + + +unit-test unary_tests + : unary_tests.cpp + : + ; + + +unit-test new_tests + : new_test.cpp + : + ; + diff --git a/src/boost/libs/spirit/classic/phoenix/test/binary_tests.cpp b/src/boost/libs/spirit/classic/phoenix/test/binary_tests.cpp new file mode 100644 index 00000000..56725316 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/binary_tests.cpp @@ -0,0 +1,98 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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) +==============================================================================*/ +#ifdef __GNUC__ // Darn these relops! +#ifndef __SGI_STL_INTERNAL_RELOPS +#define __SGI_STL_INTERNAL_RELOPS +#endif +#endif + +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + +#define PHOENIX_LIMIT 15 +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_operators.hpp> + +using namespace phoenix; +using namespace std; + +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + int i2 = 2, i3 = 3, i = 5; + const char* world = " world"; + +/////////////////////////////////////////////////////////////////////////////// +// +// Binary operators +// +/////////////////////////////////////////////////////////////////////////////// + BOOST_TEST((var(i) = var(i))() == 5); + BOOST_TEST((var(i) = 3)() == 3); + BOOST_TEST(i == 3); + i = 5; + int x, y, z; + (var(x) = var(y) = var(z) = 10)(); + BOOST_TEST(x == 10 && y == 10 && z == 10); + BOOST_TEST((val(world)[3])() == world[3]); + + BOOST_TEST((var(i) += 5)() == 10); + BOOST_TEST((var(i) -= 5)() == 5); + BOOST_TEST((var(i) *= 5)() == 25); + BOOST_TEST((var(i) /= 5)() == 5); + BOOST_TEST((var(i) %= 2)() == 1); + + BOOST_TEST((var(i) <<= 3)() == 8); + BOOST_TEST((var(i) >>= 1)() == 4); + BOOST_TEST((var(i) |= 0xFF)() == 0xFF); + BOOST_TEST((var(i) &= 0xF0)() == 0xF0); + BOOST_TEST((var(i) ^= 0xFFFFFFFF)() == int(0xFFFFFF0F)); + + BOOST_TEST((val(5) == val(5))()); + BOOST_TEST((val(5) == 5)()); + + BOOST_TEST((arg1 + arg2)(i2, i3) == i2 + i3); + BOOST_TEST((arg1 - arg2)(i2, i3) == i2 - i3); + BOOST_TEST((arg1 * arg2)(i2, i3) == i2 * i3); + BOOST_TEST((arg1 / arg2)(i2, i3) == i2 / i3); + BOOST_TEST((arg1 % arg2)(i2, i3) == i2 % i3); + BOOST_TEST((arg1 & arg2)(i2, i3) == (i2 & i3)); + BOOST_TEST((arg1 | arg2)(i2, i3) == (i2 | i3)); + BOOST_TEST((arg1 ^ arg2)(i2, i3) == (i2 ^ i3)); + BOOST_TEST((arg1 << arg2)(i2, i3) == i2 << i3); + BOOST_TEST((arg1 >> arg2)(i2, i3) == i2 >> i3); + + BOOST_TEST((val(5) != val(6))()); + BOOST_TEST((val(5) < val(6))()); + BOOST_TEST(!(val(5) > val(6))()); + BOOST_TEST((val(5) < val(6))()); + BOOST_TEST((val(5) <= val(6))()); + BOOST_TEST((val(5) <= val(5))()); + BOOST_TEST((val(7) >= val(6))()); + BOOST_TEST((val(7) >= val(7))()); + + BOOST_TEST((val(false) && val(false))() == false); + BOOST_TEST((val(true) && val(false))() == false); + BOOST_TEST((val(false) && val(true))() == false); + BOOST_TEST((val(true) && val(true))() == true); + + BOOST_TEST((val(false) || val(false))() == false); + BOOST_TEST((val(true) || val(false))() == true); + BOOST_TEST((val(false) || val(true))() == true); + BOOST_TEST((val(true) || val(true))() == true); + +/////////////////////////////////////////////////////////////////////////////// +// +// End asserts +// +/////////////////////////////////////////////////////////////////////////////// + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/phoenix/test/binders_tests.cpp b/src/boost/libs/spirit/classic/phoenix/test/binders_tests.cpp new file mode 100644 index 00000000..c73ce5cc --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/binders_tests.cpp @@ -0,0 +1,123 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <functional> +#include <boost/detail/lightweight_test.hpp> + +#define PHOENIX_LIMIT 15 +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_composite.hpp> +#include <boost/spirit/include/phoenix1_binders.hpp> + +using namespace phoenix; +using std::cout; +using std::endl; + + /////////////////////////////////////////////////////////////////////////////// + struct print_ { // a typical STL style monomorphic functor + + typedef void result_type; + void operator()() { cout << "got no args\n"; } + void operator()(int n0) { cout << "got 1 arg " << n0 << " \n"; } + void operator()(int n0, int n1) { cout << "got 2 args " << n0 << ", " << n1 << " \n"; } + + void foo0() const { cout << "print_::foo0\n"; } + void foo1(int n0) { cout << "print_::foo1 " << n0 << " \n"; } + void foo2(int n0, int n1) { cout << "print_::foo2 " << n0 << ", " << n1 << " \n"; } + + int x; + }; + + functor<print_> print = print_(); + member_function_ptr<void, print_, int> print_foo1 = &print_::foo1; + member_function_ptr<void, print_, int, int> print_foo2 = &print_::foo2; + member_var_ptr<int, print_> print_x = &print_::x; + print_ p; + bound_member<void, print_, int> bound_print_foo1(p,&print_::foo1); + bound_member<void, print_, int, int> bound_print_foo2(&p,&print_::foo2); + + /////////////////////////////////////////////////////////////////////////////// + void foo0() // a function w/ 0 args + { cout << "foo0\n"; } + + void foo1(int n0) // a function w/ 1 arg + { cout << "foo1 " << n0 << " \n"; } + + void foo2(int n0, int n1) // a function w/ 2 args + { cout << "foo2 " << n0 << ", " << n1 << " \n"; } + + void foo3_(int n0, int n1, int n2) // a function w/ 3 args + { cout << "foo3 " << n0 << ", " << n1 << ", " << n2 << " \n"; } + + function_ptr<void, int, int, int> foo3 = &foo3_; + +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + int i50 = 50, i20 = 20, i100 = 100; + +/////////////////////////////////////////////////////////////////////////////// +// +// Binders +// +/////////////////////////////////////////////////////////////////////////////// + +// Functor binders + + print()(); + print(111)(); + print(111, arg1)(i100); + print(111, 222)(); + cout << bind(std::negate<int>())(arg1)(i20) << endl; + cout << bind(std::plus<int>())(arg1, arg2)(i20, i50) << endl; + +// Function binders + + bind(&foo0)()(); + bind(&foo1)(111)(); + bind(&foo2)(111, arg1)(i100); + bind(&foo2)(111, 222)(); + + foo3(111, 222, 333)(); + foo3(arg1, arg2, arg3)(i20, i50, i100); + foo3(111, arg1, arg2)(i50, i100); + +// Member function binders + + print_ printer; + bind(&print_::foo0)(arg1)(printer); + + bind(&print_::foo1)(arg1, 111)(printer); + print_foo1(arg1, 111)(printer); + print_foo1(var(printer), 111)(); + print_foo2(var(printer), 111, 222)(); + print_foo2(var(printer), 111, arg1)(i100); + +// Member var binders + + printer.x = 3; + BOOST_TEST(bind(&print_::x)(arg1)(printer) == 3); + BOOST_TEST(print_x(arg1)(printer) == 3); + BOOST_TEST(print_x(printer)() == 3); + BOOST_TEST(0 != (print_x(var(printer))() = 4)); + BOOST_TEST(printer.x == 4); + +// Bound member functions + + bind(&printer,&print_::foo0)()(); + + bind(printer,&print_::foo1)(111)(); + bound_print_foo1(111)(); + bound_print_foo1(111)(); + bound_print_foo2(111, 222)(); + bound_print_foo2(111, arg1)(i100); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/phoenix/test/functors_tests.cpp b/src/boost/libs/spirit/classic/phoenix/test/functors_tests.cpp new file mode 100644 index 00000000..e0b84672 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/functors_tests.cpp @@ -0,0 +1,95 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <cmath> +#include <boost/detail/lightweight_test.hpp> + +#define PHOENIX_LIMIT 15 +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_composite.hpp> +#include <boost/spirit/include/phoenix1_functions.hpp> +#include <boost/spirit/include/phoenix1_operators.hpp> + +using namespace phoenix; +using namespace std; + + /////////////////////////////////////////////////////////////////////////////// + struct test_ { + + typedef void result_type; + void operator()() const { cout << "TEST LAZY FUNCTION\n"; } + }; + + function<test_> test; + + /////////////////////////////////////////////////////////////////////////////// + struct sqr_ { + + template <typename ArgT> + struct result { typedef ArgT type; }; + + template <typename ArgT> + ArgT operator()(ArgT n) const { return n * n; } + }; + + function<sqr_> sqr; + + /////////////////////////////////////////////////////////////////////////////// + struct fact_ { + + template <typename ArgT> + struct result { typedef ArgT type; }; + + template <typename ArgT> + ArgT operator()(ArgT n) const + { return (n <= 0) ? 1 : n * this->operator()(n-1); } + }; + + function<fact_> fact; + + /////////////////////////////////////////////////////////////////////////////// + struct pow_ { + + template <typename Arg1T, typename Arg2T> + struct result { typedef Arg1T type; }; + + template <typename Arg1T, typename Arg2T> + Arg1T operator()(Arg1T a, Arg2T b) const { return pow(a, b); } + }; + + function<pow_> power; + +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + int i5 = 5; + double d5 = 5, d3 = 3; + +/////////////////////////////////////////////////////////////////////////////// +// +// Lazy functors +// +/////////////////////////////////////////////////////////////////////////////// + + test()(); + BOOST_TEST(sqr(arg1)(i5) == (i5*i5)); + BOOST_TEST(fact(4)() == 24); + BOOST_TEST(fact(arg1)(i5) == 120); + BOOST_TEST((int)power(arg1, arg2)(d5, d3) == (int)pow(d5, d3)); + BOOST_TEST((sqr(arg1) + 5)(i5) == ((i5*i5)+5)); + +/////////////////////////////////////////////////////////////////////////////// +// +// End asserts +// +/////////////////////////////////////////////////////////////////////////////// + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/phoenix/test/iostream_tests.cpp b/src/boost/libs/spirit/classic/phoenix/test/iostream_tests.cpp new file mode 100644 index 00000000..1677938b --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/iostream_tests.cpp @@ -0,0 +1,86 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <vector> +#include <algorithm> +#include <string> +#include <boost/detail/lightweight_test.hpp> + +#include <boost/config.hpp> +#ifdef BOOST_NO_STRINGSTREAM +#include <strstream> +#define SSTREAM strstream +std::string GETSTRING(std::strstream& ss) +{ + ss << ends; + std::string rval = ss.str(); + ss.freeze(false); + return rval; +} +#else +#include <sstream> +#define GETSTRING(ss) ss.str() +#define SSTREAM stringstream +#endif + +//#define PHOENIX_LIMIT 15 +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_composite.hpp> +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <boost/spirit/include/phoenix1_special_ops.hpp> + +using namespace phoenix; +using namespace std; + +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + int i100 = 100; + string hello = "hello"; + const char* world = " world"; + +/////////////////////////////////////////////////////////////////////////////// +// +// IO streams +// +/////////////////////////////////////////////////////////////////////////////// + vector<int> v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + v.push_back(4); + v.push_back(5); + + char const* msg = "cout assert\n"; + (cout << arg1)(msg); + (cout << val(hello) << world << ", you da man!\n")(); + for_each(v.begin(), v.end(), cout << arg1 << ','); + cout << endl; + +#ifdef __BORLANDC__ // *** See special_ops.hpp why *** + (cout << arg1 << "this is it, shukz:" << hex_ << arg2 << endl_ << endl_)(msg, i100); +#else + (cout << arg1 << "this is it, shukz:" << hex << arg2 << endl << endl)(msg, i100); +#endif + int in; + int out = 12345; + SSTREAM sstr; + (sstr << arg1)(out); + (sstr >> arg1)(in); + BOOST_TEST(in == out); + +/////////////////////////////////////////////////////////////////////////////// +// +// End asserts +// +/////////////////////////////////////////////////////////////////////////////// + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/phoenix/test/mixed_binary_tests.cpp b/src/boost/libs/spirit/classic/phoenix/test/mixed_binary_tests.cpp new file mode 100644 index 00000000..9f60a368 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/mixed_binary_tests.cpp @@ -0,0 +1,50 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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> + +#define PHOENIX_LIMIT 15 +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_operators.hpp> + +using namespace phoenix; +using namespace std; + +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + int i1 = 1, i2 = 2, i50 = 50, i100 = 100; + double d2_5 = 2.5; + string hello = "hello"; + const char* world = " world"; + +/////////////////////////////////////////////////////////////////////////////// +// +// Mixed type operators +// +/////////////////////////////////////////////////////////////////////////////// + BOOST_TEST((arg1 + arg2)(i100, i50) == (i100 + i50)); + BOOST_TEST((arg1 + 3)(i100) == (3 + i100)); + BOOST_TEST((arg1 + arg2)(hello, world) == "hello world"); + BOOST_TEST((arg1 + arg2)(i1, d2_5) == (i1 + d2_5)); + + BOOST_TEST((*(arg1 + arg2))(world, i2) == *(world + i2)); + BOOST_TEST((*(arg1 + arg2))(i2, world) == *(i2 + world)); + BOOST_TEST((*(val(world+i2) - arg1))(i2) == *world); + +/////////////////////////////////////////////////////////////////////////////// +// +// End asserts +// +/////////////////////////////////////////////////////////////////////////////// + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/phoenix/test/more_expressions_tests.cpp b/src/boost/libs/spirit/classic/phoenix/test/more_expressions_tests.cpp new file mode 100644 index 00000000..51837416 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/more_expressions_tests.cpp @@ -0,0 +1,104 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 PHOENIX_LIMIT 15 +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_composite.hpp> +#include <boost/spirit/include/phoenix1_functions.hpp> +#include <boost/spirit/include/phoenix1_operators.hpp> + +using namespace phoenix; +using namespace std; + + /////////////////////////////////////////////////////////////////////////////// + struct sqr_ { + + template <typename ArgT> + struct result { typedef ArgT type; }; + + template <typename ArgT> + ArgT operator()(ArgT n) const { return n * n; } + }; + + function<sqr_> sqr; + + /////////////////////////////////////////////////////////////////////////////// + struct adder_ { + + template <typename Arg1T, typename Arg2T, typename ArgT3> + struct result { typedef Arg1T type; }; + + template <typename Arg1T, typename Arg2T, typename ArgT3> + Arg1T operator()(Arg1T a, Arg2T b, ArgT3 c) const { return a + b + c; } + }; + + function<adder_> adder; + +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + int i2 = 2, i = 4, i50 = 50, i10 = 10, i20 = 20, i100 = 100; + double d5 = 5, d10 = 10; + string hello = "hello"; + +/////////////////////////////////////////////////////////////////////////////// +// +// More complex expressions +// +/////////////////////////////////////////////////////////////////////////////// + BOOST_TEST((10 - arg1)(i100) == (10 - i100)); + BOOST_TEST((20 - arg1)(i100) == (20 - i100)); + BOOST_TEST((arg1 - 10)(i100) == (i100 - 10)); + BOOST_TEST((arg1 - 20)(i100) == (i100 - 20)); + BOOST_TEST((arg1 - arg2)(i100, i50) == (i100 - i50)); + BOOST_TEST((arg1 - var(i))(i10) == (i10 - i)); + BOOST_TEST((arg1 + arg2 - arg3)(i100, i50, i20) == (i100 + i50 - i20)); + BOOST_TEST((sqr(arg1) + arg2 - arg3)(i100, i50, i20) == ((i100*i100) + i50 - i20)); + + int ii = i; + BOOST_TEST((var(i) += arg1)(i2) == (ii += i2)); + BOOST_TEST((sqr(sqr(arg1)))(i100) == (i100*i100*i100*i100)); + + +#if 0 /*** SHOULD NOT COMPILE ***/ + (val(3) += arg1)(i100); + (val(3) = 3)(); +#endif + + BOOST_TEST(((adder(arg1, arg2, arg3) + arg2 - arg3)(i100, i50, i20)) == (i100 + i50 + i20) + i50 - i20); + BOOST_TEST((adder(arg1, arg2, arg3)(i100, i50, i20)) == (i100 + i50 + i20)); + BOOST_TEST((sqr(sqr(sqr(sqr(arg1)))))(d10) == 1e16); + BOOST_TEST((sqr(sqr(arg1)) / arg1 / arg1)(d5) == 25); + + for (int j = 0; j < 20; ++j) + { + cout << (10 < arg1)(j); + BOOST_TEST((10 < arg1)(j) == (10 < j)); + } + cout << endl; + + for (int k = 0; k < 20; ++k) + { + bool r = ((arg1 % 2 == 0) && (arg1 < 15))(k); + cout << r; + BOOST_TEST(r == ((k % 2 == 0) && (k < 15))); + } + cout << endl; + +/////////////////////////////////////////////////////////////////////////////// +// +// End asserts +// +/////////////////////////////////////////////////////////////////////////////// + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/phoenix/test/new_test.cpp b/src/boost/libs/spirit/classic/phoenix/test/new_test.cpp new file mode 100644 index 00000000..22c3b181 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/new_test.cpp @@ -0,0 +1,46 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2003 Vaclav Vesely + + 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 PHOENIX_LIMIT 15 +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_new.hpp> + +using namespace phoenix; +using namespace std; + +class X +{ +public: + X(int i_ = 1) + : i(i_) + {} + + int i; +}; + +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + int i2 = 2; + X x3(3); + + BOOST_TEST(new_<int>()() != NULL); + BOOST_TEST(*new_<int>(arg1)(i2) == 2); + + BOOST_TEST(new_<X>()() != NULL); + BOOST_TEST(new_<X>()()->i == 1); + BOOST_TEST(new_<X>(arg1)(i2)->i == 2); + BOOST_TEST(new_<X>(arg1)(x3)->i == 3); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/phoenix/test/primitives_tests.cpp b/src/boost/libs/spirit/classic/phoenix/test/primitives_tests.cpp new file mode 100644 index 00000000..ada53334 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/primitives_tests.cpp @@ -0,0 +1,42 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 PHOENIX_LIMIT 15 +#include <boost/spirit/include/phoenix1_primitives.hpp> + +using namespace phoenix; +using namespace std; + +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + char c1 = '1'; + int i1 = 1, i2 = 2, i = 4; + const char* s2 = "2"; + +/////////////////////////////////////////////////////////////////////////////// +// +// Values, variables and arguments +// +/////////////////////////////////////////////////////////////////////////////// + cout << val("Hello")() << val(' ')() << val("World")() << endl; + + BOOST_TEST(arg1(c1) == c1); + BOOST_TEST(arg1(i1, i2) == i1); + BOOST_TEST(arg2(i1, s2) == s2); + + BOOST_TEST(val(3)() == 3); + BOOST_TEST(var(i)() == 4); + BOOST_TEST(var(++i)() == 5); + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/phoenix/test/runtest.sh b/src/boost/libs/spirit/classic/phoenix/test/runtest.sh new file mode 100644 index 00000000..09b804ea --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/runtest.sh @@ -0,0 +1,25 @@ +#============================================================================== +# Copyright (c) 2002 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) +#============================================================================== +#!/bin/sh +#./test1 << EOS || exit 1 +#123321 +#EOS +./binary_tests || exit 1 +./binders_tests || exit 1 +./functors_tests || exit 1 +./iostream_tests << EOS || exit 1 +123321 +EOS +./mixed_binary_tests || exit 1 +./more_expressions_tests || exit 1 +./primitives_tests || exit 1 +./statements_tests || exit 1 +./stl_tests || exit 1 +./tuples_tests || exit 1 +./unary_tests || exit 1 diff --git a/src/boost/libs/spirit/classic/phoenix/test/statements_tests.cpp b/src/boost/libs/spirit/classic/phoenix/test/statements_tests.cpp new file mode 100644 index 00000000..83db0acf --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/statements_tests.cpp @@ -0,0 +1,165 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <vector> +#include <algorithm> +#include <boost/detail/lightweight_test.hpp> + +#define PHOENIX_LIMIT 15 +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_functions.hpp> +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <boost/spirit/include/phoenix1_special_ops.hpp> +#include <boost/spirit/include/phoenix1_statements.hpp> + +using namespace phoenix; +using namespace std; + + /////////////////////////////////////////////////////////////////////////////// + struct poly_print_ { + + template <typename ArgT> + struct result { typedef void type; }; + + template <typename ArgT> + void operator()(ArgT v) const + { cout << v; } + }; + + function<poly_print_> poly_print; + +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + char c1 = '1'; + int i1 = 1; + double d2_5 = 2.5; + string hello = "hello"; + const char* world = " world"; + +/////////////////////////////////////////////////////////////////////////////// +// +// Block statements +// +/////////////////////////////////////////////////////////////////////////////// + ( + poly_print(arg1), + poly_print(arg2), + poly_print(arg3), + poly_print(arg4), + poly_print(arg5), + poly_print("\n\n") + ) + (hello, c1, world, i1, d2_5); + +/////////////////////////////////////////////////////////////////////////////// +// +// If-else, while, do-while, for tatements +// +/////////////////////////////////////////////////////////////////////////////// + + vector<int> v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + v.push_back(4); + v.push_back(5); + v.push_back(6); + v.push_back(7); + v.push_back(8); + v.push_back(9); + v.push_back(10); + + cout << dec; + + ////////////////////////////////// + for_each(v.begin(), v.end(), + if_(arg1 > 3 && arg1 <= 8) + [ + cout << arg1 << ", " + ] + ); + + cout << endl; + + ////////////////////////////////// + for_each(v.begin(), v.end(), + if_(arg1 > 5) + [ + cout << arg1 << " > 5\n" + ] + .else_ + [ + if_(arg1 == 5) + [ + cout << arg1 << " == 5\n" + ] + .else_ + [ + cout << arg1 << " < 5\n" + ] + ] + ); + + cout << endl; + + vector<int> t = v; + ////////////////////////////////// + for_each(v.begin(), v.end(), + ( + while_(arg1--) + [ + cout << arg1 << ", " + ], + cout << val("\n") + ) + ); + + v = t; + cout << endl; + + ////////////////////////////////// + for_each(v.begin(), v.end(), + ( + do_ + [ + cout << arg1 << ", " + ] + .while_(arg1--), + cout << val("\n") + ) + ); + + v = t; + cout << endl; + + ////////////////////////////////// + int iii; + for_each(v.begin(), v.end(), + ( + for_(var(iii) = 0, var(iii) < arg1, ++var(iii)) + [ + cout << arg1 << ", " + ], + cout << val("\n") + ) + ); + + v = t; + cout << endl; + +/////////////////////////////////////////////////////////////////////////////// +// +// End asserts +// +/////////////////////////////////////////////////////////////////////////////// + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/phoenix/test/stl_tests.cpp b/src/boost/libs/spirit/classic/phoenix/test/stl_tests.cpp new file mode 100644 index 00000000..2fe461f0 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/stl_tests.cpp @@ -0,0 +1,95 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 <vector> +#include <list> +#include <algorithm> +#include <boost/detail/lightweight_test.hpp> + +#define PHOENIX_LIMIT 15 +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_composite.hpp> +#include <boost/spirit/include/phoenix1_functions.hpp> +#include <boost/spirit/include/phoenix1_operators.hpp> +#include <boost/spirit/include/phoenix1_binders.hpp> +#include <boost/spirit/include/phoenix1_special_ops.hpp> + +using namespace phoenix; +using namespace std; + + /////////////////////////////////////////////////////////////////////////////// + struct print_ { // a typical STL style monomorphic functor + + typedef void result_type; + void operator()(int n0) { cout << "got 1 arg " << n0 << " \n"; } + }; + + functor<print_> print = print_(); + +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + +/////////////////////////////////////////////////////////////////////////////// +// +// STL algorithms +// +/////////////////////////////////////////////////////////////////////////////// + vector<int> v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + v.push_back(4); + v.push_back(5); + + for_each(v.begin(), v.end(), arg1 *= 2); + for (int m = 0; m < 5; ++m, (cout << ',')) + { + cout << v[m]; + BOOST_TEST(v[m] == (m+1)*2); + } + cout << endl; + + for_each(v.begin(), v.end(), print(arg1)); + + vector<int>::iterator it = find_if(v.begin(), v.end(), arg1 > 5); + if (it != v.end()) + cout << *it << endl; + +/////////////////////////////////////////////////////////////////////////////// +// +// STL iterators and containers +// +/////////////////////////////////////////////////////////////////////////////// + + BOOST_TEST((arg1[0])(v) == v[0]); + BOOST_TEST((arg1[1])(v) == v[1]); + + list<int> l; + l.push_back(1); + l.push_back(2); + l.push_back(3); + l.push_back(4); + l.push_back(5); + + list<int>::iterator first = l.begin(); + list<int>::iterator last = l.end(); + + BOOST_TEST((*(++arg1))(first) == 2); + BOOST_TEST((*(----arg1))(last) == 4); + +/////////////////////////////////////////////////////////////////////////////// +// +// End asserts +// +/////////////////////////////////////////////////////////////////////////////// + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/classic/phoenix/test/tuples_tests.cpp b/src/boost/libs/spirit/classic/phoenix/test/tuples_tests.cpp new file mode 100644 index 00000000..43b53fdd --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/tuples_tests.cpp @@ -0,0 +1,57 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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/phoenix1_tuples.hpp> + +using namespace phoenix; +using namespace phoenix::tuple_index_names; +using std::cout; +using std::endl; +using std::string; + +int +main() +{ + { + typedef tuple<int, char> tuple_t; + tuple_t ttt(3, 'c'); + + tuple_element<0, tuple_t>::type& e0 = ttt[_1]; + tuple_element<1, tuple_t>::type& e1 = ttt[_2]; + + BOOST_TEST(e0 == 3); + BOOST_TEST(e1 == 'c'); + + cout << e0 << endl; + cout << e1 << endl; + } + + { + typedef tuple<int, char, char const*> tuple_t; + tuple_t ttt(3, 'c', "hello world"); + cout << ttt.length << endl; + + tuple_element<0, tuple_t>::type& e0 = ttt[_1]; + tuple_element<1, tuple_t>::type& e1 = ttt[_2]; + tuple_element<2, tuple_t>::type& e2 = ttt[_3]; + + BOOST_TEST(e0 == 3); + BOOST_TEST(e1 == 'c'); + BOOST_TEST(string(e2) == "hello world"); + + cout << e0 << endl; + cout << e1 << endl; + cout << e2 << endl; + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/classic/phoenix/test/unary_tests.cpp b/src/boost/libs/spirit/classic/phoenix/test/unary_tests.cpp new file mode 100644 index 00000000..6ac72cb6 --- /dev/null +++ b/src/boost/libs/spirit/classic/phoenix/test/unary_tests.cpp @@ -0,0 +1,47 @@ +/*============================================================================= + Phoenix V1.2.1 + Copyright (c) 2001-2003 Joel de Guzman + + 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 PHOENIX_LIMIT 15 +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_operators.hpp> + +using namespace phoenix; +using namespace std; + +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + int i1 = 1, i = 5; + +/////////////////////////////////////////////////////////////////////////////// +// +// Unary operators +// +/////////////////////////////////////////////////////////////////////////////// + BOOST_TEST((!val(true))() == false); + BOOST_TEST((-val(1))() == -1); + BOOST_TEST((+val(1))() == +1); + BOOST_TEST((~val(1))() == ~1); + BOOST_TEST(*(&arg1)(i1) == *(&i1)); + BOOST_TEST((&arg1)(i1) == &i1); + + BOOST_TEST((*val(&i1))() == *(&i1)); + BOOST_TEST((*&arg1)(i1) == *(&i1)); + BOOST_TEST((++var(i))() == 6); + BOOST_TEST((--var(i))() == 5); + BOOST_TEST((var(i)++)() == 5); + BOOST_TEST(i == 6); + BOOST_TEST((var(i)--)() == 6); + BOOST_TEST(i == 5); + + return boost::report_errors(); +} 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; +} |