209 const char *start =
pattern.c_str();
210 const char *ps = start;
217 std::vector<size_t> captureStack;
218 size_t nextCaptureId = 0;
220 auto addToken = [&](
PToken tok)
223 data.emplace_back(tok);
226 auto getNextCharacter = [&]() ->
PToken
236 case 'n': result =
PToken(
'\n');
break;
237 case 'r': result =
PToken(
'\r');
break;
238 case 't': result =
PToken(
'\t');
break;
249 for (
int i=0;i<2 && (cs=(*(ps+1)));i++)
251 int d = (cs>=
'a' && cs<=
'f') ? cs-
'a'+10 :
252 (cs>=
'A' && cs<=
'F') ? cs-
'A'+10 :
253 (cs>=
'0' && cs<=
'9') ? cs-
'0' :
255 if (d>=0) { v<<=4; v|=d; ps++; }
else break;
260 case '\0': ps--;
break;
274 prevTokenPos = tokenPos;
279 prevTokenPos = tokenPos;
284 prevTokenPos = tokenPos;
289 prevTokenPos = tokenPos;
291 size_t id = ++nextCaptureId;
292 data.back().setValue(
static_cast<uint16_t
>(
id));
293 captureStack.push_back(
id);
298 prevTokenPos = tokenPos;
299 if (captureStack.empty())
304 size_t id = captureStack.back();
305 captureStack.pop_back();
307 data.back().setValue(
static_cast<uint16_t
>(
id));
312 prevTokenPos = tokenPos;
314 if (*ps==0) {
error=
true;
return; }
315 bool esc = *ps==
'\\';
316 PToken tok = getNextCharacter();
322 if (*ps==0) {
error=
true;
return; }
323 tok = getNextCharacter();
330 uint16_t numTokens=0;
333 if (c==
'-' && *(ps+1)!=
']' && *(ps+1)!=0)
337 PToken endTok = getNextCharacter();
361 if (*ps==0) {
error=
true;
return; }
363 tok = getNextCharacter();
365 tok.
value()==
static_cast<uint16_t
>(
']'))
369 if (*ps==0) {
error=
true;
return; }
373 data[prevTokenPos].setValue(numTokens);
380 if (prevTokenPos==-1)
385 switch (
data[prevTokenPos].kind())
397 int ddiff =
static_cast<int>(tokenPos-prevTokenPos);
403 std::copy_n(
data.begin()+prevTokenPos,ddiff,
data.begin()+tokenPos);
411 while (prevTokenPos>0 && depth>0)
418 data.insert(
data.begin()+prevTokenPos,
428 prevTokenPos = tokenPos;
429 addToken(getNextCharacter());
434 if (!captureStack.empty())
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
493 uint16_t numFields = tok.
value();
495 for (uint16_t i=0;i<numFields;i++)
510 uint16_t v =
static_cast<uint16_t
>(c);
511 if (tok.
from()<=v && v<=tok.
to())
518 DBG(
"matchCharClass(tp=%zu,c=%c (x%02x))=%d\n",tp,c,c,negate?!found:found);
519 return negate ? !found : found;
522 enum SequenceType { Star, Optional, OptionalRange };
523 auto processSequence = [
this,&tokenPos,&tokenLen,&index,&str,&matchCharClass,
524 &isStartIdChar,&isIdChar,&
match,&level,&pos](SequenceType type) ->
bool
526 size_t startIndex = index;
527 size_t len = str.length();
533 size_t groupId = tok.
value();
534 size_t innerStart = tokenPos + 1;
537 size_t tp = innerStart;
539 while (tp<tokenLen && depth>0)
545 if (depth!=0)
return false;
546 size_t endCapturePos = tp - 1;
547 size_t afterSeqPos = endCapturePos + 2;
552 bool innerOk =
matchAt(innerStart,endCapturePos,str,tmp,index,level+1);
555 size_t capLen = tmp.
length();
558 for (
size_t gid=1; gid<tmp.
size(); gid++)
561 size_t sl = tmp[gid].
length();
562 if (sp!=std::string::npos && sl!=std::string::npos)
564 match.startCapture(gid,sp);
565 match.endCapture(gid,sp+sl);
569 match.startCapture(groupId,index);
570 match.endCapture(groupId,index+capLen);
572 bool ok =
matchAt(afterSeqPos,tokenLen,str,
match,index+capLen,level+1);
575 match.setMatch(pos,(index+capLen)-pos+
match.length());
581 match.startCapture(groupId,index);
582 match.endCapture(groupId,index);
584 bool ok2 =
matchAt(afterSeqPos,tokenLen,str,
match,index,level+1);
596 while (index<len && str[index]==c_tok) { index++;
if (type==Optional)
break; }
601 while (index<len && matchCharClass(tokenPos,str[index])) { index++;
if (type==Optional)
break; }
602 tokenPos+=tok.
value()+1;
606 while (index<len && isStartIdChar(str[index])) { index++;
if (type==Optional)
break; }
611 while (index<len && isIdChar(str[index])) { index++;
if (type==Optional)
break; }
616 while (index<len &&
isspace(str[index])) { index++;
if (type==Optional)
break; }
621 while (index<len &&
isdigit(str[index])) { index++;
if (type==Optional)
break; }
626 if (type==Optional) index++;
else index = str.length();
631 size_t tokenStart = ++tokenPos;
634 rangeMatch.
init(str,0);
635 bool found =
matchAt(tokenStart,tokenPos,str,rangeMatch,index,level+1);
638 index+=rangeMatch.
length();
643 while (index>=startIndex)
646 bool found =
matchAt(tokenPos,tokenLen,str,
match,index,level+1);
658 while (tokenPos<tokenLen)
661 DBG(
"loop tokenPos=%zu token=%s\n",tokenPos,tok.
kindStr());
665 if (index>=str.length() || str[index]!=c_tok)
return false;
671 if (index>=str.length() || !matchCharClass(tokenPos,str[index]))
return false;
673 tokenPos+=tok.
value()+1;
680 if (index>=str.length() || !isStartIdChar(str[index]))
return false;
684 if (index>=str.length() || !isIdChar(str[index]))
return false;
688 if (index>=str.length() || !
isspace(str[index]))
return false;
692 if (index>=str.length() || !
isdigit(str[index]))
return false;
696 if (index!=pos)
return false;
699 if (index<str.length())
return false;
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;
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;
719 DBG(
"BeginCapture(%zu) gid=%u\n",index,tok.
value());
723 DBG(
"EndCapture(%zu) gid=%u\n",index,tok.
value());
727 if (index>=str.length())
return false;
731 return processSequence(Star);
735 return processSequence(OptionalRange);
739 return processSequence(Optional);
747 match.setMatch(pos,index-pos);