• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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