diff options
Diffstat (limited to 'src/boost/libs/spirit/example/support')
8 files changed, 762 insertions, 0 deletions
diff --git a/src/boost/libs/spirit/example/support/Jamfile b/src/boost/libs/spirit/example/support/Jamfile new file mode 100644 index 00000000..273e341b --- /dev/null +++ b/src/boost/libs/spirit/example/support/Jamfile @@ -0,0 +1,16 @@ +#============================================================================== +# Copyright (c) 2001-2011 Joel de Guzman +# Copyright (c) 2001-2011 Hartmut Kaiser +# Copyright (C) 2011 Bryce Lelbach +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#============================================================================== +project spirit-support-example + : requirements <toolset>gcc:<c++-template-depth>300 + : + : + ; + +exe multi_pass : multi_pass.cpp ; +exe parse_sexpr : utree/parse_sexpr.cpp ; diff --git a/src/boost/libs/spirit/example/support/multi_pass.cpp b/src/boost/libs/spirit/example/support/multi_pass.cpp new file mode 100644 index 00000000..27e529c7 --- /dev/null +++ b/src/boost/libs/spirit/example/support/multi_pass.cpp @@ -0,0 +1,50 @@ +// 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 <iostream> +#include <fstream> +#include <vector> + +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/include/support_multi_pass.hpp> + +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +//[tutorial_multi_pass +int main() +{ + namespace spirit = boost::spirit; + using spirit::ascii::space; + using spirit::ascii::char_; + using spirit::qi::double_; + using spirit::qi::eol; + + std::ifstream in("multi_pass.txt"); // we get our input from this file + if (!in.is_open()) { + std::cout << "Could not open input file: '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)); + + std::vector<double> v; + bool result = spirit::qi::phrase_parse(first + , spirit::make_default_multi_pass(base_iterator_type()) + , double_ >> *(',' >> double_) // recognize list of doubles + , space | '#' >> *(char_ - eol) >> eol // comment skipper + , v); // data read from file + + 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/example/support/multi_pass.txt b/src/boost/libs/spirit/example/support/multi_pass.txt new file mode 100644 index 00000000..54368f38 --- /dev/null +++ b/src/boost/libs/spirit/example/support/multi_pass.txt @@ -0,0 +1,6 @@ +# 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) + +1.0,2.0,3.0 diff --git a/src/boost/libs/spirit/example/support/utree/error_handler.hpp b/src/boost/libs/spirit/example/support/utree/error_handler.hpp new file mode 100644 index 00000000..6f5ba1bc --- /dev/null +++ b/src/boost/libs/spirit/example/support/utree/error_handler.hpp @@ -0,0 +1,112 @@ +/*============================================================================== + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2010-2011 Bryce Lelbach + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#if !defined(BOOST_SPIRIT_UTREE_EXAMPLE_ERROR_HANDLER_HPP) +#define BOOST_SPIRIT_UTREE_EXAMPLE_ERROR_HANDLER_HPP + +#include <string> +#include <sstream> + +#include <boost/config.hpp> +#include <boost/spirit/home/support/info.hpp> +#include <boost/spirit/include/support_line_pos_iterator.hpp> + +namespace sexpr +{ + +using boost::spirit::info; + +template <typename Out> +struct print_info +{ + typedef boost::spirit::utf8_string string; + + print_info(Out& out) : out(out), first(true) {} + + void element(string const& tag, string const& value, int) const + { + if (!first) { + out << ' '; + first = false; + } + + if (value == "") + out << tag; + else + out << "\"" << value << '"'; + } + + Out& out; + mutable bool first; +}; + +struct expected_component : std::exception +{ + std::string msg; + + expected_component(std::string const& source, std::size_t line + , info const& w) + { + using boost::spirit::basic_info_walker; + + std::ostringstream oss; + oss << "(exception \"" << source << "\" "; + + if (line == -1) + oss << -1; + else + oss << line; + + oss << " '(expected_component ("; + + print_info<std::ostringstream> pr(oss); + basic_info_walker<print_info<std::ostringstream> > + walker(pr, w.tag, 0); + + boost::apply_visitor(walker, w.value); + + oss << ")))"; + + msg = oss.str(); + } + + virtual ~expected_component() BOOST_NOEXCEPT_OR_NOTHROW {} + + virtual char const* what() const BOOST_NOEXCEPT_OR_NOTHROW + { + return msg.c_str(); + } +}; + +template <typename Iterator> +struct error_handler +{ + template <typename, typename, typename, typename> + struct result + { + typedef void type; + }; + + std::string source; + + error_handler(std::string const& source_ = "<string>") : source(source_) {} + + void operator()(Iterator first, Iterator last, Iterator err_pos + , info const& what) const + { + using boost::spirit::get_line; + Iterator eol = err_pos; + std::size_t line = get_line(err_pos); + throw expected_component(source, line, what); + } +}; + +} // sexpr + +#endif // BOOST_SPIRIT_UTREE_EXAMPLE_ERROR_HANDLER_HPP + diff --git a/src/boost/libs/spirit/example/support/utree/parse_sexpr.cpp b/src/boost/libs/spirit/example/support/utree/parse_sexpr.cpp new file mode 100644 index 00000000..72d49ea5 --- /dev/null +++ b/src/boost/libs/spirit/example/support/utree/parse_sexpr.cpp @@ -0,0 +1,62 @@ +/*============================================================================== + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2010-2011 Bryce Lelbach + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include <boost/spirit/include/support_istream_iterator.hpp> +#include <boost/spirit/include/support_line_pos_iterator.hpp> +#include <boost/spirit/include/qi_parse.hpp> + +#include "sexpr_parser.hpp" + +int +main() +{ + using boost::spirit::qi::phrase_parse; + + std::cout << "/////////////////////////////////////////////////////////\n\n"; + std::cout << "sexpr parser...\n\n"; + std::cout << "/////////////////////////////////////////////////////////\n\n"; + std::cout << "Type an expression... or [q or Q] to quit\n\n"; + + typedef std::string::const_iterator iterator_type; + typedef sexpr::parser<iterator_type> parser; + typedef sexpr::whitespace<iterator_type> space; + + parser p; + space ws; + + 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, p, ws); + + 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/example/support/utree/sexpr_generator.hpp b/src/boost/libs/spirit/example/support/utree/sexpr_generator.hpp new file mode 100644 index 00000000..5dc56223 --- /dev/null +++ b/src/boost/libs/spirit/example/support/utree/sexpr_generator.hpp @@ -0,0 +1,128 @@ +/*============================================================================== + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2010-2011 Bryce Lelbach + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#if !defined(BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_GENERATOR_HPP) +#define BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_GENERATOR_HPP + +#include <boost/spirit/include/support_utree.hpp> +#include <boost/spirit/include/karma.hpp> + +namespace boost { +namespace spirit { +namespace traits { + +template<> +struct transform_attribute<utree::nil_type, unused_type, karma::domain> { + typedef unused_type type; + + static unused_type pre (utree::nil_type&) { return unused_type(); } +}; + +} // traits +} // spirit +} // boost + +namespace sexpr +{ + +namespace karma = boost::spirit::karma; +namespace standard = boost::spirit::standard; + +using boost::spirit::utree; +using boost::spirit::utf8_symbol_range_type; +using boost::spirit::utf8_string_range_type; +using boost::spirit::binary_range_type; + +struct bool_output_policies : karma::bool_policies<> +{ + template <typename CharEncoding, typename Tag, typename Iterator> + static bool generate_true(Iterator& sink, bool) + { + return string_inserter<CharEncoding, Tag>::call(sink, "#t"); + } + + template <typename CharEncoding, typename Tag, typename Iterator> + static bool generate_false(Iterator& sink, bool) + { + return string_inserter<CharEncoding, Tag>::call(sink, "#f"); + } +}; + +template <typename Iterator> +struct generator : karma::grammar<Iterator, utree()> +{ + typedef boost::iterator_range<utree::const_iterator> utree_list; + + karma::rule<Iterator, utree()> + start, ref_; + + karma::rule<Iterator, utree_list()> + list; + + karma::rule<Iterator, utf8_symbol_range_type()> + symbol; + + karma::rule<Iterator, utree::nil_type()> + nil_; + + karma::rule<Iterator, utf8_string_range_type()> + utf8; + + karma::rule<Iterator, binary_range_type()> + binary; + + generator() : generator::base_type(start) + { + using standard::char_; + using standard::string; + using karma::bool_generator; + using karma::uint_generator; + using karma::double_; + using karma::int_; + using karma::lit; + using karma::right_align; + + uint_generator<unsigned char, 16> hex2; + bool_generator<bool, bool_output_policies> boolean; + + start = nil_ + | double_ + | int_ + | boolean + | utf8 + | symbol + | binary + | list + | ref_; + + ref_ = start; + + list = '(' << -(start % ' ') << ')'; + + utf8 = '"' << *(&char_('"') << "\\\"" | char_) << '"'; + + symbol = string; + + binary = '#' << *right_align(2, '0')[hex2] << '#'; + + nil_ = karma::attr_cast(lit("nil")); + + start.name("sexpr"); + ref_.name("ref"); + list.name("list"); + utf8.name("string"); + symbol.name("symbol"); + binary.name("binary"); + nil_.name("nil"); + } +}; + +} // sexpr + +#endif // BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_GENERATOR_HPP + diff --git a/src/boost/libs/spirit/example/support/utree/sexpr_parser.hpp b/src/boost/libs/spirit/example/support/utree/sexpr_parser.hpp new file mode 100644 index 00000000..15dfdfbd --- /dev/null +++ b/src/boost/libs/spirit/example/support/utree/sexpr_parser.hpp @@ -0,0 +1,250 @@ +/*============================================================================== + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2010-2011 Bryce Lelbach + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#if !defined(BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP) +#define BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP + +#include "utf8_parser.hpp" +#include "error_handler.hpp" + +namespace boost { +namespace spirit { +namespace traits { + +template<> +struct transform_attribute<utree::nil_type, unused_type, qi::domain> { + typedef unused_type type; + + static unused_type pre (utree::nil_type&) { return unused_type(); } + static void post (utree::nil_type&, unused_type) { } + static void fail (utree::nil_type&) { } +}; + +} // traits +} // spirit +} // boost + +namespace sexpr +{ + +namespace qi = boost::spirit::qi; +namespace px = boost::phoenix; +namespace standard = boost::spirit::standard; + +using boost::spirit::utree; +using boost::spirit::utf8_symbol_type; +using boost::spirit::utf8_string_type; +using boost::spirit::binary_string_type; + +struct bool_input_policies +{ + template <typename Iterator, typename Attribute> + static bool + parse_true(Iterator& first, Iterator const& last, Attribute& attr) + { + using boost::spirit::qi::detail::string_parse; + using boost::spirit::qi::bool_policies; + using boost::spirit::qi::unused; + using boost::spirit::traits::assign_to; + if (string_parse("#t", first, last, unused)) + { + assign_to(true, attr); // result is true + return true; + } + return bool_policies<bool>::parse_true(first, last, attr); + } + + template <typename Iterator, typename Attribute> + static bool + parse_false(Iterator& first, Iterator const& last, Attribute& attr) + { + using boost::spirit::qi::detail::string_parse; + using boost::spirit::qi::bool_policies; + using boost::spirit::qi::unused; + using boost::spirit::traits::assign_to; + if (string_parse("#f", first, last, unused)) + { + assign_to(false, attr); // result is false + return true; + } + return bool_policies<bool>::parse_false(first, last, attr); + } +}; + +struct save_line_pos +{ + template <typename, typename> + struct result + { + typedef void type; + }; + + template <typename Range> + void operator()(utree& ast, Range const& rng) const + { + using boost::spirit::get_line; + std::size_t n = get_line(rng.begin()); + if (n != -1) + { + BOOST_ASSERT(n <= (std::numeric_limits<short>::max)()); + ast.tag(n); + } + else + ast.tag(-1); + } +}; + +template <typename Iterator, typename F> +struct tagger : qi::grammar<Iterator, void(utree&, char)> +{ + qi::rule<Iterator, void(utree&, char)> + start; + + qi::rule<Iterator, void(utree&)> + epsilon; + + px::function<F> + f; + + tagger(F f_ = F()) : tagger::base_type(start), f(f_) + { + using qi::omit; + using qi::raw; + using qi::eps; + using qi::lit; + using qi::_1; + using qi::_r1; + using qi::_r2; + + start = omit[raw[lit(_r2)] [f(_r1, _1)]]; + + epsilon = omit[raw[eps] [f(_r1, _1)]]; + } +}; + +template <typename Iterator> +struct whitespace : qi::grammar<Iterator> { + qi::rule<Iterator> + start; + + whitespace() : whitespace::base_type(start) + { + using standard::space; + using standard::char_; + using qi::eol; + + start = space | (';' >> *(char_ - eol) >> eol); + } +}; + +} // sexpr + +//[utree_sexpr_parser +namespace sexpr +{ + +template <typename Iterator, typename ErrorHandler = error_handler<Iterator> > +struct parser : qi::grammar<Iterator, utree(), whitespace<Iterator> > +{ + qi::rule<Iterator, utree(), whitespace<Iterator> > + start, element, list; + + qi::rule<Iterator, utree()> + atom; + + qi::rule<Iterator, int()> + integer; + + qi::rule<Iterator, utf8_symbol_type()> + symbol; + + qi::rule<Iterator, utree::nil_type()> + nil_; + + qi::rule<Iterator, binary_string_type()> + binary; + + utf8::parser<Iterator> + string; + + px::function<ErrorHandler> const + error; + + tagger<Iterator, save_line_pos> + pos; + + parser(std::string const& source_file = "<string>"): + parser::base_type(start), error(ErrorHandler(source_file)) + { + using standard::char_; + using qi::unused_type; + using qi::lexeme; + using qi::hex; + using qi::oct; + using qi::no_case; + using qi::real_parser; + using qi::strict_real_policies; + using qi::uint_parser; + using qi::bool_parser; + using qi::on_error; + using qi::fail; + using qi::int_; + using qi::lit; + using qi::_val; + using qi::_1; + using qi::_2; + using qi::_3; + using qi::_4; + + real_parser<double, strict_real_policies<double> > strict_double; + uint_parser<unsigned char, 16, 2, 2> hex2; + bool_parser<bool, sexpr::bool_input_policies> boolean; + + start = element.alias(); + + element = atom | list; + + list = pos(_val, '(') > *element > ')'; + + atom = nil_ + | strict_double + | integer + | boolean + | string + | symbol + | binary; + + nil_ = qi::attr_cast(lit("nil")); + + integer = lexeme[ no_case["#x"] > hex] + | lexeme[ no_case["#o"] >> oct] + | lexeme[-no_case["#d"] >> int_]; + + std::string exclude = std::string(" ();\"\x01-\x1f\x7f") + '\0'; + symbol = lexeme[+(~char_(exclude))]; + + binary = lexeme['#' > *hex2 > '#']; + + start.name("sexpr"); + element.name("element"); + list.name("list"); + atom.name("atom"); + nil_.name("nil"); + integer.name("integer"); + symbol.name("symbol"); + binary.name("binary"); + + on_error<fail>(start, error(_1, _2, _3, _4)); + } +}; + +} // sexpr +//] + +#endif // BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP + diff --git a/src/boost/libs/spirit/example/support/utree/utf8_parser.hpp b/src/boost/libs/spirit/example/support/utree/utf8_parser.hpp new file mode 100644 index 00000000..b06046ae --- /dev/null +++ b/src/boost/libs/spirit/example/support/utree/utf8_parser.hpp @@ -0,0 +1,138 @@ +/*============================================================================== + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2010-2011 Bryce Lelbach + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#if !defined(BOOST_SPIRIT_UTREE_EXAMPLE_UTF8_PARSER_HPP) +#define BOOST_SPIRIT_UTREE_EXAMPLE_UTF8_PARSER_HPP + +#include <string> + +#include <boost/cstdint.hpp> + +#include <boost/regex/pending/unicode_iterator.hpp> + +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_container.hpp> +#include <boost/spirit/include/phoenix_statement.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> +#include <boost/spirit/include/support_utree.hpp> + +namespace utf8 +{ + +namespace qi = boost::spirit::qi; +namespace px = boost::phoenix; +namespace standard = boost::spirit::standard; + +using boost::spirit::utree; +using boost::spirit::utf8_symbol_type; +using boost::spirit::utf8_string_type; +using boost::spirit::binary_string_type; + +typedef boost::uint32_t uchar; + +struct push_string +{ + template <typename, typename> + struct result + { + typedef void type; + }; + + void operator()(std::string& s, uchar code_point) const + { + typedef std::back_insert_iterator<std::string> insert_iter; + insert_iter out_iter(s); + boost::utf8_output_iterator<insert_iter> s_iter(out_iter); + *s_iter++ = code_point; + } +}; + +struct push_escaped_string +{ + template <typename, typename> + struct result + { + typedef void type; + }; + + void operator()(std::string& s, uchar c) const + { + switch (c) { + case 'b': + s += '\b'; + break; + case 't': + s += '\t'; + break; + case 'n': + s += '\n'; + break; + case 'f': + s += '\f'; + break; + case 'r': + s += '\r'; + break; + case '"': + s += '"'; + break; + case '\\': + s += '\\'; + break; + } + } +}; + +template <typename Iterator> +struct parser : qi::grammar<Iterator, std::string()> +{ + qi::rule<Iterator, void(std::string&)> + escaped; + + qi::rule<Iterator, std::string()> + start; + + px::function<push_string> + push_str; + + px::function<push_escaped_string> + push_esc; + + parser() : parser::base_type (start) + { + using standard::char_; + using qi::uint_parser; + using qi::_val; + using qi::_r1; + using qi::_1; + + uint_parser<uchar, 16, 4, 4> hex4; + uint_parser<uchar, 16, 8, 8> hex8; + + escaped + = '\\' + > ( ('u' > hex4) [push_str(_r1, _1)] + | ('U' > hex8) [push_str(_r1, _1)] + | char_("btnfr\\\"'") [push_esc(_r1, _1)] + ); + + start + = '"' + > *(escaped(_val) | (~char_('"')) [_val += _1]) + > '"'; + + escaped.name("escaped_string"); + start.name("string"); + } +}; + +} // utf8 + +#endif // BOOST_SPIRIT_UTREE_EXAMPLE_UTF8_PARSER_HPP + |