#include <stdlib.h>
#include "mem.h"
#include "regexFrontEnd.h"
#include "NFARuntime.h"
#include "DFAProcess.h"
#include "struct.h"
static int DFASubsetInChain(struct _NFANode *subset,struct _DFASubsetChain *chain)
{
while(chain)
{
if(chain->subset>subset) return 0;
else if(chain->subset==subset) return 1;
chain=chain->next;
}
return 0;
}
static struct _DFASubsetChain *DFAMergeChains(struct _DFASubsetChain *chain1,struct _DFASubsetChain *chain2)
{
struct _DFASubsetChain p;
struct _DFASubsetChain *head=&p,*cur=head;
p.next=NULL;
while((chain1)&&(chain2))
{
if(chain1->subset<chain2->subset)
{
cur->next=chain1;
chain1=chain1->next;
cur=cur->next;
cur->next=0;
}
else
{
cur->next=chain2;
chain2=chain2->next;
cur=cur->next;
cur->next=0;
}
}
if(chain1)
{
cur->next=chain1;
}
else if(chain2)
{
cur->next=chain2;
}
return p.next;
}
static struct _DFASubsetChain *DFAAddSubsetToChain(struct _NFANode *subset,struct _DFASubsetChain *chain)
{
struct _DFASubsetChain *node=(struct _DFASubsetChain *)s_calloc(sizeof(struct _DFASubsetChain),1);
node->subset=subset;
return DFAMergeChains(chain,node);
}
static struct _DFASubsetChain *DFACreateSubsetChain(struct _DFASubsetChain *head,struct _NFANode *NFAStart)
{
struct queue *visitQueue=queueini();
struct _NFANode *node=NFAStart;
queuepush(visitQueue,NFAStart);
do
{
queuepop(visitQueue,(void **)&node);
if(!DFASubsetInChain(node,head))
{
head=DFAAddSubsetToChain(node,head);
if(node->edgetable)
{
struct _NodeEdgeList *p=NULL;
if(int_hashquery(node->edgetable,0,(void **)&p))
{
while(p)
{
queuepush(visitQueue,p->edge);
p=p->next;
}
}
}
}
}while(!queueisnull(visitQueue));
s_free(visitQueue);
return head;
}
struct _DFASubsetChain *getSubsetChain(struct _NFANode *NFAStart)
{
return DFACreateSubsetChain(NULL,NFAStart);
}
struct _DFANode *DFAStates=NULL;
int DFALimit=0;
int DFATop=0;
static void DFAIni(void)
{
DFAStates=(struct _DFANode *)s_calloc(sizeof(struct _DFANode)*(nodecount+32)*1024,1);
DFALimit=(nodecount+32)*1024;
DFATop=0;
return;
}
static int DFASubsetChainCompare(const struct _DFASubsetChain *chain1,const struct _DFASubsetChain *chain2)
{
while(chain1&&chain2)
{
if(chain1->subset!=chain2->subset) return 1;
chain1=chain1->next;
chain2=chain2->next;
}
return chain1||chain2;
}
static int DFAMatchStates(const struct _DFASubsetChain *chain)
{
int count=0;
for(;count<DFATop;count++)
{
if(!DFASubsetChainCompare(DFAStates[count].id,chain)) return count;
}
return -1;
}
static int DFAStateIsEnd(const struct _DFASubsetChain *chain)
{
while(chain)
{
if(!chain->subset->edgetable) return 1;
chain=chain->next;
}
return 0;
}
static struct _DFASubsetChain *DFAGetNextSubset(unsigned int ch,const struct _DFASubsetChain *cur)
{
struct _DFASubsetChain *follow=NULL;
while(cur)
{
struct _NodeEdgeList *p=NULL;
if(cur->subset->edgetable)
{
if(int_hashquery(cur->subset->edgetable,ch,(void **)&p))
{
while(p)
{
follow=DFACreateSubsetChain(follow,p->edge);
p=p->next;
}
}
}
cur=cur->next;
}
return follow;
}
static struct _DFACharChain *DFAMergeAction(struct _DFACharChain *chain1,struct _DFACharChain *chain2)
{
struct _DFACharChain p;
struct _DFACharChain *head=&p,*cur=head;
p.next=NULL;
while((chain1)&&(chain2))
{
if(chain1->ch<chain2->ch)
{
cur->next=chain1;
chain1=chain1->next;
cur=cur->next;
cur->next=0;
}
else
{
cur->next=chain2;
chain2=chain2->next;
cur=cur->next;
cur->next=0;
}
}
if(chain1)
{
cur->next=chain1;
}
else if(chain2)
{
cur->next=chain2;
}
return p.next;
}
static struct _DFACharChain *DFAAddCharToActionlist(unsigned int ch,struct _DFACharChain *chain)
{
struct _DFACharChain *node=(struct _DFACharChain *)s_calloc(sizeof(struct _DFACharChain),1);
node->ch=ch;
node->state=0;
return DFAMergeAction(chain,node);
}
static int DFACharInAction(unsigned int ch,struct _DFACharChain *chain)
{
while(chain)
{
if(chain->ch>ch) return 0;
else if(chain->ch==ch) return 1;
chain=chain->next;
}
return 0;
}
static struct _DFACharChain *DFACreateActionList(const struct _DFASubsetChain *chain)
{
struct _DFACharChain *action=NULL;
while(chain)
{
if(chain->subset->validchar)
{
struct _NodeCharList *chlist=chain->subset->validchar;
while(chlist)
{
if(chlist->ch&&(!DFACharInAction(chlist->ch,action)))
{
action=DFAAddCharToActionlist(chlist->ch,action);
}
chlist=chlist->next;
}
}
chain=chain->next;
}
return action;
}
static int DFAAddNewState(struct _DFASubsetChain *chain)
{
if(DFATop==DFALimit) return 1;
DFAStates[DFATop].id=chain;
DFAStates[DFATop].type=DFAStateIsEnd(chain);
DFAStates[DFATop].actionlist=DFACreateActionList(chain);
DFATop++;
return 0;
}
static void DFAFreeSubsetChain(struct _DFASubsetChain *chain)
{
struct _DFASubsetChain *pre=chain;
while(chain)
{
pre=chain->next;
s_free(chain);
chain=pre;
}
return;
}
int ConvertNFAToDFA(struct _NFAType *NFA)
{
int count=0;
struct _DFASubsetChain *chain=DFACreateSubsetChain(NULL,NFA->begin);
DFAIni();
if(DFAAddNewState(chain)) return 1;
for(count=0;count<DFATop;count++)
{
struct _DFACharChain *action=DFAStates[count].actionlist;
struct _DFASubsetChain *cur=DFAStates[count].id;
struct _DFASubsetChain *follow=NULL;
while(action)
{
int state=0;
follow=DFAGetNextSubset(action->ch,cur);
if(0>(state=DFAMatchStates(follow)))
{
if(DFAAddNewState(follow)) return 1;
action->state=DFATop-1;
}
else
{
DFAFreeSubsetChain(follow);
action->state=state;
}
action=action->next;
}
}
return 0;
}