You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
2.8 KiB
140 lines
2.8 KiB
8 years ago
|
#include "modgmt_strcomp.h"
|
||
|
|
||
|
TemplateComparator::Block::pBlock TemplateComparator::Parse()
|
||
|
{
|
||
|
size_t e=0;
|
||
|
struct Block* blk;
|
||
|
struct Block* root;
|
||
|
auto c=s[e];
|
||
|
bool init,next;
|
||
|
|
||
|
// First symbol
|
||
|
if('['==c || '('==c) blk=new Block(('['==c)?Block::OPTIONAL:Block::VARIANTS);
|
||
|
else blk=new Block(e,e+1);
|
||
|
root=blk;
|
||
|
init=root->type!=Block::TEXT;
|
||
|
next=!init;
|
||
|
|
||
|
e++;
|
||
|
while(e<s.length())
|
||
|
{
|
||
|
c=s[e];
|
||
|
|
||
|
switch(c)
|
||
|
{
|
||
|
case '[':
|
||
|
case '(':
|
||
|
{
|
||
|
(next?blk->next:blk->child).reset(new Block(('['==c)?Block::OPTIONAL:Block::VARIANTS,(next?blk->parent:blk)));
|
||
|
blk=(next?blk->next:blk->child).get();
|
||
|
init=true;
|
||
|
next=false;
|
||
|
break;
|
||
|
}
|
||
|
case ']':
|
||
|
case ')':
|
||
|
{
|
||
|
blk=const_cast<struct Block*>(blk->parent);
|
||
|
init=true;
|
||
|
next=true;
|
||
|
break;
|
||
|
}
|
||
|
case '|': {blk->next.reset(new Block(Block::DELIM,blk->parent)); blk=blk->next.get(); init=next=true; break;}
|
||
|
default:
|
||
|
{
|
||
|
if(init)
|
||
|
{
|
||
|
(next?blk->next:blk->child).reset(new Block(e,e+1,(next?blk->parent:blk)));
|
||
|
blk=(next?blk->next:blk->child).get();
|
||
|
}
|
||
|
else blk->e=e+1;
|
||
|
init=false;
|
||
|
next=true;
|
||
|
}
|
||
|
}
|
||
|
e++;
|
||
|
}
|
||
|
return Block::pBlock(root);
|
||
|
}
|
||
|
|
||
|
void TemplateComparator::InitCursors(const struct TemplateComparator::Block* blk)
|
||
|
{
|
||
|
switch(blk->type)
|
||
|
{
|
||
|
case Block::TEXT: {cursors.insert({blk,0}); break;}
|
||
|
case Block::OPTIONAL:
|
||
|
{
|
||
|
auto b=blk;
|
||
|
InitCursors(b->child.get());
|
||
|
while(true)
|
||
|
{
|
||
|
if(!b->next) break;
|
||
|
b=b->next.get();
|
||
|
InitCursors(b);
|
||
|
if(b->type!=Block::OPTIONAL) break;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case Block::VARIANTS:
|
||
|
{
|
||
|
auto b=blk->child.get();
|
||
|
while(true)
|
||
|
{
|
||
|
InitCursors(b);
|
||
|
while(b->type!=Block::DELIM)
|
||
|
{
|
||
|
if(!b->next) break;
|
||
|
b=b->next.get();
|
||
|
}
|
||
|
if(!b->next) break;
|
||
|
b=b->next.get();
|
||
|
}
|
||
|
}
|
||
|
default: {}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool TemplateComparator::CmpSmb(const char c)
|
||
|
{
|
||
|
pCursor p=cursors.cbegin();
|
||
|
bool res=false;
|
||
|
|
||
|
// Compare symbol with all cursors
|
||
|
while(p!=cursors.end())
|
||
|
{
|
||
|
if(p->compare(s,c)) {res=true; p++;}
|
||
|
else p=cursors.erase(p);
|
||
|
}
|
||
|
|
||
|
Cursors old(std::move(cursors));
|
||
|
for(const auto& p:old)
|
||
|
{
|
||
|
auto blk=p.block;
|
||
|
// Increment cursors
|
||
|
if(blk->b+p.offset+1<blk->e) cursors.insert({blk,p.offset+1}); // Advance in current block
|
||
|
else // Move to next block
|
||
|
{
|
||
|
if(!blk->next || blk->next->type==Block::DELIM) // End of chain, must go up
|
||
|
{
|
||
|
while(blk->parent!=nullptr)
|
||
|
{
|
||
|
blk=blk->parent;
|
||
|
if(!blk->next || blk->next->type==Block::DELIM) continue;
|
||
|
InitCursors(blk->next.get());
|
||
|
}
|
||
|
}
|
||
|
else InitCursors(blk->next.get()); // Next block in chain
|
||
|
}
|
||
|
|
||
|
// Try to leave optional blocks
|
||
|
blk=p.block;
|
||
|
while(blk->parent!=nullptr)
|
||
|
{
|
||
|
blk=blk->parent;
|
||
|
if(blk->type!=Block::OPTIONAL || !blk->next || blk->next->type==Block::DELIM) continue;
|
||
|
InitCursors(blk->next.get());
|
||
|
}
|
||
|
}
|
||
|
return res;
|
||
|
}
|