Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:11:11

0001 ///////////////////////////////////////////////////////////////////////////////
0002 /// \file parser.hpp
0003 /// Contains the definition of regex_compiler, a factory for building regex objects
0004 /// from strings.
0005 //
0006 //  Copyright 2008 Eric Niebler. Distributed under the Boost
0007 //  Software License, Version 1.0. (See accompanying file
0008 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 #ifndef BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_HPP_EAN_10_04_2005
0011 #define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_HPP_EAN_10_04_2005
0012 
0013 // MS compatible compilers support #pragma once
0014 #if defined(_MSC_VER)
0015 # pragma once
0016 # pragma warning(push)
0017 # pragma warning(disable : 4127) // conditional expression is constant
0018 #endif
0019 
0020 #include <boost/assert.hpp>
0021 #include <boost/xpressive/regex_constants.hpp>
0022 #include <boost/xpressive/detail/detail_fwd.hpp>
0023 #include <boost/xpressive/detail/core/matchers.hpp>
0024 #include <boost/xpressive/detail/utility/ignore_unused.hpp>
0025 #include <boost/xpressive/detail/dynamic/dynamic.hpp>
0026 
0027 // The Regular Expression grammar, in pseudo BNF:
0028 //
0029 // expression   = alternates ;
0030 //
0031 // alternates   = sequence, *('|', sequence) ;
0032 //
0033 // sequence     = quant, *(quant) ;
0034 //
0035 // quant        = atom, [*+?] ;
0036 //
0037 // atom         = literal             |
0038 //                '.'                 |
0039 //                '\' any             |
0040 //                '(' expression ')' ;
0041 //
0042 // literal      = not a meta-character ;
0043 //
0044 
0045 namespace boost { namespace xpressive { namespace detail
0046 {
0047 
0048 ///////////////////////////////////////////////////////////////////////////////
0049 // make_char_xpression
0050 //
0051 template<typename BidiIter, typename Char, typename Traits>
0052 inline sequence<BidiIter> make_char_xpression
0053 (
0054     Char ch
0055   , regex_constants::syntax_option_type flags
0056   , Traits const &tr
0057 )
0058 {
0059     if(0 != (regex_constants::icase_ & flags))
0060     {
0061         literal_matcher<Traits, mpl::true_, mpl::false_> matcher(ch, tr);
0062         return make_dynamic<BidiIter>(matcher);
0063     }
0064     else
0065     {
0066         literal_matcher<Traits, mpl::false_, mpl::false_> matcher(ch, tr);
0067         return make_dynamic<BidiIter>(matcher);
0068     }
0069 }
0070 
0071 ///////////////////////////////////////////////////////////////////////////////
0072 // make_any_xpression
0073 //
0074 template<typename BidiIter, typename Traits>
0075 inline sequence<BidiIter> make_any_xpression
0076 (
0077     regex_constants::syntax_option_type flags
0078   , Traits const &tr
0079 )
0080 {
0081     using namespace regex_constants;
0082     typedef typename iterator_value<BidiIter>::type char_type;
0083     typedef detail::set_matcher<Traits, mpl::int_<2> > set_matcher;
0084     typedef literal_matcher<Traits, mpl::false_, mpl::true_> literal_matcher;
0085 
0086     char_type const newline = tr.widen('\n');
0087     set_matcher s;
0088     s.set_[0] = newline;
0089     s.set_[1] = 0;
0090     s.inverse();
0091 
0092     switch(((int)not_dot_newline | not_dot_null) & flags)
0093     {
0094     case not_dot_null:
0095         return make_dynamic<BidiIter>(literal_matcher(char_type(0), tr));
0096 
0097     case not_dot_newline:
0098         return make_dynamic<BidiIter>(literal_matcher(newline, tr));
0099 
0100     case (int)not_dot_newline | not_dot_null:
0101         return make_dynamic<BidiIter>(s);
0102 
0103     default:
0104         return make_dynamic<BidiIter>(any_matcher());
0105     }
0106 }
0107 
0108 ///////////////////////////////////////////////////////////////////////////////
0109 // make_literal_xpression
0110 //
0111 template<typename BidiIter, typename Traits>
0112 inline sequence<BidiIter> make_literal_xpression
0113 (
0114     typename Traits::string_type const &literal
0115   , regex_constants::syntax_option_type flags
0116   , Traits const &tr
0117 )
0118 {
0119     BOOST_ASSERT(0 != literal.size());
0120     if(1 == literal.size())
0121     {
0122         return make_char_xpression<BidiIter>(literal[0], flags, tr);
0123     }
0124 
0125     if(0 != (regex_constants::icase_ & flags))
0126     {
0127         string_matcher<Traits, mpl::true_> matcher(literal, tr);
0128         return make_dynamic<BidiIter>(matcher);
0129     }
0130     else
0131     {
0132         string_matcher<Traits, mpl::false_> matcher(literal, tr);
0133         return make_dynamic<BidiIter>(matcher);
0134     }
0135 }
0136 
0137 ///////////////////////////////////////////////////////////////////////////////
0138 // make_backref_xpression
0139 //
0140 template<typename BidiIter, typename Traits>
0141 inline sequence<BidiIter> make_backref_xpression
0142 (
0143     int mark_nbr
0144   , regex_constants::syntax_option_type flags
0145   , Traits const &tr
0146 )
0147 {
0148     if(0 != (regex_constants::icase_ & flags))
0149     {
0150         return make_dynamic<BidiIter>
0151         (
0152             mark_matcher<Traits, mpl::true_>(mark_nbr, tr)
0153         );
0154     }
0155     else
0156     {
0157         return make_dynamic<BidiIter>
0158         (
0159             mark_matcher<Traits, mpl::false_>(mark_nbr, tr)
0160         );
0161     }
0162 }
0163 
0164 ///////////////////////////////////////////////////////////////////////////////
0165 // merge_charset
0166 //
0167 template<typename Char, typename Traits>
0168 inline void merge_charset
0169 (
0170     basic_chset<Char> &basic
0171   , compound_charset<Traits> const &compound
0172   , Traits const &tr
0173 )
0174 {
0175     detail::ignore_unused(tr);
0176     if(0 != compound.posix_yes())
0177     {
0178         typename Traits::char_class_type mask = compound.posix_yes();
0179         for(int i = 0; i <= static_cast<int>(UCHAR_MAX); ++i)
0180         {
0181             if(tr.isctype((Char)i, mask))
0182             {
0183                 basic.set((Char)i);
0184             }
0185         }
0186     }
0187 
0188     if(!compound.posix_no().empty())
0189     {
0190         for(std::size_t j = 0; j < compound.posix_no().size(); ++j)
0191         {
0192             typename Traits::char_class_type mask = compound.posix_no()[j];
0193             for(int i = 0; i <= static_cast<int>(UCHAR_MAX); ++i)
0194             {
0195                 if(!tr.isctype((Char)i, mask))
0196                 {
0197                     basic.set((Char)i);
0198                 }
0199             }
0200         }
0201     }
0202 
0203     if(compound.is_inverted())
0204     {
0205         basic.inverse();
0206     }
0207 }
0208 
0209 ///////////////////////////////////////////////////////////////////////////////
0210 // make_charset_xpression
0211 //
0212 template<typename BidiIter, typename Traits>
0213 inline sequence<BidiIter> make_charset_xpression
0214 (
0215     compound_charset<Traits> &chset
0216   , Traits const &tr
0217   , regex_constants::syntax_option_type flags
0218 )
0219 {
0220     typedef typename Traits::char_type char_type;
0221     bool const icase = (0 != (regex_constants::icase_ & flags));
0222     bool const optimize = is_narrow_char<char_type>::value && 0 != (regex_constants::optimize & flags);
0223 
0224     // don't care about compile speed -- fold eveything into a bitset<256>
0225     if(optimize)
0226     {
0227         typedef basic_chset<char_type> charset_type;
0228         charset_type charset(chset.base());
0229         if(icase)
0230         {
0231             charset_matcher<Traits, mpl::true_, charset_type> matcher(charset);
0232             merge_charset(matcher.charset_, chset, tr);
0233             return make_dynamic<BidiIter>(matcher);
0234         }
0235         else
0236         {
0237             charset_matcher<Traits, mpl::false_, charset_type> matcher(charset);
0238             merge_charset(matcher.charset_, chset, tr);
0239             return make_dynamic<BidiIter>(matcher);
0240         }
0241     }
0242 
0243     // special case to make [[:digit:]] fast
0244     else if(chset.base().empty() && chset.posix_no().empty())
0245     {
0246         BOOST_ASSERT(0 != chset.posix_yes());
0247         posix_charset_matcher<Traits> matcher(chset.posix_yes(), chset.is_inverted());
0248         return make_dynamic<BidiIter>(matcher);
0249     }
0250 
0251     // default, slow
0252     else
0253     {
0254         if(icase)
0255         {
0256             charset_matcher<Traits, mpl::true_> matcher(chset);
0257             return make_dynamic<BidiIter>(matcher);
0258         }
0259         else
0260         {
0261             charset_matcher<Traits, mpl::false_> matcher(chset);
0262             return make_dynamic<BidiIter>(matcher);
0263         }
0264     }
0265 }
0266 
0267 ///////////////////////////////////////////////////////////////////////////////
0268 // make_posix_charset_xpression
0269 //
0270 template<typename BidiIter, typename Traits>
0271 inline sequence<BidiIter> make_posix_charset_xpression
0272 (
0273     typename Traits::char_class_type m
0274   , bool no
0275   , regex_constants::syntax_option_type //flags
0276   , Traits const & //traits
0277 )
0278 {
0279     posix_charset_matcher<Traits> charset(m, no);
0280     return make_dynamic<BidiIter>(charset);
0281 }
0282 
0283 ///////////////////////////////////////////////////////////////////////////////
0284 // make_assert_begin_line
0285 //
0286 template<typename BidiIter, typename Traits>
0287 inline sequence<BidiIter> make_assert_begin_line
0288 (
0289     regex_constants::syntax_option_type flags
0290   , Traits const &tr
0291 )
0292 {
0293     if(0 != (regex_constants::single_line & flags))
0294     {
0295         return detail::make_dynamic<BidiIter>(detail::assert_bos_matcher());
0296     }
0297     else
0298     {
0299         detail::assert_bol_matcher<Traits> matcher(tr);
0300         return detail::make_dynamic<BidiIter>(matcher);
0301     }
0302 }
0303 
0304 ///////////////////////////////////////////////////////////////////////////////
0305 // make_assert_end_line
0306 //
0307 template<typename BidiIter, typename Traits>
0308 inline sequence<BidiIter> make_assert_end_line
0309 (
0310     regex_constants::syntax_option_type flags
0311   , Traits const &tr
0312 )
0313 {
0314     if(0 != (regex_constants::single_line & flags))
0315     {
0316         return detail::make_dynamic<BidiIter>(detail::assert_eos_matcher());
0317     }
0318     else
0319     {
0320         detail::assert_eol_matcher<Traits> matcher(tr);
0321         return detail::make_dynamic<BidiIter>(matcher);
0322     }
0323 }
0324 
0325 ///////////////////////////////////////////////////////////////////////////////
0326 // make_assert_word
0327 //
0328 template<typename BidiIter, typename Cond, typename Traits>
0329 inline sequence<BidiIter> make_assert_word(Cond, Traits const &tr)
0330 {
0331     return detail::make_dynamic<BidiIter>
0332     (
0333         detail::assert_word_matcher<Cond, Traits>(tr)
0334     );
0335 }
0336 
0337 ///////////////////////////////////////////////////////////////////////////////
0338 // make_independent_end_xpression
0339 //
0340 template<typename BidiIter>
0341 inline sequence<BidiIter> make_independent_end_xpression(bool pure)
0342 {
0343     if(pure)
0344     {
0345         return detail::make_dynamic<BidiIter>(detail::true_matcher());
0346     }
0347     else
0348     {
0349         return detail::make_dynamic<BidiIter>(detail::independent_end_matcher());
0350     }
0351 }
0352 
0353 }}} // namespace boost::xpressive::detail
0354 
0355 #if defined(_MSC_VER)
0356 # pragma warning(pop)
0357 #endif
0358 
0359 #endif