1 /*============================================================================== 2 Copyright (c) 2001-2011 Joel de Guzman 3 Copyright (c) 2010-2011 Bryce Lelbach 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt) 7 ==============================================================================*/ 8 9 #if !defined(BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP) 10 #define BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP 11 12 #include "utf8_parser.hpp" 13 #include "error_handler.hpp" 14 15 namespace boost { 16 namespace spirit { 17 namespace traits { 18 19 template<> 20 struct transform_attribute<utree::nil_type, unused_type, qi::domain> { 21 typedef unused_type type; 22 preboost::spirit::traits::transform_attribute23 static unused_type pre (utree::nil_type&) { return unused_type(); } postboost::spirit::traits::transform_attribute24 static void post (utree::nil_type&, unused_type) { } failboost::spirit::traits::transform_attribute25 static void fail (utree::nil_type&) { } 26 }; 27 28 } // traits 29 } // spirit 30 } // boost 31 32 namespace sexpr 33 { 34 35 namespace qi = boost::spirit::qi; 36 namespace px = boost::phoenix; 37 namespace standard = boost::spirit::standard; 38 39 using boost::spirit::utree; 40 using boost::spirit::utf8_symbol_type; 41 using boost::spirit::utf8_string_type; 42 using boost::spirit::binary_string_type; 43 44 struct bool_input_policies 45 { 46 template <typename Iterator, typename Attribute> 47 static bool parse_truesexpr::bool_input_policies48 parse_true(Iterator& first, Iterator const& last, Attribute& attr) 49 { 50 using boost::spirit::qi::detail::string_parse; 51 using boost::spirit::qi::bool_policies; 52 using boost::spirit::qi::unused; 53 using boost::spirit::traits::assign_to; 54 if (string_parse("#t", first, last, unused)) 55 { 56 assign_to(true, attr); // result is true 57 return true; 58 } 59 return bool_policies<bool>::parse_true(first, last, attr); 60 } 61 62 template <typename Iterator, typename Attribute> 63 static bool parse_falsesexpr::bool_input_policies64 parse_false(Iterator& first, Iterator const& last, Attribute& attr) 65 { 66 using boost::spirit::qi::detail::string_parse; 67 using boost::spirit::qi::bool_policies; 68 using boost::spirit::qi::unused; 69 using boost::spirit::traits::assign_to; 70 if (string_parse("#f", first, last, unused)) 71 { 72 assign_to(false, attr); // result is false 73 return true; 74 } 75 return bool_policies<bool>::parse_false(first, last, attr); 76 } 77 }; 78 79 struct save_line_pos 80 { 81 template <typename, typename> 82 struct result 83 { 84 typedef void type; 85 }; 86 87 template <typename Range> operator ()sexpr::save_line_pos88 void operator()(utree& ast, Range const& rng) const 89 { 90 using boost::spirit::get_line; 91 std::size_t n = get_line(rng.begin()); 92 if (n != -1) 93 { 94 BOOST_ASSERT(n <= (std::numeric_limits<short>::max)()); 95 ast.tag(n); 96 } 97 else 98 ast.tag(-1); 99 } 100 }; 101 102 template <typename Iterator, typename F> 103 struct tagger : qi::grammar<Iterator, void(utree&, char)> 104 { 105 qi::rule<Iterator, void(utree&, char)> 106 start; 107 108 qi::rule<Iterator, void(utree&)> 109 epsilon; 110 111 px::function<F> 112 f; 113 taggersexpr::tagger114 tagger(F f_ = F()) : tagger::base_type(start), f(f_) 115 { 116 using qi::omit; 117 using qi::raw; 118 using qi::eps; 119 using qi::lit; 120 using qi::_1; 121 using qi::_r1; 122 using qi::_r2; 123 124 start = omit[raw[lit(_r2)] [f(_r1, _1)]]; 125 126 epsilon = omit[raw[eps] [f(_r1, _1)]]; 127 } 128 }; 129 130 template <typename Iterator> 131 struct whitespace : qi::grammar<Iterator> { 132 qi::rule<Iterator> 133 start; 134 whitespacesexpr::whitespace135 whitespace() : whitespace::base_type(start) 136 { 137 using standard::space; 138 using standard::char_; 139 using qi::eol; 140 141 start = space | (';' >> *(char_ - eol) >> eol); 142 } 143 }; 144 145 } // sexpr 146 147 //[utree_sexpr_parser 148 namespace sexpr 149 { 150 151 template <typename Iterator, typename ErrorHandler = error_handler<Iterator> > 152 struct parser : qi::grammar<Iterator, utree(), whitespace<Iterator> > 153 { 154 qi::rule<Iterator, utree(), whitespace<Iterator> > 155 start, element, list; 156 157 qi::rule<Iterator, utree()> 158 atom; 159 160 qi::rule<Iterator, int()> 161 integer; 162 163 qi::rule<Iterator, utf8_symbol_type()> 164 symbol; 165 166 qi::rule<Iterator, utree::nil_type()> 167 nil_; 168 169 qi::rule<Iterator, binary_string_type()> 170 binary; 171 172 utf8::parser<Iterator> 173 string; 174 175 px::function<ErrorHandler> const 176 error; 177 178 tagger<Iterator, save_line_pos> 179 pos; 180 parsersexpr::parser181 parser(std::string const& source_file = "<string>"): 182 parser::base_type(start), error(ErrorHandler(source_file)) 183 { 184 using standard::char_; 185 using qi::unused_type; 186 using qi::lexeme; 187 using qi::hex; 188 using qi::oct; 189 using qi::no_case; 190 using qi::real_parser; 191 using qi::strict_real_policies; 192 using qi::uint_parser; 193 using qi::bool_parser; 194 using qi::on_error; 195 using qi::fail; 196 using qi::int_; 197 using qi::lit; 198 using qi::_val; 199 using qi::_1; 200 using qi::_2; 201 using qi::_3; 202 using qi::_4; 203 204 real_parser<double, strict_real_policies<double> > strict_double; 205 uint_parser<unsigned char, 16, 2, 2> hex2; 206 bool_parser<bool, sexpr::bool_input_policies> boolean; 207 208 start = element.alias(); 209 210 element = atom | list; 211 212 list = pos(_val, '(') > *element > ')'; 213 214 atom = nil_ 215 | strict_double 216 | integer 217 | boolean 218 | string 219 | symbol 220 | binary; 221 222 nil_ = qi::attr_cast(lit("nil")); 223 224 integer = lexeme[ no_case["#x"] > hex] 225 | lexeme[ no_case["#o"] >> oct] 226 | lexeme[-no_case["#d"] >> int_]; 227 228 std::string exclude = std::string(" ();\"\x01-\x1f\x7f") + '\0'; 229 symbol = lexeme[+(~char_(exclude))]; 230 231 binary = lexeme['#' > *hex2 > '#']; 232 233 start.name("sexpr"); 234 element.name("element"); 235 list.name("list"); 236 atom.name("atom"); 237 nil_.name("nil"); 238 integer.name("integer"); 239 symbol.name("symbol"); 240 binary.name("binary"); 241 242 on_error<fail>(start, error(_1, _2, _3, _4)); 243 } 244 }; 245 246 } // sexpr 247 //] 248 249 #endif // BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP 250 251