前几天突然想写一个正则表达式引擎,于是计划用5个小时搞定一个一般的RegexEngine.
不过断断续续加起来严重超时,写了十几个小时,大体功能完成。
写一个正则表达式需要考虑的内容还是不少的。
比如:
0 词法分析:涉及到怎么划分原子粒度,我把/[A..Z1..5_]/作为一个词法元素,另外用一张表索引子词法元素
1 语法分析:直接一个函数递归消化掉所有分析并转化为Epsilon-NFA,其中*号要避免空回路。
2 表达式匹配:同样一个递归消化掉所有内容,E-NFA处理空串匹配时要单独处理。
由于用到了自己上一年写的泛化adt::graph类,所以图结构基本没花很多时间,给graph扩展了一个E-NFA匹配的功能。
700行的ProBetaMinus版本,到完整的Beta版本,估计要增加200行代码(加入重复描述符检测和{m,n},{m,n}处理估计要用到递归+函数内临时堆栈).此外我会对自己的adt::graph类做一个优化,确保其更好的支持Regex.
用了几十个case,目前没发现Bug,不过随着以后使用的过程,肯定会出现不同的BUG。
另附用到的自己上一年写的adt::graph类.
一个Demo的代码:
其运行结果:
不过断断续续加起来严重超时,写了十几个小时,大体功能完成。
写一个正则表达式需要考虑的内容还是不少的。
比如:
0 词法分析:涉及到怎么划分原子粒度,我把/[A..Z1..5_]/作为一个词法元素,另外用一张表索引子词法元素
1 语法分析:直接一个函数递归消化掉所有分析并转化为Epsilon-NFA,其中*号要避免空回路。
2 表达式匹配:同样一个递归消化掉所有内容,E-NFA处理空串匹配时要单独处理。
由于用到了自己上一年写的泛化adt::graph类,所以图结构基本没花很多时间,给graph扩展了一个E-NFA匹配的功能。
700行的ProBetaMinus版本,到完整的Beta版本,估计要增加200行代码(加入重复描述符检测和{m,n},{m,n}处理估计要用到递归+函数内临时堆栈).此外我会对自己的adt::graph类做一个优化,确保其更好的支持Regex.
用了几十个case,目前没发现Bug,不过随着以后使用的过程,肯定会出现不同的BUG。
/**/
/*regex.h :vgl::regex*/
/**/ /*----------------------------------------------------------------------------
Simplex v1.2
Developer: Zblc
vgl::regex
enumes:
classes:
AtomToken :原子词
Regex :正则表达式分析类
macros:
MAX_SUB_ROW :[]的最大数
MAX_SUB_COW :[]中原子字符的最大数
MAX_TOKEN :最大接受的原子字符数
CAPA_LIST :调试用
CAPA_LIST_LETTER :调试用
namespace variable:
AtomToken subList[MAX_SUB_ROW][MAX_SUB_COW]; :存储正则表达式中每个[]中原子字符
static int subListLen[MAX_SUB_ROW]; :存储正则表达式中每个[]中原子字符个数
static int subLen; :存储正则表达式中[]的个数
includes:
graph.h :VGL::ADT::有向图
-------------------------------------------------------------------------------*/
#ifndef REGEX__
#define REGEX__
#include " graph.h "
namespace simplex
{
typedef char AtomChar;
enum AtomType{AtomNormChar,AtomRangeLeft,AtomRangeRight,AtomRangeOne,AtomRangeBoth,AtomLeftMB,
AtomRightMB,AtomLeftBB,AtomRightBB,AtomLeftSB,AtomRightSB,
AtomNormESC,AtomMoreOne,AtomMoreZero,AtomZeroOne,AtomNot,
AtomBegin,AtomEnd,AtomDigit,AtomNotDigit,AtomLetter,AtomNotLetter,
AtomAny,AtomLetterRange,AtomDigitRange,AtomMu,AtomOr,AtomOrList,AtomNotAndList};
#define CAPA_LIST 35
#define CAPA_LIST_LETTER 25
char list[CAPA_LIST][CAPA_LIST_LETTER]={"AtomNormChar","AtomRangeLeft","AtomRangeRight","AtomRangeOne","AtomRangeBoth","AtomLeftMB",
"AtomRightMB","AtomLeftBB","AtomRightBB","AtomLeftSB","AtomRightSB",
"AtomNormESC","AtomMoreOne","AtomMoreZero","AtomZeroOne","AtomNot",
"AtomBegin","AtomEnd","AtomDigit","AtomNotDigit","AtomLetter","AtomNotLetter",
"AtomAny","AtomLetterRange","AtomDigitRange","AtomMu","AtomOr","AtomOrList","AtomNotAndList"};
#define MAX_SUB_ROW 50
#define MAX_SUB_COW 30
#define MAX_TOKEN 200
static int subListLen[MAX_SUB_ROW];
static int subLen;
class AtomToken;
class AtomToken
{
public:
AtomChar c[3];
AtomType type;
int subIndex;
AtomToken()
{
memcpy(c,"",3);
type=AtomNormChar;
subIndex=0;
}
~AtomToken()
{
subIndex=0;
}
AtomToken* operator=(AtomToken& _copy)
{
memcpy(c,_copy.c,3*sizeof(char));
type=_copy.type;
subIndex=_copy.subIndex;
return this;
}
int operator ==(AtomToken & _token)
{
AtomToken* b,*ob;
if(type==AtomNormChar)
{
b=&_token;
ob=this;
}else
{
b=this;
ob=&_token;
}
if(b->type==AtomMu)
{
return 2;
}
switch(b->type)
{
case AtomNotAndList:
case AtomOrList:
for(int j=0;j!=subListLen[b->subIndex];j++)
{
if(subList[b->subIndex][j]==*ob)
return 1;
}
return 0;
case AtomAny:
return ob->type==AtomNormChar;
case AtomNormChar:
return b->c[0]==ob->c[0];
case AtomNormESC:
switch(b->c[0])
{
case 'd':
return ob->c[0]>='0'&&ob->c[0]<='9';
case 'D':
return ob->c[0]<'0'||ob->c[0]>'9';
case 'b':
return (ob->c[0]>='a'&&ob->c[0]<='z')||(ob->c[0]>='A'&&ob->c[0]<='Z');
case 'B':
return (ob->c[0]<'a'||ob->c[0]>'z')&&(ob->c[0]<'A'||ob->c[0]>'Z');
}
return _token.c[0]==c[0];
case AtomDigitRange:
return ob->c[0]>=b->c[0]&&ob->c[0]<=b->c[1];
case AtomLetterRange:
return ob->c[0]>=b->c[0]&&ob->c[0]<=b->c[1];
default:
return 0;
}
}
}subList[MAX_SUB_ROW][MAX_SUB_COW];
class Regex /**//* Regex Analyser :Scanning and Grammar,Match*/
{
protected:
AtomToken tokens[MAX_TOKEN];
adt::graph<int,AtomToken> nfa;/**//* Epsilon-NFA */
int len;
int isDigit(char c)
{
return c<='9'&&c>='0';
}
int isLetter(char c)
{
return (c<='z'&&c>='a')||(c<='Z'&&c>='A');
}
int getFirstNum(char * _buf,int & _len)
{
int i,num=0;
for(i=0;isDigit(_buf[i]);i++);
_len=i;
i--;
for(int j=0;i!=-1;i--,j++)
{
num+=(_buf[i]-'0')*atom::pow10(j);
}
return num;
}
AtomToken* buf_tokens;
public:
Regex()
{
subLen=0;
}
~Regex()
{
if(!buf_tokens)
delete []buf_tokens;
}
void atomParse(char* _buf)
{
int buf_len=atom::lenof(_buf),temp_len=0;
len=0;
AtomToken _list[MAX_SUB_COW];
int lenList=0;
for(int i=0;i!=buf_len;)
{
switch(_buf[i])
{
case '^':
tokens[len].c[0]='^';
if(i==0)
tokens[len].type=AtomBegin;
else
tokens[len].type=AtomNot;
i++;
break;
case '.':
tokens[len].c[0]='.';
tokens[len].type=AtomAny;
i++;
break;
case '|':
tokens[len].c[0]='|';
tokens[len].type=AtomOr;
i++;
break;
case '+':
tokens[len].c[0]='+';
tokens[len].type=AtomMoreOne;
i++;
break;
case '*':
tokens[len].c[0]='*';
tokens[len].type=AtomMoreZero;
i++;
break;
case '?':
tokens[len].c[0]='?';
tokens[len].type=AtomZeroOne;
i++;
break;
case '$':
tokens[len].c[0]='$';
tokens[len].type=AtomZeroOne;
i++;
break;
case '{':
if(_buf[i+1]==',')
{
tokens[len].c[0]=getFirstNum(&_buf[i+2],temp_len);
tokens[len].type=AtomRangeRight;
i+=temp_len+3;
break;
}else
{
tokens[len].c[0]=getFirstNum(&_buf[i+1],temp_len);
tokens[len].type=AtomRangeLeft;
if(_buf[i+temp_len+1]==',')
{
if(isDigit(_buf[i+temp_len+2]))
{
i+=temp_len+2;
tokens[len].type=AtomRangeBoth;
tokens[len].c[1]=getFirstNum(_buf+i+temp_len+2,temp_len);
i+=temp_len;
if(_buf[i]=='}')
{
i++;
break;
}else
{
cout<<"Error\n";
break;
}
}else if(_buf[i+temp_len+2]=='}')
{
i+=temp_len+3;
tokens[len].type=AtomRangeLeft;
break;
}
}else if(_buf[i+temp_len+1]=='}')
{
i+=temp_len+2;
tokens[len].type=AtomRangeOne;
break;
}
}
case '[':
lenList=0;
if(_buf[i+1]!='^')
{
tokens[len].type=AtomOrList;
}else
{
i++;
tokens[len].type=AtomNotAndList;
}
i++;
for(;_buf[i]!=']';)
{
if(isDigit(_buf[i]))
{
if(i+4<buf_len)
{
if(_buf[i+1]=='.'&&_buf[i+2]=='.'&&isDigit(_buf[i+3]))
{
_list[lenList].c[0]=_buf[i];
_list[lenList].c[1]=_buf[i+3];
_list[lenList].type=AtomDigitRange;
lenList++;
i+=4;
continue;
}else
{
_list[lenList].c[0]=_buf[i];
_list[lenList].type=AtomNormChar;
lenList++;
i++;
continue;
}
}else
{
_list[lenList].c[0]=_buf[i];
_list[lenList].type=AtomNormChar;
lenList++;
i++;
continue;
}
}else if(isLetter(_buf[i]))
{
if(i+4<buf_len)
{
if(_buf[i+1]=='.'&&_buf[i+2]=='.'&&isLetter(_buf[i+3]))
{
_list[lenList].c[0]=_buf[i];
_list[lenList].c[1]=_buf[i+3];
_list[lenList].type=AtomLetterRange;
lenList++;
i+=4;
continue;
}else
{
_list[lenList].c[0]=_buf[i];
_list[lenList].type=AtomNormChar;
lenList++;
i++;
continue;
}
}else
{
_list[lenList].c[0]=_buf[i];
_list[lenList].type=AtomNormChar;
lenList++;
i++;
continue;
}
}else
{
switch(_buf[i])
{
case '\\':
i++;
switch(_buf[i])
{
case '|':
case '\\':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case '*':
case '?':
case '+':
case '^':
case '$':
case '.':
_list[lenList].c[0]=_buf[i];
_list[lenList].type=AtomNormChar;
lenList++;
i++;
break;
case 'd':
case 'D':
case 'b':
case 'B':
_list[lenList].c[0]=_buf[i];
_list[lenList].type=AtomNormESC;
lenList++;
i++;
break;
}
}
}
}
for(int j=0;j!=lenList;j++)
{
subList[subLen][j]=_list[j];
}
tokens[len].subIndex=subLen;
subListLen[subLen++]=lenList;
++i;
break;
case '(':
tokens[len].c[0]='(';
tokens[len].type=AtomLeftSB;
i++;
break;
case ')':
tokens[len].c[0]=')';
tokens[len].type=AtomRightSB;
i++;
break;
case '\\':
i++;
switch(_buf[i])
{
case '|':
case '\\':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case '*':
case '?':
case '+':
case '^':
case '$':
case '.':
tokens[len].c[0]=_buf[i];
tokens[len].type=AtomNormChar;
i++;
break;
case 'd':
case 'D':
case 'b':
case 'B':
tokens[len].c[0]=_buf[i];
tokens[len].type=AtomNormESC;
i++;
break;
}
break;
default:
tokens[len].c[0]=_buf[i];
tokens[len].type=AtomNormChar;
i++;
break;
}
len++;
}
#ifdef TEST_OPEN_CONSOLE
/**//* DEBUG:display all the results */
cout<<"\nScanning list:\nPrinting format:Token[i](Type,Attribut_1,Attribute_2)\n";
for(int k=0;k!=len;k++)
{
cout<<"Token["<<k<<"]:(\'";
cout<<list[tokens[k].type]<<"\',\'";
cout<<tokens[k].c[0]<<"\',\'"<<tokens[k].c[1]<<"\')\t\n";
}
#endif
}
enum NfaStatus{NfaBegin,NfaNormState,NfaEnd};
void grammarParse(int _index=0,int _deep=0)
{
static AtomToken token;
static int numArc;
static int lastKey,nowKey,lastBegin;
static int i;
if(_index==0)
{
lastBegin=1;
nowKey=1;
numArc=1;
}
int beginNode,endNode;
nfa.addNode(nowKey,NfaBegin,0);
beginNode=nowKey++;
nfa.addNode(nowKey,NfaEnd,0);
endNode=nowKey++;
if(_index!=0)
{
token.type=AtomMu;
nfa.addArc(lastKey,beginNode,numArc++,token);
}
lastKey=beginNode;
int temp=0;
for(i=_index;i!=len;i++)
{
switch(tokens[i].type)
{
case AtomBegin:
break;
case AtomEnd:
break;
case AtomRightSB:
temp=1;
if(i+1!=len)
{
if(tokens[i+1].type==AtomMoreOne)
{
token.type=AtomMu;
nfa.addArc(endNode,beginNode,numArc++,token);
}else if(tokens[i+1].type==AtomMoreZero)
{
token.type=AtomMu;
nfa.addNode(nowKey,NfaNormState,0);
nfa.addArc(beginNode,endNode,numArc++,token);
nfa.addArc(lastKey,nowKey,numArc++,token);
nfa.addArc(nowKey,beginNode,numArc++,token);
lastKey=nowKey++;
//AtomRangeLeft,AtomRangeRight,AtomRangeOne,AtomRangeBoth
}else if(tokens[i+1].type==AtomRangeLeft)
{
}
}
break;
case AtomLeftSB:
grammarParse(i+1,_deep+1);
break;
case AtomLeftMB:
grammarParse(i,_deep+1);
break;
case AtomAny:
case AtomOrList:
case AtomNotAndList:
case AtomNormESC:
case AtomNormChar:
nfa.addNode(nowKey,NfaNormState,0);
nfa.addArc(lastKey,nowKey,numArc++,tokens[i]);
if(i+1!=len)
{
if(tokens[i+1].type==AtomMoreOne)
{
nfa.addArc(lastKey,lastKey,numArc++,tokens[i]);
}else if(tokens[i+1].type==AtomMoreZero)
{
token.type=AtomMu;
nfa.addArc(lastKey,nowKey,numArc++,token);
nfa.addArc(lastKey,lastKey,numArc++,tokens[i]);
}
}
lastKey=nowKey++;
break;
case AtomOr:
token.type=AtomMu;
nfa.addArc(lastKey,endNode,numArc++,token);
nfa.addNode(nowKey,NfaNormState,0);
nfa.addArc(beginNode,nowKey,numArc++,token);
lastKey=nowKey++;
break;
default:
break;
}
if(temp==1)
break;
}
token.type=AtomMu;
nfa.addArc(lastKey,endNode,numArc++,token);
lastKey=endNode;
lastBegin=beginNode;
}
void parse(char* _buf)
{
atomParse(_buf);
grammarParse();
}
int match(char* _buf=0)
{
int buf_len=atom::lenof(_buf),buf_max,temp;
buf_tokens=new AtomToken[buf_len];
for(int i=0;i!=buf_len;i++)
{
buf_tokens[i].c[0]=_buf[i];
}
/**//*Restricted in beginning match*/
buf_max=(tokens[0].type==AtomBegin)?1:buf_len;
for(int i=0;i!=buf_max;i++)
{
if(temp=nfa.isGoEPath(1,buf_tokens,buf_len,i,2))
{
if(tokens[len-1].c[0]=='$')
{
if(temp==2)
return 1;
else
return 0;
}else
{
return 1;
}
}
}
return 0;
}
};
}
#endif
/**/ /*----------------------------------------------------------------------------
Simplex v1.2
Developer: Zblc
vgl::regex
enumes:
classes:
AtomToken :原子词
Regex :正则表达式分析类
macros:
MAX_SUB_ROW :[]的最大数
MAX_SUB_COW :[]中原子字符的最大数
MAX_TOKEN :最大接受的原子字符数
CAPA_LIST :调试用
CAPA_LIST_LETTER :调试用
namespace variable:
AtomToken subList[MAX_SUB_ROW][MAX_SUB_COW]; :存储正则表达式中每个[]中原子字符
static int subListLen[MAX_SUB_ROW]; :存储正则表达式中每个[]中原子字符个数
static int subLen; :存储正则表达式中[]的个数
includes:
graph.h :VGL::ADT::有向图
-------------------------------------------------------------------------------*/
#ifndef REGEX__
#define REGEX__
#include " graph.h "
namespace simplex
{
typedef char AtomChar;
enum AtomType{AtomNormChar,AtomRangeLeft,AtomRangeRight,AtomRangeOne,AtomRangeBoth,AtomLeftMB,
AtomRightMB,AtomLeftBB,AtomRightBB,AtomLeftSB,AtomRightSB,
AtomNormESC,AtomMoreOne,AtomMoreZero,AtomZeroOne,AtomNot,
AtomBegin,AtomEnd,AtomDigit,AtomNotDigit,AtomLetter,AtomNotLetter,
AtomAny,AtomLetterRange,AtomDigitRange,AtomMu,AtomOr,AtomOrList,AtomNotAndList};
#define CAPA_LIST 35
#define CAPA_LIST_LETTER 25
char list[CAPA_LIST][CAPA_LIST_LETTER]={"AtomNormChar","AtomRangeLeft","AtomRangeRight","AtomRangeOne","AtomRangeBoth","AtomLeftMB",
"AtomRightMB","AtomLeftBB","AtomRightBB","AtomLeftSB","AtomRightSB",
"AtomNormESC","AtomMoreOne","AtomMoreZero","AtomZeroOne","AtomNot",
"AtomBegin","AtomEnd","AtomDigit","AtomNotDigit","AtomLetter","AtomNotLetter",
"AtomAny","AtomLetterRange","AtomDigitRange","AtomMu","AtomOr","AtomOrList","AtomNotAndList"};
#define MAX_SUB_ROW 50
#define MAX_SUB_COW 30
#define MAX_TOKEN 200
static int subListLen[MAX_SUB_ROW];
static int subLen;
class AtomToken;
class AtomToken
{
public:
AtomChar c[3];
AtomType type;
int subIndex;
AtomToken()
{
memcpy(c,"",3);
type=AtomNormChar;
subIndex=0;
}
~AtomToken()
{
subIndex=0;
}
AtomToken* operator=(AtomToken& _copy)
{
memcpy(c,_copy.c,3*sizeof(char));
type=_copy.type;
subIndex=_copy.subIndex;
return this;
}
int operator ==(AtomToken & _token)
{
AtomToken* b,*ob;
if(type==AtomNormChar)
{
b=&_token;
ob=this;
}else
{
b=this;
ob=&_token;
}
if(b->type==AtomMu)
{
return 2;
}
switch(b->type)
{
case AtomNotAndList:
case AtomOrList:
for(int j=0;j!=subListLen[b->subIndex];j++)
{
if(subList[b->subIndex][j]==*ob)
return 1;
}
return 0;
case AtomAny:
return ob->type==AtomNormChar;
case AtomNormChar:
return b->c[0]==ob->c[0];
case AtomNormESC:
switch(b->c[0])
{
case 'd':
return ob->c[0]>='0'&&ob->c[0]<='9';
case 'D':
return ob->c[0]<'0'||ob->c[0]>'9';
case 'b':
return (ob->c[0]>='a'&&ob->c[0]<='z')||(ob->c[0]>='A'&&ob->c[0]<='Z');
case 'B':
return (ob->c[0]<'a'||ob->c[0]>'z')&&(ob->c[0]<'A'||ob->c[0]>'Z');
}
return _token.c[0]==c[0];
case AtomDigitRange:
return ob->c[0]>=b->c[0]&&ob->c[0]<=b->c[1];
case AtomLetterRange:
return ob->c[0]>=b->c[0]&&ob->c[0]<=b->c[1];
default:
return 0;
}
}
}subList[MAX_SUB_ROW][MAX_SUB_COW];
class Regex /**//* Regex Analyser :Scanning and Grammar,Match*/
{
protected:
AtomToken tokens[MAX_TOKEN];
adt::graph<int,AtomToken> nfa;/**//* Epsilon-NFA */
int len;
int isDigit(char c)
{
return c<='9'&&c>='0';
}
int isLetter(char c)
{
return (c<='z'&&c>='a')||(c<='Z'&&c>='A');
}
int getFirstNum(char * _buf,int & _len)
{
int i,num=0;
for(i=0;isDigit(_buf[i]);i++);
_len=i;
i--;
for(int j=0;i!=-1;i--,j++)
{
num+=(_buf[i]-'0')*atom::pow10(j);
}
return num;
}
AtomToken* buf_tokens;
public:
Regex()
{
subLen=0;
}
~Regex()
{
if(!buf_tokens)
delete []buf_tokens;
}
void atomParse(char* _buf)
{
int buf_len=atom::lenof(_buf),temp_len=0;
len=0;
AtomToken _list[MAX_SUB_COW];
int lenList=0;
for(int i=0;i!=buf_len;)
{
switch(_buf[i])
{
case '^':
tokens[len].c[0]='^';
if(i==0)
tokens[len].type=AtomBegin;
else
tokens[len].type=AtomNot;
i++;
break;
case '.':
tokens[len].c[0]='.';
tokens[len].type=AtomAny;
i++;
break;
case '|':
tokens[len].c[0]='|';
tokens[len].type=AtomOr;
i++;
break;
case '+':
tokens[len].c[0]='+';
tokens[len].type=AtomMoreOne;
i++;
break;
case '*':
tokens[len].c[0]='*';
tokens[len].type=AtomMoreZero;
i++;
break;
case '?':
tokens[len].c[0]='?';
tokens[len].type=AtomZeroOne;
i++;
break;
case '$':
tokens[len].c[0]='$';
tokens[len].type=AtomZeroOne;
i++;
break;
case '{':
if(_buf[i+1]==',')
{
tokens[len].c[0]=getFirstNum(&_buf[i+2],temp_len);
tokens[len].type=AtomRangeRight;
i+=temp_len+3;
break;
}else
{
tokens[len].c[0]=getFirstNum(&_buf[i+1],temp_len);
tokens[len].type=AtomRangeLeft;
if(_buf[i+temp_len+1]==',')
{
if(isDigit(_buf[i+temp_len+2]))
{
i+=temp_len+2;
tokens[len].type=AtomRangeBoth;
tokens[len].c[1]=getFirstNum(_buf+i+temp_len+2,temp_len);
i+=temp_len;
if(_buf[i]=='}')
{
i++;
break;
}else
{
cout<<"Error\n";
break;
}
}else if(_buf[i+temp_len+2]=='}')
{
i+=temp_len+3;
tokens[len].type=AtomRangeLeft;
break;
}
}else if(_buf[i+temp_len+1]=='}')
{
i+=temp_len+2;
tokens[len].type=AtomRangeOne;
break;
}
}
case '[':
lenList=0;
if(_buf[i+1]!='^')
{
tokens[len].type=AtomOrList;
}else
{
i++;
tokens[len].type=AtomNotAndList;
}
i++;
for(;_buf[i]!=']';)
{
if(isDigit(_buf[i]))
{
if(i+4<buf_len)
{
if(_buf[i+1]=='.'&&_buf[i+2]=='.'&&isDigit(_buf[i+3]))
{
_list[lenList].c[0]=_buf[i];
_list[lenList].c[1]=_buf[i+3];
_list[lenList].type=AtomDigitRange;
lenList++;
i+=4;
continue;
}else
{
_list[lenList].c[0]=_buf[i];
_list[lenList].type=AtomNormChar;
lenList++;
i++;
continue;
}
}else
{
_list[lenList].c[0]=_buf[i];
_list[lenList].type=AtomNormChar;
lenList++;
i++;
continue;
}
}else if(isLetter(_buf[i]))
{
if(i+4<buf_len)
{
if(_buf[i+1]=='.'&&_buf[i+2]=='.'&&isLetter(_buf[i+3]))
{
_list[lenList].c[0]=_buf[i];
_list[lenList].c[1]=_buf[i+3];
_list[lenList].type=AtomLetterRange;
lenList++;
i+=4;
continue;
}else
{
_list[lenList].c[0]=_buf[i];
_list[lenList].type=AtomNormChar;
lenList++;
i++;
continue;
}
}else
{
_list[lenList].c[0]=_buf[i];
_list[lenList].type=AtomNormChar;
lenList++;
i++;
continue;
}
}else
{
switch(_buf[i])
{
case '\\':
i++;
switch(_buf[i])
{
case '|':
case '\\':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case '*':
case '?':
case '+':
case '^':
case '$':
case '.':
_list[lenList].c[0]=_buf[i];
_list[lenList].type=AtomNormChar;
lenList++;
i++;
break;
case 'd':
case 'D':
case 'b':
case 'B':
_list[lenList].c[0]=_buf[i];
_list[lenList].type=AtomNormESC;
lenList++;
i++;
break;
}
}
}
}
for(int j=0;j!=lenList;j++)
{
subList[subLen][j]=_list[j];
}
tokens[len].subIndex=subLen;
subListLen[subLen++]=lenList;
++i;
break;
case '(':
tokens[len].c[0]='(';
tokens[len].type=AtomLeftSB;
i++;
break;
case ')':
tokens[len].c[0]=')';
tokens[len].type=AtomRightSB;
i++;
break;
case '\\':
i++;
switch(_buf[i])
{
case '|':
case '\\':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case '*':
case '?':
case '+':
case '^':
case '$':
case '.':
tokens[len].c[0]=_buf[i];
tokens[len].type=AtomNormChar;
i++;
break;
case 'd':
case 'D':
case 'b':
case 'B':
tokens[len].c[0]=_buf[i];
tokens[len].type=AtomNormESC;
i++;
break;
}
break;
default:
tokens[len].c[0]=_buf[i];
tokens[len].type=AtomNormChar;
i++;
break;
}
len++;
}
#ifdef TEST_OPEN_CONSOLE
/**//* DEBUG:display all the results */
cout<<"\nScanning list:\nPrinting format:Token[i](Type,Attribut_1,Attribute_2)\n";
for(int k=0;k!=len;k++)
{
cout<<"Token["<<k<<"]:(\'";
cout<<list[tokens[k].type]<<"\',\'";
cout<<tokens[k].c[0]<<"\',\'"<<tokens[k].c[1]<<"\')\t\n";
}
#endif
}
enum NfaStatus{NfaBegin,NfaNormState,NfaEnd};
void grammarParse(int _index=0,int _deep=0)
{
static AtomToken token;
static int numArc;
static int lastKey,nowKey,lastBegin;
static int i;
if(_index==0)
{
lastBegin=1;
nowKey=1;
numArc=1;
}
int beginNode,endNode;
nfa.addNode(nowKey,NfaBegin,0);
beginNode=nowKey++;
nfa.addNode(nowKey,NfaEnd,0);
endNode=nowKey++;
if(_index!=0)
{
token.type=AtomMu;
nfa.addArc(lastKey,beginNode,numArc++,token);
}
lastKey=beginNode;
int temp=0;
for(i=_index;i!=len;i++)
{
switch(tokens[i].type)
{
case AtomBegin:
break;
case AtomEnd:
break;
case AtomRightSB:
temp=1;
if(i+1!=len)
{
if(tokens[i+1].type==AtomMoreOne)
{
token.type=AtomMu;
nfa.addArc(endNode,beginNode,numArc++,token);
}else if(tokens[i+1].type==AtomMoreZero)
{
token.type=AtomMu;
nfa.addNode(nowKey,NfaNormState,0);
nfa.addArc(beginNode,endNode,numArc++,token);
nfa.addArc(lastKey,nowKey,numArc++,token);
nfa.addArc(nowKey,beginNode,numArc++,token);
lastKey=nowKey++;
//AtomRangeLeft,AtomRangeRight,AtomRangeOne,AtomRangeBoth
}else if(tokens[i+1].type==AtomRangeLeft)
{
}
}
break;
case AtomLeftSB:
grammarParse(i+1,_deep+1);
break;
case AtomLeftMB:
grammarParse(i,_deep+1);
break;
case AtomAny:
case AtomOrList:
case AtomNotAndList:
case AtomNormESC:
case AtomNormChar:
nfa.addNode(nowKey,NfaNormState,0);
nfa.addArc(lastKey,nowKey,numArc++,tokens[i]);
if(i+1!=len)
{
if(tokens[i+1].type==AtomMoreOne)
{
nfa.addArc(lastKey,lastKey,numArc++,tokens[i]);
}else if(tokens[i+1].type==AtomMoreZero)
{
token.type=AtomMu;
nfa.addArc(lastKey,nowKey,numArc++,token);
nfa.addArc(lastKey,lastKey,numArc++,tokens[i]);
}
}
lastKey=nowKey++;
break;
case AtomOr:
token.type=AtomMu;
nfa.addArc(lastKey,endNode,numArc++,token);
nfa.addNode(nowKey,NfaNormState,0);
nfa.addArc(beginNode,nowKey,numArc++,token);
lastKey=nowKey++;
break;
default:
break;
}
if(temp==1)
break;
}
token.type=AtomMu;
nfa.addArc(lastKey,endNode,numArc++,token);
lastKey=endNode;
lastBegin=beginNode;
}
void parse(char* _buf)
{
atomParse(_buf);
grammarParse();
}
int match(char* _buf=0)
{
int buf_len=atom::lenof(_buf),buf_max,temp;
buf_tokens=new AtomToken[buf_len];
for(int i=0;i!=buf_len;i++)
{
buf_tokens[i].c[0]=_buf[i];
}
/**//*Restricted in beginning match*/
buf_max=(tokens[0].type==AtomBegin)?1:buf_len;
for(int i=0;i!=buf_max;i++)
{
if(temp=nfa.isGoEPath(1,buf_tokens,buf_len,i,2))
{
if(tokens[len-1].c[0]=='$')
{
if(temp==2)
return 1;
else
return 0;
}else
{
return 1;
}
}
}
return 0;
}
};
}
#endif
另附用到的自己上一年写的adt::graph类.
/**/
/* graph.h :base::adt::graph */
#ifndef GRAPH__
#define GRAPH__
#include " base.h "
#include " vector.h "
namespace adt
{
using adt::vector;
template<typename VTypeN,typename VTypeE>
class graph : public base::adt
{
public:
struct VArc;
struct VNode;
struct VArc
{
VNode* begin;
VNode* end;
int *tag_begin;
int *tag_end;
VTypeE weight;
int tag;/**//*internal index tag*/
int key;/**//*external index tag*/
VArc()
{
tag=0;
key=0;
}
VArc(VNode *_begin,VNode * _end,int _key,int _tag,VTypeE _w)
{
begin=_begin;
end=_end;
weight=_w;
tag=_tag;
key=_key;
tag_begin=&begin->tag;
tag_end=&end->tag;
}
~VArc()
{
begin=0;
end=0;
tag=0;
key=0;
}
/**//*copy to _arc only by data not adr*/
void copyTo(VArc * _arc)
{
_arc->weight=weight;
_arc->tag=tag;
_arc->key=key;
}
void setKey(int _key)
{
key=_key;
}
void setTag(int _tag)
{
tag=_tag;
}
void setWeight(VTypeE _w)
{
weight=_w;
}
void setBegin(VNode* _begin)
{
begin=_begin;
tag_begin=&begin->tag;
}
void setEnd(VNode* _end)
{
end=_end;
tag_end=&end->tag;
}
};
struct VNode
{
vector<VArc*> inArc;
vector<VArc*> outArc;
int &inNum;
int &outNum;
VTypeN weight;
int tag;/**//*internal index tag*/
int key;/**//*external index tag*/
int status;/**//*node status*/
/**//*copy to _arc only by data not adr*/
void copyTo(VNode * _node)
{
_node->weight=weight;
_node->tag=tag;
_node->key=key;
_node->status=status;
}
VNode():/**//*build up ref*/inNum(inArc.n),outNum(outArc.n)
{
status=0;
tag=0;
key=0;
}
VNode(int _key,int _tag,VTypeN _w,int _status):/**//*build up ref*/inNum(inArc.n),outNum(outArc.n)
{
weight=_w;
status=_status;
tag=_tag;
key=_key;
}
~VNode()
{
tag=0;
key=0;
status=0;
}
/**//* set key */
void setKey(int _key)
{
key=_key;
}
/**//* set tag */
void setTag(int _tag)
{
tag=_tag;
}
/**//* set weight */
int setWeight(VTypeN _w)
{
weight=_w;
return 1;
}
/**//* set status */
void setStatus(int _status)
{
status=_status;
}
/**//* add inArc */
int addIn(VArc *_inArc )
{
if(!_inArc)
return 0;
inArc.push(_inArc);
//++inNum;
return 1;
}
/**//* and outArc */
int addOut(VArc *_outArc )
{
if(!_outArc)
return 0;
outArc.push(_outArc);
//++outNum;
return 1;
}
/**//* remove inArc by weight */
int removeInWeight(VTypeE _w)
{
for(int i=0;i!=inArc_.n;i++)
{
if(inArc[i]->weight==_w)
{
inArc.remove(i);
//--inNum;
--i;
}
}
return 1;
}
/**//* remove outArc by weight */
int removeOutWeight(VTypeE _w)
{
for(int i=0;i!=outArc_.n;i++)
{
if(outArc[i]->weight==_w)
{
outArc.remove(i);
//--outNum;
--i;
}
}
return 1;
}
/**//* remove inArc by tag */
int removeInTag(int _tag)
{
for(int i=0;i!=inArc.n;i++)
{
if(inArc[i]->tag==_tag)
{
inArc.remove(i);
//--inNum;
return 1;
}
}
return 0;
}
/**//* remove outArc by tag */
int removeOutTag(int _tag)
{
for(int i=0;i!=outArc.n;i++)
{
if(outArc[i]->tag==_tag)
{
outArc.remove(i);
//--outNum;
return 1;
}
}
return 0;
}
/**//* remove inArc by key */
int removeInKey(int _key)
{
for(int i=0;i!=inArc_.n;i++)
{
if(inArc[i]->key==_key)
{
inArc.remove(i);
//--inNum;
return 1;
}
}
return 0;
}
/**//* remove outArc by key */
int removeOutKey(int _key)
{
for(int i=0;i!=outArc_.n;i++)
{
if(outArc[i]->key==_key)
{
outArc.remove(i);
//--outNum;
return 1;
}
}
return 0;
}
/**//* search inArc by weight */
VArc* findInWeight(VTypeE _w)
{
for(int i=0;i!=inArc_.n;i++)
{
if(inArc[i]->weight==_w)
{
return inArc_[i];
}
}
return 0;
}
/**//* search outArc by weight */
VArc* findOutWeight(VTypeE _w)
{
for(int i=0;i!=outArc.n;i++)
{
if(outArc[i]->weight==_w)
{
return outArc[i];
}
}
return 0;
}
/**//* search inArc by tag */
VArc* findInTag(int _t)
{
for(int i=0;i!=inArc.n;i++)
{
if(inArc[i]->tag==_t)
{
return inArc[i];
}
}
return 0;
}
/**//* search outArc by tag */
VArc* findOutTag(int _t)
{
for(int i=0;i!=outArc_.n;i++)
{
if(outArc[i]->tag==_t)
{
return outArc_[i];
}
}
return 0;
}
/**//* search inArc by key */
VArc* findInKey(int _key)
{
for(int i=0;i!=inArc_.n;i++)
{
if(inArc[i]->key==_key)
{
return inArc_[i];
}
}
return 0;
}
/**//* search outArc by key */
VArc* findOutKey(int _key)
{
for(int i=0;i!=outArc_.n;i++)
{
if(outArc[i]->key==_key)
{
return outArc_[i];
}
}
return 0;
}
};
vector<VNode*> allNode;
vector<VArc*> allArc;
int& nodeNum;
int& arcNum;
graph():/**//*build up ref*/nodeNum(allNode.n),arcNum(allArc.n)
{
}
graph(graph & obj):/**//*build up ref*/nodeNum(allNode.n),arcNum(allArc.n)
{
obj.copyTo(*this);
}
int addNode(int _key,VTypeN _w,int _status)
{
if(findNodeTag(_key)!=-1)
{
#ifdef TEST_OPEN
TEST_THROW("Exception in graph.h graph::addNode Function.")
#endif
return 0;
}
VNode* _node=new VNode;
/**//*init data*/
_node->setKey(_key);
_node->setWeight(_w);
_node->setStatus(_status);
_node->setTag(nodeNum);/**//*index reciprocally beginning with 0 */
/**//*push in index list*/
allNode.push(_node);
return 1;
}
int setNode(int _key,VTypeN _w,int _status)
{
int _tag;
if((_tag=findNodeTag(_key))==-1)
{
#ifdef TEST_OPEN
TEST_THROW("Exception in graph.h graph::setNode Function.")
#endif
return 0;
}
VNode* _node=allNode[_tag];
/**//*init data*/
_node->setWeight(_w);
_node->setStatus(_status);
return 1;
}
/**//* switch key to tag */
int findNodeTag(int _key)
{
for(int i=0;i!=allNode.n;i++)
{
if(allNode[i]->key==_key)
{
return allNode[i]->tag;
}
}
return -1;
}
/**//* switch key to tag */
int findArcTag(int _key)
{
for(int i=0;i!=allArc.n;i++)
{
if(allArc[i]->key==_key)
{
return allArc[i]->tag;
}
}
return -1;
}
/**//* find node by key */
int findNode(int _key)
{
for(int i=0;i!=allNode.n;i++)
{
if(allNode[i]->key==_key)
{
return 1;
}
}
return 0;
}
/**//* find arc by key */
int findArc(int _key)
{
for(int i=0;i!=allArc.n;i++)
{
if(allArc[i]->key==_key)
{
return 1;
}
}
return 0;
}
int isGo(int _key,VTypeE _w,int &_next_key)
{
int _tag = findNodeTag(_key);
if(_tag>=nodeNum||_tag==-1)
{
#ifdef TEST_OPEN
TEST_THROW("Exception in graph.h graph::isGo function.")
#endif
return 0;
}
VNode * _node = allNode[_tag];
VArc* _arc = _node->findOutWeight(_w);
if(!_arc)
return 0;
_next_key = _arc->end->key;
return 1;
}
int getStatus(int _key)
{
int _tag = findNodeTag(_key);
return allNode[_tag]->status;
}
/**//* add arc by begin and end 's key */
void addArc(int _k_begin,int _k_end,int _key,VTypeE& _w)
{
if(findArcTag(_key)!=-1)
{
#ifdef TEST_OPEN
TEST_THROW("Exception in graph.h graph::addArc function.")
#endif
return;
}
VArc* _arc=new VArc;
/**//* switch key to tag,get begin's and end's adr*/
int _tag_begin = findNodeTag(_k_begin);
int _tag_end = findNodeTag(_k_end);
VNode* _begin=allNode[_tag_begin];
VNode* _end =allNode[_tag_end];
/**//*init data*/
_arc->setBegin(_begin);
_arc->setEnd(_end);
_arc->setKey(_key);
_arc->setWeight(_w);
/**//*index reciprocally beginning with zero */
_arc->setTag(arcNum);
/**//*building begin-end link.*/
_begin->addOut(_arc);
_end->addIn(_arc);
/**//*push in index list*/
allArc.push(_arc);
}
int setArc(int _key,VTypeE& _w)
{
int _tag;
if((_tag=findArcTag(_key))==-1)
{
#ifdef TEST_OPEN
TEST_THROW("Exception in graph.h graph::setArc function.")
#endif
return 0;
}
VArc* _arc=allArc[_tag];
VNode* _begin=allNode[_arc->begin->tag];
VNode* _end =allNode[_arc->end->tag];
/**//*init data*/
_arc->setBegin(_begin);
_arc->setEnd(_end);
_arc->setWeight(_w);
}
/**//* copy self to graph-obj */
int copyTo(graph & _obj)
{
VNode *_node;
VArc *_arc;
for(int i=0;i!=nodeNum;i++)
{
_node=allNode[i];
_obj.allNode.push(new VNode(_node->key,_node->tag,_node->weight,_node->status));
}
for(int i=0;i!=arcNum;i++)
{
_arc=allArc[i];
_obj.addArc(_arc->begin->key,_arc->end->key,_arc->key,_arc->weight);
}
return 1;
}
int copyFrom(graph & _obj)
{
_obj.copyTo(*this);
return 1;
}
/**//* get value from rightObj */
void operator = (graph& _rObj)
{
copyFrom(_rObj);
}
/**//* remove arc by tag */
int removeArcTag(int _tag)
{
VArc* _arc=allArc[_tag];
_arc->begin->removeOutTag(_tag);
_arc->end->removeInTag(_tag);
allArc.remove(_tag);
for(int i=_tag;i!=arcNum;i++)
--allArc[i]->tag;
return 1;
}
/**//* remove arc by key */
int removeArcKey(int _key)
{
VArc* _arc;
/**//* search by key */
for(int i=0;i!=arcNum;i++)
{
if(allArc[i]->key==_key)
{
_arc=allArc[i];
removeArcTag(_arc->tag);
return 1;
}
}
return 0;
}
/**//* remove node by tag*/
int removeNodeTag(int _tag)
{
VNode* _node=allNode[_tag];
/**//* remove all inArc */
for(;0!=_node->inNum;)
{
removeArcTag(_node->inArc[0]->tag);
//_node->inArc.remove(0);
}
/**//* remove all outArc */
for(;0!=_node->outNum;)
{
removeArcTag(_node->outArc[0]->tag);
//cout<<_node->outNum;
//_node->outArc.remove(0);
}
/**//* remove itself*/
allNode.remove(_tag);
for(int i=_tag;i!=arcNum;i++)
--allArc[i]->tag;
return 1;
}
/**//* remove node by key*/
int removeNodeKey(int _key)
{
VNode* _node;
/**//* search by key */
for(int i=0;i!=nodeNum;i++)
{
if(allNode[i]->key==_key)
{
_node=allNode[i];
removeNodeTag(_node->tag);
return 1;
}
}
return 0;
}
int isGoEPath(int _beginKey,VTypeE * _edges,int _num,int _pos,int _endKey,int _deep=-1,int _type=25)
{
_deep++;
static int temp=0,result;
if(_pos>=_num+1)
{
_deep--;
return 0;
}if(_deep==0)
result=0;
int _tag = findNodeTag(_beginKey);
VNode * _node = allNode[_tag];
for(int i=0;i!=_node->outArc.n;i++)
{
if(_node->outArc[i]->weight.type!=_type)
{
if((_node->outArc[i]->weight==_edges[_pos])==2)
{
if(_node->outArc[i]->end->key==_endKey&&_pos>=_num)
{
_deep--;
return 2;
}else if(_node->outArc[i]->end->key==_endKey)
{
_deep--;
return 1;
}
if(temp=isGoEPath(_node->outArc[i]->end->key,_edges,_num,_pos,_endKey,_deep))
if(_deep!=0)
{
_deep--;
return temp;
}else if(temp==2)
{
_deep--;
return temp;
}else
result=1;
}else if((_node->outArc[i]->weight==_edges[_pos])==1)
{
if(_node->outArc[i]->end->key==_endKey&&_pos>=_num)
{
_deep--;
return 2;
}else if(_node->outArc[i]->end->key==_endKey)
{
_deep--;
return 1;
}if(temp=isGoEPath(_node->outArc[i]->end->key,_edges,_num,_pos+1,_endKey,_deep))
if(_deep!=0)
{
_deep--;
return temp;
}else if(temp==2)
{
_deep--;
return temp;
}else
result=1;
}else
{
continue;
}
}
}
for(int i=0;i!=_node->outArc.n;i++)
{
if(_node->outArc[i]->weight.type==_type)
{
if((_node->outArc[i]->weight==_edges[_pos])==2)
{
if(_node->outArc[i]->end->key==_endKey&&_pos>=_num)
{
_deep--;
return 2;
}else if(_node->outArc[i]->end->key==_endKey)
{
_deep--;
return 1;
}
if(temp=isGoEPath(_node->outArc[i]->end->key,_edges,_num,_pos,_endKey,_deep))
if(_deep!=0)
{
_deep--;
return temp;
}else if(temp==2)
{
_deep--;
return temp;
}else
result=1;
}else if((_node->outArc[i]->weight==_edges[_pos])==1)
{
if(_node->outArc[i]->end->key==_endKey&&_pos>=_num)
{
_deep--;
return 2;
}else if(_node->outArc[i]->end->key==_endKey)
{
_deep--;
return 1;
}if(temp=isGoEPath(_node->outArc[i]->end->key,_edges,_num,_pos+1,_endKey,_deep))
if(_deep!=0)
{
_deep--;
return temp;
}else if(temp==2)
{
_deep--;
return temp;
}else
result=1;
}else
{
continue;
}
}
}
_deep--;
if(result==1)
{
return 1;
}
return 0;
}
int free()
{
for(;0!=nodeNum;)
{
delete allNode.pop();
}
for(;0!=arcNum;)
{
delete allArc.pop();
}
return 1;
}
~graph()
{
free();
}
};
} ;
#endif
#ifndef GRAPH__
#define GRAPH__
#include " base.h "
#include " vector.h "
namespace adt
{
using adt::vector;
template<typename VTypeN,typename VTypeE>
class graph : public base::adt
{
public:
struct VArc;
struct VNode;
struct VArc
{
VNode* begin;
VNode* end;
int *tag_begin;
int *tag_end;
VTypeE weight;
int tag;/**//*internal index tag*/
int key;/**//*external index tag*/
VArc()
{
tag=0;
key=0;
}
VArc(VNode *_begin,VNode * _end,int _key,int _tag,VTypeE _w)
{
begin=_begin;
end=_end;
weight=_w;
tag=_tag;
key=_key;
tag_begin=&begin->tag;
tag_end=&end->tag;
}
~VArc()
{
begin=0;
end=0;
tag=0;
key=0;
}
/**//*copy to _arc only by data not adr*/
void copyTo(VArc * _arc)
{
_arc->weight=weight;
_arc->tag=tag;
_arc->key=key;
}
void setKey(int _key)
{
key=_key;
}
void setTag(int _tag)
{
tag=_tag;
}
void setWeight(VTypeE _w)
{
weight=_w;
}
void setBegin(VNode* _begin)
{
begin=_begin;
tag_begin=&begin->tag;
}
void setEnd(VNode* _end)
{
end=_end;
tag_end=&end->tag;
}
};
struct VNode
{
vector<VArc*> inArc;
vector<VArc*> outArc;
int &inNum;
int &outNum;
VTypeN weight;
int tag;/**//*internal index tag*/
int key;/**//*external index tag*/
int status;/**//*node status*/
/**//*copy to _arc only by data not adr*/
void copyTo(VNode * _node)
{
_node->weight=weight;
_node->tag=tag;
_node->key=key;
_node->status=status;
}
VNode():/**//*build up ref*/inNum(inArc.n),outNum(outArc.n)
{
status=0;
tag=0;
key=0;
}
VNode(int _key,int _tag,VTypeN _w,int _status):/**//*build up ref*/inNum(inArc.n),outNum(outArc.n)
{
weight=_w;
status=_status;
tag=_tag;
key=_key;
}
~VNode()
{
tag=0;
key=0;
status=0;
}
/**//* set key */
void setKey(int _key)
{
key=_key;
}
/**//* set tag */
void setTag(int _tag)
{
tag=_tag;
}
/**//* set weight */
int setWeight(VTypeN _w)
{
weight=_w;
return 1;
}
/**//* set status */
void setStatus(int _status)
{
status=_status;
}
/**//* add inArc */
int addIn(VArc *_inArc )
{
if(!_inArc)
return 0;
inArc.push(_inArc);
//++inNum;
return 1;
}
/**//* and outArc */
int addOut(VArc *_outArc )
{
if(!_outArc)
return 0;
outArc.push(_outArc);
//++outNum;
return 1;
}
/**//* remove inArc by weight */
int removeInWeight(VTypeE _w)
{
for(int i=0;i!=inArc_.n;i++)
{
if(inArc[i]->weight==_w)
{
inArc.remove(i);
//--inNum;
--i;
}
}
return 1;
}
/**//* remove outArc by weight */
int removeOutWeight(VTypeE _w)
{
for(int i=0;i!=outArc_.n;i++)
{
if(outArc[i]->weight==_w)
{
outArc.remove(i);
//--outNum;
--i;
}
}
return 1;
}
/**//* remove inArc by tag */
int removeInTag(int _tag)
{
for(int i=0;i!=inArc.n;i++)
{
if(inArc[i]->tag==_tag)
{
inArc.remove(i);
//--inNum;
return 1;
}
}
return 0;
}
/**//* remove outArc by tag */
int removeOutTag(int _tag)
{
for(int i=0;i!=outArc.n;i++)
{
if(outArc[i]->tag==_tag)
{
outArc.remove(i);
//--outNum;
return 1;
}
}
return 0;
}
/**//* remove inArc by key */
int removeInKey(int _key)
{
for(int i=0;i!=inArc_.n;i++)
{
if(inArc[i]->key==_key)
{
inArc.remove(i);
//--inNum;
return 1;
}
}
return 0;
}
/**//* remove outArc by key */
int removeOutKey(int _key)
{
for(int i=0;i!=outArc_.n;i++)
{
if(outArc[i]->key==_key)
{
outArc.remove(i);
//--outNum;
return 1;
}
}
return 0;
}
/**//* search inArc by weight */
VArc* findInWeight(VTypeE _w)
{
for(int i=0;i!=inArc_.n;i++)
{
if(inArc[i]->weight==_w)
{
return inArc_[i];
}
}
return 0;
}
/**//* search outArc by weight */
VArc* findOutWeight(VTypeE _w)
{
for(int i=0;i!=outArc.n;i++)
{
if(outArc[i]->weight==_w)
{
return outArc[i];
}
}
return 0;
}
/**//* search inArc by tag */
VArc* findInTag(int _t)
{
for(int i=0;i!=inArc.n;i++)
{
if(inArc[i]->tag==_t)
{
return inArc[i];
}
}
return 0;
}
/**//* search outArc by tag */
VArc* findOutTag(int _t)
{
for(int i=0;i!=outArc_.n;i++)
{
if(outArc[i]->tag==_t)
{
return outArc_[i];
}
}
return 0;
}
/**//* search inArc by key */
VArc* findInKey(int _key)
{
for(int i=0;i!=inArc_.n;i++)
{
if(inArc[i]->key==_key)
{
return inArc_[i];
}
}
return 0;
}
/**//* search outArc by key */
VArc* findOutKey(int _key)
{
for(int i=0;i!=outArc_.n;i++)
{
if(outArc[i]->key==_key)
{
return outArc_[i];
}
}
return 0;
}
};
vector<VNode*> allNode;
vector<VArc*> allArc;
int& nodeNum;
int& arcNum;
graph():/**//*build up ref*/nodeNum(allNode.n),arcNum(allArc.n)
{
}
graph(graph & obj):/**//*build up ref*/nodeNum(allNode.n),arcNum(allArc.n)
{
obj.copyTo(*this);
}
int addNode(int _key,VTypeN _w,int _status)
{
if(findNodeTag(_key)!=-1)
{
#ifdef TEST_OPEN
TEST_THROW("Exception in graph.h graph::addNode Function.")
#endif
return 0;
}
VNode* _node=new VNode;
/**//*init data*/
_node->setKey(_key);
_node->setWeight(_w);
_node->setStatus(_status);
_node->setTag(nodeNum);/**//*index reciprocally beginning with 0 */
/**//*push in index list*/
allNode.push(_node);
return 1;
}
int setNode(int _key,VTypeN _w,int _status)
{
int _tag;
if((_tag=findNodeTag(_key))==-1)
{
#ifdef TEST_OPEN
TEST_THROW("Exception in graph.h graph::setNode Function.")
#endif
return 0;
}
VNode* _node=allNode[_tag];
/**//*init data*/
_node->setWeight(_w);
_node->setStatus(_status);
return 1;
}
/**//* switch key to tag */
int findNodeTag(int _key)
{
for(int i=0;i!=allNode.n;i++)
{
if(allNode[i]->key==_key)
{
return allNode[i]->tag;
}
}
return -1;
}
/**//* switch key to tag */
int findArcTag(int _key)
{
for(int i=0;i!=allArc.n;i++)
{
if(allArc[i]->key==_key)
{
return allArc[i]->tag;
}
}
return -1;
}
/**//* find node by key */
int findNode(int _key)
{
for(int i=0;i!=allNode.n;i++)
{
if(allNode[i]->key==_key)
{
return 1;
}
}
return 0;
}
/**//* find arc by key */
int findArc(int _key)
{
for(int i=0;i!=allArc.n;i++)
{
if(allArc[i]->key==_key)
{
return 1;
}
}
return 0;
}
int isGo(int _key,VTypeE _w,int &_next_key)
{
int _tag = findNodeTag(_key);
if(_tag>=nodeNum||_tag==-1)
{
#ifdef TEST_OPEN
TEST_THROW("Exception in graph.h graph::isGo function.")
#endif
return 0;
}
VNode * _node = allNode[_tag];
VArc* _arc = _node->findOutWeight(_w);
if(!_arc)
return 0;
_next_key = _arc->end->key;
return 1;
}
int getStatus(int _key)
{
int _tag = findNodeTag(_key);
return allNode[_tag]->status;
}
/**//* add arc by begin and end 's key */
void addArc(int _k_begin,int _k_end,int _key,VTypeE& _w)
{
if(findArcTag(_key)!=-1)
{
#ifdef TEST_OPEN
TEST_THROW("Exception in graph.h graph::addArc function.")
#endif
return;
}
VArc* _arc=new VArc;
/**//* switch key to tag,get begin's and end's adr*/
int _tag_begin = findNodeTag(_k_begin);
int _tag_end = findNodeTag(_k_end);
VNode* _begin=allNode[_tag_begin];
VNode* _end =allNode[_tag_end];
/**//*init data*/
_arc->setBegin(_begin);
_arc->setEnd(_end);
_arc->setKey(_key);
_arc->setWeight(_w);
/**//*index reciprocally beginning with zero */
_arc->setTag(arcNum);
/**//*building begin-end link.*/
_begin->addOut(_arc);
_end->addIn(_arc);
/**//*push in index list*/
allArc.push(_arc);
}
int setArc(int _key,VTypeE& _w)
{
int _tag;
if((_tag=findArcTag(_key))==-1)
{
#ifdef TEST_OPEN
TEST_THROW("Exception in graph.h graph::setArc function.")
#endif
return 0;
}
VArc* _arc=allArc[_tag];
VNode* _begin=allNode[_arc->begin->tag];
VNode* _end =allNode[_arc->end->tag];
/**//*init data*/
_arc->setBegin(_begin);
_arc->setEnd(_end);
_arc->setWeight(_w);
}
/**//* copy self to graph-obj */
int copyTo(graph & _obj)
{
VNode *_node;
VArc *_arc;
for(int i=0;i!=nodeNum;i++)
{
_node=allNode[i];
_obj.allNode.push(new VNode(_node->key,_node->tag,_node->weight,_node->status));
}
for(int i=0;i!=arcNum;i++)
{
_arc=allArc[i];
_obj.addArc(_arc->begin->key,_arc->end->key,_arc->key,_arc->weight);
}
return 1;
}
int copyFrom(graph & _obj)
{
_obj.copyTo(*this);
return 1;
}
/**//* get value from rightObj */
void operator = (graph& _rObj)
{
copyFrom(_rObj);
}
/**//* remove arc by tag */
int removeArcTag(int _tag)
{
VArc* _arc=allArc[_tag];
_arc->begin->removeOutTag(_tag);
_arc->end->removeInTag(_tag);
allArc.remove(_tag);
for(int i=_tag;i!=arcNum;i++)
--allArc[i]->tag;
return 1;
}
/**//* remove arc by key */
int removeArcKey(int _key)
{
VArc* _arc;
/**//* search by key */
for(int i=0;i!=arcNum;i++)
{
if(allArc[i]->key==_key)
{
_arc=allArc[i];
removeArcTag(_arc->tag);
return 1;
}
}
return 0;
}
/**//* remove node by tag*/
int removeNodeTag(int _tag)
{
VNode* _node=allNode[_tag];
/**//* remove all inArc */
for(;0!=_node->inNum;)
{
removeArcTag(_node->inArc[0]->tag);
//_node->inArc.remove(0);
}
/**//* remove all outArc */
for(;0!=_node->outNum;)
{
removeArcTag(_node->outArc[0]->tag);
//cout<<_node->outNum;
//_node->outArc.remove(0);
}
/**//* remove itself*/
allNode.remove(_tag);
for(int i=_tag;i!=arcNum;i++)
--allArc[i]->tag;
return 1;
}
/**//* remove node by key*/
int removeNodeKey(int _key)
{
VNode* _node;
/**//* search by key */
for(int i=0;i!=nodeNum;i++)
{
if(allNode[i]->key==_key)
{
_node=allNode[i];
removeNodeTag(_node->tag);
return 1;
}
}
return 0;
}
int isGoEPath(int _beginKey,VTypeE * _edges,int _num,int _pos,int _endKey,int _deep=-1,int _type=25)
{
_deep++;
static int temp=0,result;
if(_pos>=_num+1)
{
_deep--;
return 0;
}if(_deep==0)
result=0;
int _tag = findNodeTag(_beginKey);
VNode * _node = allNode[_tag];
for(int i=0;i!=_node->outArc.n;i++)
{
if(_node->outArc[i]->weight.type!=_type)
{
if((_node->outArc[i]->weight==_edges[_pos])==2)
{
if(_node->outArc[i]->end->key==_endKey&&_pos>=_num)
{
_deep--;
return 2;
}else if(_node->outArc[i]->end->key==_endKey)
{
_deep--;
return 1;
}
if(temp=isGoEPath(_node->outArc[i]->end->key,_edges,_num,_pos,_endKey,_deep))
if(_deep!=0)
{
_deep--;
return temp;
}else if(temp==2)
{
_deep--;
return temp;
}else
result=1;
}else if((_node->outArc[i]->weight==_edges[_pos])==1)
{
if(_node->outArc[i]->end->key==_endKey&&_pos>=_num)
{
_deep--;
return 2;
}else if(_node->outArc[i]->end->key==_endKey)
{
_deep--;
return 1;
}if(temp=isGoEPath(_node->outArc[i]->end->key,_edges,_num,_pos+1,_endKey,_deep))
if(_deep!=0)
{
_deep--;
return temp;
}else if(temp==2)
{
_deep--;
return temp;
}else
result=1;
}else
{
continue;
}
}
}
for(int i=0;i!=_node->outArc.n;i++)
{
if(_node->outArc[i]->weight.type==_type)
{
if((_node->outArc[i]->weight==_edges[_pos])==2)
{
if(_node->outArc[i]->end->key==_endKey&&_pos>=_num)
{
_deep--;
return 2;
}else if(_node->outArc[i]->end->key==_endKey)
{
_deep--;
return 1;
}
if(temp=isGoEPath(_node->outArc[i]->end->key,_edges,_num,_pos,_endKey,_deep))
if(_deep!=0)
{
_deep--;
return temp;
}else if(temp==2)
{
_deep--;
return temp;
}else
result=1;
}else if((_node->outArc[i]->weight==_edges[_pos])==1)
{
if(_node->outArc[i]->end->key==_endKey&&_pos>=_num)
{
_deep--;
return 2;
}else if(_node->outArc[i]->end->key==_endKey)
{
_deep--;
return 1;
}if(temp=isGoEPath(_node->outArc[i]->end->key,_edges,_num,_pos+1,_endKey,_deep))
if(_deep!=0)
{
_deep--;
return temp;
}else if(temp==2)
{
_deep--;
return temp;
}else
result=1;
}else
{
continue;
}
}
}
_deep--;
if(result==1)
{
return 1;
}
return 0;
}
int free()
{
for(;0!=nodeNum;)
{
delete allNode.pop();
}
for(;0!=arcNum;)
{
delete allArc.pop();
}
return 1;
}
~graph()
{
free();
}
};
} ;
#endif
一个Demo的代码:
/**/
/* init.h */
#include " frame.h "
#include " conio.h "
#include " runtime.h "
#include " regex.h "
using simplex::Regex;
int cpp() {
cout<<"【VGL::Regex()v.1.0】\n";
while(1)
{
char buf[100],buf_2[500];
int len;
cout<<"Regex>>>";os::control::read(buf,len,'\n');
cout<<"String>>>";os::control::read(buf_2,len,'\n');
Regex re;
re.parse(buf);
cout<<endl;
cout<<(re.match(buf_2)?"〖True〗":"〖False〗");
cout<<endl<<endl;
}
return 0;
}
#include " frame.h "
#include " conio.h "
#include " runtime.h "
#include " regex.h "
using simplex::Regex;
int cpp() {
cout<<"【VGL::Regex()v.1.0】\n";
while(1)
{
char buf[100],buf_2[500];
int len;
cout<<"Regex>>>";os::control::read(buf,len,'\n');
cout<<"String>>>";os::control::read(buf_2,len,'\n');
Regex re;
re.parse(buf);
cout<<endl;
cout<<(re.match(buf_2)?"〖True〗":"〖False〗");
cout<<endl<<endl;
}
return 0;
}
其运行结果: