Chris@16
|
1 // Copyright (c) 2001-2011 Hartmut Kaiser
|
Chris@16
|
2 //
|
Chris@16
|
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 #if !defined(BOOST_SPIRIT_LEXER_PARSE_NOV_17_2007_0246PM)
|
Chris@16
|
7 #define BOOST_SPIRIT_LEXER_PARSE_NOV_17_2007_0246PM
|
Chris@16
|
8
|
Chris@16
|
9 #if defined(_MSC_VER)
|
Chris@16
|
10 #pragma once
|
Chris@16
|
11 #endif
|
Chris@16
|
12
|
Chris@16
|
13 #include <boost/spirit/home/qi/skip_over.hpp>
|
Chris@16
|
14 #include <boost/spirit/home/qi/parse.hpp>
|
Chris@16
|
15 #include <boost/spirit/home/qi/nonterminal/grammar.hpp>
|
Chris@16
|
16 #include <boost/spirit/home/support/unused.hpp>
|
Chris@16
|
17 #include <boost/spirit/home/lex/lexer.hpp>
|
Chris@16
|
18 #include <boost/mpl/assert.hpp>
|
Chris@16
|
19
|
Chris@16
|
20 namespace boost { namespace spirit { namespace lex
|
Chris@16
|
21 {
|
Chris@16
|
22 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
23 // Import skip_flag enumerator type from Qi namespace
|
Chris@16
|
24 using qi::skip_flag;
|
Chris@16
|
25
|
Chris@16
|
26 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
27 //
|
Chris@16
|
28 // The tokenize_and_parse() function is one of the main Spirit API
|
Chris@16
|
29 // functions. It simplifies using a lexer as the underlying token source
|
Chris@16
|
30 // while parsing a given input sequence.
|
Chris@16
|
31 //
|
Chris@16
|
32 // The function takes a pair of iterators spanning the underlying input
|
Chris@16
|
33 // stream to parse, the lexer object (built from the token definitions)
|
Chris@16
|
34 // and a parser object (built from the parser grammar definition).
|
Chris@16
|
35 //
|
Chris@16
|
36 // The second version of this function additionally takes an attribute to
|
Chris@16
|
37 // be used as the top level data structure instance the parser should use
|
Chris@16
|
38 // to store the recognized input to.
|
Chris@16
|
39 //
|
Chris@16
|
40 // The function returns true if the parsing succeeded (the given input
|
Chris@16
|
41 // sequence has been successfully matched by the given grammar).
|
Chris@16
|
42 //
|
Chris@16
|
43 // first, last: The pair of iterators spanning the underlying input
|
Chris@16
|
44 // sequence to parse. These iterators must at least
|
Chris@16
|
45 // conform to the requirements of the std::intput_iterator
|
Chris@16
|
46 // category.
|
Chris@16
|
47 // On exit the iterator 'first' will be updated to the
|
Chris@16
|
48 // position right after the last successfully matched
|
Chris@16
|
49 // token.
|
Chris@16
|
50 // lex: The lexer object (encoding the token definitions) to be
|
Chris@16
|
51 // used to convert the input sequence into a sequence of
|
Chris@16
|
52 // tokens. This token sequence is passed to the parsing
|
Chris@16
|
53 // process. The LexerExpr type must conform to the
|
Chris@16
|
54 // lexer interface described in the corresponding section
|
Chris@16
|
55 // of the documentation.
|
Chris@16
|
56 // xpr: The grammar object (encoding the parser grammar) to be
|
Chris@16
|
57 // used to match the token sequence generated by the lex
|
Chris@16
|
58 // object instance. The ParserExpr type must conform to
|
Chris@16
|
59 // the grammar interface described in the corresponding
|
Chris@16
|
60 // section of the documentation.
|
Chris@16
|
61 // attr: The top level attribute passed to the parser. It will
|
Chris@16
|
62 // be populated during the parsing of the input sequence.
|
Chris@16
|
63 // On exit it will hold the 'parser result' corresponding
|
Chris@16
|
64 // to the matched input sequence.
|
Chris@16
|
65 //
|
Chris@16
|
66 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
67 template <typename Iterator, typename Lexer, typename ParserExpr>
|
Chris@16
|
68 inline bool
|
Chris@16
|
69 tokenize_and_parse(Iterator& first, Iterator last, Lexer const& lex,
|
Chris@16
|
70 ParserExpr const& xpr)
|
Chris@16
|
71 {
|
Chris@16
|
72 // Report invalid expression error as early as possible.
|
Chris@16
|
73 // If you got an error_invalid_expression error message here,
|
Chris@16
|
74 // then the expression (expr) is not a valid spirit qi expression.
|
Chris@16
|
75 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
|
Chris@16
|
76
|
Chris@16
|
77 typename Lexer::iterator_type iter = lex.begin(first, last);
|
Chris@16
|
78 return compile<qi::domain>(xpr).parse(
|
Chris@16
|
79 iter, lex.end(), unused, unused, unused);
|
Chris@16
|
80 }
|
Chris@16
|
81
|
Chris@16
|
82 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
83 template <typename Iterator, typename Lexer, typename ParserExpr
|
Chris@16
|
84 , typename Attribute>
|
Chris@16
|
85 inline bool
|
Chris@16
|
86 tokenize_and_parse(Iterator& first, Iterator last, Lexer const& lex
|
Chris@16
|
87 , ParserExpr const& xpr, Attribute& attr)
|
Chris@16
|
88 {
|
Chris@16
|
89 // Report invalid expression error as early as possible.
|
Chris@16
|
90 // If you got an error_invalid_expression error message here,
|
Chris@16
|
91 // then the expression (expr) is not a valid spirit qi expression.
|
Chris@16
|
92 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
|
Chris@16
|
93
|
Chris@16
|
94 typename Lexer::iterator_type iter = lex.begin(first, last);
|
Chris@16
|
95 return compile<qi::domain>(xpr).parse(
|
Chris@16
|
96 iter, lex.end(), unused, unused, attr);
|
Chris@16
|
97 }
|
Chris@16
|
98
|
Chris@16
|
99 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
100 //
|
Chris@16
|
101 // The tokenize_and_phrase_parse() function is one of the main Spirit API
|
Chris@16
|
102 // functions. It simplifies using a lexer as the underlying token source
|
Chris@16
|
103 // while phrase parsing a given input sequence.
|
Chris@16
|
104 //
|
Chris@16
|
105 // The function takes a pair of iterators spanning the underlying input
|
Chris@16
|
106 // stream to parse, the lexer object (built from the token definitions)
|
Chris@16
|
107 // and a parser object (built from the parser grammar definition). The
|
Chris@16
|
108 // additional skipper parameter will be used as the skip parser during
|
Chris@16
|
109 // the parsing process.
|
Chris@16
|
110 //
|
Chris@16
|
111 // The second version of this function additionally takes an attribute to
|
Chris@16
|
112 // be used as the top level data structure instance the parser should use
|
Chris@16
|
113 // to store the recognized input to.
|
Chris@16
|
114 //
|
Chris@16
|
115 // The function returns true if the parsing succeeded (the given input
|
Chris@16
|
116 // sequence has been successfully matched by the given grammar).
|
Chris@16
|
117 //
|
Chris@16
|
118 // first, last: The pair of iterators spanning the underlying input
|
Chris@16
|
119 // sequence to parse. These iterators must at least
|
Chris@16
|
120 // conform to the requirements of the std::intput_iterator
|
Chris@16
|
121 // category.
|
Chris@16
|
122 // On exit the iterator 'first' will be updated to the
|
Chris@16
|
123 // position right after the last successfully matched
|
Chris@16
|
124 // token.
|
Chris@16
|
125 // lex: The lexer object (encoding the token definitions) to be
|
Chris@16
|
126 // used to convert the input sequence into a sequence of
|
Chris@16
|
127 // tokens. This token sequence is passed to the parsing
|
Chris@16
|
128 // process. The LexerExpr type must conform to the
|
Chris@16
|
129 // lexer interface described in the corresponding section
|
Chris@16
|
130 // of the documentation.
|
Chris@16
|
131 // xpr: The grammar object (encoding the parser grammar) to be
|
Chris@16
|
132 // used to match the token sequence generated by the lex
|
Chris@16
|
133 // object instance. The ParserExpr type must conform to
|
Chris@16
|
134 // the grammar interface described in the corresponding
|
Chris@16
|
135 // section of the documentation.
|
Chris@16
|
136 // skipper: The skip parser to be used while parsing the given
|
Chris@16
|
137 // input sequence. Note, the skip parser will have to
|
Chris@16
|
138 // act on the same token sequence as the main parser
|
Chris@16
|
139 // 'xpr'.
|
Chris@16
|
140 // post_skip: The post_skip flag controls whether the function will
|
Chris@16
|
141 // invoke an additional post skip after the main parser
|
Chris@16
|
142 // returned.
|
Chris@16
|
143 // attr: The top level attribute passed to the parser. It will
|
Chris@16
|
144 // be populated during the parsing of the input sequence.
|
Chris@16
|
145 // On exit it will hold the 'parser result' corresponding
|
Chris@16
|
146 // to the matched input sequence.
|
Chris@16
|
147 //
|
Chris@16
|
148 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
149 template <typename Iterator, typename Lexer, typename ParserExpr
|
Chris@16
|
150 , typename Skipper>
|
Chris@16
|
151 inline bool
|
Chris@16
|
152 tokenize_and_phrase_parse(Iterator& first, Iterator last
|
Chris@16
|
153 , Lexer const& lex, ParserExpr const& xpr, Skipper const& skipper
|
Chris@16
|
154 , BOOST_SCOPED_ENUM(skip_flag) post_skip = skip_flag::postskip)
|
Chris@16
|
155 {
|
Chris@16
|
156 // Report invalid expression error as early as possible.
|
Chris@16
|
157 // If you got an error_invalid_expression error message here,
|
Chris@16
|
158 // then the expression (expr) is not a valid spirit qi expression.
|
Chris@16
|
159 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
|
Chris@16
|
160 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Skipper);
|
Chris@16
|
161
|
Chris@16
|
162 typedef
|
Chris@16
|
163 typename spirit::result_of::compile<qi::domain, Skipper>::type
|
Chris@16
|
164 skipper_type;
|
Chris@16
|
165 skipper_type const skipper_ = compile<qi::domain>(skipper);
|
Chris@16
|
166
|
Chris@16
|
167 typename Lexer::iterator_type iter = lex.begin(first, last);
|
Chris@16
|
168 typename Lexer::iterator_type end = lex.end();
|
Chris@16
|
169 if (!compile<qi::domain>(xpr).parse(
|
Chris@16
|
170 iter, end, unused, skipper_, unused))
|
Chris@16
|
171 return false;
|
Chris@16
|
172
|
Chris@16
|
173 // do a final post-skip
|
Chris@16
|
174 if (post_skip == skip_flag::postskip)
|
Chris@16
|
175 qi::skip_over(iter, end, skipper_);
|
Chris@16
|
176 return true;
|
Chris@16
|
177 }
|
Chris@16
|
178
|
Chris@16
|
179 template <typename Iterator, typename Lexer, typename ParserExpr
|
Chris@16
|
180 , typename Skipper, typename Attribute>
|
Chris@16
|
181 inline bool
|
Chris@16
|
182 tokenize_and_phrase_parse(Iterator& first, Iterator last
|
Chris@16
|
183 , Lexer const& lex, ParserExpr const& xpr, Skipper const& skipper
|
Chris@16
|
184 , BOOST_SCOPED_ENUM(skip_flag) post_skip, Attribute& attr)
|
Chris@16
|
185 {
|
Chris@16
|
186 // Report invalid expression error as early as possible.
|
Chris@16
|
187 // If you got an error_invalid_expression error message here,
|
Chris@16
|
188 // then the expression (expr) is not a valid spirit qi expression.
|
Chris@16
|
189 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
|
Chris@16
|
190 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Skipper);
|
Chris@16
|
191
|
Chris@16
|
192 typedef
|
Chris@16
|
193 typename spirit::result_of::compile<qi::domain, Skipper>::type
|
Chris@16
|
194 skipper_type;
|
Chris@16
|
195 skipper_type const skipper_ = compile<qi::domain>(skipper);
|
Chris@16
|
196
|
Chris@16
|
197 typename Lexer::iterator_type iter = lex.begin(first, last);
|
Chris@16
|
198 typename Lexer::iterator_type end = lex.end();
|
Chris@16
|
199 if (!compile<qi::domain>(xpr).parse(
|
Chris@16
|
200 iter, end, unused, skipper_, attr))
|
Chris@16
|
201 return false;
|
Chris@16
|
202
|
Chris@16
|
203 // do a final post-skip
|
Chris@16
|
204 if (post_skip == skip_flag::postskip)
|
Chris@16
|
205 qi::skip_over(iter, end, skipper_);
|
Chris@16
|
206 return true;
|
Chris@16
|
207 }
|
Chris@16
|
208
|
Chris@16
|
209 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
210 template <typename Iterator, typename Lexer, typename ParserExpr
|
Chris@16
|
211 , typename Skipper, typename Attribute>
|
Chris@16
|
212 inline bool
|
Chris@16
|
213 tokenize_and_phrase_parse(Iterator& first, Iterator last
|
Chris@16
|
214 , Lexer const& lex, ParserExpr const& xpr, Skipper const& skipper
|
Chris@16
|
215 , Attribute& attr)
|
Chris@16
|
216 {
|
Chris@16
|
217 return tokenize_and_phrase_parse(first, last, lex, xpr, skipper
|
Chris@16
|
218 , skip_flag::postskip, attr);
|
Chris@16
|
219 }
|
Chris@16
|
220
|
Chris@16
|
221 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
222 //
|
Chris@16
|
223 // The tokenize() function is one of the main Spirit API functions. It
|
Chris@16
|
224 // simplifies using a lexer to tokenize a given input sequence. It's main
|
Chris@16
|
225 // purpose is to use the lexer to tokenize all the input.
|
Chris@16
|
226 //
|
Chris@16
|
227 // The second version below discards all generated tokens afterwards.
|
Chris@16
|
228 // This is useful whenever all the needed functionality has been
|
Chris@16
|
229 // implemented directly inside the lexer semantic actions, which are being
|
Chris@16
|
230 // executed while the tokens are matched.
|
Chris@16
|
231 //
|
Chris@16
|
232 // The function takes a pair of iterators spanning the underlying input
|
Chris@16
|
233 // stream to scan, the lexer object (built from the token definitions),
|
Chris@16
|
234 // and a (optional) functor being called for each of the generated tokens.
|
Chris@16
|
235 //
|
Chris@16
|
236 // The function returns true if the scanning of the input succeeded (the
|
Chris@16
|
237 // given input sequence has been successfully matched by the given token
|
Chris@16
|
238 // definitions).
|
Chris@16
|
239 //
|
Chris@16
|
240 // first, last: The pair of iterators spanning the underlying input
|
Chris@16
|
241 // sequence to parse. These iterators must at least
|
Chris@16
|
242 // conform to the requirements of the std::intput_iterator
|
Chris@16
|
243 // category.
|
Chris@16
|
244 // On exit the iterator 'first' will be updated to the
|
Chris@16
|
245 // position right after the last successfully matched
|
Chris@16
|
246 // token.
|
Chris@16
|
247 // lex: The lexer object (encoding the token definitions) to be
|
Chris@16
|
248 // used to convert the input sequence into a sequence of
|
Chris@16
|
249 // tokens. The LexerExpr type must conform to the
|
Chris@16
|
250 // lexer interface described in the corresponding section
|
Chris@16
|
251 // of the documentation.
|
Chris@16
|
252 // f: A functor (callable object) taking a single argument of
|
Chris@16
|
253 // the token type and returning a bool, indicating whether
|
Chris@16
|
254 // the tokenization should be canceled.
|
Chris@16
|
255 // initial_state: The name of the state the lexer should start matching.
|
Chris@16
|
256 // The default value is zero, causing the lexer to start
|
Chris@16
|
257 // in its 'INITIAL' state.
|
Chris@16
|
258 //
|
Chris@16
|
259 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
260 namespace detail
|
Chris@16
|
261 {
|
Chris@16
|
262 template <typename Token, typename F>
|
Chris@16
|
263 bool tokenize_callback(Token const& t, F f)
|
Chris@16
|
264 {
|
Chris@16
|
265 return f(t);
|
Chris@16
|
266 }
|
Chris@16
|
267
|
Chris@16
|
268 template <typename Token, typename Eval>
|
Chris@16
|
269 bool tokenize_callback(Token const& t, phoenix::actor<Eval> const& f)
|
Chris@16
|
270 {
|
Chris@16
|
271 f(t);
|
Chris@16
|
272 return true;
|
Chris@16
|
273 }
|
Chris@16
|
274
|
Chris@16
|
275 template <typename Token>
|
Chris@16
|
276 bool tokenize_callback(Token const& t, void (*f)(Token const&))
|
Chris@16
|
277 {
|
Chris@16
|
278 f(t);
|
Chris@16
|
279 return true;
|
Chris@16
|
280 }
|
Chris@16
|
281
|
Chris@16
|
282 template <typename Token>
|
Chris@16
|
283 bool tokenize_callback(Token const& t, bool (*f)(Token const&))
|
Chris@16
|
284 {
|
Chris@16
|
285 return f(t);
|
Chris@16
|
286 }
|
Chris@16
|
287 }
|
Chris@16
|
288
|
Chris@16
|
289 template <typename Iterator, typename Lexer, typename F>
|
Chris@16
|
290 inline bool
|
Chris@16
|
291 tokenize(Iterator& first, Iterator last, Lexer const& lex, F f
|
Chris@16
|
292 , typename Lexer::char_type const* initial_state = 0)
|
Chris@16
|
293 {
|
Chris@16
|
294 typedef typename Lexer::iterator_type iterator_type;
|
Chris@16
|
295
|
Chris@16
|
296 iterator_type iter = lex.begin(first, last, initial_state);
|
Chris@16
|
297 iterator_type end = lex.end();
|
Chris@16
|
298 for (/**/; iter != end && token_is_valid(*iter); ++iter)
|
Chris@16
|
299 {
|
Chris@16
|
300 if (!detail::tokenize_callback(*iter, f))
|
Chris@16
|
301 return false;
|
Chris@16
|
302 }
|
Chris@16
|
303 return (iter == end) ? true : false;
|
Chris@16
|
304 }
|
Chris@16
|
305
|
Chris@16
|
306 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
307 template <typename Iterator, typename Lexer>
|
Chris@16
|
308 inline bool
|
Chris@16
|
309 tokenize(Iterator& first, Iterator last, Lexer const& lex
|
Chris@16
|
310 , typename Lexer::char_type const* initial_state = 0)
|
Chris@16
|
311 {
|
Chris@16
|
312 typedef typename Lexer::iterator_type iterator_type;
|
Chris@16
|
313
|
Chris@16
|
314 iterator_type iter = lex.begin(first, last, initial_state);
|
Chris@16
|
315 iterator_type end = lex.end();
|
Chris@16
|
316
|
Chris@16
|
317 while (iter != end && token_is_valid(*iter))
|
Chris@16
|
318 ++iter;
|
Chris@16
|
319
|
Chris@16
|
320 return (iter == end) ? true : false;
|
Chris@16
|
321 }
|
Chris@16
|
322
|
Chris@16
|
323 }}}
|
Chris@16
|
324
|
Chris@16
|
325 #endif
|