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/example | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/spirit/repository/example')
18 files changed, 2043 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; +} |