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 + -
显示快捷键?