regex_match.hpp
来自「CGAL is a collaborative effort of severa」· HPP 代码 · 共 1,914 行 · 第 1/5 页
HPP
1,914 行
{ // 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; } else if((unsigned int)accumulators[cur_acc] < static_cast<const re_repeat*>(ptr)->min) { // the repeat was null, and we haven't gone round min times yet, // since all subsequent repeats will be null as well, just update // our repeat count and skip out. accumulators[cur_acc] = static_cast<const re_repeat*>(ptr)->min; ptr = static_cast<const re_repeat*>(ptr)->alt.p; continue; } goto failure; } // see if we can skip the repeat: if(((unsigned int)accumulators[cur_acc] >= static_cast<const re_repeat*>(ptr)->min) && access::can_start(*first, static_cast<const re_repeat*>(ptr)->_map, mask_skip)) { ptr = static_cast<const re_repeat*>(ptr)->alt.p; continue;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?