/*============================================================================= Copyright (c) 2001-2010 Joel de Guzman Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #if !defined(BOOST_SPIRIT_SEXPR) #define BOOST_SPIRIT_SEXPR #include #include #include #include #include #include #include #include #include #include #include #include namespace scheme { namespace input { using boost::spirit::standard::char_; using boost::spirit::standard::space; using boost::spirit::qi::grammar; using boost::spirit::qi::rule; using boost::spirit::qi::eol; using boost::spirit::qi::uint_parser; using boost::spirit::qi::real_parser; using boost::spirit::qi::strict_real_policies; using boost::spirit::qi::int_; using boost::spirit::qi::hex; using boost::spirit::qi::oct; using boost::spirit::qi::bool_; using boost::spirit::qi::no_case; using boost::spirit::qi::lexeme; using boost::spirit::qi::on_error; using boost::spirit::qi::fail; using boost::spirit::qi::_val; using boost::spirit::qi::_1; using boost::spirit::qi::_2; using boost::spirit::qi::_3; using boost::spirit::qi::_4; using boost::spirit::qi::locals; using boost::spirit::qi::raw; using boost::spirit::qi::eps; using boost::spirit::qi::omit; using boost::spirit::info; typedef boost::uint32_t uchar; // a unicode code point template struct sexpr_white_space : grammar { sexpr_white_space() : sexpr_white_space::base_type(start) { start = space // tab/space/cr/lf | ';' >> *(char_ - eol) >> eol // comments ; } rule start; }; struct save_line_pos_ { template struct result { typedef void type; }; template void operator()(utree& ast, Range const& rng) const { int n = get_line(rng.begin()); BOOST_ASSERT(n <= (std::numeric_limits::max)()); ast.tag(n); } }; boost::phoenix::function const save_line_pos = save_line_pos_(); template > struct sexpr : grammar, utree()> { sexpr(std::string const& source_file = "") : sexpr::base_type(start), error_handler(ErrorHandler(source_file)) { real_parser > strict_double; uint_parser hex2; start = element.alias(); element = atom | list; list %= '(' > omit[raw[eps] [save_line_pos(_val, _1)]] > *element > ')' ; atom = strict_double | integer | bool_ | string | byte_str | symbol ; std::string exclude = std::string(" ();\"\x01-\x1f\x7f") + '\0'; symbol = lexeme[+(~char_(exclude))]; integer = lexeme[no_case["0x"] > hex] | lexeme['0' >> oct] | int_ ; byte_str = lexeme['#' > +hex2 > '#']; start.name("sexpr"); list.name("list"); atom.name("atom"); symbol.name("symbol"); integer.name("integer"); byte_str.name("byte_str"); on_error(start, error_handler(_1, _2, _3, _4)); } rule, utree()> start, element, list; rule integer; rule atom; rule symbol; rule byte_str; scheme::input::string string; function const error_handler; }; }} #endif