/////////////////////////////////////////////////////////////////////////////// /// \file parser.hpp /// Contains the definition of regex_compiler, a factory for building regex objects /// from strings. // // Copyright 2008 Eric Niebler. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_HPP_EAN_10_04_2005 #define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_HPP_EAN_10_04_2005 // MS compatible compilers support #pragma once #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once # pragma warning(push) # pragma warning(disable : 4127) // conditional expression is constant #endif #include #include #include #include #include #include // The Regular Expression grammar, in pseudo BNF: // // expression = alternates ; // // alternates = sequence, *('|', sequence) ; // // sequence = quant, *(quant) ; // // quant = atom, [*+?] ; // // atom = literal | // '.' | // '\' any | // '(' expression ')' ; // // literal = not a meta-character ; // namespace boost { namespace xpressive { namespace detail { /////////////////////////////////////////////////////////////////////////////// // make_char_xpression // template inline sequence make_char_xpression ( Char ch , regex_constants::syntax_option_type flags , Traits const &tr ) { if(0 != (regex_constants::icase_ & flags)) { literal_matcher matcher(ch, tr); return make_dynamic(matcher); } else { literal_matcher matcher(ch, tr); return make_dynamic(matcher); } } /////////////////////////////////////////////////////////////////////////////// // make_any_xpression // template inline sequence make_any_xpression ( regex_constants::syntax_option_type flags , Traits const &tr ) { using namespace regex_constants; typedef typename iterator_value::type char_type; typedef detail::set_matcher > set_matcher; typedef literal_matcher literal_matcher; char_type const newline = tr.widen('\n'); set_matcher s; s.set_[0] = newline; s.set_[1] = 0; s.inverse(); switch(((int)not_dot_newline | not_dot_null) & flags) { case not_dot_null: return make_dynamic(literal_matcher(char_type(0), tr)); case not_dot_newline: return make_dynamic(literal_matcher(newline, tr)); case (int)not_dot_newline | not_dot_null: return make_dynamic(s); default: return make_dynamic(any_matcher()); } } /////////////////////////////////////////////////////////////////////////////// // make_literal_xpression // template inline sequence make_literal_xpression ( typename Traits::string_type const &literal , regex_constants::syntax_option_type flags , Traits const &tr ) { BOOST_ASSERT(0 != literal.size()); if(1 == literal.size()) { return make_char_xpression(literal[0], flags, tr); } if(0 != (regex_constants::icase_ & flags)) { string_matcher matcher(literal, tr); return make_dynamic(matcher); } else { string_matcher matcher(literal, tr); return make_dynamic(matcher); } } /////////////////////////////////////////////////////////////////////////////// // make_backref_xpression // template inline sequence make_backref_xpression ( int mark_nbr , regex_constants::syntax_option_type flags , Traits const &tr ) { if(0 != (regex_constants::icase_ & flags)) { return make_dynamic ( mark_matcher(mark_nbr, tr) ); } else { return make_dynamic ( mark_matcher(mark_nbr, tr) ); } } /////////////////////////////////////////////////////////////////////////////// // merge_charset // template inline void merge_charset ( basic_chset &basic , compound_charset const &compound , Traits const &tr ) { detail::ignore_unused(tr); if(0 != compound.posix_yes()) { typename Traits::char_class_type mask = compound.posix_yes(); for(int i = 0; i <= static_cast(UCHAR_MAX); ++i) { if(tr.isctype((Char)i, mask)) { basic.set((Char)i); } } } if(!compound.posix_no().empty()) { for(std::size_t j = 0; j < compound.posix_no().size(); ++j) { typename Traits::char_class_type mask = compound.posix_no()[j]; for(int i = 0; i <= static_cast(UCHAR_MAX); ++i) { if(!tr.isctype((Char)i, mask)) { basic.set((Char)i); } } } } if(compound.is_inverted()) { basic.inverse(); } } /////////////////////////////////////////////////////////////////////////////// // make_charset_xpression // template inline sequence make_charset_xpression ( compound_charset &chset , Traits const &tr , regex_constants::syntax_option_type flags ) { typedef typename Traits::char_type char_type; bool const icase = (0 != (regex_constants::icase_ & flags)); bool const optimize = is_narrow_char::value && 0 != (regex_constants::optimize & flags); // don't care about compile speed -- fold eveything into a bitset<256> if(optimize) { typedef basic_chset charset_type; charset_type charset(chset.base()); if(icase) { charset_matcher matcher(charset); merge_charset(matcher.charset_, chset, tr); return make_dynamic(matcher); } else { charset_matcher matcher(charset); merge_charset(matcher.charset_, chset, tr); return make_dynamic(matcher); } } // special case to make [[:digit:]] fast else if(chset.base().empty() && chset.posix_no().empty()) { BOOST_ASSERT(0 != chset.posix_yes()); posix_charset_matcher matcher(chset.posix_yes(), chset.is_inverted()); return make_dynamic(matcher); } // default, slow else { if(icase) { charset_matcher matcher(chset); return make_dynamic(matcher); } else { charset_matcher matcher(chset); return make_dynamic(matcher); } } } /////////////////////////////////////////////////////////////////////////////// // make_posix_charset_xpression // template inline sequence make_posix_charset_xpression ( typename Traits::char_class_type m , bool no , regex_constants::syntax_option_type //flags , Traits const & //traits ) { posix_charset_matcher charset(m, no); return make_dynamic(charset); } /////////////////////////////////////////////////////////////////////////////// // make_assert_begin_line // template inline sequence make_assert_begin_line ( regex_constants::syntax_option_type flags , Traits const &tr ) { if(0 != (regex_constants::single_line & flags)) { return detail::make_dynamic(detail::assert_bos_matcher()); } else { detail::assert_bol_matcher matcher(tr); return detail::make_dynamic(matcher); } } /////////////////////////////////////////////////////////////////////////////// // make_assert_end_line // template inline sequence make_assert_end_line ( regex_constants::syntax_option_type flags , Traits const &tr ) { if(0 != (regex_constants::single_line & flags)) { return detail::make_dynamic(detail::assert_eos_matcher()); } else { detail::assert_eol_matcher matcher(tr); return detail::make_dynamic(matcher); } } /////////////////////////////////////////////////////////////////////////////// // make_assert_word // template inline sequence make_assert_word(Cond, Traits const &tr) { typedef typename iterator_value::type char_type; return detail::make_dynamic ( detail::assert_word_matcher(tr) ); } /////////////////////////////////////////////////////////////////////////////// // make_independent_end_xpression // template inline sequence make_independent_end_xpression(bool pure) { if(pure) { return detail::make_dynamic(detail::true_matcher()); } else { return detail::make_dynamic(detail::independent_end_matcher()); } } }}} // namespace boost::xpressive::detail #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma warning(pop) #endif #endif