/*============================================================================== 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 { 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 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::parse_true(first, last, attr); } template 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::parse_false(first, last, attr); } }; struct save_line_pos { template struct result { typedef void type; }; template 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::max)()); ast.tag(n); } else ast.tag(-1); } }; template struct tagger : qi::grammar { qi::rule start; qi::rule epsilon; px::function 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 struct whitespace : qi::grammar { qi::rule 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 > struct parser : qi::grammar > { qi::rule > start, element, list; qi::rule atom; qi::rule integer; qi::rule symbol; qi::rule nil_; qi::rule binary; utf8::parser string; px::function const error; tagger pos; parser(std::string const& source_file = ""): 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 > strict_double; uint_parser hex2; bool_parser 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(start, error(_1, _2, _3, _4)); } }; } // sexpr //] #endif // BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP