📄 regex_match.hpp
字号:
// longer one.
if((flags & match_not_null) && (first == temp_match[0].first))
goto failure;
if((flags & match_all) && (first != last))
goto failure;
temp_match.set_second(first);
m.maybe_assign(temp_match);
match_found = true;
if(((flags & match_any) && ((first == last) || !(flags & match_all))) || ((first == last) && (need_push_match == false)))
{
// either we don't care what we match or we've matched
// the whole string and can't match anything longer.
while(matches.empty() == false)
matches.pop();
while(prev_pos.empty() == false)
prev_pos.pop();
while(prev_record.empty() == false)
prev_record.pop();
while(prev_acc.empty() == false)
prev_acc.pop();
return true;
}
}
goto failure;
case syntax_element_startmark:
start_mark_jump:
if(static_cast<const re_brace*>(ptr)->index > 0)
{
temp_match.set_first(first, static_cast<const re_brace*>(ptr)->index);
}
else if(
(static_cast<const re_brace*>(ptr)->index == -1)
|| (static_cast<const re_brace*>(ptr)->index == -2)
)
{
matches.push(temp_match);
for(k = 0; k <= cur_acc; ++k)
prev_pos.push(start_loop[k]);
prev_pos.push(first);
prev_record.push(ptr);
for(k = 0; k <= cur_acc; ++k)
prev_acc.push(accumulators[k]);
prev_acc.push(cur_acc);
prev_acc.push(match_found);
match_found = false;
// skip next jump and fall through:
ptr = ptr->next.p;
}
ptr = ptr->next.p;
break;
case syntax_element_endmark:
end_mark_jump:
if(static_cast<const re_brace*>(ptr)->index > 0)
{
temp_match.set_second(first, static_cast<const re_brace*>(ptr)->index);
}
else if(
(static_cast<const re_brace*>(ptr)->index == -1)
|| (static_cast<const re_brace*>(ptr)->index == -2)
)
{
match_found = true;
unwind_stack = true;
goto failure;
}
ptr = ptr->next.p;
break;
case syntax_element_literal:
{
unsigned int len = static_cast<const re_literal*>(ptr)->length;
const charT* what = reinterpret_cast<const charT*>(static_cast<const re_literal*>(ptr) + 1);
//
// compare string with what we stored in
// our records:
for(unsigned int i = 0; i < len; ++i, ++first)
{
if((first == last) || (traits_inst.translate(*first, icase) != what[i]))
goto failure;
}
ptr = ptr->next.p;
break;
}
case syntax_element_start_line:
outer_line_check:
if(first == temp_match[0].first)
{
// we're at the start of the buffer
if(flags & match_prev_avail)
{
inner_line_check:
// check the previous value even though its before
// the start of our "buffer".
iterator t(first);
--t;
if(traits::is_separator(*t) && !((*t == '\r') && (*first == '\n')) )
{
ptr = ptr->next.p;
continue;
}
goto failure;
}
if((flags & match_not_bol) == 0)
{
ptr = ptr->next.p;
continue;
}
goto failure;
}
// we're in the middle of the string
goto inner_line_check;
case syntax_element_end_line:
// we're not yet at the end so *first is always valid:
if(traits::is_separator(*first))
{
if((first != base) || (flags & match_prev_avail))
{
// check that we're not in the middle of \r\n sequence
iterator t(first);
--t;
if((*t == '\r') && (*first == '\n'))
{
goto failure;
}
}
ptr = ptr->next.p;
continue;
}
goto failure;
case syntax_element_wild:
// anything except possibly NULL or \n:
if(traits::is_separator(*first))
{
if(flags & match_not_dot_newline)
goto failure;
ptr = ptr->next.p;
++first;
continue;
}
if(*first == charT(0))
{
if(flags & match_not_dot_null)
goto failure;
ptr = ptr->next.p;
++first;
continue;
}
ptr = ptr->next.p;
++first;
break;
case syntax_element_word_boundary:
{
// prev and this character must be opposites:
#if defined(BOOST_REGEX_USE_C_LOCALE) && defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95)
bool b = traits::is_class(*first, traits::char_class_word);
#else
bool b = traits_inst.is_class(*first, traits::char_class_word);
#endif
if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0))
{
if(flags & match_not_bow)
b ^= true;
else
b ^= false;
}
else
{
--first;
b ^= traits_inst.is_class(*first, traits::char_class_word);
++first;
}
if(b)
{
ptr = ptr->next.p;
continue;
}
goto failure;
}
case syntax_element_within_word:
// both prev and this character must be traits::char_class_word:
if(traits_inst.is_class(*first, traits::char_class_word))
{
bool b;
if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0))
b = false;
else
{
--first;
b = traits_inst.is_class(*first, traits::char_class_word);
++first;
}
if(b)
{
ptr = ptr->next.p;
continue;
}
}
goto failure;
case syntax_element_word_start:
if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0))
{
// start of buffer:
if(flags & match_not_bow)
goto failure;
if(traits_inst.is_class(*first, traits::char_class_word))
{
ptr = ptr->next.p;
continue;
}
goto failure;
}
// otherwise inside buffer:
if(traits_inst.is_class(*first, traits::char_class_word))
{
iterator t(first);
--t;
if(traits_inst.is_class(*t, traits::char_class_word) == false)
{
ptr = ptr->next.p;
continue;
}
}
goto failure; // if we fall through to here then we've failed
case syntax_element_word_end:
if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0))
goto failure; // start of buffer can't be end of word
// otherwise inside buffer:
if(traits_inst.is_class(*first, traits::char_class_word) == false)
{
iterator t(first);
--t;
if(traits_inst.is_class(*t, traits::char_class_word))
{
ptr = ptr->next.p;
continue;
}
}
goto failure; // if we fall through to here then we've failed
case syntax_element_buffer_start:
if((first != temp_match[0].first) || (flags & match_not_bob))
goto failure;
// OK match:
ptr = ptr->next.p;
break;
case syntax_element_buffer_end:
if((first != last) || (flags & match_not_eob))
goto failure;
// OK match:
ptr = ptr->next.p;
break;
case syntax_element_backref:
{
// compare with what we previously matched:
iterator i = temp_match[static_cast<const re_brace*>(ptr)->index].first;
iterator j = temp_match[static_cast<const re_brace*>(ptr)->index].second;
while(i != j)
{
if((first == last) || (traits_inst.translate(*first, icase) != traits_inst.translate(*i, icase)))
goto failure;
++i;
++first;
}
ptr = ptr->next.p;
break;
}
case syntax_element_long_set:
{
// let the traits class do the work:
iterator t = re_is_set_member(first, last, static_cast<const re_set_long*>(ptr), e);
if(t != first)
{
ptr = ptr->next.p;
first = t;
continue;
}
goto failure;
}
case syntax_element_set:
// lookup character in table:
if(static_cast<const re_set*>(ptr)->_map[(traits_uchar_type)traits_inst.translate(*first, icase)])
{
ptr = ptr->next.p;
++first;
continue;
}
goto failure;
case syntax_element_jump:
ptr = static_cast<const re_jump*>(ptr)->alt.p;
continue;
case syntax_element_alt:
{
// alt_jump:
if(access::can_start(*first, static_cast<const re_jump*>(ptr)->_map, (unsigned char)mask_take))
{
// we can take the first alternative,
// see if we need to push next alternative:
if(access::can_start(*first, static_cast<const re_jump*>(ptr)->_map, mask_skip))
{
if(need_push_match)
matches.push(temp_match);
for(k = 0; k <= cur_acc; ++k)
prev_pos.push(start_loop[k]);
prev_pos.push(first);
prev_record.push(ptr);
for(k = 0; k <= cur_acc; ++k)
prev_acc.push(accumulators[k]);
prev_acc.push(cur_acc);
}
ptr = ptr->next.p;
continue;
}
if(access::can_start(*first, static_cast<const re_jump*>(ptr)->_map, mask_skip))
{
ptr = static_cast<const re_jump*>(ptr)->alt.p;
continue;
}
goto failure; // neither option is possible
}
case syntax_element_rep:
{
// repeater_jump:
// if we're moving to a higher id (nested repeats etc)
// zero out our accumualtors:
if(cur_acc < static_cast<const re_repeat*>(ptr)->id)
{
cur_acc = static_cast<const re_repeat*>(ptr)->id;
accumulators[cur_acc] = 0;
start_loop[cur_acc] = first;
}
cur_acc = static_cast<const re_repeat*>(ptr)->id;
if(static_cast<const re_repeat*>(ptr)->leading)
*restart = first;
//charT c = traits_inst.translate(*first);
// first of all test for special case where this is last element,
// if that is the case then repeat as many times as possible,
// as long as the repeat is greedy:
if((static_cast<const re_repeat*>(ptr)->alt.p->type == syntax_element_match)
&& (static_cast<const re_repeat*>(ptr)->greedy == true))
{
// see if we can take the repeat:
if(((unsigned int)accumulators[cur_acc] < static_cast<const re_repeat*>(ptr)->max)
&& access::can_start(*first, static_cast<const re_repeat*>(ptr)->_map, mask_take))
{
// push terminating match as fallback:
if((unsigned int)accumulators[cur_acc] >= static_cast<const re_repeat*>(ptr)->min)
{
if((prev_record.empty() == false) && (prev_record.peek() == static_cast<const re_repeat*>(ptr)->alt.p))
{
// we already have the required fallback
// don't add any more, just update this one:
if(need_push_match)
matches.peek() = temp_match;
prev_pos.peek() = first;
}
else
{
if(need_push_match)
matches.push(temp_match);
prev_pos.push(first);
prev_record.push(static_cast<const re_repeat*>(ptr)->alt.p);
}
}
// move to next item in list:
if((first != start_loop[cur_acc]) || !accumulators[cur_acc])
{
++accumulators[cur_acc];
ptr = ptr->next.p;
start_loop[cur_acc] = first;
continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -