Chris@16
|
1 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 /// \file parser.hpp
|
Chris@16
|
3 /// Contains the definition of regex_compiler, a factory for building regex objects
|
Chris@16
|
4 /// from strings.
|
Chris@16
|
5 //
|
Chris@16
|
6 // Copyright 2008 Eric Niebler. Distributed under the Boost
|
Chris@16
|
7 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
8 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
9
|
Chris@16
|
10 #ifndef BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_HPP_EAN_10_04_2005
|
Chris@16
|
11 #define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_HPP_EAN_10_04_2005
|
Chris@16
|
12
|
Chris@16
|
13 // MS compatible compilers support #pragma once
|
Chris@101
|
14 #if defined(_MSC_VER)
|
Chris@16
|
15 # pragma once
|
Chris@16
|
16 # pragma warning(push)
|
Chris@16
|
17 # pragma warning(disable : 4127) // conditional expression is constant
|
Chris@16
|
18 #endif
|
Chris@16
|
19
|
Chris@16
|
20 #include <boost/assert.hpp>
|
Chris@16
|
21 #include <boost/xpressive/regex_constants.hpp>
|
Chris@16
|
22 #include <boost/xpressive/detail/detail_fwd.hpp>
|
Chris@16
|
23 #include <boost/xpressive/detail/core/matchers.hpp>
|
Chris@16
|
24 #include <boost/xpressive/detail/utility/ignore_unused.hpp>
|
Chris@16
|
25 #include <boost/xpressive/detail/dynamic/dynamic.hpp>
|
Chris@16
|
26
|
Chris@16
|
27 // The Regular Expression grammar, in pseudo BNF:
|
Chris@16
|
28 //
|
Chris@16
|
29 // expression = alternates ;
|
Chris@16
|
30 //
|
Chris@16
|
31 // alternates = sequence, *('|', sequence) ;
|
Chris@16
|
32 //
|
Chris@16
|
33 // sequence = quant, *(quant) ;
|
Chris@16
|
34 //
|
Chris@16
|
35 // quant = atom, [*+?] ;
|
Chris@16
|
36 //
|
Chris@16
|
37 // atom = literal |
|
Chris@16
|
38 // '.' |
|
Chris@16
|
39 // '\' any |
|
Chris@16
|
40 // '(' expression ')' ;
|
Chris@16
|
41 //
|
Chris@16
|
42 // literal = not a meta-character ;
|
Chris@16
|
43 //
|
Chris@16
|
44
|
Chris@16
|
45 namespace boost { namespace xpressive { namespace detail
|
Chris@16
|
46 {
|
Chris@16
|
47
|
Chris@16
|
48 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
49 // make_char_xpression
|
Chris@16
|
50 //
|
Chris@16
|
51 template<typename BidiIter, typename Char, typename Traits>
|
Chris@16
|
52 inline sequence<BidiIter> make_char_xpression
|
Chris@16
|
53 (
|
Chris@16
|
54 Char ch
|
Chris@16
|
55 , regex_constants::syntax_option_type flags
|
Chris@16
|
56 , Traits const &tr
|
Chris@16
|
57 )
|
Chris@16
|
58 {
|
Chris@16
|
59 if(0 != (regex_constants::icase_ & flags))
|
Chris@16
|
60 {
|
Chris@16
|
61 literal_matcher<Traits, mpl::true_, mpl::false_> matcher(ch, tr);
|
Chris@16
|
62 return make_dynamic<BidiIter>(matcher);
|
Chris@16
|
63 }
|
Chris@16
|
64 else
|
Chris@16
|
65 {
|
Chris@16
|
66 literal_matcher<Traits, mpl::false_, mpl::false_> matcher(ch, tr);
|
Chris@16
|
67 return make_dynamic<BidiIter>(matcher);
|
Chris@16
|
68 }
|
Chris@16
|
69 }
|
Chris@16
|
70
|
Chris@16
|
71 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
72 // make_any_xpression
|
Chris@16
|
73 //
|
Chris@16
|
74 template<typename BidiIter, typename Traits>
|
Chris@16
|
75 inline sequence<BidiIter> make_any_xpression
|
Chris@16
|
76 (
|
Chris@16
|
77 regex_constants::syntax_option_type flags
|
Chris@16
|
78 , Traits const &tr
|
Chris@16
|
79 )
|
Chris@16
|
80 {
|
Chris@16
|
81 using namespace regex_constants;
|
Chris@16
|
82 typedef typename iterator_value<BidiIter>::type char_type;
|
Chris@16
|
83 typedef detail::set_matcher<Traits, mpl::int_<2> > set_matcher;
|
Chris@16
|
84 typedef literal_matcher<Traits, mpl::false_, mpl::true_> literal_matcher;
|
Chris@16
|
85
|
Chris@16
|
86 char_type const newline = tr.widen('\n');
|
Chris@16
|
87 set_matcher s;
|
Chris@16
|
88 s.set_[0] = newline;
|
Chris@16
|
89 s.set_[1] = 0;
|
Chris@16
|
90 s.inverse();
|
Chris@16
|
91
|
Chris@16
|
92 switch(((int)not_dot_newline | not_dot_null) & flags)
|
Chris@16
|
93 {
|
Chris@16
|
94 case not_dot_null:
|
Chris@16
|
95 return make_dynamic<BidiIter>(literal_matcher(char_type(0), tr));
|
Chris@16
|
96
|
Chris@16
|
97 case not_dot_newline:
|
Chris@16
|
98 return make_dynamic<BidiIter>(literal_matcher(newline, tr));
|
Chris@16
|
99
|
Chris@16
|
100 case (int)not_dot_newline | not_dot_null:
|
Chris@16
|
101 return make_dynamic<BidiIter>(s);
|
Chris@16
|
102
|
Chris@16
|
103 default:
|
Chris@16
|
104 return make_dynamic<BidiIter>(any_matcher());
|
Chris@16
|
105 }
|
Chris@16
|
106 }
|
Chris@16
|
107
|
Chris@16
|
108 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
109 // make_literal_xpression
|
Chris@16
|
110 //
|
Chris@16
|
111 template<typename BidiIter, typename Traits>
|
Chris@16
|
112 inline sequence<BidiIter> make_literal_xpression
|
Chris@16
|
113 (
|
Chris@16
|
114 typename Traits::string_type const &literal
|
Chris@16
|
115 , regex_constants::syntax_option_type flags
|
Chris@16
|
116 , Traits const &tr
|
Chris@16
|
117 )
|
Chris@16
|
118 {
|
Chris@16
|
119 BOOST_ASSERT(0 != literal.size());
|
Chris@16
|
120 if(1 == literal.size())
|
Chris@16
|
121 {
|
Chris@16
|
122 return make_char_xpression<BidiIter>(literal[0], flags, tr);
|
Chris@16
|
123 }
|
Chris@16
|
124
|
Chris@16
|
125 if(0 != (regex_constants::icase_ & flags))
|
Chris@16
|
126 {
|
Chris@16
|
127 string_matcher<Traits, mpl::true_> matcher(literal, tr);
|
Chris@16
|
128 return make_dynamic<BidiIter>(matcher);
|
Chris@16
|
129 }
|
Chris@16
|
130 else
|
Chris@16
|
131 {
|
Chris@16
|
132 string_matcher<Traits, mpl::false_> matcher(literal, tr);
|
Chris@16
|
133 return make_dynamic<BidiIter>(matcher);
|
Chris@16
|
134 }
|
Chris@16
|
135 }
|
Chris@16
|
136
|
Chris@16
|
137 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
138 // make_backref_xpression
|
Chris@16
|
139 //
|
Chris@16
|
140 template<typename BidiIter, typename Traits>
|
Chris@16
|
141 inline sequence<BidiIter> make_backref_xpression
|
Chris@16
|
142 (
|
Chris@16
|
143 int mark_nbr
|
Chris@16
|
144 , regex_constants::syntax_option_type flags
|
Chris@16
|
145 , Traits const &tr
|
Chris@16
|
146 )
|
Chris@16
|
147 {
|
Chris@16
|
148 if(0 != (regex_constants::icase_ & flags))
|
Chris@16
|
149 {
|
Chris@16
|
150 return make_dynamic<BidiIter>
|
Chris@16
|
151 (
|
Chris@16
|
152 mark_matcher<Traits, mpl::true_>(mark_nbr, tr)
|
Chris@16
|
153 );
|
Chris@16
|
154 }
|
Chris@16
|
155 else
|
Chris@16
|
156 {
|
Chris@16
|
157 return make_dynamic<BidiIter>
|
Chris@16
|
158 (
|
Chris@16
|
159 mark_matcher<Traits, mpl::false_>(mark_nbr, tr)
|
Chris@16
|
160 );
|
Chris@16
|
161 }
|
Chris@16
|
162 }
|
Chris@16
|
163
|
Chris@16
|
164 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
165 // merge_charset
|
Chris@16
|
166 //
|
Chris@16
|
167 template<typename Char, typename Traits>
|
Chris@16
|
168 inline void merge_charset
|
Chris@16
|
169 (
|
Chris@16
|
170 basic_chset<Char> &basic
|
Chris@16
|
171 , compound_charset<Traits> const &compound
|
Chris@16
|
172 , Traits const &tr
|
Chris@16
|
173 )
|
Chris@16
|
174 {
|
Chris@16
|
175 detail::ignore_unused(tr);
|
Chris@16
|
176 if(0 != compound.posix_yes())
|
Chris@16
|
177 {
|
Chris@16
|
178 typename Traits::char_class_type mask = compound.posix_yes();
|
Chris@16
|
179 for(int i = 0; i <= static_cast<int>(UCHAR_MAX); ++i)
|
Chris@16
|
180 {
|
Chris@16
|
181 if(tr.isctype((Char)i, mask))
|
Chris@16
|
182 {
|
Chris@16
|
183 basic.set((Char)i);
|
Chris@16
|
184 }
|
Chris@16
|
185 }
|
Chris@16
|
186 }
|
Chris@16
|
187
|
Chris@16
|
188 if(!compound.posix_no().empty())
|
Chris@16
|
189 {
|
Chris@16
|
190 for(std::size_t j = 0; j < compound.posix_no().size(); ++j)
|
Chris@16
|
191 {
|
Chris@16
|
192 typename Traits::char_class_type mask = compound.posix_no()[j];
|
Chris@16
|
193 for(int i = 0; i <= static_cast<int>(UCHAR_MAX); ++i)
|
Chris@16
|
194 {
|
Chris@16
|
195 if(!tr.isctype((Char)i, mask))
|
Chris@16
|
196 {
|
Chris@16
|
197 basic.set((Char)i);
|
Chris@16
|
198 }
|
Chris@16
|
199 }
|
Chris@16
|
200 }
|
Chris@16
|
201 }
|
Chris@16
|
202
|
Chris@16
|
203 if(compound.is_inverted())
|
Chris@16
|
204 {
|
Chris@16
|
205 basic.inverse();
|
Chris@16
|
206 }
|
Chris@16
|
207 }
|
Chris@16
|
208
|
Chris@16
|
209 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
210 // make_charset_xpression
|
Chris@16
|
211 //
|
Chris@16
|
212 template<typename BidiIter, typename Traits>
|
Chris@16
|
213 inline sequence<BidiIter> make_charset_xpression
|
Chris@16
|
214 (
|
Chris@16
|
215 compound_charset<Traits> &chset
|
Chris@16
|
216 , Traits const &tr
|
Chris@16
|
217 , regex_constants::syntax_option_type flags
|
Chris@16
|
218 )
|
Chris@16
|
219 {
|
Chris@16
|
220 typedef typename Traits::char_type char_type;
|
Chris@16
|
221 bool const icase = (0 != (regex_constants::icase_ & flags));
|
Chris@16
|
222 bool const optimize = is_narrow_char<char_type>::value && 0 != (regex_constants::optimize & flags);
|
Chris@16
|
223
|
Chris@16
|
224 // don't care about compile speed -- fold eveything into a bitset<256>
|
Chris@16
|
225 if(optimize)
|
Chris@16
|
226 {
|
Chris@16
|
227 typedef basic_chset<char_type> charset_type;
|
Chris@16
|
228 charset_type charset(chset.base());
|
Chris@16
|
229 if(icase)
|
Chris@16
|
230 {
|
Chris@16
|
231 charset_matcher<Traits, mpl::true_, charset_type> matcher(charset);
|
Chris@16
|
232 merge_charset(matcher.charset_, chset, tr);
|
Chris@16
|
233 return make_dynamic<BidiIter>(matcher);
|
Chris@16
|
234 }
|
Chris@16
|
235 else
|
Chris@16
|
236 {
|
Chris@16
|
237 charset_matcher<Traits, mpl::false_, charset_type> matcher(charset);
|
Chris@16
|
238 merge_charset(matcher.charset_, chset, tr);
|
Chris@16
|
239 return make_dynamic<BidiIter>(matcher);
|
Chris@16
|
240 }
|
Chris@16
|
241 }
|
Chris@16
|
242
|
Chris@16
|
243 // special case to make [[:digit:]] fast
|
Chris@16
|
244 else if(chset.base().empty() && chset.posix_no().empty())
|
Chris@16
|
245 {
|
Chris@16
|
246 BOOST_ASSERT(0 != chset.posix_yes());
|
Chris@16
|
247 posix_charset_matcher<Traits> matcher(chset.posix_yes(), chset.is_inverted());
|
Chris@16
|
248 return make_dynamic<BidiIter>(matcher);
|
Chris@16
|
249 }
|
Chris@16
|
250
|
Chris@16
|
251 // default, slow
|
Chris@16
|
252 else
|
Chris@16
|
253 {
|
Chris@16
|
254 if(icase)
|
Chris@16
|
255 {
|
Chris@16
|
256 charset_matcher<Traits, mpl::true_> matcher(chset);
|
Chris@16
|
257 return make_dynamic<BidiIter>(matcher);
|
Chris@16
|
258 }
|
Chris@16
|
259 else
|
Chris@16
|
260 {
|
Chris@16
|
261 charset_matcher<Traits, mpl::false_> matcher(chset);
|
Chris@16
|
262 return make_dynamic<BidiIter>(matcher);
|
Chris@16
|
263 }
|
Chris@16
|
264 }
|
Chris@16
|
265 }
|
Chris@16
|
266
|
Chris@16
|
267 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
268 // make_posix_charset_xpression
|
Chris@16
|
269 //
|
Chris@16
|
270 template<typename BidiIter, typename Traits>
|
Chris@16
|
271 inline sequence<BidiIter> make_posix_charset_xpression
|
Chris@16
|
272 (
|
Chris@16
|
273 typename Traits::char_class_type m
|
Chris@16
|
274 , bool no
|
Chris@16
|
275 , regex_constants::syntax_option_type //flags
|
Chris@16
|
276 , Traits const & //traits
|
Chris@16
|
277 )
|
Chris@16
|
278 {
|
Chris@16
|
279 posix_charset_matcher<Traits> charset(m, no);
|
Chris@16
|
280 return make_dynamic<BidiIter>(charset);
|
Chris@16
|
281 }
|
Chris@16
|
282
|
Chris@16
|
283 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
284 // make_assert_begin_line
|
Chris@16
|
285 //
|
Chris@16
|
286 template<typename BidiIter, typename Traits>
|
Chris@16
|
287 inline sequence<BidiIter> make_assert_begin_line
|
Chris@16
|
288 (
|
Chris@16
|
289 regex_constants::syntax_option_type flags
|
Chris@16
|
290 , Traits const &tr
|
Chris@16
|
291 )
|
Chris@16
|
292 {
|
Chris@16
|
293 if(0 != (regex_constants::single_line & flags))
|
Chris@16
|
294 {
|
Chris@16
|
295 return detail::make_dynamic<BidiIter>(detail::assert_bos_matcher());
|
Chris@16
|
296 }
|
Chris@16
|
297 else
|
Chris@16
|
298 {
|
Chris@16
|
299 detail::assert_bol_matcher<Traits> matcher(tr);
|
Chris@16
|
300 return detail::make_dynamic<BidiIter>(matcher);
|
Chris@16
|
301 }
|
Chris@16
|
302 }
|
Chris@16
|
303
|
Chris@16
|
304 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
305 // make_assert_end_line
|
Chris@16
|
306 //
|
Chris@16
|
307 template<typename BidiIter, typename Traits>
|
Chris@16
|
308 inline sequence<BidiIter> make_assert_end_line
|
Chris@16
|
309 (
|
Chris@16
|
310 regex_constants::syntax_option_type flags
|
Chris@16
|
311 , Traits const &tr
|
Chris@16
|
312 )
|
Chris@16
|
313 {
|
Chris@16
|
314 if(0 != (regex_constants::single_line & flags))
|
Chris@16
|
315 {
|
Chris@16
|
316 return detail::make_dynamic<BidiIter>(detail::assert_eos_matcher());
|
Chris@16
|
317 }
|
Chris@16
|
318 else
|
Chris@16
|
319 {
|
Chris@16
|
320 detail::assert_eol_matcher<Traits> matcher(tr);
|
Chris@16
|
321 return detail::make_dynamic<BidiIter>(matcher);
|
Chris@16
|
322 }
|
Chris@16
|
323 }
|
Chris@16
|
324
|
Chris@16
|
325 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
326 // make_assert_word
|
Chris@16
|
327 //
|
Chris@16
|
328 template<typename BidiIter, typename Cond, typename Traits>
|
Chris@16
|
329 inline sequence<BidiIter> make_assert_word(Cond, Traits const &tr)
|
Chris@16
|
330 {
|
Chris@16
|
331 return detail::make_dynamic<BidiIter>
|
Chris@16
|
332 (
|
Chris@16
|
333 detail::assert_word_matcher<Cond, Traits>(tr)
|
Chris@16
|
334 );
|
Chris@16
|
335 }
|
Chris@16
|
336
|
Chris@16
|
337 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
338 // make_independent_end_xpression
|
Chris@16
|
339 //
|
Chris@16
|
340 template<typename BidiIter>
|
Chris@16
|
341 inline sequence<BidiIter> make_independent_end_xpression(bool pure)
|
Chris@16
|
342 {
|
Chris@16
|
343 if(pure)
|
Chris@16
|
344 {
|
Chris@16
|
345 return detail::make_dynamic<BidiIter>(detail::true_matcher());
|
Chris@16
|
346 }
|
Chris@16
|
347 else
|
Chris@16
|
348 {
|
Chris@16
|
349 return detail::make_dynamic<BidiIter>(detail::independent_end_matcher());
|
Chris@16
|
350 }
|
Chris@16
|
351 }
|
Chris@16
|
352
|
Chris@16
|
353 }}} // namespace boost::xpressive::detail
|
Chris@16
|
354
|
Chris@101
|
355 #if defined(_MSC_VER)
|
Chris@16
|
356 # pragma warning(pop)
|
Chris@16
|
357 #endif
|
Chris@16
|
358
|
Chris@16
|
359 #endif
|