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/repository | |
parent | Initial commit. (diff) | |
download | ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.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/repository')
34 files changed, 4083 insertions, 0 deletions
diff --git a/src/boost/libs/spirit/repository/example/karma/Jamfile b/src/boost/libs/spirit/repository/example/karma/Jamfile new file mode 100644 index 00000000..b52e3b80 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/karma/Jamfile @@ -0,0 +1,16 @@ +#============================================================================== +# Copyright (c) 2009 Chris Hoeppler +# +# 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) +#============================================================================== + +project spirit_v2_repository/example_karma + : requirements + <c++-template-depth>300 + ; + +exe karma_confix : confix.cpp ; +exe calc2_ast_dump_sr : calc2_ast_dump_sr.cpp ; +exe mini_xml_karma_sr : mini_xml_karma_sr.cpp ; + diff --git a/src/boost/libs/spirit/repository/example/karma/calc2_ast.hpp b/src/boost/libs/spirit/repository/example/karma/calc2_ast.hpp new file mode 100644 index 00000000..53fadf76 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/karma/calc2_ast.hpp @@ -0,0 +1,179 @@ +/*============================================================================= + Copyright (c) 2001-2010 Joel de Guzman + Copyright (c) 2001-2012 Hartmut Kaiser + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A Calculator example demonstrating generation of AST which gets dumped into +// a human readable format afterwards. +// +// [ JDG April 28, 2008 ] +// [ HK April 28, 2008 ] +// +/////////////////////////////////////////////////////////////////////////////// + +#if !defined(SPIRIT_EXAMPLE_CALC2_AST_APR_30_2008_1011AM) +#define SPIRIT_EXAMPLE_CALC2_AST_APR_30_2008_1011AM + +#include <boost/variant.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> +#include <boost/spirit/include/phoenix_function.hpp> +#include <boost/spirit/include/phoenix_statement.hpp> +#include <boost/spirit/home/karma/domain.hpp> +#include <boost/spirit/include/support_attributes_fwd.hpp> + +/////////////////////////////////////////////////////////////////////////////// +// Our AST +/////////////////////////////////////////////////////////////////////////////// +struct binary_op; +struct unary_op; +struct nil {}; + +struct expression_ast +{ + typedef + boost::variant< + nil // can't happen! + , int + , boost::recursive_wrapper<binary_op> + , boost::recursive_wrapper<unary_op> + > + type; + + // expose variant types + typedef type::types types; + + // expose variant functionality + int which() const { return expr.which(); } + + // constructors + expression_ast() + : expr(nil()) {} + + expression_ast(unary_op const& expr) + : expr(expr) {} + + expression_ast(binary_op const& expr) + : expr(expr) {} + + expression_ast(unsigned int expr) + : expr(expr) {} + + expression_ast(type const& expr) + : expr(expr) {} + + expression_ast& operator+=(expression_ast const& rhs); + expression_ast& operator-=(expression_ast const& rhs); + expression_ast& operator*=(expression_ast const& rhs); + expression_ast& operator/=(expression_ast const& rhs); + + type expr; +}; + +// expose variant functionality +namespace boost +{ + // this function has to live in namespace boost for ADL to correctly find it + template <typename T> + inline T get(expression_ast const& expr) + { + return boost::get<T>(expr.expr); + } + + // the specialization below tells Spirit to handle expression_ast as if it + // where a 'real' variant + namespace spirit { namespace traits + { + // the specialization below tells Spirit to handle expression_ast as + // if it where a 'real' variant (if used with Spirit.Karma) + template <> + struct not_is_variant<expression_ast, karma::domain> + : mpl::false_ {}; + + // the specialization of variant_which allows to generically extract + // the current type stored in the given variant like type + template <> + struct variant_which<expression_ast> + { + static int call(expression_ast const& v) + { + return v.which(); + } + }; + }} +} + +/////////////////////////////////////////////////////////////////////////////// +struct binary_op +{ + binary_op() {} + + binary_op( + char op + , expression_ast const& left + , expression_ast const& right) + : op(op), left(left), right(right) {} + + char op; + expression_ast left; + expression_ast right; +}; + +struct unary_op +{ + unary_op( + char op + , expression_ast const& right) + : op(op), right(right) {} + + char op; + expression_ast right; +}; + +inline expression_ast& expression_ast::operator+=(expression_ast const& rhs) +{ + expr = binary_op('+', expr, rhs); + return *this; +} + +inline expression_ast& expression_ast::operator-=(expression_ast const& rhs) +{ + expr = binary_op('-', expr, rhs); + return *this; +} + +inline expression_ast& expression_ast::operator*=(expression_ast const& rhs) +{ + expr = binary_op('*', expr, rhs); + return *this; +} + +inline expression_ast& expression_ast::operator/=(expression_ast const& rhs) +{ + expr = binary_op('/', expr, rhs); + return *this; +} + +// We should be using expression_ast::operator-. There's a bug +// in phoenix type deduction mechanism that prevents us from +// doing so. Phoenix will be switching to BOOST_TYPEOF. In the +// meantime, we will use a phoenix::function below: +template <char Op> +struct unary_expr +{ + template <typename T> + struct result { typedef T type; }; + + expression_ast operator()(expression_ast const& expr) const + { + return unary_op(Op, expr); + } +}; + +boost::phoenix::function<unary_expr<'+'> > pos; +boost::phoenix::function<unary_expr<'-'> > neg; + +#endif diff --git a/src/boost/libs/spirit/repository/example/karma/calc2_ast_dump_sr.cpp b/src/boost/libs/spirit/repository/example/karma/calc2_ast_dump_sr.cpp new file mode 100644 index 00000000..12f18931 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/karma/calc2_ast_dump_sr.cpp @@ -0,0 +1,181 @@ +/*============================================================================= + Copyright (c) 2001-2010 Joel de Guzman + Copyright (c) 2001-2010 Hartmut Kaiser + Copyright (c) 2009 Francois Barel + + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A Calculator example demonstrating generation of AST which gets dumped into +// a human readable format afterwards. +// +// [ JDG April 28, 2008 ] +// [ HK April 28, 2008 ] +// +/////////////////////////////////////////////////////////////////////////////// +#include <boost/config/warning_disable.hpp> + +#include <iostream> +#include <vector> +#include <string> + +#include "calc2_ast.hpp" + +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/include/karma.hpp> +#include <boost/spirit/repository/include/karma_subrule.hpp> +#include <boost/fusion/include/adapt_struct.hpp> + +using namespace boost::spirit; +using namespace boost::spirit::ascii; +namespace repo = boost::spirit::repository; + +/////////////////////////////////////////////////////////////////////////////// +// Our calculator parser grammar +/////////////////////////////////////////////////////////////////////////////// +template <typename Iterator> +struct calculator + : qi::grammar<Iterator, expression_ast(), space_type> +{ + calculator() : calculator::base_type(expression) + { + expression = + term [_val = _1] + >> *( ('+' >> term [_val += _1]) + | ('-' >> term [_val -= _1]) + ) + ; + + term = + factor [_val = _1] + >> *( ('*' >> factor [_val *= _1]) + | ('/' >> factor [_val /= _1]) + ) + ; + + factor = + uint_ [_val = _1] + | '(' >> expression [_val = _1] >> ')' + | ('-' >> factor [_val = neg(_1)]) + | ('+' >> factor [_val = pos(_1)]) + ; + } + + qi::rule<Iterator, expression_ast(), space_type> expression, term, factor; +}; + +// We need to tell fusion about our binary_op and unary_op structs +// to make them a first-class fusion citizen +// +// Note: we register the members exactly in the same sequence as we need them +// in the grammar +BOOST_FUSION_ADAPT_STRUCT( + binary_op, + (expression_ast, left) + (char, op) + (expression_ast, right) +) + +BOOST_FUSION_ADAPT_STRUCT( + unary_op, + (char, op) + (expression_ast, right) +) + +/////////////////////////////////////////////////////////////////////////////// +// Our AST grammar for the generator, this just dumps the AST as a expression +/////////////////////////////////////////////////////////////////////////////// +template <typename OuputIterator> +struct dump_ast + : karma::grammar<OuputIterator, expression_ast(), space_type> +{ + dump_ast() : dump_ast::base_type(entry) + { + //[calc2_ast_dump_sr_def + entry %= ( + ast_node %= int_ | binary_node | unary_node + + , binary_node %= '(' << ast_node << char_ << ast_node << ')' + + , unary_node %= '(' << char_ << ast_node << ')' + ); + //] + } + + karma::rule<OuputIterator, expression_ast(), space_type> entry; + + repo::karma::subrule<0, expression_ast()> ast_node; + repo::karma::subrule<1, binary_op()> binary_node; + repo::karma::subrule<2, unary_op()> unary_node; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Main program +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + std::cout << "/////////////////////////////////////////////////////////\n\n"; + std::cout << "Dump AST's for simple expressions...\n\n"; + std::cout << "/////////////////////////////////////////////////////////\n\n"; + std::cout << "Type an expression...or [q or Q] to quit\n\n"; + + // Our parser grammar definitions + typedef std::string::const_iterator iterator_type; + typedef calculator<iterator_type> calculator; + + calculator calc; + + // Our generator grammar definitions + typedef std::back_insert_iterator<std::string> output_iterator_type; + typedef dump_ast<output_iterator_type> dump_ast; + + dump_ast ast_grammar; + + std::string str; + while (std::getline(std::cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + expression_ast ast; + std::string::const_iterator iter = str.begin(); + std::string::const_iterator end = str.end(); + bool r = qi::phrase_parse(iter, end, calc, space, ast); + + if (r && iter == end) + { + std::string generated; + output_iterator_type outit(generated); + r = karma::generate_delimited(outit, ast_grammar, space, ast); + + if (r) + { + std::cout << "Got AST:" << std::endl << generated + << std::endl; + std::cout << "-------------------------\n"; + } + else + { + std::cout << "-------------------------\n"; + std::cout << "Generating failed\n"; + std::cout << "-------------------------\n"; + } + } + else + { + std::string rest(iter, end); + std::cout << "-------------------------\n"; + std::cout << "Parsing failed\n"; + std::cout << "stopped at: \": " << rest << "\"\n"; + std::cout << "-------------------------\n"; + } + } + + std::cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/repository/example/karma/confix.cpp b/src/boost/libs/spirit/repository/example/karma/confix.cpp new file mode 100644 index 00000000..4ea6f21c --- /dev/null +++ b/src/boost/libs/spirit/repository/example/karma/confix.cpp @@ -0,0 +1,63 @@ +// Copyright (c) 2001-2010 Hartmut Kaiser +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// The purpose of this example is to demonstrate different use cases for the +// confix generator. + +#include <iostream> +#include <string> +#include <vector> + +//[karma_confix_includes +#include <boost/spirit/include/karma.hpp> +#include <boost/spirit/repository/include/karma_confix.hpp> +//] + +//[karma_confix_namespace +using namespace boost::spirit; +using namespace boost::spirit::ascii; +using boost::spirit::repository::confix; +//] + +int main() +{ +//[karma_confix_cpp_comment + // C++ comment + std::cout << + karma::format_delimited( + confix("//", eol)[string], // format description + space, // delimiter + "This is a comment" // data + ) << std::endl; +//] + +//[karma_confix_c_comment + // C comment + std::cout << + karma::format_delimited( + confix("/*", "*/")[string], // format description + space, // delimiter + "This is a comment" // data + ) << std::endl; +//] + +//[karma_confix_function + // Generate a function call with an arbitrary parameter list + std::vector<std::string> parameters; + parameters.push_back("par1"); + parameters.push_back("par2"); + parameters.push_back("par3"); + + std::cout << + karma::format( + string << confix('(', ')')[string % ','], // format description + "func", // function name + parameters // parameter names + ) << std::endl; +//] + + return 0; +} + diff --git a/src/boost/libs/spirit/repository/example/karma/mini_xml_karma_sr.cpp b/src/boost/libs/spirit/repository/example/karma/mini_xml_karma_sr.cpp new file mode 100644 index 00000000..677cb263 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/karma/mini_xml_karma_sr.cpp @@ -0,0 +1,235 @@ +/*============================================================================= + Copyright (c) 2001-2010 Joel de Guzman + Copyright (c) 2001-2010 Hartmut Kaiser + Copyright (c) 2009 Francois Barel + + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A mini XML-like parser, Karma is used to print out the generated AST +// +// [ JDG March 25, 2007 ] spirit2 +// [ HK April 02, 2007 ] spirit2 +// +/////////////////////////////////////////////////////////////////////////////// + +#include <boost/config/warning_disable.hpp> + +#include <boost/spirit/include/qi.hpp> +//[mini_xml_karma_sr_includes +#include <boost/spirit/include/karma.hpp> +#include <boost/spirit/repository/include/karma_subrule.hpp> +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> +#include <boost/spirit/include/phoenix_fusion.hpp> +//] +#include <boost/spirit/include/phoenix_function.hpp> +#include <boost/spirit/include/phoenix_stl.hpp> +#include <boost/fusion/include/adapt_struct.hpp> +#include <boost/variant/recursive_variant.hpp> + +#include <iostream> +#include <fstream> +#include <string> +#include <vector> + +//[mini_xml_karma_sr_using +using namespace boost::spirit; +using namespace boost::spirit::ascii; +namespace repo = boost::spirit::repository; +//] + +namespace fusion = boost::fusion; +namespace phoenix = boost::phoenix; + +using phoenix::at_c; +using phoenix::push_back; + +/////////////////////////////////////////////////////////////////////////////// +// Our mini XML tree representation +/////////////////////////////////////////////////////////////////////////////// +struct mini_xml; + +typedef + boost::variant< + boost::recursive_wrapper<mini_xml> + , std::string + > +mini_xml_node; + +struct mini_xml +{ + std::string name; // tag name + std::vector<mini_xml_node> children; // children +}; + +// We need to tell fusion about our mini_xml struct +// to make it a first-class fusion citizen +BOOST_FUSION_ADAPT_STRUCT( + mini_xml, + (std::string, name) + (std::vector<mini_xml_node>, children) +) + +/////////////////////////////////////////////////////////////////////////////// +// Our mini XML grammar definition +/////////////////////////////////////////////////////////////////////////////// +template <typename Iterator> +struct mini_xml_parser : + qi::grammar<Iterator, mini_xml(), space_type> +{ + mini_xml_parser() : mini_xml_parser::base_type(xml) + { + text = lexeme[+(char_ - '<') [_val += _1]]; + node = (xml | text) [_val = _1]; + + start_tag = + '<' + >> !lit('/') + >> lexeme[+(char_ - '>') [_val += _1]] + >> '>' + ; + + end_tag = + "</" + >> lit(_r1) + >> '>' + ; + + xml = + start_tag [at_c<0>(_val) = _1] + >> *node [push_back(at_c<1>(_val), _1)] + >> end_tag(at_c<0>(_val)) + ; + } + + qi::rule<Iterator, mini_xml(), space_type> xml; + qi::rule<Iterator, mini_xml_node(), space_type> node; + qi::rule<Iterator, std::string(), space_type> text; + qi::rule<Iterator, std::string(), space_type> start_tag; + qi::rule<Iterator, void(std::string), space_type> end_tag; +}; + +/////////////////////////////////////////////////////////////////////////////// +// A couple of phoenix functions helping to access the elements of the +// generated AST +/////////////////////////////////////////////////////////////////////////////// +template <typename T> +struct get_element +{ + template <typename T1> + struct result { typedef T const& type; }; + + T const& operator()(mini_xml_node const& node) const + { + return boost::get<T>(node); + } +}; + +phoenix::function<get_element<std::string> > _string; +phoenix::function<get_element<mini_xml> > _xml; + +/////////////////////////////////////////////////////////////////////////////// +// The output grammar defining the format of the generated data +/////////////////////////////////////////////////////////////////////////////// +//[mini_xml_karma_sr_grammar +template <typename OutputIterator> +struct mini_xml_generator + : karma::grammar<OutputIterator, mini_xml()> +{ + mini_xml_generator() : mini_xml_generator::base_type(entry) + { + entry %= ( + xml = + '<' << string[_1 = at_c<0>(_val)] << '>' + << (*node)[_1 = at_c<1>(_val)] + << "</" << string[_1 = at_c<0>(_val)] << '>' + + , node %= string | xml + ); + } + + karma::rule<OutputIterator, mini_xml()> entry; + + repo::karma::subrule<0, mini_xml()> xml; + repo::karma::subrule<1, mini_xml_node()> node; +}; +//] + +/////////////////////////////////////////////////////////////////////////////// +// Main program +/////////////////////////////////////////////////////////////////////////////// +int main(int argc, char **argv) +{ + char const* filename; + if (argc > 1) + { + filename = argv[1]; + } + else + { + std::cerr << "Error: No input file provided." << std::endl; + return 1; + } + + std::ifstream in(filename, std::ios_base::in); + + if (!in) + { + std::cerr << "Error: Could not open input file: " + << filename << std::endl; + return 1; + } + + std::string storage; // We will read the contents here. + in.unsetf(std::ios::skipws); // No white space skipping! + std::copy( + std::istream_iterator<char>(in), + std::istream_iterator<char>(), + std::back_inserter(storage)); + + typedef mini_xml_parser<std::string::const_iterator> mini_xml_parser; + mini_xml_parser xmlin; // Our grammar definition + mini_xml ast; // our tree + + std::string::const_iterator iter = storage.begin(); + std::string::const_iterator end = storage.end(); + bool r = qi::phrase_parse(iter, end, xmlin, space, ast); + + if (r && iter == end) + { + std::cout << "-------------------------\n"; + std::cout << "Parsing succeeded\n"; + std::cout << "-------------------------\n"; + + typedef std::back_insert_iterator<std::string> outiter_type; + typedef mini_xml_generator<outiter_type> mini_xml_generator; + + mini_xml_generator xmlout; // Our grammar definition + + std::string generated; + outiter_type outit(generated); + bool r = karma::generate(outit, xmlout, ast); + + if (r) + std::cout << generated << std::endl; + return 0; + } + else + { + std::string::const_iterator begin = storage.begin(); + std::size_t dist = std::distance(begin, iter); + std::string::const_iterator some = + iter + (std::min)(storage.size()-dist, std::size_t(30)); + std::string context(iter, some); + std::cout << "-------------------------\n"; + std::cout << "Parsing failed\n"; + std::cout << "stopped at: \": " << context << "...\"\n"; + std::cout << "-------------------------\n"; + return 1; + } +} + + diff --git a/src/boost/libs/spirit/repository/example/qi/Jamfile b/src/boost/libs/spirit/repository/example/qi/Jamfile new file mode 100644 index 00000000..1857b318 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/qi/Jamfile @@ -0,0 +1,23 @@ +#============================================================================== +# Copyright (c) 2001-2009 Joel de Guzman +# Copyright (c) 2001-2009 Hartmut Kaiser +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#============================================================================== + +project spirit_v2_repository/example_qi + : requirements + <c++-template-depth>300 + ; + +exe qi_confix : confix.cpp ; +exe qi_distinct : distinct.cpp ; +exe flush_multi_pass : flush_multi_pass.cpp ; +exe calc1_sr : calc1_sr.cpp ; +exe mini_xml2_sr : mini_xml2_sr.cpp ; +exe advance : advance.cpp ; +exe keywords : keywords.cpp ; +exe derived : derived.cpp ; +exe options : options.cpp ; +exe seek : seek.cpp ; diff --git a/src/boost/libs/spirit/repository/example/qi/advance.cpp b/src/boost/libs/spirit/repository/example/qi/advance.cpp new file mode 100644 index 00000000..e47d32ee --- /dev/null +++ b/src/boost/libs/spirit/repository/example/qi/advance.cpp @@ -0,0 +1,110 @@ +// Copyright (c) 2011 Aaron Graham +// +// 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) + +// The purpose of this example is to demonstrate the use of the advance parser. + +//[qi_advance_includes +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> +#include <boost/spirit/repository/include/qi_advance.hpp> +//] + +#include <list> +#include <string> + +//[qi_advance_namespaces +namespace qi = boost::spirit::qi; +using boost::spirit::repository::qi::advance; +//] + +namespace client +{ + //[qi_advance_grammar + template <typename Iterator> + struct advance_grammar : qi::grammar<Iterator, qi::locals<int> > + { + advance_grammar() : advance_grammar::base_type(start) + { + using qi::byte_; + using qi::eoi; + using namespace qi::labels; + + start + = byte_ [_a = _1] + >> advance(_a) + >> "boost" + >> byte_ [_a = _1] + >> (advance(_a) | "qi") // note alternative when advance fails + >> eoi + ; + } + + qi::rule<Iterator, qi::locals<int> > start; + }; + //] +} + +int main() +{ + // This parser is tested with both random access iterators (std::string) + // and bidirectional iterators (std::list). + char const* result; + + //[qi_advance_example1 + unsigned char const alt1[] = + { + 5, // number of bytes to advance + 1, 2, 3, 4, 5, // data to advance through + 'b', 'o', 'o', 's', 't', // word to parse + 2, // number of bytes to advance + 11, 12 // more data to advance through + // eoi + }; + + std::string const alt1_string(alt1, alt1 + sizeof alt1); + std::list<unsigned char> const alt1_list(alt1, alt1 + sizeof alt1); + + result = + qi::parse(alt1_string.begin(), alt1_string.end() + , client::advance_grammar<std::string::const_iterator>()) + ? "succeeded" : "failed"; + std::cout << "Parsing alt1 using random access iterator " << result << std::endl; + + result = + qi::parse(alt1_list.begin(), alt1_list.end() + , client::advance_grammar<std::list<unsigned char>::const_iterator>()) + ? "succeeded" : "failed"; + std::cout << "Parsing alt1 using bidirectional iterator " << result << std::endl; + //] + + //[qi_advance_example2 + unsigned char const alt2[] = + { + 2, // number of bytes to advance + 1, 2, // data to advance through + 'b', 'o', 'o', 's', 't', // word to parse + 4, // number of bytes to advance + 'q', 'i' // alternative (advance won't work) + // eoi + }; + + std::string const alt2_string(alt2, alt2 + sizeof alt2); + std::list<unsigned char> const alt2_list(alt2, alt2 + sizeof alt2); + + result = + qi::parse(alt2_string.begin(), alt2_string.end() + , client::advance_grammar<std::string::const_iterator>()) + ? "succeeded" : "failed"; + std::cout << "Parsing alt2 using random access iterator " << result << std::endl; + + result = + qi::parse(alt2_list.begin(), alt2_list.end() + , client::advance_grammar<std::list<unsigned char>::const_iterator>()) + ? "succeeded" : "failed"; + std::cout << "Parsing alt2 using bidirectional iterator " << result << std::endl; + //] + + return 0; +} diff --git a/src/boost/libs/spirit/repository/example/qi/calc1_sr.cpp b/src/boost/libs/spirit/repository/example/qi/calc1_sr.cpp new file mode 100644 index 00000000..031a33f5 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/qi/calc1_sr.cpp @@ -0,0 +1,118 @@ +/*============================================================================= + Copyright (c) 2001-2010 Joel de Guzman + Copyright (c) 2009 Francois Barel + + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// Plain calculator example demonstrating the grammar. The parser is a +// syntax checker only and does not do any semantic evaluation. +// +// [ JDG May 10, 2002 ] spirit1 +// [ JDG March 4, 2007 ] spirit2 +// +/////////////////////////////////////////////////////////////////////////////// + +#include <boost/config/warning_disable.hpp> +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/repository/include/qi_subrule.hpp> +#include <iostream> +#include <string> + +namespace client +{ + namespace qi = boost::spirit::qi; + namespace repo = boost::spirit::repository; + namespace ascii = boost::spirit::ascii; + + /////////////////////////////////////////////////////////////////////////////// + // Our calculator grammar + /////////////////////////////////////////////////////////////////////////////// + template <typename Iterator> + struct calculator : qi::grammar<Iterator, ascii::space_type> + { + calculator() : calculator::base_type(entry) + { + using qi::uint_; + + //[calc1_sr_def + entry = ( + expression = + term + >> *( ('+' >> term) + | ('-' >> term) + ) + + , term = + factor + >> *( ('*' >> factor) + | ('/' >> factor) + ) + + , factor = + uint_ + | '(' >> expression >> ')' + | ('-' >> factor) + | ('+' >> factor) + ); + //] + } + + qi::rule<Iterator, ascii::space_type> entry; + + repo::qi::subrule<0> expression; + repo::qi::subrule<1> term; + repo::qi::subrule<2> factor; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// Main program +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + std::cout << "/////////////////////////////////////////////////////////\n\n"; + std::cout << "Expression parser...\n\n"; + std::cout << "/////////////////////////////////////////////////////////\n\n"; + std::cout << "Type an expression...or [q or Q] to quit\n\n"; + + using boost::spirit::ascii::space; + typedef std::string::const_iterator iterator_type; + typedef client::calculator<iterator_type> calculator; + + calculator calc; // Our grammar + + std::string str; + while (std::getline(std::cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + std::string::const_iterator iter = str.begin(); + std::string::const_iterator end = str.end(); + bool r = phrase_parse(iter, end, calc, space); + + if (r && iter == end) + { + std::cout << "-------------------------\n"; + std::cout << "Parsing succeeded\n"; + std::cout << "-------------------------\n"; + } + else + { + std::string rest(iter, end); + std::cout << "-------------------------\n"; + std::cout << "Parsing failed\n"; + std::cout << "stopped at: \": " << rest << "\"\n"; + std::cout << "-------------------------\n"; + } + } + + std::cout << "Bye... :-) \n\n"; + return 0; +} + + diff --git a/src/boost/libs/spirit/repository/example/qi/confix.cpp b/src/boost/libs/spirit/repository/example/qi/confix.cpp new file mode 100644 index 00000000..2426e824 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/qi/confix.cpp @@ -0,0 +1,113 @@ +// Copyright (c) 2009 Chris Hoeppler +// +// 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) + +// The purpose of this example is to demonstrate different use cases for the +// confix directive. + +#include <iostream> +#include <string> +#include <vector> + +//[qi_confix_includes +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/repository/include/qi_confix.hpp> +//] + +namespace client { +//[qi_confix_using + using boost::spirit::eol; + using boost::spirit::lexeme; + using boost::spirit::ascii::alnum; + using boost::spirit::ascii::char_; + using boost::spirit::ascii::space; + using boost::spirit::qi::parse; + using boost::spirit::qi::phrase_parse; + using boost::spirit::repository::confix; +//] + +//[qi_confix_cpp_comment + template <typename Iterator> + bool parse_cpp_comment(Iterator first, Iterator last, std::string& attr) + { + bool r = parse(first, last, + confix("//", eol)[*(char_ - eol)], // grammar + attr); // attribute + + if (!r || first != last) // fail if we did not get a full match + return false; + return r; + } +//] + +//[qi_confix_c_comment + template <typename Iterator> + bool parse_c_comment(Iterator first, Iterator last, std::string& attr) + { + bool r = parse(first, last, + confix("/*", "*/")[*(char_ - "*/")], // grammar + attr); // attribute + + if (!r || first != last) // fail if we did not get a full match + return false; + return r; + } +//] + +//[qi_confix_tagged_data + template <typename Iterator> + bool parse_tagged(Iterator first, Iterator last, std::string& attr) + { + bool r = phrase_parse(first, last, + confix("<b>", "</b>")[lexeme[*(char_ - '<')]], // grammar + space, // skip + attr); // attribute + + if (!r || first != last) // fail if we did not get a full match + return false; + return r; + } +//] +} + + +int main() +{ + // C++ comment + std::string comment("// This is a comment\n"); + std::string attr; + bool r = client::parse_cpp_comment(comment.begin(), comment.end(), attr); + + std::cout << "Parsing a C++ comment"; + if (r && attr == " This is a comment") + std::cout << " succeeded." << std::endl; + else + std::cout << " failed" << std::endl; + + // C comment + comment = "/* This is another comment */"; + attr.clear(); + r = client::parse_c_comment(comment.begin(), comment.end(), attr); + + std::cout << "Parsing a C comment"; + if (r && attr == " This is another comment ") + std::cout << " succeeded." << std::endl; + else + std::cout << " failed" << std::endl; + + // Tagged data + std::string data = "<b> This is the body. </b>"; + attr.clear(); + + r = client::parse_tagged(data.begin(), data.end(), attr); + + std::cout << "Parsing tagged data"; + if (r && attr == "This is the body. ") + std::cout << " succeeded." << std::endl; + else + std::cout << " failed" << std::endl; + + return 0; +} + diff --git a/src/boost/libs/spirit/repository/example/qi/derived.cpp b/src/boost/libs/spirit/repository/example/qi/derived.cpp new file mode 100644 index 00000000..a92490a9 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/qi/derived.cpp @@ -0,0 +1,158 @@ +/*============================================================================= + Copyright (c) 2011 Thomas Bernard + http://spirit.sourceforge.net/ + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +//[reference_includes +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> +#include <boost/spirit/include/phoenix_container.hpp> +#include <boost/spirit/include/phoenix_object.hpp> +#include <boost/spirit/include/phoenix_fusion.hpp> +#include <boost/fusion/include/adapt_struct.hpp> +#include <boost/spirit/repository/include/qi_kwd.hpp> +#include <boost/spirit/repository/include/qi_keywords.hpp> +#include <iostream> +#include <string> +#include <cstdlib> +#include <iterator> +//] + + +// Data structure definitions + +struct base_type { + base_type(const std::string &name) : name(name) {} + std::string name; + + virtual std::ostream &output(std::ostream &os) const + { + os<<"Base : "<<name; + return os; + } + +}; + +struct derived1 : public base_type { + derived1(const std::string &name, unsigned int data1) : base_type(name), data1(data1) {} + unsigned int data1; + + virtual std::ostream &output(std::ostream &os) const + { + base_type::output(os); + os<<", "<<data1; + return os; + } + +}; + +struct derived2 : public base_type { + derived2(const std::string &name, unsigned int data2) : base_type(name), data2(data2) {} + unsigned int data2; + virtual std::ostream &output(std::ostream &os) const + { + base_type::output(os); + os<<", "<<data2; + return os; + } + +}; + +struct derived3 : public derived2 { + derived3(const std::string &name, unsigned int data2, double data3) : + derived2(name,data2), + data3(data3) {} + double data3; + + virtual std::ostream &output(std::ostream &os) const + { + derived2::output(os); + os<<", "<<data3; + return os; + } + + +}; + +std::ostream &operator<<(std::ostream &os, const base_type &obj) +{ + return obj.output(os); +} + +BOOST_FUSION_ADAPT_STRUCT( base_type, + (std::string, name) +) + +BOOST_FUSION_ADAPT_STRUCT( derived1, + (std::string , name) + (unsigned int , data1) +) +BOOST_FUSION_ADAPT_STRUCT( derived2, + (std::string , name) + (unsigned int, data2) +) +BOOST_FUSION_ADAPT_STRUCT( derived3, + (std::string , name) + (unsigned int, data2) + (double, data3) +) +//] + +int +main() +{ + + + using boost::spirit::repository::qi::kwd; + using boost::spirit::qi::inf; + using boost::spirit::ascii::space_type; + using boost::spirit::ascii::char_; + using boost::spirit::qi::double_; + using boost::spirit::qi::int_; + using boost::spirit::qi::rule; + using boost::spirit::_val; + using boost::spirit::_1; + using boost::spirit::_2; + using boost::spirit::_3; + + + //Rule declarations + rule<const char *, std::string(), space_type> parse_string; + rule<const char *, std::vector<base_type*>(), space_type> kwd_rule; + + // Our string parsing helper + parse_string %= '"'> *(char_-'"') > '"'; + + namespace phx=boost::phoenix; + //[ kwd rule + kwd_rule = + kwd("derived1")[ ('=' > parse_string > int_ ) [phx::push_back(_val,phx::new_<derived1>(_1,_2))] ] + / kwd("derived2")[ ('=' > parse_string > int_ ) [phx::push_back(_val,phx::new_<derived2>(_1,_2))]] + / kwd("derived3")[ ('=' > parse_string > int_ > double_) [phx::push_back(_val,phx::new_<derived3>(_1,_2,_3))] ] + ; + //] + + using boost::spirit::qi::phrase_parse; + using boost::spirit::qi::ascii::space; + + // The result vector + std::vector<base_type*> result; + + char const input[]="derived2 = \"object1\" 10 derived3= \"object2\" 40 20.0 "; + char const* f(input); + char const* l(f + strlen(f)); + + if (phrase_parse(f, l, kwd_rule, space,result) && (f == l)) + std::cout << "ok" << std::endl; + else + std::cout << "fail" << std::endl; + + using namespace boost::phoenix::arg_names; + std::for_each(result.begin(),result.end(),std::cout<<*arg1<<std::endl); + // Clean up the vector of pointers + std::for_each(result.begin(),result.end(),phx::delete_(arg1)); + return 0; +} diff --git a/src/boost/libs/spirit/repository/example/qi/distinct.cpp b/src/boost/libs/spirit/repository/example/qi/distinct.cpp new file mode 100644 index 00000000..78bac6ed --- /dev/null +++ b/src/boost/libs/spirit/repository/example/qi/distinct.cpp @@ -0,0 +1,60 @@ +// Copyright (c) 2001-2010 Hartmut Kaiser +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// The purpose of this example is to demonstrate different use cases for the +// distinct parser. + +#include <iostream> +#include <string> +#include <vector> + +//[qi_distinct_includes +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/repository/include/qi_distinct.hpp> +//] + +//[qi_distinct_namespace +using namespace boost::spirit; +using namespace boost::spirit::ascii; +using boost::spirit::repository::distinct; +//] + +int main() +{ + //[qi_distinct_description_ident + { + std::string str("description ident"); + std::string::iterator first(str.begin()); + bool r = qi::phrase_parse(first, str.end() + , distinct(alnum | '_')["description"] >> -lit("--") >> +(alnum | '_') + , space); + BOOST_ASSERT(r && first == str.end()); + } + //] + + //[qi_distinct_description__ident + { + std::string str("description--ident"); + std::string::iterator first(str.begin()); + bool r = qi::phrase_parse(first, str.end() + , distinct(alnum | '_')["description"] >> -lit("--") >> +(alnum | '_') + , space); + BOOST_ASSERT(r && first == str.end()); + } + //] + + //[qi_distinct_description_ident_error + { + std::string str("description-ident"); + std::string::iterator first(str.begin()); + bool r = qi::phrase_parse(first, str.end() + , distinct(alnum | '_')["description"] >> -lit("--") >> +(alnum | '_') + , space); + BOOST_ASSERT(!r && first == str.begin()); + } + //] + + return 0; +} diff --git a/src/boost/libs/spirit/repository/example/qi/flush_multi_pass.cpp b/src/boost/libs/spirit/repository/example/qi/flush_multi_pass.cpp new file mode 100644 index 00000000..79fa2e57 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/qi/flush_multi_pass.cpp @@ -0,0 +1,98 @@ +// Copyright (c) 2001-2010 Hartmut Kaiser +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// The purpose of this example is to demonstrate a simple use case for the +// flush_multi_pass parser. + +#include <iostream> +#include <fstream> +#include <string> + +//[qi_flush_multi_pass_includes +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/repository/include/qi_flush_multi_pass.hpp> +//] + +//[qi_flush_multi_pass_namespace +namespace spirit = boost::spirit; +using boost::spirit::repository::flush_multi_pass; +//] + +namespace client +{ + //[qi_flush_multi_pass_clear_buffer + template <typename Iterator, typename Skipper> + struct preprocessor : spirit::qi::grammar<Iterator, Skipper> + { + // This is a simplified preprocessor grammar recognizing + // + // #define MACRONAME something + // #undef MACRONAME + // + // Its sole purpose is to show an example how to use the + // flush_multi_pass parser. At the end of each line no backtracking can + // occur anymore so that it's safe to clear all internal buffers in the + // multi_pass. + preprocessor() : preprocessor::base_type(file) + { + using spirit::ascii::char_; + using spirit::qi::eol; + using spirit::qi::lit; + + file = + *line + ; + + line = ( command | *(char_ - eol) ) + >> eol + >> flush_multi_pass + ; + + command = + "#define" >> *lit(' ') >> *(char_ - ' ') >> *lit(' ') >> *(char_ - eol) + | "#undef" >> *lit(' ') >> *(char_ - eol) + ; + } + + spirit::qi::rule<Iterator, Skipper> file, line, command; + }; + //] +} + +template <typename Iterator, typename Skipper> +bool parse(Iterator& first, Iterator end, Skipper const& skipper) +{ + client::preprocessor<Iterator, Skipper> g; + return boost::spirit::qi::phrase_parse(first, end, g, skipper); +} + +int main() +{ + namespace spirit = boost::spirit; + using spirit::ascii::char_; + using spirit::qi::eol; + + std::ifstream in("flush_multi_pass.txt"); // we get our input from this file + if (!in.is_open()) { + std::cout << "Could not open input file: 'flush_multi_pass.txt'" << std::endl; + return -1; + } + + typedef std::istreambuf_iterator<char> base_iterator_type; + spirit::multi_pass<base_iterator_type> first = + spirit::make_default_multi_pass(base_iterator_type(in)); + spirit::multi_pass<base_iterator_type> end = + spirit::make_default_multi_pass(base_iterator_type()); + + bool result = parse(first, end, '#' >> *(char_ - eol) >> eol); + if (!result) { + std::cout << "Failed parsing input file!" << std::endl; + return -2; + } + + std::cout << "Successfully parsed input file!" << std::endl; + return 0; +} + diff --git a/src/boost/libs/spirit/repository/example/qi/flush_multi_pass.txt b/src/boost/libs/spirit/repository/example/qi/flush_multi_pass.txt new file mode 100644 index 00000000..46cd92eb --- /dev/null +++ b/src/boost/libs/spirit/repository/example/qi/flush_multi_pass.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2001-2009 Hartmut Kaiser +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define MACRO foo +#undef MACRO + diff --git a/src/boost/libs/spirit/repository/example/qi/iter_pos_parser.cpp b/src/boost/libs/spirit/repository/example/qi/iter_pos_parser.cpp new file mode 100644 index 00000000..28081405 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/qi/iter_pos_parser.cpp @@ -0,0 +1,51 @@ +// Copyright (c) 2001-2010 Hartmut Kaiser +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// The purpose of this example is to show how a simple custom primitive parser +// component can be written. We develop a custom parser exposing the current +// iterator position as its attribute. +// +// For more information see: http://spirit.sourceforge.net/home/?page_id=567 + +#include <boost/spirit/include/qi_parse_attr.hpp> +#include <boost/spirit/include/qi_char.hpp> +#include <boost/spirit/include/qi_operator.hpp> +#include <boost/spirit/repository/include/qi_iter_pos.hpp> + +#include <string> + +namespace qi = boost::spirit::qi; + +int main() +{ + using boost::spirit::repository::qi::iter_pos; + + std::string prefix, suffix; // attributes receiving the + std::string::iterator position; // parsed values + + std::string input("prefix1234567"); + std::string::iterator first = input.begin(); + bool result = + qi::parse(first, input.end() + , +qi::alpha >> iter_pos >> +qi::digit + , prefix, position, suffix); + + if (result) + { + std::cout << "-------------------------------- \n"; + std::cout << "Parsing succeeded\n"; + std::cout << "prefix is: " << prefix << "\n"; + std::cout << "suffix is: " << suffix << "\n"; + std::cout << "position is: " << std::distance(input.begin(), position) << "\n"; + std::cout << "-------------------------------- \n"; + } + else + { + std::cout << "-------------------------------- \n"; + std::cout << "Parsing failed\n"; + std::cout << "-------------------------------- \n"; + } + return 0; +} diff --git a/src/boost/libs/spirit/repository/example/qi/keywords.cpp b/src/boost/libs/spirit/repository/example/qi/keywords.cpp new file mode 100644 index 00000000..51ea7353 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/qi/keywords.cpp @@ -0,0 +1,214 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + http://spirit.sourceforge.net/ + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +//[reference_includes +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> +#include <boost/fusion/include/adapt_struct.hpp> +#include <boost/spirit/repository/include/qi_kwd.hpp> +#include <boost/spirit/repository/include/qi_keywords.hpp> +#include <iostream> +#include <string> +#include <cstdlib> +#include <iterator> +//] + +//[reference_test +template <typename P> +void test_parser( + char const* input, P const& p, bool full_match = true) +{ + using boost::spirit::qi::parse; + + char const* f(input); + char const* l(f + strlen(f)); + if (parse(f, l, p) && (!full_match || (f == l))) + std::cout << "ok" << std::endl; + else + std::cout << "fail" << std::endl; +} + +template <typename P> +void test_phrase_parser( + char const* input, P const& p, bool full_match = true) +{ + using boost::spirit::qi::phrase_parse; + using boost::spirit::qi::ascii::space; + + char const* f(input); + char const* l(f + strlen(f)); + if (phrase_parse(f, l, p, space) && (!full_match || (f == l))) + std::cout << "ok" << std::endl; + else + std::cout << "fail" << std::endl; +} +//] + +//[reference_test_attr +template <typename P, typename T> +void test_parser_attr( + char const* input, P const& p, T& attr, bool full_match = true) +{ + using boost::spirit::qi::parse; + + char const* f(input); + char const* l(f + strlen(f)); + if (parse(f, l, p, attr) && (!full_match || (f == l))) + std::cout << "ok" << std::endl; + else + std::cout << "fail" << std::endl; +} + +template <typename P, typename T> +void test_phrase_parser_attr( + char const* input, P const& p, T& attr, bool full_match = true) +{ + using boost::spirit::qi::phrase_parse; + using boost::spirit::qi::ascii::space; + + char const* f(input); + char const* l(f + strlen(f)); + if (phrase_parse(f, l, p, space, attr) && (!full_match || (f == l))) + std::cout << "ok" << std::endl; + else + std::cout << "fail" << std::endl; +} +//] + + + +//[reference_keyword_list_test_data_structure +// Data structure definitions to test the kwd directive +// and the keywords list operator + +struct person { + std::string name; + int age; + double size; + std::vector<std::string> favorite_colors; + +}; + +std::ostream &operator<<(std::ostream &os, const person &p) +{ + os<<"Person : "<<p.name<<", "<<p.age<<", "<<p.size<<std::endl; + std::copy(p.favorite_colors.begin(),p.favorite_colors.end(),std::ostream_iterator<std::string>(os,"\n")); + return os; +} + +BOOST_FUSION_ADAPT_STRUCT( person, + (std::string, name) + (int, age) + (double, size) + (std::vector<std::string>, favorite_colors) +) +//] + +int +main() +{ + + // keyword_list + { + //[reference_using_declarations_keyword_list + using boost::spirit::repository::qi::kwd; + using boost::spirit::qi::inf; + using boost::spirit::ascii::space_type; + using boost::spirit::ascii::char_; + using boost::spirit::qi::double_; + using boost::spirit::qi::int_; + using boost::spirit::qi::rule; + //] + + //[reference_keyword_list_rule_declarations + rule<const char *, std::string(), space_type> parse_string; + rule<const char *, person(), space_type> no_constraint_person_rule, constraint_person_rule; + + parse_string %= '"'> *(char_-'"') > '"'; + //] + + //[reference_keyword_list_no_constraint_rule + no_constraint_person_rule %= + kwd("name")['=' > parse_string ] + / kwd("age") ['=' > int_] + / kwd("size") ['=' > double_ > 'm'] + ; + //] + + + //[reference_keyword_list + //`Parsing a keyword list: + // Let's declare a small list of people for which we want to collect information. + person John,Mary,Mike,Hellen,Johny; + test_phrase_parser_attr( + "name = \"John\" \n age = 10 \n size = 1.69m " + ,no_constraint_person_rule + ,John); // full in orginal order + std::cout<<John; + + test_phrase_parser_attr( + "age = 10 \n size = 1.69m \n name = \"Mary\"" + ,no_constraint_person_rule + ,Mary); // keyword oder doesn't matter + std::cout<<Mary; + + test_phrase_parser_attr( + "size = 1.69m \n name = \"Mike\" \n age = 10 " + ,no_constraint_person_rule + ,Mike); // still the same result + + std::cout<<Mike; + + /*`The code above will print:[teletype] + + Person : John, 10, 1.69 + Person : Mary, 10, 1.69 + Person : Mike, 10, 1.69 + */ + //] + + //[reference_keyword_list_constraint_rule + /*`The parser definition below uses the kwd directive occurrence constraint variants to + make sure that the name and age keyword occur only once and allows the favorite color + entry to appear 0 or more times. */ + constraint_person_rule %= + kwd("name",1) ['=' > parse_string ] + / kwd("age" ,1) ['=' > int_] + / kwd("size" ,1) ['=' > double_ > 'm'] + / kwd("favorite color",0,inf) [ '=' > parse_string ] + ; + //] + + //[reference_keyword_list_constraints + + // Here all the give constraint are resepected : parsing will succeed. + test_phrase_parser_attr( + "name = \"Hellen\" \n age = 10 \n size = 1.80m \n favorite color = \"blue\" \n favorite color = \"green\" " + ,constraint_person_rule + ,Hellen); + std::cout<<Hellen; + + // Parsing this string will fail because the age and size minimum occurrence requirements aren't met. + test_phrase_parser_attr( + "name = \"Johny\" \n favorite color = \"blue\" \n favorite color = \"green\" " + ,constraint_person_rule + ,Johny ); + + /*`Parsing the first string will succeed but fail for the second string as the + occurrence constraints aren't met. This code should print:[teletype] + + Person : Hellen, 10, 1.8 + blue + green + */ + //] + } + + + return 0; +} diff --git a/src/boost/libs/spirit/repository/example/qi/mini_xml2_sr.cpp b/src/boost/libs/spirit/repository/example/qi/mini_xml2_sr.cpp new file mode 100644 index 00000000..a0d2f3a4 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/qi/mini_xml2_sr.cpp @@ -0,0 +1,246 @@ +/*============================================================================= + Copyright (c) 2001-2010 Joel de Guzman + Copyright (c) 2009 Francois Barel + + 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A mini XML-like parser +// +// [ JDG March 25, 2007 ] spirit2 +// +/////////////////////////////////////////////////////////////////////////////// + +#include <boost/config/warning_disable.hpp> +//[mini_xml2_sr_includes +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/repository/include/qi_subrule.hpp> +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> +//] +#include <boost/spirit/include/phoenix_fusion.hpp> +#include <boost/spirit/include/phoenix_stl.hpp> +#include <boost/fusion/include/adapt_struct.hpp> +#include <boost/variant/recursive_variant.hpp> +#include <boost/foreach.hpp> + +#include <iostream> +#include <fstream> +#include <string> +#include <vector> + +namespace client +{ + namespace fusion = boost::fusion; + namespace phoenix = boost::phoenix; + //[mini_xml2_sr_using + namespace qi = boost::spirit::qi; + namespace repo = boost::spirit::repository; + namespace ascii = boost::spirit::ascii; + //] + + /////////////////////////////////////////////////////////////////////////// + // Our mini XML tree representation + /////////////////////////////////////////////////////////////////////////// + struct mini_xml; + + typedef + boost::variant< + boost::recursive_wrapper<mini_xml> + , std::string + > + mini_xml_node; + + struct mini_xml + { + std::string name; // tag name + std::vector<mini_xml_node> children; // children + }; +} + +// We need to tell fusion about our mini_xml struct +// to make it a first-class fusion citizen +BOOST_FUSION_ADAPT_STRUCT( + client::mini_xml, + (std::string, name) + (std::vector<client::mini_xml_node>, children) +) + +namespace client +{ + /////////////////////////////////////////////////////////////////////////// + // Print out the mini xml tree + /////////////////////////////////////////////////////////////////////////// + int const tabsize = 4; + + void tab(int indent) + { + for (int i = 0; i < indent; ++i) + std::cout << ' '; + } + + struct mini_xml_printer + { + mini_xml_printer(int indent = 0) + : indent(indent) + { + } + + void operator()(mini_xml const& xml) const; + + int indent; + }; + + struct mini_xml_node_printer : boost::static_visitor<> + { + mini_xml_node_printer(int indent = 0) + : indent(indent) + { + } + + void operator()(mini_xml const& xml) const + { + mini_xml_printer(indent+tabsize)(xml); + } + + void operator()(std::string const& text) const + { + tab(indent+tabsize); + std::cout << "text: \"" << text << '"' << std::endl; + } + + int indent; + }; + + void mini_xml_printer::operator()(mini_xml const& xml) const + { + tab(indent); + std::cout << "tag: " << xml.name << std::endl; + tab(indent); + std::cout << '{' << std::endl; + + BOOST_FOREACH(mini_xml_node const& node, xml.children) + { + boost::apply_visitor(mini_xml_node_printer(indent), node); + } + + tab(indent); + std::cout << '}' << std::endl; + } + + /////////////////////////////////////////////////////////////////////////// + // Our mini XML grammar definition + /////////////////////////////////////////////////////////////////////////// + //[mini_xml2_sr_grammar + template <typename Iterator> + struct mini_xml_grammar + : qi::grammar<Iterator, mini_xml(), ascii::space_type> + { + mini_xml_grammar() + : mini_xml_grammar::base_type(entry) + { + using qi::lit; + using qi::lexeme; + using ascii::char_; + using ascii::string; + using namespace qi::labels; + + entry %= ( + xml %= + start_tag[_a = _1] + >> *node + >> end_tag(_a) + + , node %= xml | text + + , text %= lexeme[+(char_ - '<')] + + , start_tag %= + '<' + >> !lit('/') + >> lexeme[+(char_ - '>')] + >> '>' + + , end_tag %= + "</" + >> lit(_r1) + >> '>' + ); + } + + qi::rule<Iterator, mini_xml(), ascii::space_type> entry; + + repo::qi::subrule<0, mini_xml(), qi::locals<std::string> > xml; + repo::qi::subrule<1, mini_xml_node()> node; + repo::qi::subrule<2, std::string()> text; + repo::qi::subrule<3, std::string()> start_tag; + repo::qi::subrule<4, void(std::string)> end_tag; + }; + //] +} + +/////////////////////////////////////////////////////////////////////////////// +// Main program +/////////////////////////////////////////////////////////////////////////////// +int main(int argc, char **argv) +{ + char const* filename; + if (argc > 1) + { + filename = argv[1]; + } + else + { + std::cerr << "Error: No input file provided." << std::endl; + return 1; + } + + std::ifstream in(filename, std::ios_base::in); + + if (!in) + { + std::cerr << "Error: Could not open input file: " + << filename << std::endl; + return 1; + } + + std::string storage; // We will read the contents here. + in.unsetf(std::ios::skipws); // No white space skipping! + std::copy( + std::istream_iterator<char>(in), + std::istream_iterator<char>(), + std::back_inserter(storage)); + + typedef client::mini_xml_grammar<std::string::const_iterator> mini_xml_grammar; + mini_xml_grammar xml; // Our grammar + client::mini_xml ast; // Our tree + + using boost::spirit::ascii::space; + std::string::const_iterator iter = storage.begin(); + std::string::const_iterator end = storage.end(); + bool r = phrase_parse(iter, end, xml, space, ast); + + if (r && iter == end) + { + std::cout << "-------------------------\n"; + std::cout << "Parsing succeeded\n"; + std::cout << "-------------------------\n"; + client::mini_xml_printer printer; + printer(ast); + return 0; + } + else + { + std::string::const_iterator some = iter + std::min(30, int(end - iter)); + std::string context(iter, (some>end)?end:some); + std::cout << "-------------------------\n"; + std::cout << "Parsing failed\n"; + std::cout << "stopped at: \"" << context << "...\"\n"; + std::cout << "-------------------------\n"; + return 1; + } +} + + diff --git a/src/boost/libs/spirit/repository/example/qi/options.cpp b/src/boost/libs/spirit/repository/example/qi/options.cpp new file mode 100644 index 00000000..3bad27c2 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/qi/options.cpp @@ -0,0 +1,122 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + http://spirit.sourceforge.net/ + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/include/karma.hpp> +#include <boost/fusion/include/adapt_struct.hpp> +#include <boost/spirit/repository/include/qi_kwd.hpp> +#include <boost/spirit/repository/include/qi_keywords.hpp> +#include <boost/optional.hpp> +#include <boost/cstdint.hpp> +#include <iostream> +#include <string> +#include <cstdlib> +#include <iterator> +#include <map> +#include <vector> + +// Data structure definitions + +// preprocessor constants +typedef std::pair<std::string, boost::int32_t> preprocessor_symbol; + +BOOST_FUSION_ADAPT_STRUCT( preprocessor_symbol, + (std::string, first) + (boost::int32_t, second) +) + +// A data structure to store our program options +struct program_options { + std::vector<std::string> includes; // include paths + typedef std::vector< preprocessor_symbol > preprocessor_symbols_container; // symbol container type definition + preprocessor_symbols_container preprocessor_symbols; // preprocessor symbols + boost::optional<std::string> output_filename; // output file name + std::string source_filename; // source file name + +}; + +// Make the program_options compatible with fusion sequences +BOOST_FUSION_ADAPT_STRUCT( program_options, + (std::vector<std::string>, includes) + (program_options::preprocessor_symbols_container, preprocessor_symbols) + (boost::optional<std::string>, output_filename) + (std::string, source_filename) +) + + +// Output helper to check that the data parsed matches what we expect +std::ostream &operator<<(std::ostream &os, const program_options &obj) +{ + using boost::spirit::karma::string; + using boost::spirit::karma::int_; + using boost::spirit::karma::lit; + using boost::spirit::karma::buffer; + using boost::spirit::karma::eol; + using boost::spirit::karma::format; + return os<<format( + lit("Includes:") << (string % ',') << eol + << lit("Preprocessor symbols:") << ((string <<"="<< int_) % ',') << eol + << buffer[-( lit("Output file:")<< string << eol)] + << lit("Source file:")<< string << eol + ,obj); + return os; +} + + +int +main() +{ + + { + // Pull everything we need from qi into this scope + using boost::spirit::repository::qi::kwd; + using boost::spirit::qi::inf; + using boost::spirit::ascii::space_type; + using boost::spirit::ascii::alnum; + using boost::spirit::qi::int_; + using boost::spirit::qi::rule; + using boost::spirit::qi::lit; + using boost::spirit::qi::attr; + using boost::spirit::qi::lexeme; + using boost::spirit::qi::hold; + using boost::spirit::qi::ascii::space; + + //Rule declarations + rule<const char *, std::string(), space_type> parse_string; + rule<const char *, program_options(), space_type> kwd_rule; + + // A string parser + parse_string %= lexeme[*alnum]; + + namespace phx=boost::phoenix; + // kwd rule + kwd_rule %= + kwd("--include")[ parse_string ] + / kwd("--define")[ parse_string >> ((lit('=') > int_) | attr(1)) ] + / kwd("--output",0,1)[ parse_string ] + / hold [kwd("--source",1)[ parse_string ]] + ; + // + + using boost::spirit::qi::phrase_parse; + + // Let's check what that parser can do + program_options result; + + char const input[]="--include path1 --source file1 --define SYMBOL1=10 --include path2 --source file2"; + char const* f(input); + char const* l(f + strlen(f)); + if (phrase_parse(f, l, kwd_rule, space,result) && (f == l)) + std::cout << "ok" << std::endl; + else + std::cout << "fail" << std::endl; + + // Output the result to the console + std::cout<<result<<std::endl; +} + return 0; +} diff --git a/src/boost/libs/spirit/repository/example/qi/seek.cpp b/src/boost/libs/spirit/repository/example/qi/seek.cpp new file mode 100644 index 00000000..c33bc1f3 --- /dev/null +++ b/src/boost/libs/spirit/repository/example/qi/seek.cpp @@ -0,0 +1,48 @@ +/*////////////////////////////////////////////////////////////////////////////// + Copyright (c) 2011 Jamboree + + 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) +//////////////////////////////////////////////////////////////////////////////*/ + +// [ Jamboree Oct 27, 2011 ] new example. + + +#include <cstdlib> +#include <iostream> + +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/repository/include/qi_seek.hpp> + + +int main() +{ + //[reference_qi_seek_namespace + namespace qi = boost::spirit::qi; + namespace repo = boost::spirit::repository; + //] + + typedef std::string::const_iterator iterator; + + //[reference_qi_seek_vars + std::string str("/*C-style comment*/"); + iterator it = str.begin(); + iterator end = str.end(); + //] + + //[reference_qi_seek_parse + if (qi::parse(it, end, "/*" >> repo::qi::seek["*/"])) + { + std::cout << "-------------------------------- \n"; + std::cout << "Parsing succeeded.\n"; + std::cout << "---------------------------------\n"; + } + else + { + std::cout << "-------------------------------- \n"; + std::cout << "Unterminated /* comment.\n"; + std::cout << "-------------------------------- \n"; + }//] + + return EXIT_SUCCESS; +} diff --git a/src/boost/libs/spirit/repository/index.html b/src/boost/libs/spirit/repository/index.html new file mode 100644 index 00000000..1eb81150 --- /dev/null +++ b/src/boost/libs/spirit/repository/index.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> + <head> + <meta http-equiv="refresh" content="0; URL=doc/html/index.html"> + </head> + <body> + Automatic redirection failed, click this + <a href="doc/html/index.html">link</a> <hr> + <p>© Copyright Beman Dawes, 2001</p> + <p>Distributed under the Boost Software License, Version 1.0. (See + accompanying file <a href="../../LICENSE_1_0.txt"> + LICENSE_1_0.txt</a> or copy at + <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p> + </body> +</html>
\ No newline at end of file diff --git a/src/boost/libs/spirit/repository/meta/libraries.json b/src/boost/libs/spirit/repository/meta/libraries.json new file mode 100644 index 00000000..83d22efa --- /dev/null +++ b/src/boost/libs/spirit/repository/meta/libraries.json @@ -0,0 +1,18 @@ +{ + "key": "spirit/repository", + "name": "Spirit Repository", + "authors": [ + "Joel de Guzman", + "Hartmut Kaiser", + "Dan Nuffer" + ], + "description": "The Spirit repository is a community effort collecting different reusable components (primitives, directives, grammars, etc.) for Qi parsers and Karma generators.", + "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/repository/test/Jamfile b/src/boost/libs/spirit/repository/test/Jamfile new file mode 100644 index 00000000..18cf1774 --- /dev/null +++ b/src/boost/libs/spirit/repository/test/Jamfile @@ -0,0 +1,56 @@ +#============================================================================== +# Copyright (c) 2001-2009 Joel de Guzman +# Copyright (c) 2001-2009 Hartmut Kaiser +# Copyright (c) 2017-2019 Nikita Kniazev +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +#============================================================================== +project spirit_v2_repository/test + : requirements + <include>. + <c++-template-depth>300 + : + : + ; + +############################################################################### + +alias qi-pch : : <pch>on-spirit:<source>../../test/qi//pch ; +alias ka-pch : : <pch>on-spirit:<source>../../test/karma//pch ; +explicit qi-pch ka-pch ; + +############################################################################### + +import os ; + +local keywords_reqs ; + +if [ os.environ APPVEYOR ] +{ + # Workaround MSVC codegen bug. See #400 for the info. + keywords_reqs = <toolset>msvc-14.1:<inlining>off ; +} + +# bring in rules for testing +import testing ; + +{ + test-suite spirit_v2_repository : + + # run Qi repository tests + [ run qi-pch qi/advance.cpp : : : : qi_repo_advance ] + [ run qi-pch qi/confix.cpp : : : : qi_repo_confix ] + [ run qi-pch qi/distinct.cpp : : : : qi_repo_distinct ] + [ run qi-pch qi/subrule.cpp : : : : qi_repo_subrule ] + [ run qi-pch qi/keywords.cpp : : : $(keywords_reqs) : qi_repo_keywords ] + [ run qi-pch qi/seek.cpp : : : : qi_repo_seek ] + + # run Karma repository tests + [ run ka-pch karma/confix.cpp : : : : karma_repo_confix ] + [ run ka-pch karma/subrule.cpp : : : : karma_repo_subrule ] + + ; +} + diff --git a/src/boost/libs/spirit/repository/test/karma/confix.cpp b/src/boost/libs/spirit/repository/test/karma/confix.cpp new file mode 100644 index 00000000..adbe9903 --- /dev/null +++ b/src/boost/libs/spirit/repository/test/karma/confix.cpp @@ -0,0 +1,123 @@ +// Copyright (c) 2001-2010 Hartmut Kaiser +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/config/warning_disable.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/include/karma_auxiliary.hpp> +#include <boost/spirit/include/karma_char.hpp> +#include <boost/spirit/include/karma_string.hpp> +#include <boost/spirit/include/karma_generate.hpp> + +#include <boost/spirit/repository/include/karma_confix.hpp> + +#include <iostream> +#include "test.hpp" + +namespace html +{ + namespace spirit = boost::spirit; + namespace repo = boost::spirit::repository; + + /////////////////////////////////////////////////////////////////////////////// + // define a HTML tag helper generator + namespace traits + { + template <typename Prefix, typename Suffix = Prefix> + struct confix_spec + : spirit::result_of::terminal<repo::tag::confix(Prefix, Suffix)> + {}; + } + + template <typename Prefix, typename Suffix> + inline typename traits::confix_spec<Prefix, Suffix>::type + confix_spec(Prefix const& prefix, Suffix const& suffix) + { + return repo::confix(prefix, suffix); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Char, typename Traits, typename Allocator> + inline typename traits::confix_spec< + std::basic_string<Char, Traits, Allocator> + >::type + tag (std::basic_string<Char, Traits, Allocator> const& tagname) + { + typedef std::basic_string<Char, Traits, Allocator> string_type; + return confix_spec(string_type("<") + tagname + ">" + , string_type("</") + tagname + ">"); + } + + inline traits::confix_spec<std::string>::type + tag (char const* tagname) + { + return tag(std::string(tagname)); + } + + /////////////////////////////////////////////////////////////////////////// + typedef traits::confix_spec<std::string>::type html_tag_type; + + html_tag_type const ol = tag("ol"); +} + +/////////////////////////////////////////////////////////////////////////////// +int main() +{ + using namespace spirit_test; + using namespace boost::spirit; + using namespace boost::spirit::repository; + + { + using namespace boost::spirit::ascii; + + BOOST_TEST((test("<tag>a</tag>", + confix("<tag>", "</tag>")[char_('a')]))); + BOOST_TEST((test("<tag>a</tag>", + confix("<tag>", "</tag>")[char_], 'a'))); + BOOST_TEST((test("// some C++ comment\n", + confix(string("//"), eol)[" some C++ comment"]))); + BOOST_TEST((test("// some C++ comment\n", + confix(string("//"), eol)[string], " some C++ comment"))); + + BOOST_TEST((test("<ol>some text</ol>", html::ol["some text"]))); + BOOST_TEST((test("<ol>some text</ol>", html::ol[string], "some text"))); + } + + { + using namespace boost::spirit::standard_wide; + + BOOST_TEST((test(L"<tag>a</tag>", + confix(L"<tag>", L"</tag>")[char_(L'a')]))); + BOOST_TEST((test(L"// some C++ comment\n", + confix(string(L"//"), eol)[L" some C++ comment"]))); + + BOOST_TEST((test(L"<ol>some text</ol>", html::ol[L"some text"]))); + } + + { + using namespace boost::spirit::ascii; + + BOOST_TEST((test_delimited("<tag> a </tag> ", + confix("<tag>", "</tag>")[char_('a')], space))); + BOOST_TEST((test_delimited("// some C++ comment \n ", + confix(string("//"), eol)["some C++ comment"], space))); + + BOOST_TEST((test_delimited("<ol> some text </ol> ", + html::ol["some text"], space))); + } + + { + using namespace boost::spirit::standard_wide; + + BOOST_TEST((test_delimited(L"<tag> a </tag> ", + confix(L"<tag>", L"</tag>")[char_(L'a')], space))); + BOOST_TEST((test_delimited(L"// some C++ comment \n ", + confix(string(L"//"), eol)[L"some C++ comment"], space))); + + BOOST_TEST((test_delimited(L"<ol> some text </ol> ", + html::ol[L"some text"], space))); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/repository/test/karma/subrule.cpp b/src/boost/libs/spirit/repository/test/karma/subrule.cpp new file mode 100644 index 00000000..dd6bdabe --- /dev/null +++ b/src/boost/libs/spirit/repository/test/karma/subrule.cpp @@ -0,0 +1,186 @@ +// Copyright (c) 2001-2010 Hartmut Kaiser +// Copyright (c) 2009 Francois Barel +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/config/warning_disable.hpp> +#include <boost/detail/lightweight_test.hpp> + +#include <boost/spirit/include/karma_operator.hpp> +#include <boost/spirit/include/karma_char.hpp> +#include <boost/spirit/include/karma_auxiliary.hpp> +#include <boost/spirit/include/karma_string.hpp> +#include <boost/spirit/include/karma_numeric.hpp> +#include <boost/spirit/include/karma_nonterminal.hpp> +#include <boost/spirit/include/karma_action.hpp> +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> +#include <boost/spirit/include/phoenix_statement.hpp> +#include <boost/spirit/include/phoenix_fusion.hpp> + +#include <boost/spirit/repository/include/karma_subrule.hpp> + +#include "test.hpp" + +using namespace spirit_test; + +/////////////////////////////////////////////////////////////////////////////// +int main() +{ + using namespace boost; + using namespace boost::spirit; + using namespace boost::spirit::karma; +// using namespace boost::spirit::ascii; + using boost::spirit::repository::karma::subrule; + + typedef spirit_test::output_iterator<char>::type outiter_type; + + // basic tests + { + rule<outiter_type> start; + subrule<0> sr; + + start = ( + sr = char_[_1 = 'a'] << int_[_1 = 10] << double_[_1 = 12.4] + ); + BOOST_TEST(test("a1012.4", start)); + + BOOST_TEST(test("a1012.4", ( + sr = (char_ << int_ << double_)[_1 = 'a', _2 = 10, _3 = 12.4] + ))); + + subrule<1> a; + subrule<2> b; + subrule<3> c; + + start = ( + sr = a << b << c + , a = char_[_1 = 'a'] + , b = int_[_1 = 10] + , c = double_[_1 = 12.4] + ); + BOOST_TEST(test("a1012.4", start)); + } + + // basic tests with delimiter + { + rule<outiter_type, space_type> start; + subrule<0> sr; + + start = ( + sr = char_[_1 = 'a'] << int_[_1 = 10] << double_[_1 = 12.4] + ); + BOOST_TEST(test_delimited("a 10 12.4 ", start, space)); + + BOOST_TEST(test_delimited("a 10 12.4 ", ( + sr = (char_ << int_ << double_)[_1 = 'a', _2 = 10, _3 = 12.4] + ), space)); + + subrule<1> a; + subrule<2> b; + subrule<3> c; + + start = ( + sr = a << b << c + , a = char_[_1 = 'a'] + , b = int_[_1 = 10] + , c = double_[_1 = 12.4] + ); + BOOST_TEST(test_delimited("a 10 12.4 ", start, space)); + } + + // basic tests involving a direct parameter + { + typedef variant<char, int, double> var_type; + + rule<outiter_type, var_type()> start; + subrule<0, var_type()> sr; + + start = ( + sr = (char_ | int_ | double_)[_1 = _r0] + )[_1 = _val]; + + var_type v ('a'); + BOOST_TEST(test("a", start, v)); + v = 10; + BOOST_TEST(test("10", start, v)); + v = 12.4; + BOOST_TEST(test("12.4", start, v)); + } + + { + typedef variant<char, int, double> var_type; + + rule<outiter_type, space_type, var_type()> start; + subrule<0, var_type()> sr; + + start %= ( + sr = (char_ | int_ | double_)[_1 = _r0] + ); + + var_type v ('a'); + BOOST_TEST(test_delimited("a ", start, v, space)); + v = 10; + BOOST_TEST(test_delimited("10 ", start, v, space)); + v = 12.4; + BOOST_TEST(test_delimited("12.4 ", start, v, space)); + } + + { + rule<outiter_type, void(char, int, double)> start; + subrule<0, void(char, int, double)> sr; + + start = ( + sr = char_[_1 = _r1] << int_[_1 = _r2] << double_[_1 = _r3] + )(_r1, _r2, _r3); + BOOST_TEST(test("a1012.4", start('a', 10, 12.4))); + + BOOST_TEST(test("a1012.4", ( + sr = (char_ << int_ << double_)[_1 = _r1, _2 = _r2, _3 = _r3] + )('a', 10, 12.4))); + + subrule<1, void(char, int, double)> entry; + subrule<2, void(char)> a; + subrule<3, void(int)> b; + subrule<4, void(double)> c; + + start = ( + entry = a(_r1) << b(_r2) << c(_r3) + , a = char_[_1 = _r1] + , b = int_[_1 = _r1] + , c = double_[_1 = _r1] + )(_r1, _r2, _r3); + BOOST_TEST(test("a1012.4", start('a', 10, 12.4))); + } + + { + rule<outiter_type, space_type, void(char, int, double)> start; + subrule<0, void(char, int, double)> sr; + + start = ( + sr = char_[_1 = _r1] << int_[_1 = _r2] << double_[_1 = _r3] + )(_r1, _r2, _r3); + BOOST_TEST(test_delimited("a 10 12.4 ", start('a', 10, 12.4), space)); + + BOOST_TEST(test_delimited("a 10 12.4 ", ( + sr = (char_ << int_ << double_)[_1 = _r1, _2 = _r2, _3 = _r3] + )('a', 10, 12.4), space)); + + subrule<1, void(char, int, double)> entry; + subrule<2, void(char)> a; + subrule<3, void(int)> b; + subrule<4, void(double)> c; + + start = ( + entry = a(_r1) << b(_r2) << c(_r3) + , a = char_[_1 = _r1] + , b = int_[_1 = _r1] + , c = double_[_1 = _r1] + )(_r1, _r2, _r3); + BOOST_TEST(test_delimited("a 10 12.4 ", start('a', 10, 12.4), space)); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/repository/test/karma/test.hpp b/src/boost/libs/spirit/repository/test/karma/test.hpp new file mode 100644 index 00000000..70b89ce5 --- /dev/null +++ b/src/boost/libs/spirit/repository/test/karma/test.hpp @@ -0,0 +1,297 @@ +// Copyright (c) 2001-2010 Hartmut Kaiser +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_SPIRIT_KARMA_TEST_FEB_23_2007_1221PM) +#define BOOST_SPIRIT_KARMA_TEST_FEB_23_2007_1221PM + +#include <cstring> +#include <string> +#include <iterator> +#include <iostream> +#include <typeinfo> + +#include <boost/spirit/include/karma_generate.hpp> +#include <boost/spirit/include/karma_what.hpp> + +namespace spirit_test +{ + /////////////////////////////////////////////////////////////////////////// + struct display_type + { + template<typename T> + void operator()(T const &) const + { + std::cout << typeid(T).name() << std::endl; + } + + template<typename T> + static void print() + { + std::cout << typeid(T).name() << std::endl; + } + }; + + display_type const display = {}; + + /////////////////////////////////////////////////////////////////////////// + template <typename Char> + struct output_iterator + { + typedef std::basic_string<Char> string_type; + typedef std::back_insert_iterator<string_type> type; + }; + + /////////////////////////////////////////////////////////////////////////// + template <typename Char, typename T> + void print_if_failed(char const* func, bool result + , std::basic_string<Char> const& generated, T const& expected) + { + if (!result) + std::cerr << "in " << func << ": result is false" << std::endl; + else if (generated != expected) + std::cerr << "in " << func << ": generated \"" + << std::string(generated.begin(), generated.end()) + << "\"" << std::endl; + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Char, typename Generator> + inline bool test(Char const *expected, Generator const& g) + { + namespace karma = boost::spirit::karma; + typedef std::basic_string<Char> string_type; + + // we don't care about the result of the "what" function. + // we only care that all generators have it: + karma::what(g); + + string_type generated; + std::back_insert_iterator<string_type> outit(generated); + bool result = karma::generate(outit, g); + + print_if_failed("test", result, generated, expected); + return result && generated == expected; + } + + template <typename Char, typename Generator> + inline bool test(std::basic_string<Char> const& expected, Generator const& g) + { + namespace karma = boost::spirit::karma; + typedef std::basic_string<Char> string_type; + + // we don't care about the result of the "what" function. + // we only care that all generators have it: + karma::what(g); + + string_type generated; + std::back_insert_iterator<string_type> outit(generated); + bool result = karma::generate(outit, g); + + print_if_failed("test", result, generated, expected); + return result && generated == expected; + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Char, typename Generator, typename Attribute> + inline bool test(Char const *expected, Generator const& g, + Attribute const &attr) + { + namespace karma = boost::spirit::karma; + typedef std::basic_string<Char> string_type; + + // we don't care about the result of the "what" function. + // we only care that all generators have it: + karma::what(g); + + string_type generated; + std::back_insert_iterator<string_type> outit(generated); + bool result = karma::generate(outit, g, attr); + + print_if_failed("test", result, generated, expected); + return result && generated == expected; + } + + template <typename Char, typename Generator, typename Attribute> + inline bool test(std::basic_string<Char> const& expected, Generator const& g, + Attribute const &attr) + { + namespace karma = boost::spirit::karma; + typedef std::basic_string<Char> string_type; + + // we don't care about the result of the "what" function. + // we only care that all generators have it: + karma::what(g); + + string_type generated; + std::back_insert_iterator<string_type> outit(generated); + bool result = karma::generate(outit, g, attr); + + print_if_failed("test", result, generated, expected); + return result && generated == expected; + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Char, typename Generator, typename Delimiter> + inline bool test_delimited(Char const *expected, Generator const& g, + Delimiter const& d) + { + namespace karma = boost::spirit::karma; + typedef std::basic_string<Char> string_type; + + // we don't care about the result of the "what" function. + // we only care that all generators have it: + karma::what(g); + + string_type generated; + std::back_insert_iterator<string_type> outit(generated); + bool result = karma::generate_delimited(outit, g, d); + + print_if_failed("test_delimited", result, generated, expected); + return result && generated == expected; + } + + template <typename Char, typename Generator, typename Delimiter> + inline bool test_delimited(std::basic_string<Char> const& expected, + Generator const& g, Delimiter const& d) + { + namespace karma = boost::spirit::karma; + typedef std::basic_string<Char> string_type; + + // we don't care about the result of the "what" function. + // we only care that all generators have it: + karma::what(g); + + string_type generated; + std::back_insert_iterator<string_type> outit(generated); + bool result = karma::generate_delimited(outit, g, d); + + print_if_failed("test_delimited", result, generated, expected); + return result && generated == expected; + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Char, typename Generator, typename Attribute, + typename Delimiter> + inline bool test_delimited(Char const *expected, Generator const& g, + Attribute const &attr, Delimiter const& d) + { + namespace karma = boost::spirit::karma; + typedef std::basic_string<Char> string_type; + + // we don't care about the result of the "what" function. + // we only care that all generators have it: + karma::what(g); + + string_type generated; + std::back_insert_iterator<string_type> outit(generated); + bool result = karma::generate_delimited(outit, g, d, attr); + + print_if_failed("test_delimited", result, generated, expected); + return result && generated == expected; + } + + template <typename Char, typename Generator, typename Attribute, + typename Delimiter> + inline bool test_delimited(std::basic_string<Char> const& expected, + Generator const& g, Attribute const &attr, Delimiter const& d) + { + namespace karma = boost::spirit::karma; + typedef std::basic_string<Char> string_type; + + // we don't care about the result of the "what" function. + // we only care that all generators have it: + karma::what(g); + + string_type generated; + std::back_insert_iterator<string_type> outit(generated); + bool result = karma::generate_delimited(outit, g, d, attr); + + print_if_failed("test_delimited", result, generated, expected); + return result && generated == expected; + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Generator> + inline bool + binary_test(char const *expected, std::size_t size, + Generator const& g) + { + namespace karma = boost::spirit::karma; + typedef std::basic_string<char> string_type; + + // we don't care about the result of the "what" function. + // we only care that all generators have it: + karma::what(g); + + string_type generated; + std::back_insert_iterator<string_type> outit(generated); + bool result = karma::generate(outit, g); + + return result && !std::memcmp(generated.c_str(), expected, size); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Generator, typename Attribute> + inline bool + binary_test(char const *expected, std::size_t size, + Generator const& g, Attribute const &attr) + { + namespace karma = boost::spirit::karma; + typedef std::basic_string<char> string_type; + + // we don't care about the result of the "what" function. + // we only care that all generators have it: + karma::what(g); + + string_type generated; + std::back_insert_iterator<string_type> outit(generated); + bool result = karma::generate(outit, g, attr); + + return result && !std::memcmp(generated.c_str(), expected, size); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Generator, typename Delimiter> + inline bool + binary_test_delimited(char const *expected, std::size_t size, + Generator const& g, Delimiter const& d) + { + namespace karma = boost::spirit::karma; + typedef std::basic_string<char> string_type; + + // we don't care about the result of the "what" function. + // we only care that all generators have it: + karma::what(g); + + string_type generated; + std::back_insert_iterator<string_type> outit(generated); + bool result = karma::generate_delimited(outit, g, d); + + return result && !std::memcmp(generated.c_str(), expected, size); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename Generator, typename Attribute, typename Delimiter> + inline bool + binary_test_delimited(char const *expected, std::size_t size, + Generator const& g, Attribute const &attr, Delimiter const& d) + { + namespace karma = boost::spirit::karma; + typedef std::basic_string<char> string_type; + + // we don't care about the result of the "what" function. + // we only care that all generators have it: + karma::what(g); + + string_type generated; + std::back_insert_iterator<string_type> outit(generated); + bool result = karma::generate_delimited(outit, g, d, attr); + + return result && !std::memcmp(generated.c_str(), expected, size); + } + +} // namespace spirit_test + +#endif // !BOOST_SPIRIT_KARMA_TEST_FEB_23_2007_1221PM diff --git a/src/boost/libs/spirit/repository/test/qi/advance.cpp b/src/boost/libs/spirit/repository/test/qi/advance.cpp new file mode 100644 index 00000000..160ac55f --- /dev/null +++ b/src/boost/libs/spirit/repository/test/qi/advance.cpp @@ -0,0 +1,111 @@ +// Copyright (c) 2001-2010 Hartmut Kaiser +// Copyright (c) 2001-2010 Joel de Guzman +// Copyright (c) 2011 Aaron Graham +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/detail/lightweight_test.hpp> + +#include <boost/spirit/include/qi_action.hpp> +#include <boost/spirit/include/qi_auxiliary.hpp> +#include <boost/spirit/include/qi_binary.hpp> +#include <boost/spirit/include/qi_char.hpp> +#include <boost/spirit/include/qi_directive.hpp> +#include <boost/spirit/include/qi_nonterminal.hpp> +#include <boost/spirit/include/qi_numeric.hpp> +#include <boost/spirit/include/qi_operator.hpp> +#include <boost/spirit/include/qi_string.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> + +#include <boost/spirit/repository/include/qi_advance.hpp> + +#include <boost/assign/std/list.hpp> +#include "test.hpp" + +namespace spirit_test +{ + template <typename Container, typename Parser> + bool test_c(Container const& in, Parser const& p, bool full_match = true) + { + // we don't care about the results of the "what" function. + // we only care that all parsers have it: + boost::spirit::qi::what(p); + + typename Container::const_iterator first = in.begin(); + typename Container::const_iterator const last = in.end(); + return boost::spirit::qi::parse(first, last, p) + && (!full_match || (first == last)); + } +} + +int main() +{ + using spirit_test::test; + using spirit_test::test_c; + + using namespace boost::spirit::qi::labels; + using boost::spirit::qi::locals; + using boost::spirit::qi::rule; + using boost::spirit::qi::uint_; + using boost::spirit::qi::byte_; + + using namespace boost::assign; + using boost::spirit::repository::qi::advance; + + { // test basic functionality with random-access iterators + rule<char const*> start; + + start = 'a' >> advance(3) >> "bc"; + BOOST_TEST(test("a123bc", start)); + + start = (advance(3) | 'q') >> 'i'; + BOOST_TEST(test("qi", start)); + + start = advance(-1); + BOOST_TEST(!test("0", start)); + + start = advance(-1) | "qi"; + BOOST_TEST(test("qi", start)); + + start = advance(0) >> "abc" >> advance(10) >> "nopq" >> advance(0) + >> advance(8) >> 'z'; + BOOST_TEST(test("abcdefghijklmnopqrstuvwxyz", start)); + } + + { // test locals + rule<char const*, locals<unsigned> > start; + + start = byte_ [_a = _1] >> advance(_a) >> "345"; + BOOST_TEST(test("\x02""12345", start)); + BOOST_TEST(!test("\x60""345", start)); + } + + { // test basic functionality with bidirectional iterators + rule<std::list<char>::const_iterator, locals<int> > start; + std::list<char> list; + + list.clear(); + list += 1,2,'a','b','c'; + start = byte_ [_a = _1] >> advance(_a) >> "abc"; + BOOST_TEST(test_c(list, start)); + + list.clear(); + list += 3,'q','i'; + start = byte_ [_a = _1] >> advance(_a); + BOOST_TEST(!test_c(list, start)); + + start = byte_ [_a = _1] >> (advance(_a) | "qi"); + BOOST_TEST(test_c(list, start)); + + list.clear(); + list += 'a','b','c','d','e','f','g','h','i','j','k','l','m'; + list += 'n','o','p','q','r','s','t','u','v','w','x','y','z'; + start = advance(0) >> "abc" >> advance(10) >> "nopq" >> advance(0) + >> advance(8) >> 'z'; + BOOST_TEST(test_c(list, start)); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/repository/test/qi/confix.cpp b/src/boost/libs/spirit/repository/test/qi/confix.cpp new file mode 100644 index 00000000..e045026c --- /dev/null +++ b/src/boost/libs/spirit/repository/test/qi/confix.cpp @@ -0,0 +1,147 @@ +/*============================================================================= + Copyright (c) 2009 Chris Hoeppler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> + +#include <boost/spirit/include/qi_action.hpp> +#include <boost/spirit/include/qi_auxiliary.hpp> +#include <boost/spirit/include/qi_char.hpp> +#include <boost/spirit/include/qi_directive.hpp> +#include <boost/spirit/include/qi_nonterminal.hpp> +#include <boost/spirit/include/qi_numeric.hpp> +#include <boost/spirit/include/qi_operator.hpp> +#include <boost/spirit/include/qi_string.hpp> +#include <boost/spirit/include/phoenix_bind.hpp> +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_object.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> + +#include <boost/spirit/repository/include/qi_confix.hpp> + +#include <string> +#include "test.hpp" + +namespace comment { + namespace spirit = boost::spirit; + namespace repo = boost::spirit::repository; + + // Define a metafunction allowing to compute the type + // of the confix() construct + template <typename Prefix, typename Suffix = Prefix> + struct confix_spec_traits + { + typedef typename spirit::result_of::terminal< + repo::tag::confix(Prefix, Suffix) + >::type type; + }; + + template <typename Prefix, typename Suffix> + inline typename confix_spec_traits<Prefix, Suffix>::type + confix_spec(Prefix const& prefix, Suffix const& suffix) + { + return repo::confix(prefix, suffix); + } + + inline confix_spec_traits<std::string>::type + confix_spec(const char* prefix, const char* suffix) + { + return repo::confix(std::string(prefix), std::string(suffix)); + } + confix_spec_traits<std::string>::type const c_comment = confix_spec("/*", "*/"); + confix_spec_traits<std::string>::type const cpp_comment = confix_spec("//", "\n"); +} + +int main() +{ + using spirit_test::test_attr; + using spirit_test::test; + + using namespace boost::spirit::ascii; + using namespace boost::spirit::qi::labels; + using boost::spirit::qi::locals; + using boost::spirit::qi::rule; + using boost::spirit::qi::debug; + + namespace phx = boost::phoenix; + namespace repo = boost::spirit::repository; + + { // basic tests + + rule<char const*> start; + + start = repo::confix('a', 'c')['b']; + BOOST_TEST(test("abc", start)); + + start = repo::confix('a', 'c')['b'] | "abd"; + BOOST_TEST(test("abd", start)); + + start = repo::confix("/*", "*/")[*(alpha - "*/")]; + BOOST_TEST(test("/*aaaabababaaabbb*/", start)); + + start = repo::confix(char_('/') >> '*', '*' >> char_('/'))[*alpha - "*/"]; + BOOST_TEST(test("/*aaaabababaaabba*/", start)); + + start = comment::c_comment[*(alpha - "*/")]; + BOOST_TEST(test("/*aaaabababaaabbb*/", start)); + + // ignore the skipper! + BOOST_TEST(!test("/* aaaabababaaabba*/", start, space)); + } + + { // basic tests w/ skipper + + rule<char const*, space_type> start; + + start = repo::confix('a', 'c')['b']; + BOOST_TEST(test(" a b c ", start, space)); + + start = repo::confix(char_('/') >> '*', '*' >> char_('/'))[*alpha - "*/"]; + BOOST_TEST(test(" / *a b a b a b a a a b b b * / ", start, space)); + } + + { // context tests + char ch; + rule<char const*, char()> a; + a = repo::confix("/*", "*/")[alpha][_val = _1]; + + BOOST_TEST(test("/*x*/", a[phx::ref(ch) = _1])); + BOOST_TEST(ch == 'x'); + + a %= repo::confix("/*", "*/")[alpha]; + BOOST_TEST(test_attr("/*z*/", a, ch)); // attribute is given. + BOOST_TEST(ch == 'z'); + } + + { // rules test + rule<char const*> a, b, c, start; + + a = 'a'; + b = 'b'; + c = 'c'; + + a.name("a"); + b.name("b"); + c.name("c"); + start.name("start"); + + debug(a); + debug(b); + debug(c); + debug(start); + + start = repo::confix(a.alias(), c.alias())[b]; + BOOST_TEST(test("abc", start)); + } + + { // modifiers test + rule<char const*> start; + start = no_case[repo::confix("_A_", "_Z_")["heLLo"]]; + BOOST_TEST(test("_a_hello_z_", start)); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/repository/test/qi/distinct.cpp b/src/boost/libs/spirit/repository/test/qi/distinct.cpp new file mode 100644 index 00000000..7ba4c521 --- /dev/null +++ b/src/boost/libs/spirit/repository/test/qi/distinct.cpp @@ -0,0 +1,101 @@ +// Copyright (c) 2001-2010 Hartmut Kaiser +// Copyright (c) 2001-2010 Joel de Guzman +// Copyright (c) 2003 Vaclav Vesely +// +// 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/mpl/print.hpp> +#include <boost/config/warning_disable.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/include/qi_char.hpp> +#include <boost/spirit/include/qi_string.hpp> +#include <boost/spirit/include/qi_nonterminal.hpp> +#include <boost/spirit/include/qi_numeric.hpp> +#include <boost/spirit/include/qi_action.hpp> +#include <boost/spirit/include/qi_operator.hpp> + +#include <boost/spirit/repository/include/qi_distinct.hpp> + +#include <iostream> +#include "test.hpp" + +using namespace boost; + +/////////////////////////////////////////////////////////////////////////////// +namespace distinct +{ + //[qi_distinct_encapsulation + namespace spirit = boost::spirit; + namespace ascii = boost::spirit::ascii; + namespace repo = boost::spirit::repository; + + // Define metafunctions allowing to compute the type of the distinct() + // and ascii::char_() constructs + namespace traits + { + // Metafunction allowing to get the type of any repository::distinct(...) + // construct + template <typename Tail> + struct distinct_spec + : spirit::result_of::terminal<repo::tag::distinct(Tail)> + {}; + + // Metafunction allowing to get the type of any ascii::char_(...) construct + template <typename String> + struct char_spec + : spirit::result_of::terminal<spirit::tag::ascii::char_(String)> + {}; + } + + // Define a helper function allowing to create a distinct() construct from + // an arbitrary tail parser + template <typename Tail> + inline typename traits::distinct_spec<Tail>::type + distinct_spec(Tail const& tail) + { + return repo::distinct(tail); + } + + // Define a helper function allowing to create a ascii::char_() construct + // from an arbitrary string representation + template <typename String> + inline typename traits::char_spec<String>::type + char_spec(String const& str) + { + return ascii::char_(str); + } + + // the following constructs the type of a distinct_spec holding a + // charset("0-9a-zA-Z_") as its tail parser + typedef traits::char_spec<std::string>::type charset_tag_type; + typedef traits::distinct_spec<charset_tag_type>::type keyword_tag_type; + + // Define a new Qi 'keyword' directive usable as a shortcut for a + // repository::distinct(char_(std::string("0-9a-zA-Z_"))) + std::string const keyword_spec("0-9a-zA-Z_"); + keyword_tag_type const keyword = distinct_spec(char_spec(keyword_spec)); + //] +} + +/////////////////////////////////////////////////////////////////////////////// +int main() +{ + using namespace spirit_test; + using namespace boost::spirit; + + { + using namespace boost::spirit::ascii; + + qi::rule<char const*, space_type> r; + r = distinct::keyword["description"] >> -lit(':') >> distinct::keyword["ident"]; + + BOOST_TEST(test("description ident", r, space)); + BOOST_TEST(test("description:ident", r, space)); + BOOST_TEST(test("description: ident", r, space)); + BOOST_TEST(!test("descriptionident", r, space)); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/repository/test/qi/keywords.cpp b/src/boost/libs/spirit/repository/test/qi/keywords.cpp new file mode 100644 index 00000000..eb224d65 --- /dev/null +++ b/src/boost/libs/spirit/repository/test/qi/keywords.cpp @@ -0,0 +1,269 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2011 Thomas Bernard + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#include <string> +#include <vector> + +#include <boost/detail/lightweight_test.hpp> +#include <boost/utility/enable_if.hpp> + +#include <boost/spirit/include/qi_operator.hpp> +#include <boost/spirit/include/qi_char.hpp> +#include <boost/spirit/include/qi_string.hpp> +#include <boost/spirit/include/qi_numeric.hpp> +#include <boost/spirit/include/qi_directive.hpp> +#include <boost/spirit/include/qi_action.hpp> +#include <boost/spirit/include/qi_nonterminal.hpp> +#include <boost/spirit/include/support_argument.hpp> +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> +#include <boost/spirit/include/phoenix_container.hpp> +#include <boost/spirit/repository/include/qi_kwd.hpp> +#include <boost/spirit/repository/include/qi_keywords.hpp> + +#include <string> +#include <iostream> +#include "test.hpp" + +struct x_attr +{ + +}; + +namespace boost { namespace spirit { namespace traits +{ + + + template <> + struct container_value<x_attr> + { + typedef char type; // value type of container + }; + + + template <> + struct push_back_container<x_attr, char> + { + static bool call(x_attr& /*c*/, char /*val*/) + { + // push back value type into container + return true; + } + }; +}}} + +int +main() +{ + using spirit_test::test_attr; + using spirit_test::test; + using namespace boost::spirit; + using namespace boost::spirit::ascii; + using boost::spirit::repository::kwd; + using boost::spirit::repository::ikwd; + using boost::spirit::repository::dkwd; + using boost::spirit::qi::inf; + using boost::spirit::qi::omit; + using boost::spirit::qi::int_; + using boost::spirit::qi::lit; + using boost::spirit::qi::_1; + using boost::spirit::qi::lexeme; + + + { + + // no constraints + boost::fusion::vector<char,char,int> data; + BOOST_TEST( test_attr("c=1 a=a", kwd("a")[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], data, space)); + BOOST_TEST( boost::fusion::at_c<0>(data) == 'a' ); + BOOST_TEST( boost::fusion::at_c<1>(data) == 0 ); + BOOST_TEST( boost::fusion::at_c<2>(data) == 1 ); + + BOOST_TEST( test("a=a c=1", kwd("a")[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space)); + + BOOST_TEST( test("", kwd("a")[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space)); + + // Exact + BOOST_TEST(test("a=a b=b c=1", kwd("a",1)[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space)); + BOOST_TEST(test("a=a b=c b=e c=1", kwd("a",1)[ '=' > char_] / kwd("b",2)[ '=' > char_] / kwd("c")['=' > int_], space)); + BOOST_TEST(!test("b=c b=e c=1", kwd("a",1)[ '=' > char_] / kwd("b",2)[ '=' > char_] / kwd("c")['=' > int_], space)); + + // Min - Max + BOOST_TEST(test("a=f b=c b=e c=1", kwd("a",1,2)[ '=' > char_] / kwd("b",0,2)[ '=' > char_] / kwd("c",1,2)['=' > int_], space)); + BOOST_TEST(!test("b=c b=e c=1", kwd("a",1,2)[ '=' > char_] / kwd("b",0,1)[ '=' > char_] / kwd("c",1,2)['=' > int_], space)); + BOOST_TEST(test("a=g a=f b=c b=e c=1", kwd("a",1,2)[ '=' > char_] / kwd("b",0,2)[ '=' > char_] / kwd("c",1,2)['=' > int_], space)); + BOOST_TEST(!test("a=f a=e b=c b=e a=p c=1", kwd("a",1,2)[ '=' > char_] / kwd("b",0,1)[ '=' > char_] / kwd("c",1,2)['=' > int_], space)); + + // Min - inf + BOOST_TEST(test("a=f b=c b=e c=1", kwd("a",1,inf)[ '=' > char_] / kwd("b",0,inf)[ '=' > char_] / kwd("c",1,inf)['=' > int_], space )); + BOOST_TEST(!test("b=c b=e c=1", kwd("a",1,inf)[ '=' > char_] / kwd("b",0,inf)[ '=' > char_] / kwd("c",1,inf)['=' > int_], space )); + BOOST_TEST(test("a=f a=f a=g b=c b=e c=1 a=e", kwd("a",1,inf)[ '=' > char_] / kwd("b",0,inf)[ '=' > char_] / kwd("c",1,inf)['=' > int_], space )); + } + + { // Single keyword, empty string + BOOST_TEST(test(" ", kwd("aad")[char_],space)); + // Single keyword + BOOST_TEST(test("aad E ", kwd("aad")[char_],space)); + // Single no case keyword + BOOST_TEST(test("AaD E ", ikwd("aad")[char_],space)); + + } + + { + // Vector container + boost::fusion::vector<std::vector<int>,std::vector<int>,std::vector<int> > data; + BOOST_TEST(test_attr(" a=1 b=2 b=5 c=3",kwd("a")[ '=' > int_] / kwd("b")[ '=' > int_] / kwd("c")['=' > int_] , data, space) + && (boost::fusion::at_c<0>(data).size()==1) + && (boost::fusion::at_c<0>(data)[0]==1) + + &&(boost::fusion::at_c<1>(data).size()==2) + &&(boost::fusion::at_c<1>(data)[0]==2) + &&(boost::fusion::at_c<1>(data)[1]==5) + + &&(boost::fusion::at_c<2>(data).size()==1) + &&(boost::fusion::at_c<2>(data)[0]==3) + ); + } + + { + // no_case test + BOOST_TEST( test("B=a c=1 a=E", no_case[kwd("a")[ "=E" ] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_]], space)); + BOOST_TEST( test("B=a c=1 a=e", no_case[kwd("a")[ "=E" ] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_]], space)); + BOOST_TEST( !test("B=a c=1 A=E", no_case[kwd("a")[ '=' > char_]] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space)); + BOOST_TEST( test("b=a c=1 A=E", no_case[kwd("a")[ '=' > char_]] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space)); + BOOST_TEST( !test("A=a c=1 a=E", kwd("a")[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space)); + BOOST_TEST( test("A=a c=1 a=E", ikwd("a")[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space)); + BOOST_TEST( !test("A=a C=1 a=E", ikwd("a")[ '=' > char_] / kwd("b")[ '=' > char_] / kwd("c")['=' > int_], space)); + } + + { + // iterator restoration + BOOST_TEST( test("a=a c=1 ba=d", (kwd("a")[ '=' > char_] / kwd("b")[ '=' > int_] / kwd("c")['=' > int_] ) > lit("ba=") > char_, space)); + BOOST_TEST( test("A=a c=1 ba=d", (ikwd("a")[ '=' > char_] / kwd("b")[ '=' > int_] / kwd("c")['=' > int_] ) > lit("ba=") > char_, space)); + } + + { // actions + namespace phx = boost::phoenix; + + std::vector<int> v; + BOOST_TEST(test("b=2 c=4", kwd("b")['=' > int_][phx::ref(v)=_1] / kwd("c")[ '=' > int_ ],space) && + v[0] == 2 ); + } + + + { + // no constraints + boost::fusion::vector<char,char,int> data; + BOOST_TEST( test_attr("c,1,2=1 2,b=a", kwd( char_ >> lit(',') >> int_ )[ '=' >> char_] / kwd(int_ >> lit(',') >> char_)[ '=' >> char_] / kwd(char_ >> lit(',') >> int_ >> lit(',') >> int_)['=' >> int_], data, space)); + BOOST_TEST( boost::fusion::at_c<0>(data) == 0 ); + BOOST_TEST( boost::fusion::at_c<1>(data) == 'a'); + BOOST_TEST( boost::fusion::at_c<2>(data) == 1 ); + + BOOST_TEST( test("2,b=a c,1,2=1", kwd( char_ >> ',' >> int_ )[ '=' >> char_] / kwd(int_ >> ',' >> char_)[ '=' >> char_] / kwd(char_ >> ',' >> int_ >> ',' >> int_)['=' >> int_], space)); + + BOOST_TEST( test("", kwd( char_ >> ',' >> int_ )[ '=' >> char_] / kwd(int_ >> ',' >> char_)[ '=' >> char_] / kwd(char_ >> ',' >> int_ >> ',' >> int_)['=' >> int_], space)); + + // Exact + BOOST_TEST(test("7a=a 5b=b 2c=1", kwd(int_ >> lit('a'),1)[ '=' >> char_] / kwd(int_ >> lit('b'))[ '=' >> char_] / kwd(int_ >> lit('c'))['=' >> int_], space)); + BOOST_TEST(test("7a=a 3b=d 5b=b 2c=1", kwd(int_ >> lit('a'),1)[ '=' >> char_] / kwd(int_ >> lit('b'),2)[ '=' >> char_] / kwd(int_ >>'c')['=' >> int_], space)); + BOOST_TEST(!test("7a=a 5b=b 2c=1", kwd(int_ >> lit('a'),1)[ '=' >> char_] / kwd(int_ >> lit('b'),2)[ '=' >> char_] / kwd(int_ >>'c')['=' >> int_], space)); + + // Min - Max + BOOST_TEST(test("6a=f 2b=c 3b=e 1c=1", kwd(int_ >> "a",1,2)[ '=' >> char_] / kwd(int_ >> "b",0,2)[ '=' >> char_] / kwd(int_ >> "c",1,2)['=' >> int_], space)); + BOOST_TEST(!test("1b=c 6b=e 2c=1", kwd(int_ >> "a",1,2)[ '=' >> char_] / kwd(int_ >> "b",0,1)[ '=' >> char_] / kwd(int_ >> "c",1,2)['=' >> int_], space)); + BOOST_TEST(test("4a=g 7a=f 2b=c 1b=e 4c=1", kwd(int_ >> "a",1,2)[ '=' >> char_] / kwd(int_ >> "b",0,2)[ '=' >> char_] / kwd(int_ >> "c",1,2)['=' >> int_], space)); + BOOST_TEST(!test("1a=f a=e 2b=c 5b=e 6a=p 67c=1", kwd(int_ >> "a",1,2)[ '=' >> char_] / kwd(int_ >> "b",0,1)[ '=' >> char_] / kwd(int_ >> "c",1,2)['=' >> int_], space)); + + // Min - inf + BOOST_TEST(test("41a=f 44b=c 12b=e 45c=1", kwd(int_ >> "a",1,inf)[ '=' >> char_] / kwd(int_ >> "b",0,inf)[ '=' >> char_] / kwd(int_ >> "c",1,inf)['=' >> int_], space )); + BOOST_TEST(!test("31b=c 55b=e 2c=1", kwd("a",1,inf)[ '=' >> char_] / kwd("b",0,inf)[ '=' >> char_] / kwd("c",1,inf)['=' >> int_], space )); + BOOST_TEST(test("12a=f 45a=f 12a=g 1b=c 7b=e 12c=1 6a=e", kwd(int_ >> "a",1,inf)[ '=' >> char_] / kwd(int_ >> "b",0,inf)[ '=' >> char_] / kwd(int_ >> "c",1,inf)['=' >> int_], space )); + + } + + { + + // Vector container + boost::fusion::vector<std::vector<int>,std::vector<int>,std::vector<int> > data; + BOOST_TEST(test_attr(" 41a=1 4b=2 12b=5 5c=3",kwd(int_ >> "a")[ '=' >> int_] / kwd(int_ >> "b")[ '=' >> int_] / kwd(int_ >> "c")['=' >> int_] , data, space) + && (boost::fusion::at_c<0>(data).size()==1) + && (boost::fusion::at_c<0>(data)[0]==1) + + &&(boost::fusion::at_c<1>(data).size()==2) + &&(boost::fusion::at_c<1>(data)[0]==2) + &&(boost::fusion::at_c<1>(data)[1]==5) + + &&(boost::fusion::at_c<2>(data).size()==1) + &&(boost::fusion::at_c<2>(data)[0]==3) + ); + + + + } + + { + // no_case test + BOOST_TEST( test("12B=a 5c=1 1a=E", no_case[kwd(int_ >> "a")[ "=E" ] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_]], space)); + BOOST_TEST( test("5B=a 2c=1 5a=e", no_case[kwd(int_ >> "a")[ "=E" ] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_]], space)); + BOOST_TEST( !test("1B=a 8c=1 1A=E", no_case[kwd(int_ >> "a")[ '=' >> char_]] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_], space)); + BOOST_TEST( test("2b=a 6c=1 5A=E", no_case[kwd(int_ >> "a")[ '=' >> char_]] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_], space)); + BOOST_TEST( !test("1A=a 5c=1 1a=E", kwd(int_ >> "a")[ '=' >> char_] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_], space)); + BOOST_TEST( test("A=a 23c=1 a=E", ikwd("a")[ '=' >> char_] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_], space)); + BOOST_TEST( !test("A=a 21C=1 a=E", ikwd("a")[ '=' >> char_] / kwd(int_ >> "b")[ '=' >> char_] / kwd(int_ >> "c")['=' >> int_], space)); + } + + { + // iterator restoration + BOOST_TEST( test("4a=a c4=1 ba=d", (kwd(int_ >> "a")[ '=' >> char_] / kwd("b" >> int_)[ '=' >> int_] / kwd("c" >> int_ )['=' >> int_] ) >> lit("ba=") >> char_, space)); + } + + { // actions + namespace phx = boost::phoenix; + + std::vector<int> v; + BOOST_TEST(test("b4=2 c1=4", kwd("b" >> int_)['=' >> int_][phx::ref(v)=_1] / kwd("c" >> int_)[ '=' >> int_ ],space) && + v[0] == 2 ); + } + + { + // complex keyword single test + int result=0; + + BOOST_TEST( test_attr("(a,1) = 3214", kwd( '(' >> char_ >> ',' >> int_ >> ')' )['=' >> int_], result, space) ); + BOOST_TEST(result==3214); + } + { + // Mixed complex keyword loop + boost::fusion::vector<int,int,int> data; + + BOOST_TEST( test_attr("(a,1) = 3214 b += 2 hello 10 (a,2)=31", kwd( '(' >> char_ >> ',' >> int_ >> ')' )['=' >> int_] / kwd("hello")[int_] / kwd("b")["+=" >> int_], data, space) ); + BOOST_TEST( boost::fusion::at_c<0>(data) == 31); + BOOST_TEST( boost::fusion::at_c<1>(data) == 10); + BOOST_TEST( boost::fusion::at_c<2>(data) == 2); + } + + // dkwd and idkwd + { + BOOST_TEST( test("a =a", dkwd("a")[ '=' > char_] , space)); + BOOST_TEST( !test("a=a", dkwd("a")[ '=' > char_] , space)); + BOOST_TEST(test("a =a b =b c=1", dkwd("a",1)[ '=' > char_] / dkwd("b",1,2)[ '=' > char_] / kwd("c")['=' > int_], space)); + BOOST_TEST(!test("a=a b=b c =1", dkwd("a",1)[ '=' > char_] / dkwd("b",1,2)[ '=' > char_] / kwd("c")['=' > int_], space)); + + BOOST_TEST(test("a =a b =b b =d c=1", dkwd("a",1,inf)[ '=' > char_] / dkwd("b",2,inf)[ '=' > char_] / kwd("c")['=' > int_], space)); + + } + + { // attribute customization + +// x_attr x; +// test_attr("a = b c = d", kwd("a")['=' > char_] / kwd("c")['=' > char_], x); + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/repository/test/qi/seek.cpp b/src/boost/libs/spirit/repository/test/qi/seek.cpp new file mode 100644 index 00000000..96183024 --- /dev/null +++ b/src/boost/libs/spirit/repository/test/qi/seek.cpp @@ -0,0 +1,101 @@ +/*============================================================================= + Copyright (c) 2011 Jamboree + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + + +#include <vector> + +#include <boost/config/warning_disable.hpp> +#include <boost/detail/lightweight_test.hpp> + +#include <boost/spirit/include/qi_parse.hpp> +#include <boost/spirit/include/qi_char.hpp> +#include <boost/spirit/include/qi_string.hpp> +#include <boost/spirit/include/qi_int.hpp> +#include <boost/spirit/include/qi_sequence.hpp> +#include <boost/spirit/include/qi_plus.hpp> +#include <boost/spirit/include/qi_eoi.hpp> +#include <boost/spirit/include/qi_action.hpp> + +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> + +#include <boost/spirit/repository/include/qi_seek.hpp> + +#include "test.hpp" + + +/////////////////////////////////////////////////////////////////////////////// +int main() +{ + using namespace spirit_test; + namespace qi = boost::spirit::qi; + namespace phx = boost::phoenix; + using boost::spirit::repository::qi::seek; + using boost::spirit::standard::space; + + // test eoi + { + using qi::eoi; + + BOOST_TEST(test("", seek[eoi])); + BOOST_TEST(test(" ", seek[eoi], space)); + BOOST_TEST(test("a", seek[eoi])); + BOOST_TEST(test(" a", seek[eoi], space)); + } + + // test literal finding + { + using qi::int_; + using qi::char_; + + int i = 0; + + BOOST_TEST( + test_attr("!@#$%^&*KEY:123", seek["KEY:"] >> int_, i) + && i == 123 + ); + } + + // test sequence finding + { + using qi::int_; + using qi::lit; + + int i = 0; + + BOOST_TEST( + test_attr("!@#$%^&* KEY : 123", seek[lit("KEY") >> ':'] >> int_, i, space) + && i == 123 + ); + } + + // test attr finding + { + using qi::int_; + + std::vector<int> v; + + BOOST_TEST( // expect partial match + test_attr("a06b78c3d", +seek[int_], v, false) + && v[0] == 6 && v[1] == 78 && v[2] == 3 + ); + } + + // test action + { + using phx::ref; + + bool b = false; + + BOOST_TEST( // expect partial match + test("abcdefg", seek["def"][ref(b) = true], false) + && b + ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/spirit/repository/test/qi/subrule.cpp b/src/boost/libs/spirit/repository/test/qi/subrule.cpp new file mode 100644 index 00000000..7eb5331f --- /dev/null +++ b/src/boost/libs/spirit/repository/test/qi/subrule.cpp @@ -0,0 +1,397 @@ +/*============================================================================= + Copyright (c) 2001-2010 Joel de Guzman + Copyright (c) 2009 Francois Barel + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#include <boost/detail/lightweight_test.hpp> +#include <boost/spirit/include/qi_operator.hpp> +#include <boost/spirit/include/qi_char.hpp> +#include <boost/spirit/include/qi_string.hpp> +#include <boost/spirit/include/qi_numeric.hpp> +#include <boost/spirit/include/qi_auxiliary.hpp> +#include <boost/spirit/include/qi_nonterminal.hpp> +#include <boost/spirit/include/qi_action.hpp> +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> +#include <boost/spirit/include/phoenix_object.hpp> +#include <boost/spirit/include/phoenix_bind.hpp> +#include <boost/fusion/include/std_pair.hpp> + +#include <boost/spirit/repository/include/qi_subrule.hpp> + +#include <string> +#include <cstring> +#include <iostream> +#include "test.hpp" + +int +main() +{ + using spirit_test::test_attr; + using spirit_test::test; + + using namespace boost::spirit::ascii; + using namespace boost::spirit::qi::labels; + using boost::spirit::qi::locals; + using boost::spirit::qi::rule; + using boost::spirit::qi::int_; + using boost::spirit::qi::fail; + using boost::spirit::qi::on_error; + using boost::spirit::qi::debug; + using boost::spirit::repository::qi::subrule; + + namespace phx = boost::phoenix; + + + { // basic tests + + subrule<99> entry; + subrule<42> a; + subrule<48> b; + subrule<16> c; + rule<char const*> start; + + entry.name("entry"); + a.name("a"); + b.name("b"); + c.name("c"); + start.name("start"); + +// debug(entry); +// debug(a); +// debug(b); +// debug(c); + debug(start); + + // subrules with no rule + BOOST_TEST(test("abcabcacb", ( + entry = *(a | b | c) + , a = 'a' + , b = 'b' + , c = 'c' + ))); + + // check subrule group behaves as a parser + BOOST_TEST(test("xabcabcacb", 'x' >> ( + entry = *(a | b | c) + , a = 'a' + , b = 'b' + , c = 'c' + ))); + + // subrules in a rule + start = ( + entry = *(a | b | c) + , a = 'a' + , b = 'b' + , c = 'c' + ); + BOOST_TEST(test("abcabcacb", start)); + + // subrule -> rule call + start = ( + entry = (a | b) >> (start | b) + , a = 'a' + , b = 'b' + ); + BOOST_TEST(test("aaaabababaaabbb", start)); + BOOST_TEST(test("aaaabababaaabba", start, false)); + + // subrule recursion + start = ( + entry = (a | b) >> (entry | b) + , a = 'a' + , b = 'b' + ); + BOOST_TEST(test("aaaabababaaabbb", start)); + BOOST_TEST(test("aaaabababaaabba", start, false)); + + // no-ops +#if defined(BOOST_CLANG) && defined(__has_warning) +# pragma clang diagnostic push +# if __has_warning("-Wself-assign-overloaded") +# pragma clang diagnostic ignored "-Wself-assign-overloaded" +# endif +#endif + a = a; +#if defined(BOOST_CLANG) && defined(__has_warning) +# pragma clang diagnostic pop +#endif + subrule<42> aa(a); + } + + { // basic tests w/ skipper, subrules declared const + + subrule<0> const entry("entry"); + subrule<1> const a("a"); + subrule<2> const b("b"); + subrule<3> const c("c"); + rule<char const*, space_type> start("start"); + +// debug(entry); +// debug(a); +// debug(b); +// debug(c); + debug(start); + + start = ( + entry = *(a | b | c) + , a = 'a' + , b = 'b' + , c = 'c' + ); + BOOST_TEST(test(" a b c a b c a c b ", start, space)); + + start = ( + entry = (a | b) >> (entry | b) + , a = 'a' + , b = 'b' + ); + BOOST_TEST(test(" a a a a b a b a b a a a b b b ", start, space)); + BOOST_TEST(test(" a a a a b a b a b a a a b b a ", start, space, false)); + + // no-ops +#if defined(BOOST_CLANG) && defined(__has_warning) +# pragma clang diagnostic push +# if __has_warning("-Wself-assign-overloaded") +# pragma clang diagnostic ignored "-Wself-assign-overloaded" +# endif +#endif + a = a; +#if defined(BOOST_CLANG) && defined(__has_warning) +# pragma clang diagnostic pop +#endif + subrule<1> aa(a); + } + + { // context tests + + char ch; + rule<char const*, char()> a; + subrule<0, char()> entry; + + a = (entry = alpha[_val = _1])[_val = _1]; + BOOST_TEST(test("x", a[phx::ref(ch) = _1])); + BOOST_TEST(ch == 'x'); + + a %= (entry = alpha[_val = _1]); + BOOST_TEST(test_attr("z", a, ch)); // attribute is given. + BOOST_TEST(ch == 'z'); + } + + { // auto subrules tests + + char ch; + rule<char const*, char()> a; + subrule<0, char()> entry; + + a = (entry %= alpha)[_val = _1]; + BOOST_TEST(test("x", a[phx::ref(ch) = _1])); + BOOST_TEST(ch == 'x'); + + a %= (entry %= alpha); + BOOST_TEST(test_attr("z", a, ch)); // attribute is given. + BOOST_TEST(ch == 'z'); + } + + { // auto subrules tests: allow stl containers as attributes to + // sequences (in cases where attributes of the elements + // are convertible to the value_type of the container or if + // the element itself is an stl container with value_type + // that is convertible to the value_type of the attribute). + + std::string s; + rule<char const*, std::string()> r; + subrule<0, std::string()> entry; + + r %= (entry %= char_ >> *(',' >> char_)); + BOOST_TEST(test("a,b,c,d,e,f", r[phx::ref(s) = _1])); + BOOST_TEST(s == "abcdef"); + + BOOST_TEST(test("abcdef", ( + entry %= char_ >> char_ >> char_ >> char_ >> char_ >> char_ + )[phx::ref(s) = _1])); + BOOST_TEST(s == "abcdef"); + } + + { // synth attribute value-init + + std::string s; + subrule<0, char()> sr; + BOOST_TEST(test_attr("abcdef", +(sr = alpha[_val += _1]), s)); + BOOST_TEST(s == "abcdef"); + } + + { // auto subrules aliasing tests + + char ch; + rule<char const*, char()> r; + subrule<0, char()> a; + subrule<1, char()> b; + r %= ( + a %= b + , b %= alpha + ); + + BOOST_TEST(test("x", r[phx::ref(ch) = _1])); + BOOST_TEST(ch == 'x'); + + BOOST_TEST(test_attr("z", r, ch)); // attribute is given. + BOOST_TEST(ch == 'z'); + } + + { // context (w/arg) tests + + char ch; + + // entry subrule with 1 arg + rule<char const*, char(int)> a; + subrule<1, char(int)> sr1; + a %= ( + sr1 = alpha[_val = _1 + _r1] + )(_r1); + BOOST_TEST(test("x", a(phx::val(1))[phx::ref(ch) = _1])); + BOOST_TEST(ch == 'x' + 1); + + // other subrule with 1 arg + subrule<0, char()> sr0; + a %= ( + sr0 %= sr1(1) + , sr1 = alpha[_val = _1 + _r1] + ); + + // allow scalars as subrule args too + rule<char const*, char()> b; + b %= ( + sr1 = alpha[_val = _1 + _r1] + )(1); + BOOST_TEST(test_attr("b", b, ch)); + BOOST_TEST(ch == 'b' + 1); + + // entry subrule with 2 args + subrule<2, char(int, int)> sr2; + BOOST_TEST(test_attr("a", ( + sr2 = alpha[_val = _1 + _r1 + _r2] + )(1, 2), ch)); + BOOST_TEST(ch == 'a' + 1 + 2); + + // multiple subrules + args + BOOST_TEST(test_attr("ba", ( + sr2 = alpha[_val = _1 + _r1 + _r2] >> sr1(3)[_val -= _1] + , sr1 = alpha[_val = _1 + _r1] + )(1, 2), ch)); + BOOST_TEST(ch == ('b' + 1 + 2) - ('a' + 3)); + } + + { // context (w/ reference arg) tests + + char ch; + subrule<0, void(char&)> sr; // 1 arg (reference) - direct + BOOST_TEST(test("x", (sr = alpha[_r1 = _1])(phx::ref(ch)))); + BOOST_TEST(ch == 'x'); + + rule<char const*, void(char&)> a; // forwarded via a rule + a = (sr = alpha[_r1 = _1])(_r1); + BOOST_TEST(test("y", a(phx::ref(ch)))); + BOOST_TEST(ch == 'y'); + } + + { // context (w/locals) tests + + rule<char const*> r; + subrule<0, locals<char> > a; // 1 local + r = ( + a = alpha[_a = _1] >> char_(_a) + ); + BOOST_TEST(test("aa", r)); + BOOST_TEST(!test("ax", r)); + } + + { // context (w/args and locals) tests + + rule<char const*, void(int)> a; + subrule<0, void(int), locals<char> > sr; // 1 arg + 1 local + a = ( + sr = alpha[_a = _1 + _r1] >> char_(_a) + )(_r1); + BOOST_TEST(test("ab", a(phx::val(1)))); + BOOST_TEST(test("xy", a(phx::val(1)))); + BOOST_TEST(!test("ax", a(phx::val(1)))); + } + + { // void() has unused type (void == unused_type) + + std::pair<int, char> attr; + subrule<0, void()> sr; + BOOST_TEST(test_attr("123ax", int_ >> char_ >> (sr = char_), attr)); + BOOST_TEST(attr.first == 123); + BOOST_TEST(attr.second == 'a'); + } + + { // test that injected attributes are ok + + rule<char const*> r; + subrule<0, char(int)> sr; + + r = ( + sr = char_(_r1)[_val = _1] + )(42); + } + + { // show that sra = srb and sra %= srb works as expected + subrule<0, int()> sra; + subrule<1, int()> srb; + int attr; + + BOOST_TEST(test_attr("123", (sra %= int_), attr)); + BOOST_TEST(attr == 123); + + BOOST_TEST(test_attr("123", (srb %= sra, sra %= int_), attr)); + BOOST_TEST(attr == 123); + + BOOST_TEST(test_attr("123", (srb = sra, sra %= int_), attr)); + BOOST_TEST(attr == 123); + } + + { // std::string as container attribute with auto subrules + + subrule<0, std::string()> text; + std::string attr; + BOOST_TEST(test_attr("x", ( + text %= +(!char_(')') >> !char_('>') >> char_) + ), attr)); + BOOST_TEST(attr == "x"); + } + +// { // error handling +// +// using namespace boost::spirit::ascii; +// using boost::phoenix::construct; +// using boost::phoenix::bind; +// +// rule<char const*> r; +// r = '(' > int_ > ',' > int_ > ')'; +// +// on_error<fail> +// ( +// r, std::cout +// << phx::val("Error! Expecting: ") +// << _4 +// << phx::val(", got: \"") +// << construct<std::string>(_3, _2) +// << phx::val("\"") +// << std::endl +// ); +// +// BOOST_TEST(test("(123,456)", r)); +// BOOST_TEST(!test("(abc,def)", r)); +// BOOST_TEST(!test("(123,456]", r)); +// BOOST_TEST(!test("(123;456)", r)); +// BOOST_TEST(!test("[123,456]", r)); +// } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/spirit/repository/test/qi/test.hpp b/src/boost/libs/spirit/repository/test/qi/test.hpp new file mode 100644 index 00000000..88cc7503 --- /dev/null +++ b/src/boost/libs/spirit/repository/test/qi/test.hpp @@ -0,0 +1,102 @@ +/*============================================================================= + Copyright (c) 2001-2010 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#if !defined(BOOST_SPIRIT_TEST_FEBRUARY_01_2007_0605PM) +#define BOOST_SPIRIT_TEST_FEBRUARY_01_2007_0605PM + +#include <boost/spirit/include/qi_parse.hpp> +#include <boost/spirit/include/qi_what.hpp> +#include <boost/variant/apply_visitor.hpp> +#include <iostream> + +namespace spirit_test +{ + template <typename Char, typename Parser> + inline bool test(Char const* in, Parser const& p, bool full_match = true) + { + // we don't care about the result of the "what" function. + // we only care that all parsers have it: + boost::spirit::qi::what(p); + + Char const* last = in; + while (*last) + last++; + return boost::spirit::qi::parse(in, last, p) + && (!full_match || (in == last)); + } + + template <typename Char, typename Parser, typename Skipper> + inline bool test(Char const* in, Parser const& p + , Skipper const& s, bool full_match = true) + { + // we don't care about the result of the "what" function. + // we only care that all parsers have it: + boost::spirit::qi::what(p); + + Char const* last = in; + while (*last) + last++; + return boost::spirit::qi::phrase_parse(in, last, p, s) + && (!full_match || (in == last)); + } + + template <typename Char, typename Parser, typename Attr> + inline bool test_attr(Char const* in, Parser const& p + , Attr& attr, bool full_match = true) + { + // we don't care about the result of the "what" function. + // we only care that all parsers have it: + boost::spirit::qi::what(p); + + Char const* last = in; + while (*last) + last++; + return boost::spirit::qi::parse(in, last, p, attr) + && (!full_match || (in == last)); + } + + template <typename Char, typename Parser, typename Attr, typename Skipper> + inline bool test_attr(Char const* in, Parser const& p + , Attr& attr, Skipper const& s, bool full_match = true) + { + // we don't care about the result of the "what" function. + // we only care that all parsers have it: + boost::spirit::qi::what(p); + + Char const* last = in; + while (*last) + last++; + return boost::spirit::qi::phrase_parse(in, last, p, s, attr) + && (!full_match || (in == last)); + } + + struct printer + { + typedef boost::spirit::utf8_string string; + + void element(string const& tag, string const& value, int depth) const + { + for (int i = 0; i < (depth*4); ++i) // indent to depth + std::cout << ' '; + + std::cout << "tag: " << tag; + if (value != "") + std::cout << ", value: " << value; + std::cout << std::endl; + } + }; + + inline void print_info(boost::spirit::info const& what) + { + using boost::spirit::basic_info_walker; + + printer pr; + basic_info_walker<printer> walker(pr, what.tag, 0); + boost::apply_visitor(walker, what.value); + } +} + +#endif diff --git a/src/boost/libs/spirit/repository/test/test_headers/Jamfile b/src/boost/libs/spirit/repository/test/test_headers/Jamfile new file mode 100644 index 00000000..0b197a68 --- /dev/null +++ b/src/boost/libs/spirit/repository/test/test_headers/Jamfile @@ -0,0 +1,81 @@ +# Jamfile +# +# Copyright (c) 2007-2008 Steven Watanabe +# Copyright (c) 2009 Joel de Guzman +# Copyright (c) 2009 Hartmut Kaiser +# Copyright (c) 2009 Francois Barel +# +# 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 + +import testing ; +import path ; +import regex ; +import print ; +import sequence ; +import feature ; + +project boost/spirit/repository/test/test_headers + : requirements + <include>$(BOOST_ROOT) + <include>../../../../.. + <c++-template-depth>300 + ; + +headers = +[ + path.glob-tree ../../../../../boost/spirit/repository/include : *.hpp +] ; + +main_headers = +[ + path.glob-tree ../../../../../boost/spirit/include : *.hpp : classic* phoenix1* +] ; + +for local file in $(headers) +{ + compile test.cpp + : # requirements + <define>BOOST_SPIRIT_HEADER_NAME=$(file) + <dependency>$(file) + : # test name + [ regex.replace [ path.relative-to ../../../../../boost/spirit/repository $(file) ] "/" "_" ] + ; +} + +feature.feature <generate-include-all-order> : forward reverse : incidental ; + +rule generate-include-all ( target : sources * : properties * ) +{ + print.output $(target) ; + + if <generate-include-all-order>reverse in $(properties) + { + sources = [ sequence.reverse $(sources) ] ; + } + + for local file in $(sources) + { + print.text "#include <$(file:G=)> +" : overwrite ; + } + +} + +make auto_all1.cpp + : $(headers) $(main_headers) + : @generate-include-all + ; + +make auto_all2.cpp + : $(headers) $(main_headers) + : @generate-include-all + : <generate-include-all-order>reverse + ; + +# this ought to catch non-inlined functions and other duplicate definitions +link auto_all1.cpp auto_all2.cpp main.cpp + : <include>. + : auto_all_headers + ; diff --git a/src/boost/libs/spirit/repository/test/test_headers/main.cpp b/src/boost/libs/spirit/repository/test/test_headers/main.cpp new file mode 100644 index 00000000..99aacc62 --- /dev/null +++ b/src/boost/libs/spirit/repository/test/test_headers/main.cpp @@ -0,0 +1,14 @@ +// Copyright (c) 2003-2008 Matthias Christian Schabel +// Copyright (c) 2007-2008 Steven Watanabe +// Copyright (c) 2010 Joel de Guzman +// Copyright (c) 2010 Hartmut Kaiser +// Copyright (c) 2009 Francois Barel +// +// 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) + +int main() +{ + return 0; +} diff --git a/src/boost/libs/spirit/repository/test/test_headers/test.cpp b/src/boost/libs/spirit/repository/test/test_headers/test.cpp new file mode 100644 index 00000000..c6814198 --- /dev/null +++ b/src/boost/libs/spirit/repository/test/test_headers/test.cpp @@ -0,0 +1,22 @@ +// Copyright (c) 2003-2008 Matthias Christian Schabel +// Copyright (c) 2007-2008 Steven Watanabe +// Copyright (c) 2010 Joel de Guzman +// Copyright (c) 2010 Hartmut Kaiser +// Copyright (c) 2009 Francois Barel +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_SPIRIT_STRINGIZE_IMPL(x) #x +#define BOOST_SPIRIT_STRINGIZE(x) BOOST_SPIRIT_STRINGIZE_IMPL(x) + +#define BOOST_SPIRIT_HEADER BOOST_SPIRIT_STRINGIZE(BOOST_SPIRIT_HEADER_NAME) + +#include BOOST_SPIRIT_HEADER +#include BOOST_SPIRIT_HEADER + +int main() +{ + return 0; +} |