parser.hpp 9.7 KB

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