forked from boostorg/regex
Completed perl feature set.
Merged in changes to Docs from main branch. [SVN r22785]
This commit is contained in:
1 parent
b5cf51fbc6
commit
bb264b055f
38 files changed
+2253
-1786
No files matched your search
@@ -185,6 +185,14 @@ public:
|
||||
{
|
||||
return m_pdata->m_flags;
|
||||
}
|
||||
void flags(regbase::flag_type f)
|
||||
{
|
||||
m_pdata->m_flags = f;
|
||||
if(m_icase != static_cast<bool>(f & regbase::icase))
|
||||
{
|
||||
m_icase = static_cast<bool>(f & regbase::icase);
|
||||
}
|
||||
}
|
||||
re_syntax_base* append_state(syntax_element_type t, std::size_t s = sizeof(re_syntax_base));
|
||||
re_syntax_base* insert_state(std::ptrdiff_t pos, syntax_element_type t, std::size_t s = sizeof(re_syntax_base));
|
||||
re_literal* append_literal(charT c);
|
||||
@@ -633,10 +641,19 @@ void basic_regex_creator<charT, traits>::create_startmaps(re_syntax_base* state)
|
||||
// recursive implementation:
|
||||
// create the last map in the machine first, so that earlier maps
|
||||
// can make use of the result...
|
||||
|
||||
// start by saving the case setting:
|
||||
bool l_icase = m_icase;
|
||||
|
||||
while(state)
|
||||
{
|
||||
switch(state->type)
|
||||
{
|
||||
case syntax_element_toggle_case:
|
||||
// we need to track case changes here:
|
||||
m_icase = static_cast<re_case*>(state)->icase;
|
||||
state = state->next.p;
|
||||
continue;
|
||||
case syntax_element_alt:
|
||||
case syntax_element_rep:
|
||||
case syntax_element_dot_rep:
|
||||
@@ -652,6 +669,8 @@ void basic_regex_creator<charT, traits>::create_startmaps(re_syntax_base* state)
|
||||
create_startmap(static_cast<re_alt*>(state)->alt.p, static_cast<re_alt*>(state)->_map, &static_cast<re_alt*>(state)->can_be_null, mask_skip);
|
||||
// adjust the type of the state to allow for faster matching:
|
||||
state->type = this->get_repeat_type(state);
|
||||
// restore case sensitivity:
|
||||
m_icase = l_icase;
|
||||
return;
|
||||
case syntax_element_backstep:
|
||||
// we need to calculate how big the backstep is:
|
||||
@@ -662,6 +681,8 @@ void basic_regex_creator<charT, traits>::create_startmaps(re_syntax_base* state)
|
||||
state = state->next.p;
|
||||
}
|
||||
}
|
||||
// restore case sensitivity:
|
||||
m_icase = l_icase;
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
@@ -726,10 +747,18 @@ template <class charT, class traits>
|
||||
void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state, unsigned char* l_map, unsigned int* pnull, unsigned char mask)
|
||||
{
|
||||
int not_last_jump = 1;
|
||||
|
||||
// track case sensitivity:
|
||||
bool l_icase = m_icase;
|
||||
|
||||
while(state)
|
||||
{
|
||||
switch(state->type)
|
||||
{
|
||||
case syntax_element_toggle_case:
|
||||
l_icase = static_cast<re_case*>(state)->icase;
|
||||
state = state->next.p;
|
||||
break;
|
||||
case syntax_element_literal:
|
||||
{
|
||||
// don't set anything in *pnull, set each element in l_map
|
||||
@@ -740,7 +769,7 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
|
||||
charT first_char = *static_cast<charT*>(static_cast<void*>(static_cast<re_literal*>(state) + 1));
|
||||
for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i)
|
||||
{
|
||||
if(m_traits.translate(static_cast<charT>(i), m_icase) == first_char)
|
||||
if(m_traits.translate(static_cast<charT>(i), l_icase) == first_char)
|
||||
l_map[i] |= mask;
|
||||
}
|
||||
}
|
||||
@@ -826,7 +855,7 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
|
||||
for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i)
|
||||
{
|
||||
charT c = static_cast<charT>(i);
|
||||
if(&c != re_is_set_member(&c, &c + 1, static_cast<re_set_long<mask_type>*>(state), *m_pdata))
|
||||
if(&c != re_is_set_member(&c, &c + 1, static_cast<re_set_long<mask_type>*>(state), *m_pdata, m_icase))
|
||||
l_map[i] |= mask;
|
||||
}
|
||||
}
|
||||
@@ -841,7 +870,7 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
|
||||
for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i)
|
||||
{
|
||||
if(static_cast<re_set*>(state)->_map[
|
||||
static_cast<unsigned char>(m_traits.translate(static_cast<charT>(i), this->m_icase))])
|
||||
static_cast<unsigned char>(m_traits.translate(static_cast<charT>(i), l_icase))])
|
||||
l_map[i] |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
bool parse_perl_extension();
|
||||
digraph<charT> get_next_set_literal(basic_char_set<charT, traits>& char_set);
|
||||
charT unescape_character();
|
||||
regex_constants::syntax_option_type parse_options();
|
||||
|
||||
private:
|
||||
typedef bool (basic_regex_parser::*parser_proc_type)();
|
||||
@@ -65,6 +66,7 @@ private:
|
||||
unsigned m_mark_count; // how many sub-expressions we have
|
||||
std::ptrdiff_t m_paren_start; // where the last seen ')' began (where repeats are inserted).
|
||||
std::ptrdiff_t m_alt_insert_point; // where to insert the next alternative
|
||||
bool m_has_case_change; // true if somewhere in the current block the case has changed
|
||||
|
||||
basic_regex_parser& operator=(const basic_regex_parser&);
|
||||
basic_regex_parser(const basic_regex_parser&);
|
||||
@@ -72,7 +74,7 @@ private:
|
||||
|
||||
template <class charT, class traits>
|
||||
basic_regex_parser<charT, traits>::basic_regex_parser(regex_data<charT, traits>* data)
|
||||
: basic_regex_creator<charT, traits>(data), m_mark_count(0), m_paren_start(0), m_alt_insert_point(0)
|
||||
: basic_regex_creator<charT, traits>(data), m_mark_count(0), m_paren_start(0), m_alt_insert_point(0), m_has_case_change(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -103,6 +105,8 @@ void basic_regex_parser<charT, traits>::parse(const charT* p1, const charT* p2,
|
||||
|
||||
// parse all our characters:
|
||||
bool result = parse_all();
|
||||
// reset flags as a global scope (?imsx) may have altered them:
|
||||
this->flags(flags);
|
||||
// if we haven't gobbled up all the characters then we must
|
||||
// have had an unexpected ')' :
|
||||
if(!result)
|
||||
@@ -184,11 +188,13 @@ bool basic_regex_parser<charT, traits>::parse_extended()
|
||||
return parse_match_any();
|
||||
case regex_constants::syntax_caret:
|
||||
++m_position;
|
||||
this->append_state(syntax_element_start_line);
|
||||
this->append_state(
|
||||
(this->flags() & regex_constants::no_mod_m ? syntax_element_buffer_start : syntax_element_start_line));
|
||||
break;
|
||||
case regex_constants::syntax_dollar:
|
||||
++m_position;
|
||||
this->append_state(syntax_element_end_line);
|
||||
this->append_state(
|
||||
(this->flags() & regex_constants::no_mod_m ? syntax_element_buffer_end : syntax_element_end_line));
|
||||
break;
|
||||
case regex_constants::syntax_star:
|
||||
if(m_position == this->m_base)
|
||||
@@ -218,6 +224,19 @@ bool basic_regex_parser<charT, traits>::parse_extended()
|
||||
return parse_alt();
|
||||
case regex_constants::syntax_open_set:
|
||||
return parse_set();
|
||||
case regex_constants::syntax_hash:
|
||||
//
|
||||
// If we have a mod_x flag set, then skip until
|
||||
// we get to a newline character:
|
||||
//
|
||||
if((this->flags()
|
||||
& (regbase::no_perl_ex|regbase::mod_x))
|
||||
== regbase::mod_x)
|
||||
{
|
||||
while((m_position != m_end) && !is_separator(*m_position++)){}
|
||||
return true;
|
||||
}
|
||||
// Otherwise fall through:
|
||||
default:
|
||||
result = parse_literal();
|
||||
break;
|
||||
@@ -231,7 +250,14 @@ bool basic_regex_parser<charT, traits>::parse_extended()
|
||||
template <class charT, class traits>
|
||||
bool basic_regex_parser<charT, traits>::parse_literal()
|
||||
{
|
||||
this->append_literal(*m_position);
|
||||
// append this as a literal provided it's not a space character
|
||||
// or the perl option regbase::mod_x is not set:
|
||||
if(
|
||||
((this->flags()
|
||||
& (regbase::main_option_type|regbase::mod_x|regbase::no_perl_ex))
|
||||
!= regbase::mod_x)
|
||||
|| !this->m_traits.is_class(*m_position, this->m_mask_space))
|
||||
this->append_literal(*m_position);
|
||||
++m_position;
|
||||
return true;
|
||||
}
|
||||
@@ -266,11 +292,31 @@ bool basic_regex_parser<charT, traits>::parse_open_paren()
|
||||
this->m_pdata->m_data.align();
|
||||
m_alt_insert_point = this->m_pdata->m_data.size();
|
||||
//
|
||||
// back up the current flags in case we have a nested (?imsx) group:
|
||||
//
|
||||
regex_constants::syntax_option_type opts = this->flags();
|
||||
bool old_case_change = m_has_case_change;
|
||||
m_has_case_change = false; // no changes to this scope as yet...
|
||||
//
|
||||
// now recursively add more states, this will terminate when we get to a
|
||||
// matching ')' :
|
||||
//
|
||||
parse_all();
|
||||
//
|
||||
// restore flags:
|
||||
//
|
||||
if(m_has_case_change)
|
||||
{
|
||||
// the case has changed in one or more of the alternatives
|
||||
// within the scoped (...) block: we have to add a state
|
||||
// to reset the case sensitivity:
|
||||
static_cast<re_case*>(
|
||||
this->append_state(syntax_element_toggle_case, sizeof(re_case))
|
||||
)->icase = opts & regbase::icase;
|
||||
}
|
||||
this->flags(opts);
|
||||
m_has_case_change = old_case_change;
|
||||
//
|
||||
// we either have a ')' or we have run out of characters prematurely:
|
||||
//
|
||||
if(m_position == m_end)
|
||||
@@ -436,7 +482,12 @@ bool basic_regex_parser<charT, traits>::parse_match_any()
|
||||
// we have a '.' that can match any character:
|
||||
//
|
||||
++m_position;
|
||||
this->append_state(syntax_element_wild);
|
||||
static_cast<re_dot*>(
|
||||
this->append_state(syntax_element_wild, sizeof(re_dot))
|
||||
)->mask = this->flags() & regbase::no_mod_s
|
||||
? re_detail::force_not_newline
|
||||
: this->flags() & regbase::mod_s ?
|
||||
re_detail::force_newline : re_detail::dont_care;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -609,10 +660,13 @@ bool basic_regex_parser<charT, traits>::parse_alt()
|
||||
fail(REG_EMPTY, this->m_position - this->m_base);
|
||||
++m_position;
|
||||
//
|
||||
// we need to append a trailing jump, then insert the alternative:
|
||||
// we need to append a trailing jump:
|
||||
//
|
||||
re_syntax_base* pj = this->append_state(re_detail::syntax_element_jump, sizeof(re_jump));
|
||||
std::ptrdiff_t jump_offset = this->getoffset(pj);
|
||||
//
|
||||
// now insert the alternative:
|
||||
//
|
||||
re_alt* palt = static_cast<re_alt*>(this->insert_state(this->m_alt_insert_point, syntax_element_alt, re_alt_size));
|
||||
jump_offset += re_alt_size;
|
||||
this->m_pdata->m_data.align();
|
||||
@@ -623,6 +677,16 @@ bool basic_regex_parser<charT, traits>::parse_alt()
|
||||
//
|
||||
this->m_alt_insert_point = this->m_pdata->m_data.size();
|
||||
//
|
||||
// the start of this alternative must have a case changes state
|
||||
// if the current block has messed around with case changes:
|
||||
//
|
||||
if(m_has_case_change)
|
||||
{
|
||||
static_cast<re_case*>(
|
||||
this->append_state(syntax_element_toggle_case, sizeof(re_case))
|
||||
)->icase = this->m_icase;
|
||||
}
|
||||
//
|
||||
// recursively add states:
|
||||
//
|
||||
bool result = this->parse_all();
|
||||
@@ -633,7 +697,7 @@ bool basic_regex_parser<charT, traits>::parse_alt()
|
||||
fail(REG_EMPTY, this->m_position - this->m_base);
|
||||
//
|
||||
// fix up the jump we added to point to the end of the states
|
||||
// that we're just added:
|
||||
// that we've just added:
|
||||
//
|
||||
this->m_pdata->m_data.align();
|
||||
re_jump* jmp = static_cast<re_jump*>(this->getaddress(jump_offset));
|
||||
@@ -1083,7 +1147,13 @@ bool basic_regex_parser<charT, traits>::parse_QE()
|
||||
while((m_position != m_end)
|
||||
&& (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape))
|
||||
++m_position;
|
||||
if((m_position == m_end) || (++m_position == m_end)) // skip the escape
|
||||
if(m_position == m_end)
|
||||
{
|
||||
// a \Q...\E sequence may terminate with the end of the expression:
|
||||
end = m_position;
|
||||
break;
|
||||
}
|
||||
if(++m_position == m_end) // skip the escape
|
||||
{
|
||||
fail(REG_EESCAPE, m_position - m_base);
|
||||
return false;
|
||||
@@ -1117,6 +1187,18 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
|
||||
if(++m_position == m_end)
|
||||
fail(REG_BADRPT, m_position - m_base);
|
||||
//
|
||||
// treat comments as a special case, as these
|
||||
// are the only ones that don't start with a leading
|
||||
// startmark state:
|
||||
//
|
||||
if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_hash)
|
||||
{
|
||||
while((m_position != m_end)
|
||||
&& (this->m_traits.syntax_type(*m_position++) != regex_constants::syntax_close_mark))
|
||||
{}
|
||||
return true;
|
||||
}
|
||||
//
|
||||
// backup some state, and prepare the way:
|
||||
//
|
||||
int markid = 0;
|
||||
@@ -1128,6 +1210,10 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
|
||||
this->m_pdata->m_data.align();
|
||||
m_alt_insert_point = this->m_pdata->m_data.size();
|
||||
std::ptrdiff_t expected_alt_point = m_alt_insert_point;
|
||||
bool restore_flags = true;
|
||||
regex_constants::syntax_option_type old_flags = this->flags();
|
||||
bool old_case_change = m_has_case_change;
|
||||
m_has_case_change = false;
|
||||
//
|
||||
// select the actual extension used:
|
||||
//
|
||||
@@ -1140,15 +1226,6 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
|
||||
pb->index = markid = 0;
|
||||
++m_position;
|
||||
break;
|
||||
case regex_constants::syntax_hash:
|
||||
//
|
||||
// a comment; this actually becomes an empty non-capturing mark:
|
||||
//
|
||||
pb->index = markid = 0;
|
||||
while((m_position != m_end)
|
||||
&& (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
|
||||
++m_position;
|
||||
break;
|
||||
case regex_constants::syntax_equal:
|
||||
pb->index = markid = -1;
|
||||
++m_position;
|
||||
@@ -1235,7 +1312,37 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fail(REG_BADRPT, m_position - m_base);
|
||||
//
|
||||
// lets assume that we have a (?imsx) group and try and parse it:
|
||||
//
|
||||
regex_constants::syntax_option_type opts = parse_options();
|
||||
// make a note of whether we have a case change:
|
||||
m_has_case_change = ((opts & regbase::icase) != (this->flags() & regbase::icase));
|
||||
pb->index = markid = 0;
|
||||
if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark)
|
||||
{
|
||||
// update flags and carry on as normal:
|
||||
this->flags(opts);
|
||||
restore_flags = false;
|
||||
old_case_change |= m_has_case_change; // defer end of scope by one ')'
|
||||
}
|
||||
else if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_colon)
|
||||
{
|
||||
// update flags and carry on until the matching ')' is found:
|
||||
this->flags(opts);
|
||||
++m_position;
|
||||
}
|
||||
else
|
||||
fail(REG_BADRPT, m_position - m_base);
|
||||
|
||||
// finally append a case change state if we need it:
|
||||
if(m_has_case_change)
|
||||
{
|
||||
static_cast<re_case*>(
|
||||
this->append_state(syntax_element_toggle_case, sizeof(re_case))
|
||||
)->icase = opts & regbase::icase;
|
||||
}
|
||||
|
||||
}
|
||||
//
|
||||
// now recursively add more states, this will terminate when we get to a
|
||||
@@ -1250,6 +1357,20 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
|
||||
BOOST_ASSERT(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark);
|
||||
++m_position;
|
||||
//
|
||||
// restore the flags:
|
||||
//
|
||||
if(restore_flags)
|
||||
{
|
||||
// append a case change state if we need it:
|
||||
if(m_has_case_change)
|
||||
{
|
||||
static_cast<re_case*>(
|
||||
this->append_state(syntax_element_toggle_case, sizeof(re_case))
|
||||
)->icase = old_flags & regbase::icase;
|
||||
}
|
||||
this->flags(old_flags);
|
||||
}
|
||||
//
|
||||
// set up the jump pointer if we have one:
|
||||
//
|
||||
if(jump_offset)
|
||||
@@ -1275,6 +1396,8 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
|
||||
re_alt* alt = static_cast<re_alt*>(this->insert_state(expected_alt_point, syntax_element_alt, sizeof(re_alt)));
|
||||
alt->alt.i = this->m_pdata->m_data.size() - this->getoffset(alt);
|
||||
}
|
||||
else if(this->getaddress(static_cast<re_alt*>(b)->alt.i, b)->type == syntax_element_alt)
|
||||
fail(REG_BADPAT, m_position - m_base);
|
||||
}
|
||||
//
|
||||
// append closing parenthesis state:
|
||||
@@ -1286,9 +1409,79 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
|
||||
// restore the alternate insertion point:
|
||||
//
|
||||
this->m_alt_insert_point = last_alt_point;
|
||||
//
|
||||
// and the case change data:
|
||||
//
|
||||
m_has_case_change = old_case_change;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class charT, class traits>
|
||||
regex_constants::syntax_option_type basic_regex_parser<charT, traits>::parse_options()
|
||||
{
|
||||
// we have a (?imsx-imsx) group, convert it into a set of flags:
|
||||
regex_constants::syntax_option_type f = this->flags();
|
||||
bool breakout = false;
|
||||
do
|
||||
{
|
||||
switch(*m_position)
|
||||
{
|
||||
case 's':
|
||||
f |= regex_constants::mod_s;
|
||||
f &= ~regex_constants::no_mod_s;
|
||||
break;
|
||||
case 'm':
|
||||
f &= ~regex_constants::no_mod_m;
|
||||
break;
|
||||
case 'i':
|
||||
f |= regex_constants::icase;
|
||||
break;
|
||||
case 'x':
|
||||
f |= regex_constants::mod_x;
|
||||
break;
|
||||
default:
|
||||
breakout = true;
|
||||
continue;
|
||||
}
|
||||
if(++m_position == m_end)
|
||||
fail(REG_EPAREN, m_position - m_base);
|
||||
}
|
||||
while(!breakout);
|
||||
|
||||
if(*m_position == '-')
|
||||
{
|
||||
if(++m_position == m_end)
|
||||
fail(REG_EPAREN, m_position - m_base);
|
||||
do
|
||||
{
|
||||
switch(*m_position)
|
||||
{
|
||||
case 's':
|
||||
f &= ~regex_constants::mod_s;
|
||||
f |= regex_constants::no_mod_s;
|
||||
break;
|
||||
case 'm':
|
||||
f |= regex_constants::no_mod_m;
|
||||
break;
|
||||
case 'i':
|
||||
f &= ~regex_constants::icase;
|
||||
break;
|
||||
case 'x':
|
||||
f &= ~regex_constants::mod_x;
|
||||
break;
|
||||
default:
|
||||
breakout = true;
|
||||
continue;
|
||||
}
|
||||
if(++m_position == m_end)
|
||||
fail(REG_EPAREN, m_position - m_base);
|
||||
}
|
||||
while(!breakout);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
} // namespace re_detail
|
||||
} // namespace boost
|
||||
|
||||
|
||||
@@ -91,12 +91,12 @@ template <class iterator, class charT, class traits_type, class char_classT>
|
||||
iterator BOOST_REGEX_CALL re_is_set_member(iterator next,
|
||||
iterator last,
|
||||
const re_set_long<char_classT>* set_,
|
||||
const regex_data<charT, traits_type>& e)
|
||||
const regex_data<charT, traits_type>& e, bool icase)
|
||||
{
|
||||
const charT* p = reinterpret_cast<const charT*>(set_+1);
|
||||
iterator ptr;
|
||||
unsigned int i;
|
||||
bool icase = e.m_flags & regex_constants::icase;
|
||||
//bool icase = e.m_flags & regex_constants::icase;
|
||||
|
||||
if(next == last) return next;
|
||||
|
||||
@@ -335,6 +335,7 @@ private:
|
||||
bool match_dot_repeat_slow();
|
||||
bool match_backstep();
|
||||
bool match_assert_backref();
|
||||
bool match_toggle_case();
|
||||
bool backtrack_till_match(unsigned count);
|
||||
|
||||
// find procs stored in s_find_vtable:
|
||||
@@ -385,6 +386,8 @@ private:
|
||||
repeater_count<BidiIterator> rep_obj;
|
||||
// the mask to pass when matching word boundaries:
|
||||
typename traits::char_class_type m_word_mask;
|
||||
// the bitmask to use when determining whether a match_any matches a newline or not:
|
||||
unsigned char match_any_mask;
|
||||
|
||||
#ifdef BOOST_REGEX_NON_RECURSIVE
|
||||
//
|
||||
|
||||
@@ -73,6 +73,8 @@ perl_matcher<BidiIterator, Allocator, traits>::perl_matcher(BidiIterator first,
|
||||
// find the value to use for matching word boundaries:
|
||||
const char_type w = static_cast<char_type>('w');
|
||||
m_word_mask = traits_inst.lookup_classname(&w, &w+1);
|
||||
// find bitmask to use for matching '.':
|
||||
match_any_mask = (f & match_not_dot_newline) ? re_detail::test_not_newline : re_detail::test_newline;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
@@ -395,7 +397,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_wild()
|
||||
{
|
||||
if(position == last)
|
||||
return false;
|
||||
if(is_separator(*position) && (m_match_flags & match_not_dot_newline))
|
||||
if(is_separator(*position) && ((match_any_mask & static_cast<const re_dot*>(pstate)->mask) == 0))
|
||||
return false;
|
||||
if((*position == char_type(0)) && (m_match_flags & match_not_dot_null))
|
||||
return false;
|
||||
@@ -590,7 +592,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set()
|
||||
// let the traits class do the work:
|
||||
if(position == last)
|
||||
return false;
|
||||
BidiIterator t = re_is_set_member(position, last, static_cast<const re_set_long<char_class_type>*>(pstate), re.get_data());
|
||||
BidiIterator t = re_is_set_member(position, last, static_cast<const re_set_long<char_class_type>*>(pstate), re.get_data(), icase);
|
||||
if(t != position)
|
||||
{
|
||||
pstate = pstate->next.p;
|
||||
@@ -678,6 +680,16 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref()
|
||||
return (*m_presult)[static_cast<const re_brace*>(pstate)->index].matched;
|
||||
}
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case()
|
||||
{
|
||||
// change our case sensitivity:
|
||||
this->icase = static_cast<const re_case*>(pstate)->icase;
|
||||
pstate = pstate->next.p;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_any()
|
||||
{
|
||||
|
||||
@@ -113,7 +113,7 @@ struct saved_single_repeat : public saved_state
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
|
||||
{
|
||||
static matcher_proc_type const s_match_vtable[28] =
|
||||
static matcher_proc_type const s_match_vtable[29] =
|
||||
{
|
||||
(&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
|
||||
@@ -143,6 +143,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,
|
||||
};
|
||||
|
||||
push_recursion_stopper();
|
||||
@@ -575,7 +576,9 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow()
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast()
|
||||
{
|
||||
if(m_match_flags & (match_not_dot_newline | match_not_dot_null))
|
||||
if(m_match_flags & match_not_dot_null)
|
||||
return match_dot_repeat_slow();
|
||||
if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0)
|
||||
return match_dot_repeat_slow();
|
||||
|
||||
const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
||||
@@ -763,7 +766,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
||||
BidiIterator end = position;
|
||||
std::advance(end, (std::min)((unsigned)re_detail::distance(position, last), desired));
|
||||
BidiIterator origin(position);
|
||||
while((position != end) && (position != re_is_set_member(position, last, set, re.get_data())))
|
||||
while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
|
||||
{
|
||||
++position;
|
||||
}
|
||||
@@ -771,7 +774,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
||||
}
|
||||
else
|
||||
{
|
||||
while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data())))
|
||||
while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
|
||||
{
|
||||
++position;
|
||||
++count;
|
||||
@@ -1269,7 +1272,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat(bool
|
||||
// wind forward until we can skip out of the repeat:
|
||||
do
|
||||
{
|
||||
if(position == re_is_set_member(position, last, set, re.get_data()))
|
||||
if(position == re_is_set_member(position, last, set, re.get_data(), icase))
|
||||
{
|
||||
// failed repeat match, discard this state and look for another:
|
||||
destroy_single_repeat();
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
template <class BidiIterator, class Allocator, class traits>
|
||||
bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
|
||||
{
|
||||
static matcher_proc_type const s_match_vtable[28] =
|
||||
static matcher_proc_type const s_match_vtable[29] =
|
||||
{
|
||||
(&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
|
||||
@@ -78,6 +78,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
|
||||
&perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,
|
||||
};
|
||||
|
||||
if(state_count > max_state_count)
|
||||
@@ -427,7 +428,9 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast()
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
if(m_match_flags & (match_not_dot_newline | match_not_dot_null))
|
||||
if(m_match_flags & match_not_dot_null)
|
||||
return match_dot_repeat_slow();
|
||||
if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0)
|
||||
return match_dot_repeat_slow();
|
||||
//
|
||||
// start by working out how much we can skip:
|
||||
@@ -670,7 +673,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
||||
BidiIterator end = position;
|
||||
std::advance(end, (std::min)((unsigned)re_detail::distance(position, last), desired));
|
||||
BidiIterator origin(position);
|
||||
while((position != end) && (position != re_is_set_member(position, last, set, re.get_data())))
|
||||
while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
|
||||
{
|
||||
++position;
|
||||
}
|
||||
@@ -678,7 +681,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
||||
}
|
||||
else
|
||||
{
|
||||
while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data())))
|
||||
while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
|
||||
{
|
||||
++position;
|
||||
++count;
|
||||
@@ -698,7 +701,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
||||
{
|
||||
while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
|
||||
{
|
||||
if(position != re_is_set_member(position, last, set, re.get_data()))
|
||||
if(position != re_is_set_member(position, last, set, re.get_data(), icase))
|
||||
{
|
||||
++position;
|
||||
++count;
|
||||
@@ -718,7 +721,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
||||
if(position == last)
|
||||
return false;
|
||||
position = save_pos;
|
||||
if(position != re_is_set_member(position, last, set, re.get_data()))
|
||||
if(position != re_is_set_member(position, last, set, re.get_data(), icase))
|
||||
{
|
||||
++position;
|
||||
++count;
|
||||
|
||||
@@ -52,6 +52,10 @@ public:
|
||||
//
|
||||
no_bk_refs = 1 << 8, // \d not allowed
|
||||
no_perl_ex = 1 << 9, // disable perl extensions
|
||||
no_mod_m = 1 << 10, // disable Perl m modifier
|
||||
mod_x = 1 << 11, // Perl x modifier
|
||||
mod_s = 1 << 12, // force s modifier on (overrides match_not_dot_newline)
|
||||
no_mod_s = 1 << 13, // force s modifier off (overrides match_not_dot_newline)
|
||||
|
||||
//
|
||||
// options specific to basic group:
|
||||
@@ -125,6 +129,10 @@ namespace regex_constants{
|
||||
no_intervals = ::boost::regbase::no_intervals,
|
||||
no_char_classes = ::boost::regbase::no_char_classes,
|
||||
no_escape_in_lists = ::boost::regbase::no_escape_in_lists,
|
||||
no_mod_m = ::boost::regbase::no_mod_m,
|
||||
mod_x = ::boost::regbase::mod_x,
|
||||
mod_s = ::boost::regbase::mod_s,
|
||||
no_mod_s = ::boost::regbase::no_mod_s,
|
||||
|
||||
basic = ::boost::regbase::basic,
|
||||
extended = ::boost::regbase::extended,
|
||||
|
||||
@@ -110,7 +110,8 @@ enum syntax_element_type
|
||||
// a backstep for lookbehind repeats:
|
||||
syntax_element_backstep = syntax_element_long_set_rep + 1,
|
||||
// an assertion that a mark was matched:
|
||||
syntax_element_assert_backref = syntax_element_backstep +1
|
||||
syntax_element_assert_backref = syntax_element_backstep + 1,
|
||||
syntax_element_toggle_case = syntax_element_assert_backref + 1
|
||||
};
|
||||
|
||||
#ifdef BOOST_REGEX_DEBUG
|
||||
@@ -141,7 +142,7 @@ struct re_syntax_base
|
||||
};
|
||||
|
||||
/*** struct re_brace **************************************************
|
||||
Base class for all states in the machine.
|
||||
A marked parenthesis.
|
||||
***********************************************************************/
|
||||
struct re_brace : public re_syntax_base
|
||||
{
|
||||
@@ -150,6 +151,23 @@ struct re_brace : public re_syntax_base
|
||||
int index;
|
||||
};
|
||||
|
||||
/*** struct re_dot **************************************************
|
||||
Match anything.
|
||||
***********************************************************************/
|
||||
enum
|
||||
{
|
||||
dont_care = 1,
|
||||
force_not_newline = 0,
|
||||
force_newline = 2,
|
||||
|
||||
test_not_newline = 2,
|
||||
test_newline = 3,
|
||||
};
|
||||
struct re_dot : public re_syntax_base
|
||||
{
|
||||
unsigned char mask;
|
||||
};
|
||||
|
||||
/*** struct re_literal ************************************************
|
||||
A string of literals, following this structure will be an
|
||||
array of characters: charT[length]
|
||||
@@ -159,6 +177,14 @@ struct re_literal : public re_syntax_base
|
||||
unsigned int length;
|
||||
};
|
||||
|
||||
/*** struct re_case ************************************************
|
||||
Indicates whether we are moving to a case insensive block or not
|
||||
***********************************************************************/
|
||||
struct re_case : public re_syntax_base
|
||||
{
|
||||
bool icase;
|
||||
};
|
||||
|
||||
/*** struct re_set_long ***********************************************
|
||||
A wide character set of characters, following this structure will be
|
||||
an array of type charT:
|
||||
@@ -234,7 +260,7 @@ template <class iterator, class charT, class traits_type, class char_classT>
|
||||
iterator BOOST_REGEX_CALL re_is_set_member(iterator next,
|
||||
iterator last,
|
||||
const re_set_long<char_classT>* set_,
|
||||
const regex_data<charT, traits_type>& e);
|
||||
const regex_data<charT, traits_type>& e, bool icase);
|
||||
|
||||
} // namespace re_detail
|
||||
|
||||
|
||||
Reference in new issue
Block a user