| /*============================================================================== |
| 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 |
| |