1 /*==============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2010-2011 Bryce Lelbach
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 ==============================================================================*/
9 #if !defined(BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP)
10 #define BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP
12 #include "utf8_parser.hpp"
13 #include "error_handler.hpp"
20 struct transform_attribute<utree::nil_type, unused_type, qi::domain> {
21 typedef unused_type type;
23 static unused_type pre (utree::nil_type&) { return unused_type(); }
24 static void post (utree::nil_type&, unused_type) { }
25 static void fail (utree::nil_type&) { }
35 namespace qi = boost::spirit::qi;
36 namespace px = boost::phoenix;
37 namespace standard = boost::spirit::standard;
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;
44 struct bool_input_policies
46 template <typename Iterator, typename Attribute>
48 parse_true(Iterator& first, Iterator const& last, Attribute& attr)
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))
56 assign_to(true, attr); // result is true
59 return bool_policies<bool>::parse_true(first, last, attr);
62 template <typename Iterator, typename Attribute>
64 parse_false(Iterator& first, Iterator const& last, Attribute& attr)
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))
72 assign_to(false, attr); // result is false
75 return bool_policies<bool>::parse_false(first, last, attr);
81 template <typename, typename>
87 template <typename Range>
88 void operator()(utree& ast, Range const& rng) const
90 using boost::spirit::get_line;
91 std::size_t n = get_line(rng.begin());
94 BOOST_ASSERT(n <= (std::numeric_limits<short>::max)());
102 template <typename Iterator, typename F>
103 struct tagger : qi::grammar<Iterator, void(utree&, char)>
105 qi::rule<Iterator, void(utree&, char)>
108 qi::rule<Iterator, void(utree&)>
114 tagger(F f_ = F()) : tagger::base_type(start), f(f_)
124 start = omit[raw[lit(_r2)] [f(_r1, _1)]];
126 epsilon = omit[raw[eps] [f(_r1, _1)]];
130 template <typename Iterator>
131 struct whitespace : qi::grammar<Iterator> {
135 whitespace() : whitespace::base_type(start)
137 using standard::space;
138 using standard::char_;
141 start = space | (';' >> *(char_ - eol) >> eol);
147 //[utree_sexpr_parser
151 template <typename Iterator, typename ErrorHandler = error_handler<Iterator> >
152 struct parser : qi::grammar<Iterator, utree(), whitespace<Iterator> >
154 qi::rule<Iterator, utree(), whitespace<Iterator> >
155 start, element, list;
157 qi::rule<Iterator, utree()>
160 qi::rule<Iterator, int()>
163 qi::rule<Iterator, utf8_symbol_type()>
166 qi::rule<Iterator, utree::nil_type()>
169 qi::rule<Iterator, binary_string_type()>
172 utf8::parser<Iterator>
175 px::function<ErrorHandler> const
178 tagger<Iterator, save_line_pos>
181 parser(std::string const& source_file = "<string>"):
182 parser::base_type(start), error(ErrorHandler(source_file))
184 using standard::char_;
185 using qi::unused_type;
190 using qi::real_parser;
191 using qi::strict_real_policies;
192 using qi::uint_parser;
193 using qi::bool_parser;
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;
208 start = element.alias();
210 element = atom | list;
212 list = pos(_val, '(') > *element > ')';
222 nil_ = qi::attr_cast(lit("nil"));
224 integer = lexeme[ no_case["#x"] > hex]
225 | lexeme[ no_case["#o"] >> oct]
226 | lexeme[-no_case["#d"] >> int_];
228 std::string exclude = std::string(" ();\"\x01-\x1f\x7f") + '\0';
229 symbol = lexeme[+(~char_(exclude))];
231 binary = lexeme['#' > *hex2 > '#'];
234 element.name("element");
238 integer.name("integer");
239 symbol.name("symbol");
240 binary.name("binary");
242 on_error<fail>(start, error(_1, _2, _3, _4));
249 #endif // BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP