[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
|
/* [0] Initialize variables
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
unsigned int strIndex = 0; // String current char index
|
unsigned int strIndex = 0; // String current char index
|
||||||
unsigned int recursive;
|
|
||||||
unsigned int c, len, i, l, a, A; // counters
|
unsigned int c, len, i, l, a, A; // counters
|
||||||
char* buffer = malloc(1);
|
struct AutomateDot dotPtr;
|
||||||
char* ptr = NULL;
|
char* ptr = NULL;
|
||||||
struct AutomateDot dotPtr;
|
char* buffer = malloc(1);
|
||||||
|
unsigned int recursive = 0;
|
||||||
|
|
||||||
char* pathmem = malloc( sizeof(char) ); // will contain edge number for each dot
|
unsigned int foreignStep = 0;
|
||||||
unsigned int* indexmem = malloc( sizeof(unsigned int) ); // will contain offset of @pString for each dot
|
struct AutomateContext* foreignCtx = malloc( sizeof(struct AutomateContext) );
|
||||||
char* dotmem = malloc( sizeof(char) );
|
foreignCtx[0] = getContext(0, 0, 0);
|
||||||
pAutomate->path = realloc(pAutomate->path, 1 );
|
|
||||||
|
struct Automate* aPtr = NULL;
|
||||||
|
|
||||||
|
pCtx = realloc(pCtx, sizeof(struct AutomateContext) * (*pStep+1) );
|
||||||
|
|
||||||
/* [1] merge automates
|
/* [1] merge automates
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
while( pAutomate->aedges > 0 )
|
if( pAutomate->aedges > 0 )
|
||||||
mergeAutomate(pAutomate, pAutomate->aedges-1);
|
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
|
/* [2] For each char
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
c = 0;
|
len = strlen(pString);
|
||||||
len = strlen(pString);
|
buffer = realloc(buffer, len+1);
|
||||||
buffer = realloc(buffer, len+1);
|
c = *pStep;
|
||||||
pAutomate->dCurrent = 0;
|
|
||||||
pAutomate->steps = 0;
|
pAutomate->dCurrent = pCtx[c].dot;
|
||||||
|
strIndex = pCtx[c].index;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* (1) For each char try to match
|
/* (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 ){
|
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
|
/* (2) Initialize local data
|
||||||
---------------------------------------------------------*/
|
---------------------------------------------------------*/
|
||||||
/* (1) Check current state choices */
|
/* (1) Check current state choices */
|
||||||
dotmem[c] = pAutomate->dCurrent;
|
pCtx[c].dot = pAutomate->dCurrent;
|
||||||
dotPtr = pAutomate->dot[dotmem[c]];
|
dotPtr = pAutomate->dot[pCtx[c].dot];
|
||||||
i = ( indexmem[c] == strIndex ) ? pathmem[c] : 0;
|
i = ( pCtx[c].index == strIndex ) ? pCtx[c].path : 0;
|
||||||
// indexmem[c] = strIndex;
|
l = dotPtr.n;
|
||||||
l = dotPtr.n;
|
|
||||||
|
|
||||||
|
|
||||||
/* (2) If no more path for this branch -> exit */
|
/* (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 */
|
/* (1) If STRING match */
|
||||||
if( dotPtr.type[i] == DIRECT_T ){
|
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];
|
pAutomate->dCurrent = dotPtr.dot[i];
|
||||||
pathmem[c] = i;
|
pCtx[c].path = i;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* (2) If STRING match */
|
/* (2) If STRING match */
|
||||||
}else if( dotPtr.type[i] == STRING_T ){
|
}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]];
|
ptr = pAutomate->sedge[dotPtr.edge[i]];
|
||||||
strncpy(buffer, pString+strIndex, strlen(ptr));
|
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 ){
|
if( strcmp(buffer, ptr) == 0 ){
|
||||||
pAutomate->dCurrent = dotPtr.dot[i];
|
pAutomate->dCurrent = dotPtr.dot[i];
|
||||||
strIndex += strlen(ptr);
|
strIndex += strlen(ptr);
|
||||||
pathmem[c] = i;
|
pCtx[c].path = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (3) If RANGE match */
|
/* (3) If RANGE match */
|
||||||
}else if( dotPtr.type[i] == RANGE_T ){
|
}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]];
|
ptr = pAutomate->redge[dotPtr.edge[i]];
|
||||||
|
|
||||||
if( pString[strIndex] >= ptr[0] && pString[strIndex] <= ptr[1] ){
|
if( pString[strIndex] >= ptr[0] && pString[strIndex] <= ptr[1] ){
|
||||||
pAutomate->dCurrent = dotPtr.dot[i];
|
pAutomate->dCurrent = dotPtr.dot[i];
|
||||||
strIndex += 1;
|
strIndex += 1;
|
||||||
pathmem[c] = i;
|
pCtx[c].path = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (4) If LIST match */
|
/* (4) If LIST match */
|
||||||
}else if( dotPtr.type[i] == LIST_T ){
|
}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]];
|
ptr = pAutomate->ledge[dotPtr.edge[i]];
|
||||||
|
|
||||||
|
@ -139,24 +146,47 @@ unsigned int browse(struct Automate* pAutomate, const char* pString, const char
|
||||||
if( a < A ){
|
if( a < A ){
|
||||||
pAutomate->dCurrent = dotPtr.dot[i];
|
pAutomate->dCurrent = dotPtr.dot[i];
|
||||||
strIndex += 1;
|
strIndex += 1;
|
||||||
pathmem[c] = i;
|
pCtx[c].path = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (5) If AUTOMATE match */
|
/* (5) If AUTOMATE match */
|
||||||
}else if( dotPtr.type[i] == AUTOMATE_T ){
|
}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 )
|
while( foreignStep != 0 || foreignCtx[foreignStep].path < aPtr->dot[foreignCtx[foreignStep].dot].n ){
|
||||||
pAutomate->steps += pAutomate->aedge[dotPtr.edge[i]].steps-1;
|
|
||||||
|
|
||||||
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];
|
pAutomate->dCurrent = dotPtr.dot[i];
|
||||||
strIndex += recursive;
|
|
||||||
pathmem[c] = i;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,36 +198,30 @@ unsigned int browse(struct Automate* pAutomate, const char* pString, const char
|
||||||
/* (4) Next dot or previous if locked
|
/* (4) Next dot or previous if locked
|
||||||
---------------------------------------------------------*/
|
---------------------------------------------------------*/
|
||||||
/* (1) If no char procesed && same dot && no action performed */
|
/* (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 //
|
// {1} if not first branch -> go previous //
|
||||||
if( c > 0 )
|
if( c > 0 )
|
||||||
c--;
|
c--;
|
||||||
|
|
||||||
// {2} else next path of previous branch //
|
// {2} else next path of previous branch //
|
||||||
strIndex = indexmem[c];
|
strIndex = pCtx[c].index;
|
||||||
pathmem[c]++;
|
pCtx[c].path++;
|
||||||
pAutomate->dCurrent = dotmem[c];
|
pAutomate->dCurrent = pCtx[c].dot;
|
||||||
(ADB&&0x01) && printf("%s< not\n", pad(pDepth+1));
|
(ADB&&0x01) && printf("< not\n");
|
||||||
(ADB&&0x01) && printf("%s* back to q%d:%d\n", pad(pDepth+1), dotmem[c], pathmem[c]);
|
(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) */
|
/* (2) Next branch + reset data (if already browsed in other path) */
|
||||||
}else{
|
}else{
|
||||||
(ADB&&0x01) && printf("%s< yes\n", pad(pDepth+1));
|
(ADB&&0x01) && printf("< yes\n");
|
||||||
|
|
||||||
c++;
|
c++;
|
||||||
pathmem = realloc(pathmem, sizeof(char) * (c+1) );
|
pCtx = realloc(pCtx, sizeof(struct AutomateContext) * (c+1) );
|
||||||
indexmem = realloc(indexmem, sizeof(unsigned int) * (c+1) );
|
|
||||||
dotmem = realloc(dotmem, sizeof(char) * (c+1) );
|
|
||||||
|
|
||||||
pAutomate->n = c;
|
pCtx[c].index = strIndex;
|
||||||
pAutomate->path = realloc(pAutomate->path, sizeof(char) * (c+1) );
|
pCtx[c].path = 0;
|
||||||
pAutomate->path[c] = pAutomate->dCurrent;
|
|
||||||
|
|
||||||
|
|
||||||
indexmem[c] = strIndex;
|
|
||||||
pathmem[c] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -205,15 +229,18 @@ unsigned int browse(struct Automate* pAutomate, const char* pString, const char
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = NULL;
|
ptr = NULL;
|
||||||
free(buffer);
|
free(buffer);
|
||||||
free(pathmem);
|
free(foreignCtx);
|
||||||
free(indexmem);
|
|
||||||
free(dotmem);
|
|
||||||
|
|
||||||
(ADB&&0x01) && printf("%s>>> [done %s = %d/%d]\n", pad(pDepth), pAutomate->name, pAutomate->dCurrent, pAutomate->dFinal);
|
(ADB&&0x01) && printf(">>> [done %s = %d/%d]\n", pAutomate->name, pAutomate->dCurrent, pAutomate->dFinal);
|
||||||
return strIndex;
|
|
||||||
|
|
||||||
|
*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 )
|
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]]);
|
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 )
|
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.dCurrent = 0;
|
||||||
automate.dFinal = 0;
|
automate.dFinal = 0;
|
||||||
|
|
||||||
automate.n = 0;
|
|
||||||
|
|
||||||
/* [2] First allocation
|
/* [2] First allocation
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
automate.dot = malloc( 0 );
|
automate.dot = malloc( 0 );
|
||||||
|
@ -369,7 +394,6 @@ struct Automate createAutomate(const char* pName){
|
||||||
automate.redge = malloc( 0 );
|
automate.redge = malloc( 0 );
|
||||||
automate.ledge = malloc( 0 );
|
automate.ledge = malloc( 0 );
|
||||||
automate.aedge = malloc( 0 );
|
automate.aedge = malloc( 0 );
|
||||||
automate.path = malloc( 0 );
|
|
||||||
automate.name = malloc( strlen(pName) + 1 );
|
automate.name = malloc( strlen(pName) + 1 );
|
||||||
strcpy(automate.name, pName);
|
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
|
/* [0] Initialize variables
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
char a, d, e, dot, edge, edges, dotOffset, rtn, next_dot;
|
char a, d, e, dot, edge, edges, dotOffset, rtn, next_dot;
|
||||||
|
int sub;
|
||||||
|
|
||||||
char sedges = pMaster->sedges;
|
char sedges = pMaster->sedges;
|
||||||
char ledges = pMaster->ledges;
|
char ledges = pMaster->ledges;
|
||||||
|
@ -392,14 +488,18 @@ void mergeAutomate(struct Automate* pMaster, const char pSlaveIndex){
|
||||||
char aedges = pMaster->aedges;
|
char aedges = pMaster->aedges;
|
||||||
char dots = pMaster->dots;
|
char dots = pMaster->dots;
|
||||||
char final = pMaster->dFinal;
|
char final = pMaster->dFinal;
|
||||||
struct Automate* pSlave = &pMaster->aedge[pSlaveIndex];
|
struct Automate* pSlave = pMaster->aedge[pSlaveIndex];
|
||||||
|
|
||||||
|
|
||||||
while( pSlave->aedges > 0 )
|
/* [1] Merge automates recursively
|
||||||
mergeAutomate(pSlave, pSlave->aedges-1);
|
=========================================================*/
|
||||||
|
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) */
|
/* (1) String edges (sedges) */
|
||||||
for( a = 0 ; a < pSlave->sedges ; a++ ){
|
for( a = 0 ; a < pSlave->sedges ; a++ ){
|
||||||
|
@ -421,12 +521,12 @@ void mergeAutomate(struct Automate* pMaster, const char pSlaveIndex){
|
||||||
|
|
||||||
/* (4) Automate edges (aedges) */
|
/* (4) Automate edges (aedges) */
|
||||||
for( a = 0 ; a < pSlave->aedges ; a++ ){
|
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) ;
|
(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 */
|
/* (1) For each fot of @pMaster */
|
||||||
for( dot = 0 ; dot < dots ; dot++ ){
|
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 */
|
/* (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 */
|
/* (2) Keep old @pMaster.dFinal */
|
||||||
(ADB&&0x01) && printf("restauring final to %d\n", final);
|
(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) ;
|
(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
|
/* [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
|
/* [2] Create the aedge
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
memcpy(&pAutomate->aedge[index], pAedge, sizeof(struct Automate));
|
pAutomate->aedge[index] = pAedge;
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,13 @@
|
||||||
} AutomateType;
|
} AutomateType;
|
||||||
|
|
||||||
|
|
||||||
#define ADB 0x00
|
#define ADB 0x01
|
||||||
|
|
||||||
|
struct AutomateContext{
|
||||||
|
char dot;
|
||||||
|
char path;
|
||||||
|
unsigned int index;
|
||||||
|
};
|
||||||
|
|
||||||
struct AutomateDot{
|
struct AutomateDot{
|
||||||
char n; // number of edges
|
char n; // number of edges
|
||||||
|
@ -44,31 +50,40 @@
|
||||||
char** sedge; // string edges
|
char** sedge; // string edges
|
||||||
char** redge; // range edges (between char[0] and char[1])
|
char** redge; // range edges (between char[0] and char[1])
|
||||||
char** ledge; // list edges (in one of the given char-s)
|
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 dCurrent; // current dot index
|
||||||
char dFinal; // final dot index
|
char dFinal; // final dot index
|
||||||
unsigned int steps; // number of steps
|
|
||||||
|
|
||||||
char* name; // automate name
|
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
|
/* Try to browse an automate with a string
|
||||||
*
|
*
|
||||||
* @pAutomate<struct Automate*> Current working automate
|
* @pAutomate<struct Automate*> Current working automate
|
||||||
* @pString<const char*> String to test
|
* @pString<const char*> String to test
|
||||||
* @pDepth<const char> Padding
|
* @pCtx<struct AutomateContext*> Already browsed context
|
||||||
*
|
*
|
||||||
* @return offset<int> The @pString offset browsed to
|
* @return offset<int> The @pString offset browsed to
|
||||||
*
|
*
|
||||||
* @NOTE: Automate.dCurrent is equal to Automate.dFinal if final state reached
|
* @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
|
/* Builds an automate from a regexp
|
||||||
|
@ -95,14 +110,22 @@
|
||||||
*/
|
*/
|
||||||
struct Automate createAutomate(const char* pName);
|
struct Automate createAutomate(const char* pName);
|
||||||
|
|
||||||
|
/* Destroys an automate
|
||||||
|
*
|
||||||
|
* @pAutomate<struct Automate*> Automate pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void destroyAutomate(struct Automate* pAutomate);
|
||||||
|
|
||||||
/* Merges an automate into another
|
/* Merges an automate into another
|
||||||
*
|
*
|
||||||
* @pMaster<struct Automate*> Master automate that contains @pSlave
|
* @pMaster<struct Automate*> Master automate that contains @pSlave
|
||||||
* @pSlaveIndex<const char> Slave automate index into @pMaster
|
* @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
|
/* 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, AUTOMATE_T, 0); // q1 --a0--> q3
|
||||||
linkDots(&array, 1, 3, STRING_T, 1); // q1 --s1--> 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);
|
struct Automate test = createAutomate("test");
|
||||||
printf(" (*) in %d steps\n", array.steps);
|
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);
|
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);
|
exit(0);
|
||||||
/* Build RegExp */
|
/* Build RegExp */
|
||||||
|
|
Loading…
Reference in New Issue