| /*============================================================================= |
| 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_STRING) |
| #define BOOST_SPIRIT_SEXPR_STRING |
| |
| #include <string> |
| |
| #include <boost/cstdint.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/regex/pending/unicode_iterator.hpp> |
| |
| #include <utree/utree.hpp> |
| #include <utree/operators.hpp> |
| |
| namespace scheme { namespace input |
| { |
| using boost::spirit::standard::char_; |
| using boost::spirit::qi::grammar; |
| using boost::spirit::qi::rule; |
| using boost::spirit::qi::_val; |
| using boost::spirit::qi::_r1; |
| using boost::spirit::qi::_1; |
| using boost::spirit::qi::uint_parser; |
| using boost::phoenix::function; |
| |
| typedef boost::uint32_t uchar; // a unicode code point |
| |
| namespace detail |
| { |
| struct push_utf8 |
| { |
| template <typename S, typename C> |
| struct result { typedef void type; }; |
| |
| void operator()(std::string& utf8, uchar code_point) const |
| { |
| typedef std::back_insert_iterator<std::string> insert_iter; |
| insert_iter out_iter(utf8); |
| boost::utf8_output_iterator<insert_iter> utf8_iter(out_iter); |
| *utf8_iter++ = code_point; |
| } |
| }; |
| |
| struct push_esc |
| { |
| template <typename S, typename C> |
| struct result { typedef void type; }; |
| |
| void operator()(std::string& utf8, uchar c) const |
| { |
| switch (c) |
| { |
| case 'b': utf8 += '\b'; break; |
| case 't': utf8 += '\t'; break; |
| case 'n': utf8 += '\n'; break; |
| case 'f': utf8 += '\f'; break; |
| case 'r': utf8 += '\r'; break; |
| case '"': utf8 += '"'; break; |
| case '\\': utf8 += '\\'; break; |
| } |
| } |
| }; |
| } |
| |
| template <typename Iterator> |
| struct string : grammar<Iterator, std::string()> |
| { |
| string() : string::base_type(start) |
| { |
| uint_parser<uchar, 16, 4, 4> hex4; |
| uint_parser<uchar, 16, 8, 8> hex8; |
| function<detail::push_utf8> push_utf8; |
| function<detail::push_esc> push_esc; |
| |
| char_esc |
| = '\\' |
| > ( ('u' > hex4) [push_utf8(_r1, _1)] |
| | ('U' > hex8) [push_utf8(_r1, _1)] |
| | char_("btnfr\\\"'") [push_esc(_r1, _1)] |
| ) |
| ; |
| |
| char_lit |
| = '\'' |
| > (char_esc(_val) | (~char_('\'')) [_val += _1]) |
| > '\'' |
| ; |
| |
| start |
| = '"' |
| > *(char_esc(_val) | (~char_('"')) [_val += _1]) |
| > '"' |
| ; |
| |
| char_esc.name("char_esc"); |
| char_lit.name("char_lit"); |
| start.name("string"); |
| } |
| |
| rule<Iterator, void(std::string&)> char_esc; |
| rule<Iterator, std::string()> char_lit; |
| rule<Iterator, std::string()> start; |
| }; |
| }} |
| |
| #endif |