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