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