[update] automate can contain himself (pointer) and browse to it
[todo] manage case where you have to go backwards into self (included self automate)
This commit is contained in:
parent
bae568e3f5
commit
a92714a289
|
@ -11,29 +11,45 @@
|
|||
|
||||
|
||||
|
||||
struct AutomateContext getContext(const char pDot, const char pPath, const unsigned int pIndex){
|
||||
struct AutomateContext rtn;
|
||||
|
||||
unsigned int browse(struct Automate* pAutomate, const char* pString, const char pDepth){
|
||||
rtn.dot = pDot;
|
||||
rtn.path = pPath;
|
||||
rtn.index = pIndex;
|
||||
|
||||
printf("%s>>> [browsing %s]\n", pad(pDepth), pAutomate->name);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned int browse(struct Automate* pAutomate, const char* pString, struct AutomateContext* pCtx, unsigned int* pStep){
|
||||
|
||||
printf(">>> [browsing %s]\n", pAutomate->name);
|
||||
|
||||
/* [0] Initialize variables
|
||||
=========================================================*/
|
||||
unsigned int strIndex = 0; // String current char index
|
||||
unsigned int recursive;
|
||||
unsigned int c, len, i, l, a, A; // counters
|
||||
char* buffer = malloc(1);
|
||||
char* ptr = NULL;
|
||||
struct AutomateDot dotPtr;
|
||||
struct AutomateDot dotPtr;
|
||||
char* ptr = NULL;
|
||||
char* buffer = malloc(1);
|
||||
unsigned int recursive = 0;
|
||||
|
||||
char* pathmem = malloc( sizeof(char) ); // will contain edge number for each dot
|
||||
unsigned int* indexmem = malloc( sizeof(unsigned int) ); // will contain offset of @pString for each dot
|
||||
char* dotmem = malloc( sizeof(char) );
|
||||
pAutomate->path = realloc(pAutomate->path, 1 );
|
||||
unsigned int foreignStep = 0;
|
||||
struct AutomateContext* foreignCtx = malloc( sizeof(struct AutomateContext) );
|
||||
foreignCtx[0] = getContext(0, 0, 0);
|
||||
|
||||
struct Automate* aPtr = NULL;
|
||||
|
||||
pCtx = realloc(pCtx, sizeof(struct AutomateContext) * (*pStep+1) );
|
||||
|
||||
/* [1] merge automates
|
||||
=========================================================*/
|
||||
while( pAutomate->aedges > 0 )
|
||||
mergeAutomate(pAutomate, pAutomate->aedges-1);
|
||||
if( pAutomate->aedges > 0 )
|
||||
for( l = pAutomate->aedges-1 ; l > 0 ; l-- )
|
||||
mergeAutomate(pAutomate, l);
|
||||
|
||||
|
||||
|
||||
|
@ -42,36 +58,27 @@ unsigned int browse(struct Automate* pAutomate, const char* pString, const char
|
|||
|
||||
/* [2] For each char
|
||||
=========================================================*/
|
||||
c = 0;
|
||||
len = strlen(pString);
|
||||
buffer = realloc(buffer, len+1);
|
||||
pAutomate->dCurrent = 0;
|
||||
pAutomate->steps = 0;
|
||||
len = strlen(pString);
|
||||
buffer = realloc(buffer, len+1);
|
||||
c = *pStep;
|
||||
|
||||
pAutomate->dCurrent = pCtx[c].dot;
|
||||
strIndex = pCtx[c].index;
|
||||
|
||||
|
||||
|
||||
/* (1) For each char try to match
|
||||
---------------------------------------------------------*/
|
||||
c = 0;
|
||||
strIndex = 0;
|
||||
pathmem[0] = 0;
|
||||
pAutomate->path[0] = 0;
|
||||
|
||||
while( pAutomate->dCurrent != pAutomate->dFinal && strIndex <= len ){
|
||||
|
||||
|
||||
pAutomate->steps++;
|
||||
(ADB&&0x01) && printf("%s\b * step %d (remaining '%s')\n", pad(pDepth), pAutomate->steps, pString+strIndex);
|
||||
|
||||
|
||||
/* (2) Initialize local data
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Check current state choices */
|
||||
dotmem[c] = pAutomate->dCurrent;
|
||||
dotPtr = pAutomate->dot[dotmem[c]];
|
||||
i = ( indexmem[c] == strIndex ) ? pathmem[c] : 0;
|
||||
// indexmem[c] = strIndex;
|
||||
l = dotPtr.n;
|
||||
pCtx[c].dot = pAutomate->dCurrent;
|
||||
dotPtr = pAutomate->dot[pCtx[c].dot];
|
||||
i = ( pCtx[c].index == strIndex ) ? pCtx[c].path : 0;
|
||||
l = dotPtr.n;
|
||||
|
||||
|
||||
/* (2) If no more path for this branch -> exit */
|
||||
|
@ -86,16 +93,16 @@ unsigned int browse(struct Automate* pAutomate, const char* pString, const char
|
|||
/* (1) If STRING match */
|
||||
if( dotPtr.type[i] == DIRECT_T ){
|
||||
|
||||
(ADB&&0x01) && printf("%s> q%d --d0--> q%d ?\n", pad(pDepth+1), dotmem[c], dotPtr.dot[i]);
|
||||
(ADB&&0x01) && printf("> q%d --d0--> q%d ?\n", pCtx[c].dot, dotPtr.dot[i]);
|
||||
|
||||
pAutomate->dCurrent = dotPtr.dot[i];
|
||||
pathmem[c] = i;
|
||||
pCtx[c].path = i;
|
||||
break;
|
||||
|
||||
/* (2) If STRING match */
|
||||
}else if( dotPtr.type[i] == STRING_T ){
|
||||
|
||||
(ADB&&0x01) && printf("%s> q%d --s%d--> q%d ?\n", pad(pDepth+1), dotmem[c], dotPtr.edge[i], dotPtr.dot[i]);
|
||||
(ADB&&0x01) && printf("> q%d --s%d--> q%d ?\n", pCtx[c].dot, dotPtr.edge[i], dotPtr.dot[i]);
|
||||
|
||||
ptr = pAutomate->sedge[dotPtr.edge[i]];
|
||||
strncpy(buffer, pString+strIndex, strlen(ptr));
|
||||
|
@ -104,28 +111,28 @@ unsigned int browse(struct Automate* pAutomate, const char* pString, const char
|
|||
if( strcmp(buffer, ptr) == 0 ){
|
||||
pAutomate->dCurrent = dotPtr.dot[i];
|
||||
strIndex += strlen(ptr);
|
||||
pathmem[c] = i;
|
||||
pCtx[c].path = i;
|
||||
break;
|
||||
}
|
||||
|
||||
/* (3) If RANGE match */
|
||||
}else if( dotPtr.type[i] == RANGE_T ){
|
||||
|
||||
(ADB&&0x01) && printf("%s> q%d --r%d--> q%d ?\n", pad(pDepth+1), dotmem[c], dotPtr.edge[i], dotPtr.dot[i]);
|
||||
(ADB&&0x01) && printf("> q%d --r%d--> q%d ?\n", pCtx[c].dot, dotPtr.edge[i], dotPtr.dot[i]);
|
||||
|
||||
ptr = pAutomate->redge[dotPtr.edge[i]];
|
||||
|
||||
if( pString[strIndex] >= ptr[0] && pString[strIndex] <= ptr[1] ){
|
||||
pAutomate->dCurrent = dotPtr.dot[i];
|
||||
strIndex += 1;
|
||||
pathmem[c] = i;
|
||||
pCtx[c].path = i;
|
||||
break;
|
||||
}
|
||||
|
||||
/* (4) If LIST match */
|
||||
}else if( dotPtr.type[i] == LIST_T ){
|
||||
|
||||
(ADB&&0x01) && printf("%s> q%d --l%d--> q%d ?\n", pad(pDepth+1), dotmem[c], dotPtr.edge[i], dotPtr.dot[i]);
|
||||
(ADB&&0x01) && printf("> q%d --l%d--> q%d ?\n", pCtx[c].dot, dotPtr.edge[i], dotPtr.dot[i]);
|
||||
|
||||
ptr = pAutomate->ledge[dotPtr.edge[i]];
|
||||
|
||||
|
@ -139,24 +146,47 @@ unsigned int browse(struct Automate* pAutomate, const char* pString, const char
|
|||
if( a < A ){
|
||||
pAutomate->dCurrent = dotPtr.dot[i];
|
||||
strIndex += 1;
|
||||
pathmem[c] = i;
|
||||
pCtx[c].path = i;
|
||||
break;
|
||||
}
|
||||
|
||||
/* (5) If AUTOMATE match */
|
||||
}else if( dotPtr.type[i] == AUTOMATE_T ){
|
||||
|
||||
(ADB&&0x01) && printf("%s> q%d --a%d--> q%d ?\n", pad(pDepth+1), dotmem[c], dotPtr.edge[i], dotPtr.dot[i]);
|
||||
(ADB&&0x01) && printf("> q%d --a%d--> q%d ?\n", pCtx[c].dot, dotPtr.edge[i], dotPtr.dot[i]);
|
||||
aPtr = pAutomate->aedge[dotPtr.edge[i]];
|
||||
|
||||
recursive = browse(&pAutomate->aedge[dotPtr.edge[i]], pString+strIndex, pDepth+1);
|
||||
foreignStep = 0;
|
||||
foreignCtx = realloc(foreignCtx, sizeof(struct AutomateContext));
|
||||
foreignCtx[0] = getContext(0, 0, 0);
|
||||
|
||||
if( pAutomate->aedge[dotPtr.edge[i]].steps > 0 )
|
||||
pAutomate->steps += pAutomate->aedge[dotPtr.edge[i]].steps-1;
|
||||
while( foreignStep != 0 || foreignCtx[foreignStep].path < aPtr->dot[foreignCtx[foreignStep].dot].n ){
|
||||
|
||||
if( pAutomate->aedge[dotPtr.edge[i]].dCurrent == pAutomate->aedge[dotPtr.edge[i]].dFinal ){
|
||||
// printf("browse start -> index: '%s'\n", pString+strIndex);
|
||||
recursive = browse(aPtr, pString+strIndex, foreignCtx, &foreignStep);
|
||||
// printf("browsed end -> index: %d/%d - state: %d/%d\n", recursive, (int)strlen(pString+strIndex), aPtr->dCurrent, aPtr->dFinal);
|
||||
|
||||
// If correct -> exit from while()
|
||||
if( aPtr->dCurrent == aPtr->dFinal )
|
||||
break;
|
||||
|
||||
// If have to go backwards
|
||||
if( recursive == foreignCtx[foreignStep].index && foreignCtx[foreignStep].dot == aPtr->dCurrent && i >= l ){
|
||||
// {1} if not first branch -> go previous //
|
||||
if( foreignStep > 0 )
|
||||
foreignStep--;
|
||||
|
||||
// {2} else next path of previous branch //
|
||||
foreignCtx[foreignStep].path++;
|
||||
foreignCtx = realloc(foreignCtx, sizeof(struct AutomateContext) * (foreignStep+1) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( aPtr->dCurrent == aPtr->dFinal ){
|
||||
pCtx[c].path = i;
|
||||
strIndex += recursive;
|
||||
pAutomate->dCurrent = dotPtr.dot[i];
|
||||
strIndex += recursive;
|
||||
pathmem[c] = i;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -168,36 +198,30 @@ unsigned int browse(struct Automate* pAutomate, const char* pString, const char
|
|||
/* (4) Next dot or previous if locked
|
||||
---------------------------------------------------------*/
|
||||
/* (1) If no char procesed && same dot && no action performed */
|
||||
if( strIndex == indexmem[c] && dotmem[c] == pAutomate->dCurrent && i >= l ){
|
||||
if( strIndex == pCtx[c].index && pCtx[c].dot == pAutomate->dCurrent && i >= l ){
|
||||
|
||||
// {1} if not first branch -> go previous //
|
||||
if( c > 0 )
|
||||
c--;
|
||||
|
||||
// {2} else next path of previous branch //
|
||||
strIndex = indexmem[c];
|
||||
pathmem[c]++;
|
||||
pAutomate->dCurrent = dotmem[c];
|
||||
(ADB&&0x01) && printf("%s< not\n", pad(pDepth+1));
|
||||
(ADB&&0x01) && printf("%s* back to q%d:%d\n", pad(pDepth+1), dotmem[c], pathmem[c]);
|
||||
strIndex = pCtx[c].index;
|
||||
pCtx[c].path++;
|
||||
pAutomate->dCurrent = pCtx[c].dot;
|
||||
(ADB&&0x01) && printf("< not\n");
|
||||
(ADB&&0x01) && printf("* back to q%d:%d\n", pCtx[c].dot, pCtx[c].path);
|
||||
|
||||
pCtx = realloc(pCtx, sizeof(struct AutomateContext) * (c+1) );
|
||||
|
||||
/* (2) Next branch + reset data (if already browsed in other path) */
|
||||
}else{
|
||||
(ADB&&0x01) && printf("%s< yes\n", pad(pDepth+1));
|
||||
(ADB&&0x01) && printf("< yes\n");
|
||||
|
||||
c++;
|
||||
pathmem = realloc(pathmem, sizeof(char) * (c+1) );
|
||||
indexmem = realloc(indexmem, sizeof(unsigned int) * (c+1) );
|
||||
dotmem = realloc(dotmem, sizeof(char) * (c+1) );
|
||||
pCtx = realloc(pCtx, sizeof(struct AutomateContext) * (c+1) );
|
||||
|
||||
pAutomate->n = c;
|
||||
pAutomate->path = realloc(pAutomate->path, sizeof(char) * (c+1) );
|
||||
pAutomate->path[c] = pAutomate->dCurrent;
|
||||
|
||||
|
||||
indexmem[c] = strIndex;
|
||||
pathmem[c] = 0;
|
||||
pCtx[c].index = strIndex;
|
||||
pCtx[c].path = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -205,15 +229,18 @@ unsigned int browse(struct Automate* pAutomate, const char* pString, const char
|
|||
|
||||
}
|
||||
|
||||
ptr = NULL;
|
||||
ptr = NULL;
|
||||
free(buffer);
|
||||
free(pathmem);
|
||||
free(indexmem);
|
||||
free(dotmem);
|
||||
free(foreignCtx);
|
||||
|
||||
(ADB&&0x01) && printf("%s>>> [done %s = %d/%d]\n", pad(pDepth), pAutomate->name, pAutomate->dCurrent, pAutomate->dFinal);
|
||||
return strIndex;
|
||||
(ADB&&0x01) && printf(">>> [done %s = %d/%d]\n", pAutomate->name, pAutomate->dCurrent, pAutomate->dFinal);
|
||||
|
||||
*pStep = ( c == *pStep ) ? *pStep : c-1;
|
||||
|
||||
if( strIndex == 0 )
|
||||
return 0;
|
||||
else
|
||||
return strIndex;
|
||||
|
||||
}
|
||||
|
||||
|
@ -326,7 +353,7 @@ void debug(const struct Automate pAutomate){
|
|||
else if( pAutomate.dot[a].type[b] == RANGE_T )
|
||||
printf(" * q%d match range '%s'\n", pAutomate.dot[a].dot[b], pAutomate.redge[pAutomate.dot[a].edge[b]]);
|
||||
else if( pAutomate.dot[a].type[b] == AUTOMATE_T )
|
||||
printf(" * q%d match automate '%s'\n", pAutomate.dot[a].dot[b], pAutomate.aedge[pAutomate.dot[a].edge[b]].name);
|
||||
printf(" * q%d match automate '%s'\n", pAutomate.dot[a].dot[b], ((struct Automate*)pAutomate.aedge[pAutomate.dot[a].edge[b]])->name);
|
||||
|
||||
}
|
||||
|
||||
|
@ -360,8 +387,6 @@ struct Automate createAutomate(const char* pName){
|
|||
automate.dCurrent = 0;
|
||||
automate.dFinal = 0;
|
||||
|
||||
automate.n = 0;
|
||||
|
||||
/* [2] First allocation
|
||||
=========================================================*/
|
||||
automate.dot = malloc( 0 );
|
||||
|
@ -369,7 +394,6 @@ struct Automate createAutomate(const char* pName){
|
|||
automate.redge = malloc( 0 );
|
||||
automate.ledge = malloc( 0 );
|
||||
automate.aedge = malloc( 0 );
|
||||
automate.path = malloc( 0 );
|
||||
automate.name = malloc( strlen(pName) + 1 );
|
||||
strcpy(automate.name, pName);
|
||||
|
||||
|
@ -380,11 +404,83 @@ struct Automate createAutomate(const char* pName){
|
|||
}
|
||||
|
||||
|
||||
void mergeAutomate(struct Automate* pMaster, const char pSlaveIndex){
|
||||
void destroyAutomate(struct Automate* pAutomate){
|
||||
|
||||
/* [0] Initialize variables
|
||||
=========================================================*/
|
||||
char d, e;
|
||||
|
||||
|
||||
/* [1] Destroy edges
|
||||
=========================================================*/
|
||||
/* (1) String Edges
|
||||
---------------------------------------------------------*/
|
||||
for( e = 0 ; e < pAutomate->sedges ; e++ )
|
||||
free(pAutomate->sedge[e]);
|
||||
|
||||
free(pAutomate->sedge);
|
||||
|
||||
/* (2) List Edges
|
||||
---------------------------------------------------------*/
|
||||
for( e = 0 ; e < pAutomate->ledges ; e++ )
|
||||
free(pAutomate->ledge[e]);
|
||||
|
||||
free(pAutomate->ledge);
|
||||
|
||||
/* (3) Range Edges
|
||||
---------------------------------------------------------*/
|
||||
for( e = 0 ; e < pAutomate->redges ; e++ )
|
||||
free(pAutomate->redge[e]);
|
||||
|
||||
free(pAutomate->redge);
|
||||
|
||||
/* (4) Automate Edges
|
||||
---------------------------------------------------------*/
|
||||
free(pAutomate->aedge);
|
||||
|
||||
|
||||
/* [2] Destroy dots
|
||||
=========================================================*/
|
||||
for( d = 0 ; d < pAutomate->dots ; d++ ){
|
||||
free(pAutomate->dot[d].type);
|
||||
free(pAutomate->dot[d].dot);
|
||||
free(pAutomate->dot[d].edge);
|
||||
|
||||
free(&pAutomate->dot[d]);
|
||||
}
|
||||
|
||||
free(pAutomate->dot);
|
||||
|
||||
|
||||
/* [3] Destroy main pointer
|
||||
=========================================================*/
|
||||
free(pAutomate);
|
||||
}
|
||||
|
||||
|
||||
char mergeAutomate(struct Automate* pMaster, const char pSlaveIndex){
|
||||
|
||||
/* (1) If no such @pSlave -> abort */
|
||||
if( pSlaveIndex >= pMaster->aedges ){
|
||||
|
||||
(ADB&0x01) && printf(" (!) merge error: no such slave automate\n");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* (2) If @pSlave == @pMaster -> do not do anything */
|
||||
if( pMaster->aedge[pSlaveIndex] == pMaster ){
|
||||
|
||||
(ADB&0x01) && printf(" (!) merge error: slave is master\n");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* [0] Initialize variables
|
||||
=========================================================*/
|
||||
char a, d, e, dot, edge, edges, dotOffset, rtn, next_dot;
|
||||
int sub;
|
||||
|
||||
char sedges = pMaster->sedges;
|
||||
char ledges = pMaster->ledges;
|
||||
|
@ -392,14 +488,18 @@ void mergeAutomate(struct Automate* pMaster, const char pSlaveIndex){
|
|||
char aedges = pMaster->aedges;
|
||||
char dots = pMaster->dots;
|
||||
char final = pMaster->dFinal;
|
||||
struct Automate* pSlave = &pMaster->aedge[pSlaveIndex];
|
||||
struct Automate* pSlave = pMaster->aedge[pSlaveIndex];
|
||||
|
||||
|
||||
while( pSlave->aedges > 0 )
|
||||
mergeAutomate(pSlave, pSlave->aedges-1);
|
||||
/* [1] Merge automates recursively
|
||||
=========================================================*/
|
||||
if( pSlave->aedges > 1 )
|
||||
for( sub = pSlave->aedges-1 ; sub >= 0 ; sub-- )
|
||||
if( sub != pSlaveIndex )
|
||||
mergeAutomate(pMaster->aedge[pSlaveIndex], sub);
|
||||
|
||||
|
||||
/* [1] Merge @pSlave edges into @pMaster edges
|
||||
/* [2] Merge @pSlave edges into @pMaster edges
|
||||
=========================================================*/
|
||||
/* (1) String edges (sedges) */
|
||||
for( a = 0 ; a < pSlave->sedges ; a++ ){
|
||||
|
@ -421,12 +521,12 @@ void mergeAutomate(struct Automate* pMaster, const char pSlaveIndex){
|
|||
|
||||
/* (4) Automate edges (aedges) */
|
||||
for( a = 0 ; a < pSlave->aedges ; a++ ){
|
||||
rtn = addAutomateTransition(pMaster, &pSlave->aedge[a]);
|
||||
rtn = addAutomateTransition(pMaster, pSlave->aedge[a]);
|
||||
(ADB&0x01) && printf("merge SLAVE.automate.%d into MASTER.automate.%d\n", a, rtn) ;
|
||||
}
|
||||
|
||||
|
||||
/* [2] For each use of @pSlave in pMaster, replace
|
||||
/* [3] For each use of @pSlave in pMaster, replace
|
||||
=========================================================*/
|
||||
/* (1) For each fot of @pMaster */
|
||||
for( dot = 0 ; dot < dots ; dot++ ){
|
||||
|
@ -493,10 +593,22 @@ void mergeAutomate(struct Automate* pMaster, const char pSlaveIndex){
|
|||
|
||||
}
|
||||
|
||||
/* [3] Clean @pMaster
|
||||
/* [4] Clean @pMaster
|
||||
=========================================================*/
|
||||
/* (1) Remove @pSlave form @pMaster */
|
||||
pMaster->aedge = realloc(pMaster->aedge, sizeof(struct Automate) * --pMaster->aedges);
|
||||
|
||||
// {1} Destroy @pSlave //
|
||||
destroyAutomate(pMaster->aedge[pSlaveIndex]);
|
||||
|
||||
// {2} Shift back next automates //
|
||||
for( d = pSlaveIndex+1 ; d < pMaster->aedges ; d++ )
|
||||
memcpy(&pMaster->aedge[d-1], &pMaster->aedge[d], sizeof(struct Automate));
|
||||
|
||||
// {3} Decrement automate edges count //
|
||||
pMaster->aedges--;
|
||||
|
||||
// {4} Free last automate //
|
||||
pMaster->aedge = realloc(pMaster->aedge, sizeof(struct Automate) * pMaster->aedges);
|
||||
|
||||
/* (2) Keep old @pMaster.dFinal */
|
||||
(ADB&&0x01) && printf("restauring final to %d\n", final);
|
||||
|
@ -505,6 +617,8 @@ void mergeAutomate(struct Automate* pMaster, const char pSlaveIndex){
|
|||
|
||||
(ADB&0x01) && printf("SLAVE.%s successfully merged into MASTER.%s\n\n", pSlave->name, pMaster->name) ;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -602,12 +716,12 @@ char addAutomateTransition(struct Automate* pAutomate, struct Automate* pAedge){
|
|||
|
||||
/* [1] Reallocate memory for aedge
|
||||
=========================================================*/
|
||||
pAutomate->aedge = realloc(pAutomate->aedge, sizeof(struct Automate) * pAutomate->aedges );
|
||||
pAutomate->aedge = realloc(pAutomate->aedge, sizeof(void*) * pAutomate->aedges );
|
||||
|
||||
|
||||
/* [2] Create the aedge
|
||||
=========================================================*/
|
||||
memcpy(&pAutomate->aedge[index], pAedge, sizeof(struct Automate));
|
||||
pAutomate->aedge[index] = pAedge;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,13 @@
|
|||
} AutomateType;
|
||||
|
||||
|
||||
#define ADB 0x00
|
||||
#define ADB 0x01
|
||||
|
||||
struct AutomateContext{
|
||||
char dot;
|
||||
char path;
|
||||
unsigned int index;
|
||||
};
|
||||
|
||||
struct AutomateDot{
|
||||
char n; // number of edges
|
||||
|
@ -44,31 +50,40 @@
|
|||
char** sedge; // string edges
|
||||
char** redge; // range edges (between char[0] and char[1])
|
||||
char** ledge; // list edges (in one of the given char-s)
|
||||
struct Automate* aedge; // automate edges
|
||||
void** aedge; // automate (pointer) edges
|
||||
|
||||
char dCurrent; // current dot index
|
||||
char dFinal; // final dot index
|
||||
unsigned int steps; // number of steps
|
||||
|
||||
char* name; // automate name
|
||||
char* path; // automate path
|
||||
|
||||
unsigned int n; // automate path length
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* Creates an automate context
|
||||
*
|
||||
* @dot<char> Current
|
||||
* @path<char> Current min path
|
||||
* @index<unsigned int> Current stirng index
|
||||
*
|
||||
* @return context<struct AutomateContext> The created context
|
||||
*
|
||||
*/
|
||||
struct AutomateContext getContext(const char pDot, const char pPath, const unsigned int pIndex);
|
||||
|
||||
/* Try to browse an automate with a string
|
||||
*
|
||||
* @pAutomate<struct Automate*> Current working automate
|
||||
* @pString<const char*> String to test
|
||||
* @pDepth<const char> Padding
|
||||
* @pCtx<struct AutomateContext*> Already browsed context
|
||||
*
|
||||
* @return offset<int> The @pString offset browsed to
|
||||
*
|
||||
* @NOTE: Automate.dCurrent is equal to Automate.dFinal if final state reached
|
||||
*
|
||||
*/
|
||||
unsigned int browse(struct Automate* pAutomate, const char* pString, const char pDepth);
|
||||
unsigned int browse(struct Automate* pAutomate, const char* pString, struct AutomateContext* pCtx, unsigned int* pStep);
|
||||
|
||||
|
||||
/* Builds an automate from a regexp
|
||||
|
@ -95,14 +110,22 @@
|
|||
*/
|
||||
struct Automate createAutomate(const char* pName);
|
||||
|
||||
/* Destroys an automate
|
||||
*
|
||||
* @pAutomate<struct Automate*> Automate pointer
|
||||
*
|
||||
*/
|
||||
void destroyAutomate(struct Automate* pAutomate);
|
||||
|
||||
/* Merges an automate into another
|
||||
*
|
||||
* @pMaster<struct Automate*> Master automate that contains @pSlave
|
||||
* @pSlaveIndex<const char> Slave automate index into @pMaster
|
||||
*
|
||||
* @return status<char> 1 on success ; 0 on failure
|
||||
*
|
||||
*/
|
||||
void mergeAutomate(struct Automate* pMaster, const char pSlaveIndex);
|
||||
char mergeAutomate(struct Automate* pMaster, const char pSlaveIndex);
|
||||
|
||||
|
||||
/* Adds a dot to an automate
|
||||
|
|
42
src/linter.c
42
src/linter.c
|
@ -104,23 +104,37 @@ int main(int argc, char* argv[]){
|
|||
linkDots(&array, 1, 3, AUTOMATE_T, 0); // q1 --a0--> q3
|
||||
linkDots(&array, 1, 3, STRING_T, 1); // q1 --s1--> q3
|
||||
|
||||
char str[80] = {0};
|
||||
strcpy(str, "[null, \"abc\", \"def\", false, true, 12, -1.2, .54, -.3, 5., \"bla\\\"blo\\rbla\\n\"]\0");
|
||||
clock_t start, stop;
|
||||
unsigned int browsed = 0;
|
||||
start = clock(); browsed = browse(&array, str, 0); stop = clock();
|
||||
|
||||
printf("browse '%s': %d/%d\n", str, browsed, (int) strlen(str));
|
||||
printf(" (*) final_state: %d/%d\n", array.dCurrent, array.dFinal);
|
||||
printf(" (*) in %d steps\n", array.steps);
|
||||
|
||||
struct Automate test = createAutomate("test");
|
||||
addDot(&test); // q0
|
||||
addDot(&test); // q1
|
||||
addDot(&test); // q2
|
||||
addDot(&test); // q3
|
||||
addStringTransition(&test, "a\0"); // s0
|
||||
addStringTransition(&test, "b\0"); // s0
|
||||
addAutomateTransition(&test, &test); // a1
|
||||
linkDots(&test, 0, 1, STRING_T, 0); // q0 --s0--> q1
|
||||
linkDots(&test, 1, 2, AUTOMATE_T, 0); // q1 --s0--> q2
|
||||
linkDots(&test, 1, 2, DIRECT_T, 1); // q1 --d0--> q2
|
||||
linkDots(&test, 2, 3, STRING_T, 1); // q1 --s1--> q2
|
||||
|
||||
debug(test);
|
||||
|
||||
char str[80] = {0};
|
||||
clock_t start, stop;
|
||||
unsigned int step = 0;
|
||||
struct AutomateContext* ctx = malloc( sizeof(struct AutomateContext) * 1 );
|
||||
ctx[0] = getContext(0, 0, 0);
|
||||
|
||||
strcpy(str, "aaabbb\0");
|
||||
start = clock();
|
||||
unsigned int browsed = browse(&test, str, ctx, &step); stop = clock();
|
||||
// printf("browse '%s': %d/%d\n", str, ctx[step].index, (int) strlen(str));
|
||||
printf(" (*) final_state: %d/%d\n", test.dCurrent, test.dFinal);
|
||||
printf(" (*) read: %d/%d\n", browsed, (int)strlen(str));
|
||||
printf(" (*) in %.3lf seconds\n\n", (double)(stop-start)/CLOCKS_PER_SEC);
|
||||
|
||||
for( c = 0 ; c < array.n ; c++ ){
|
||||
if( c > 0 )
|
||||
printf(" -> ");
|
||||
printf("q%d", array.path[c]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
exit(0);
|
||||
/* Build RegExp */
|
||||
|
|
Loading…
Reference in New Issue