📄 deelx.h
字号:
// skip '*'
MoveNext();
break;
case RCHART('+'):
nMin = 1;
nMax = INT_MAX;
// skip '+'
MoveNext();
break;
default:
bIsQuantifier = 0;
break;
}
// do quantify
if(bIsQuantifier)
{
// 0 times
if(nMax == 0)
return GetStockElx(STOCKELX_EMPTY);
// fixed times
if(nMin == nMax)
{
if(curr == CHART_INFO(RCHART('?'), 1) || curr == CHART_INFO(RCHART('+'), 1))
MoveNext();
return Keep(new CRepeatElx(pSimple, nMin));
}
// range times
if(curr == CHART_INFO(RCHART('?'), 1))
{
MoveNext();
return Keep(new CReluctantElx(pSimple, nMin, nMax));
}
else if(curr == CHART_INFO(RCHART('+'), 1))
{
MoveNext();
return Keep(new CPossessiveElx(pSimple, nMin, nMax));
}
else
{
return Keep(new CGreedyElx(pSimple, nMin, nMax));
}
}
return pSimple;
}
template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildSimple(int & flags)
{
CBufferT <CHART> fixed;
while(curr != CHART_INFO(0, 1))
{
if(curr.type == 0)
{
if(next == CHART_INFO(RCHART('{'), 1) || next == CHART_INFO(RCHART('?'), 1) || next == CHART_INFO(RCHART('*'), 1) || next == CHART_INFO(RCHART('+'), 1))
{
if(fixed.GetSize() == 0)
{
fixed.Append(curr.ch, 1);
MoveNext();
}
break;
}
else
{
fixed.Append(curr.ch, 1);
MoveNext();
}
}
else if(curr.type == 1)
{
CHART vch = curr.ch;
// end of simple
if(vch == RCHART(')') || vch == RCHART('|'))
break;
// has fixed already
if(fixed.GetSize() > 0)
break;
// left parentheses
if(vch == RCHART('('))
{
return BuildRecursive(flags);
}
// char set
if( vch == RCHART('[') || vch == RCHART('.') || vch == RCHART('w') || vch == RCHART('W') ||
vch == RCHART('s') || vch == RCHART('S') || vch == RCHART('d') || vch == RCHART('D')
)
{
return BuildCharset(flags);
}
// boundary
if( vch == RCHART('^') || vch == RCHART('$') || vch == RCHART('A') || vch == RCHART('Z') || vch == RCHART('z') ||
vch == RCHART('b') || vch == RCHART('B') || vch == RCHART('G') // vch == RCHART('<') || vch == RCHART('>')
)
{
return BuildBoundary(flags);
}
// backref
if(vch == RCHART('\\') || vch == RCHART('k') || vch == RCHART('g'))
{
return BuildBackref(flags);
}
// treat vchar as char
fixed.Append(curr.ch, 1);
MoveNext();
}
}
if(fixed.GetSize() > 0)
return Keep(new CStringElxT <CHART> (fixed.GetBuffer(), fixed.GetSize(), flags & RIGHTTOLEFT, flags & IGNORECASE));
else
return GetStockElx(STOCKELX_EMPTY);
}
template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildCharset(int & flags)
{
// char
CHART ch = curr.ch;
// skip
MoveNext();
switch(ch)
{
case RCHART('.'):
return GetStockElx(
flags & RIGHTTOLEFT ?
((flags & SINGLELINE) ? STOCKELX_DOT_ALL_RIGHTLEFT : STOCKELX_DOT_NOT_ALL_RIGHTLEFT) :
((flags & SINGLELINE) ? STOCKELX_DOT_ALL : STOCKELX_DOT_NOT_ALL)
);
case RCHART('w'):
return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_WORD_RIGHTLEFT : STOCKELX_WORD);
case RCHART('W'):
return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_WORD_RIGHTLEFT_NOT : STOCKELX_WORD_NOT);
case RCHART('s'):
return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_SPACE_RIGHTLEFT : STOCKELX_SPACE);
case RCHART('S'):
return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_SPACE_RIGHTLEFT_NOT : STOCKELX_SPACE_NOT);
case RCHART('d'):
return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_DIGITAL_RIGHTLEFT : STOCKELX_DIGITAL);
case RCHART('D'):
return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_DIGITAL_RIGHTLEFT_NOT : STOCKELX_DIGITAL_NOT);
case RCHART('['):
{
CRangeElxT <CHART> * pRange;
// create
if(curr == CHART_INFO(RCHART(':'), 1))
{
CBufferT <char> posix;
do {
posix.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
MoveNext();
}
while(curr.ch != RCHART(0) && curr != CHART_INFO(RCHART(']'), 1));
MoveNext(); // skip ']'
// posix
return Keep(new CPosixElxT <CHART> (posix.GetBuffer(), flags & RIGHTTOLEFT));
}
else if(curr == CHART_INFO(RCHART('^'), 1))
{
MoveNext(); // skip '^'
pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (flags & RIGHTTOLEFT, 0));
}
else
{
pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (flags & RIGHTTOLEFT, 1));
}
// parse
while(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART(']'), 1))
{
ch = curr.ch;
if(curr.type == 1 && (
ch == RCHART('.') || ch == RCHART('w') || ch == RCHART('W') || ch == RCHART('s') || ch == RCHART('S') || ch == RCHART('d') || ch == RCHART('D') ||
(ch == RCHART('[') && next == CHART_INFO(RCHART(':'), 1))
))
{
pRange->m_embeds.Push(BuildCharset(flags));
}
else if(next == CHART_INFO(RCHART('-'), 1) && nex2.type == 0)
{
pRange->m_ranges.Push(ch); pRange->m_ranges.Push(nex2.ch);
// next
MoveNext();
MoveNext();
MoveNext();
}
else
{
pRange->m_chars.Push(ch);
// next
MoveNext();
}
}
// skip ']'
MoveNext();
return pRange;
}
}
return GetStockElx(STOCKELX_EMPTY);
}
template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildRecursive(int & flags)
{
// skip '('
MoveNext();
if(curr == CHART_INFO(RCHART('?'), 1))
{
ElxInterface * pElx = 0;
// skip '?'
MoveNext();
int bNegative = 0;
CHART named_end = RCHART('>');
switch(curr.ch)
{
case RCHART('!'):
bNegative = 1;
case RCHART('='):
{
MoveNext(); // skip '!' or '='
pElx = Keep(new CAssertElx(BuildAlternative(flags & ~RIGHTTOLEFT), !bNegative));
}
break;
case RCHART('<'):
switch(next.ch)
{
case RCHART('!'):
bNegative = 1;
case RCHART('='):
MoveNext(); // skip '<'
MoveNext(); // skip '!' or '='
{
pElx = Keep(new CAssertElx(BuildAlternative(flags | RIGHTTOLEFT), !bNegative));
}
break;
default: // named group
break;
}
// break if assertion // else named
if(pElx != 0) break;
case RCHART('P'):
if(curr.ch == RCHART('P')) MoveNext(); // skip 'P'
case RCHART('\''):
if (curr.ch == RCHART('<' )) named_end = RCHART('>' );
else if(curr.ch == RCHART('\'')) named_end = RCHART('\'');
MoveNext(); // skip '<' or '\''
{
// named number
int nThisBackref = m_nNextNamed ++;
CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT));
CBracketElx * pleft = (CBracketElx *)Keep(new CBracketElx(-1, flags & RIGHTTOLEFT ? 1 : 0));
CBracketElx * pright = (CBracketElx *)Keep(new CBracketElx(-1, flags & RIGHTTOLEFT ? 0 : 1));
// save name
CBufferT <CHART> & name = pleft->m_szNamed;
CBufferT <char> num;
while(curr.ch != RCHART(0) && curr.ch != named_end)
{
name.Append(curr.ch, 1);
num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
MoveNext();
}
MoveNext(); // skip '>' or '\''
// check <num>
unsigned int number;
char * str = num.GetBuffer();
if( ReadDec(str, number) ? ( *str == '\0') : 0 )
{
pleft ->m_nnumber = number;
pright->m_nnumber = number;
name.Release();
}
// left, center, right
pList->m_elxlist.Push(pleft);
pList->m_elxlist.Push(BuildAlternative(flags));
pList->m_elxlist.Push(pright);
// for recursive
m_namedlist.Prepare(nThisBackref);
m_namedlist[nThisBackref] = pList;
pElx = pList;
}
break;
case RCHART('>'):
{
MoveNext(); // skip '>'
pElx = Keep(new CIndependentElx(BuildAlternative(flags)));
}
break;
case RCHART('R'):
MoveNext(); // skip 'R'
while(curr.ch != RCHART(0) && isspace(curr.ch)) MoveNext(); // skip space
if(curr.ch == RCHART('<') || curr.ch == RCHART('\''))
{
named_end = curr.ch == RCHART('<') ? RCHART('>') : RCHART('\'');
CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(-3));
MoveNext(); // skip '<' or '\\'
// save name
CBufferT <CHART> & name = pDelegate->m_szNamed;
CBufferT <char> num;
while(curr.ch != RCHART(0) && curr.ch != named_end)
{
name.Append(curr.ch, 1);
num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
MoveNext();
}
MoveNext(); // skip '>' or '\''
// check <num>
unsigned int number;
char * str = num.GetBuffer();
if( ReadDec(str, number) ? ( *str == '\0') : 0 )
{
pDelegate->m_ndata = number;
name.Release();
}
m_recursivelist.Push(pDelegate);
pElx = pDelegate;
}
else
{
CBufferT <char> rto;
while(curr.ch != RCHART(0) && curr.ch != RCHART(')'))
{
rto.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
MoveNext();
}
unsigned int rtono = 0;
char * str = rto.GetBuffer();
ReadDec(str, rtono);
CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(rtono));
m_recursivelist.Push(pDelegate);
pElx = pDelegate;
}
break;
case RCHART('('):
{
CConditionElx * pConditionElx = (CConditionElx *)Keep(new CConditionElx());
// condition
ElxInterface * & pCondition = pConditionElx->m_pelxask;
if(next == CHART_INFO(RCHART('?'), 1))
{
pCondition = BuildRecursive(flags);
}
else // named, assert or number
{
MoveNext(); // skip '('
int pos0 = curr.pos;
// save elx condition
pCondition = Keep(new CAssertElx(BuildAlternative(flags), 1));
// save name
pConditionElx->m_szNamed.Append(m_pattern.GetBuffer() + pos0, curr.pos - pos0, 1);
// save number
CBufferT <char> numstr;
while(pos0 < curr.pos)
{
CHART ch = m_pattern[pos0];
numstr.Append(((ch & (CHART)0xff) == ch) ? (char)ch : 0, 1);
pos0 ++;
}
unsigned int number;
char * str = numstr.GetBuffer();
// valid group number
if( ReadDec(str, number) ? ( *str == '\0') : 0 )
{
pConditionElx->m_nnumber = number;
pCondition = 0;
}
else // maybe elx, maybe named
{
pConditionElx->m_nnumber = -1;
m_namedconditionlist.Push(pConditionElx);
}
MoveNext(); // skip ')'
}
// alternative
{
int newflags = flags;
pConditionElx->m_pelxyes = BuildList(newflags);
}
if(curr.ch == RCHART('|'))
{
MoveNext(); // skip '|'
pConditionElx->m_pelxno = BuildAlternative(flags);
}
else
{
pConditionElx->m_pelxno = 0;
}
pElx = pConditionElx;
}
break;
default:
while(curr.ch != RCHART(0) && isspace(curr.ch)) MoveNext(); // skip space
if(curr.ch >= RCHART('0') && curr.ch <= RCHART('9')) // recursive (?1) => (?R1)
{
CBufferT <char> rto;
while(curr.ch != RCHART(0) && curr.ch != RCHART(')'))
{
rto.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
MoveNext();
}
unsigned int rtono = 0;
char * str = rto.GetBuffer();
ReadDec(str, rtono);
CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(rtono));
m_recursivelist.Push(pDelegate);
pElx = pDelegate;
}
else
{
// flag
int newflags = flags;
while(curr != CHART_INFO(0, 1) && curr.ch != RCHART(':') && curr.ch != RCHART(')') && curr != CHART_INFO(RCHART('('), 1))
{
int tochange = 0;
switch(curr.ch)
{
case RCHART('i'):
case RCHART('I'):
tochange = IGNORECASE;
break;
case RCHART('s'):
case RCHART('S'):
tochange = SINGLELINE;
break;
case RCHART('m'):
case RCHART('M'):
tochange = MULTILINE;
break;
case RCHART('g'):
case RCHART('G'):
tochange = GLOBAL;
break;
case RCHART('-'):
bNegative = 1;
break;
}
if(bNegative)
newflags &= ~tochange;
else
newflags |= tochange;
// move to next char
MoveNext();
}
if(curr.ch == RCHART(':') || curr == CHART_INFO(RCHART('('), 1))
{
// skip ':'
if(curr.ch == RCHART(':')) MoveNext();
pElx = BuildAlternative(newflags);
}
else
{
// change parent flags
flags = newflags;
pElx = GetStockElx(STOCKELX_EMPTY);
}
}
break;
}
MoveNext(); // skip ')'
return pElx;
}
else
{
// group and number
CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT));
int nThisBackref = ++ m_nMaxNumber;
// left, center, right
pList->m_elxlist.Push(Keep(new CBracketElx(nThisBackref, flags & RIGHTTOLEFT ? 1 : 0)));
pList->m_elxlist.Push(BuildAlternative(flags));
pList->m_elxlist.Push(Keep(new CBracketElx(nThisBackref, flags & RIGHTTOLEFT ? 0 : 1)));
// for recursive
m_grouplist.Prepare(nThisBackref);
m_grouplist[nThisBackref] = pList;
// right
MoveNext(); // skip ')'
return pList;
}
}
template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildBoundary(int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -