Internal matching routine.
482{
483 DBG(
"%d:matchAt(tokenPos=%zu, str='%s', pos=%zu)\n",level,tokenPos,pos<str.length() ? str.substr(pos).c_str() :
"",pos);
484 auto isStartIdChar = [](
char c) {
return isalpha(c) || c==
'_'; };
485 auto isIdChar = [](
char c) {
return isalnum(c) || c==
'_'; };
486 auto matchCharClass = [this,isStartIdChar,isIdChar](size_t tp,char c) -> bool
487 {
488 PToken tok =
data[tp];
490 uint16_t numFields = tok.value();
491 bool found = false;
492 for (uint16_t i=0;i<numFields;i++)
493 {
495
500 )
501 {
502 found=true;
503 break;
504 }
505 else
506 {
507 uint16_t v = static_cast<uint16_t>(c);
508 if (tok.from()<=v && v<=tok.to())
509 {
510 found=true;
511 break;
512 }
513 }
514 }
515 DBG(
"matchCharClass(tp=%zu,c=%c (x%02x))=%d\n",tp,c,c,negate?!found:found);
516 return negate ? !found : found;
517 };
518 size_t index = pos;
519 enum SequenceType { Star, Optional, OptionalRange };
520 auto processSequence = [this,&tokenPos,&tokenLen,&index,&str,&matchCharClass,
521 &isStartIdChar,&isIdChar,&
match,&level,&pos](SequenceType type) ->
bool
522 {
523 size_t startIndex = index;
524 size_t len = str.length();
525 PToken tok =
data[++tokenPos];
526
527
529 {
530 size_t groupId = tok.value();
531 size_t innerStart = tokenPos + 1;
532
533
534 size_t tp = innerStart;
535 int depth = 1;
536 while (tp<tokenLen && depth>0)
537 {
540 tp++;
541 }
542 if (depth!=0) return false;
543 size_t endCapturePos = tp - 1;
544 size_t afterSeqPos = endCapturePos + 2;
545
546
547 Match tmp;
549 bool innerOk =
matchAt(innerStart,endCapturePos,str,tmp,index,level+1);
550 if (innerOk)
551 {
552 size_t capLen = tmp.length();
553
554
555 for (size_t gid=1; gid<tmp.size(); gid++)
556 {
557 size_t sp = tmp[gid].position();
558 size_t sl = tmp[gid].length();
559 if (sp!=std::string::npos && sl!=std::string::npos)
560 {
561 match.startCapture(gid,sp);
562 match.endCapture(gid,sp+sl);
563 }
564 }
565
566 match.startCapture(groupId,index);
567 match.endCapture(groupId,index+capLen);
568
569 bool ok =
matchAt(afterSeqPos,tokenLen,str,
match,index+capLen,level+1);
570 if (ok)
571 {
572 match.setMatch(pos,(index+capLen)-pos+
match.length());
573 return true;
574 }
575 }
576
577
578 match.startCapture(groupId,index);
579 match.endCapture(groupId,index);
580
581 bool ok2 =
matchAt(afterSeqPos,tokenLen,str,
match,index,level+1);
582 if (ok2)
583 {
585 return true;
586 }
587 return false;
588 }
589
591 {
592 char c_tok = tok.asciiValue();
593 while (index<len && str[index]==c_tok) { index++; if (type==Optional) break; }
594 tokenPos++;
595 }
596 else if (tok.isCharClass())
597 {
598 while (index<len && matchCharClass(tokenPos,str[index])) { index++; if (type==Optional) break; }
599 tokenPos+=tok.value()+1;
600 }
602 {
603 while (index<len && isStartIdChar(str[index])) { index++; if (type==Optional) break; }
604 tokenPos++;
605 }
607 {
608 while (index<len && isIdChar(str[index])) { index++; if (type==Optional) break; }
609 tokenPos++;
610 }
612 {
613 while (index<len &&
isspace(str[index])) { index++;
if (type==Optional)
break; }
614 tokenPos++;
615 }
617 {
618 while (index<len &&
isdigit(str[index])) { index++;
if (type==Optional)
break; }
619 tokenPos++;
620 }
622 {
623 if (type==Optional) index++; else index = str.length();
624 tokenPos++;
625 }
627 {
628 size_t tokenStart = ++tokenPos;
630 Match rangeMatch;
631 rangeMatch.init(str,0);
632 bool found =
matchAt(tokenStart,tokenPos,str,rangeMatch,index,level+1);
633 if (found)
634 {
635 index+=rangeMatch.length();
636 }
637 tokenPos++;
638 }
639 tokenPos++;
640 while (index>=startIndex)
641 {
642
643 bool found =
matchAt(tokenPos,tokenLen,str,
match,index,level+1);
644 if (found)
645 {
647 return true;
648 }
649 if (index==0) break;
650 index--;
651 }
652 return false;
653 };
654
655 while (tokenPos<tokenLen)
656 {
657 PToken tok =
data[tokenPos];
658 DBG(
"loop tokenPos=%zu token=%s\n",tokenPos,tok.kindStr());
660 {
661 char c_tok = tok.asciiValue();
662 if (index>=str.length() || str[index]!=c_tok) return false;
663 index++;
664 tokenPos++;
665 }
666 else if (tok.isCharClass())
667 {
668 if (index>=str.length() || !matchCharClass(tokenPos,str[index])) return false;
669 index++;
670 tokenPos+=tok.value()+1;
671 }
672 else
673 {
674 switch (tok.kind())
675 {
677 if (index>=str.length() || !isStartIdChar(str[index])) return false;
678 index++;
679 break;
681 if (index>=str.length() || !isIdChar(str[index])) return false;
682 index++;
683 break;
685 if (index>=str.length() || !
isspace(str[index]))
return false;
686 index++;
687 break;
689 if (index>=str.length() || !
isdigit(str[index]))
return false;
690 index++;
691 break;
693 if (index!=pos) return false;
694 break;
696 if (index<str.length()) return false;
697 break;
699 DBG(
"BeginOfWord: index=%zu isIdChar(%c)=%d prev.isIdChar(%c)=%d\n",
700 index,str[index],isIdChar(str[index]),
701 index>0?str[index]-1:0,
702 index>0?isIdChar(str[index-1]):-1);
703 if (index>=str.length() ||
704 !isIdChar(str[index]) ||
705 (index>0 && isIdChar(str[index-1]))) return false;
706 break;
708 DBG(
"EndOfWord: index=%zu pos=%zu idIdChar(%c)=%d prev.isIsChar(%c)=%d\n",
709 index,pos,str[index],isIdChar(str[index]),
710 index==0 ? 0 : str[index-1],
711 index==0 ? -1 : isIdChar(str[index-1]));
712 if (index<str.length() &&
713 (isIdChar(str[index]) || index==0 || !isIdChar(str[index-1]))) return false;
714 break;
716 DBG(
"BeginCapture(%zu) gid=%u\n",index,tok.value());
717 match.startCapture(tok.value(),index);
718 break;
720 DBG(
"EndCapture(%zu) gid=%u\n",index,tok.value());
721 match.endCapture(tok.value(),index);
722 break;
724 if (index>=str.length()) return false;
725 index++;
726 break;
728 return processSequence(Star);
731 {
732 return processSequence(OptionalRange);
733 }
734 else
735 {
736 return processSequence(Optional);
737 }
738 default:
739 return false;
740 }
741 tokenPos++;
742 }
743 }
744 match.setMatch(pos,index-pos);
745 return true;
746}
bool matchAt(size_t tokenPos, size_t tokenLen, std::string_view str, Match &match, size_t pos, int level) const
Internal matching routine.
bool match(std::string_view str, Match &match, size_t pos=0) const
Check if a given string matches this regular expression.
static bool isalpha(char c)
static bool isspace(char c)
static bool isalnum(char c)
static bool isdigit(char c)