[bigupdate] `mergeAutomate` works well [todo] manage @pSlave removal from @pMaster + [update] now browse is successful
This commit is contained in:
parent
ffa0c03fd6
commit
315a8be97a
|
@ -12,7 +12,9 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int browse(struct Automate* pAutomate, const char* pString){
|
unsigned int browse(struct Automate* pAutomate, const char* pString, const char pDepth){
|
||||||
|
|
||||||
|
printf("%s>>> [browsing %s]\n", pad(pDepth), pAutomate->name);
|
||||||
|
|
||||||
/* [0] Initialize variables
|
/* [0] Initialize variables
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
|
@ -23,9 +25,9 @@ unsigned int browse(struct Automate* pAutomate, const char* pString){
|
||||||
char* ptr = NULL;
|
char* ptr = NULL;
|
||||||
struct AutomateDot dotPtr;
|
struct AutomateDot dotPtr;
|
||||||
|
|
||||||
char* pathmem = malloc( strlen(pString) ); // will contain edge number for each dot
|
char* pathmem = malloc( sizeof(char) ); // will contain edge number for each dot
|
||||||
unsigned int* indexmem = malloc( sizeof(unsigned int) * strlen(pString) ); // will contain offset of @pString for each dot
|
unsigned int* indexmem = malloc( sizeof(unsigned int) ); // will contain offset of @pString for each dot
|
||||||
char* dotmem = malloc( strlen(pString) );
|
char* dotmem = malloc( sizeof(char) );
|
||||||
|
|
||||||
/* [1] For each char
|
/* [1] For each char
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
|
@ -36,24 +38,21 @@ unsigned int browse(struct Automate* pAutomate, const char* pString){
|
||||||
pAutomate->steps = 0;
|
pAutomate->steps = 0;
|
||||||
|
|
||||||
|
|
||||||
/* (1) Initialize path memory
|
|
||||||
---------------------------------------------------------*/
|
|
||||||
for( c = 0 ; c < len ; c++ ){
|
|
||||||
pathmem[c] = 0;
|
|
||||||
indexmem[c] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* (1) For each char try to match
|
||||||
/* (2) For each char try to match
|
|
||||||
---------------------------------------------------------*/
|
---------------------------------------------------------*/
|
||||||
c = 0;
|
c = 0;
|
||||||
strIndex = 0;
|
strIndex = 0;
|
||||||
while( c < len ){
|
pathmem[0] = 0;
|
||||||
|
|
||||||
|
while( pAutomate->dCurrent != pAutomate->dFinal && strIndex <= len ){
|
||||||
|
|
||||||
|
|
||||||
pAutomate->steps++;
|
pAutomate->steps++;
|
||||||
|
(ADB&&0x01) && printf("%s\b * step %d (remaining '%s')\n", pad(pDepth), pAutomate->steps, pString+strIndex);
|
||||||
|
|
||||||
|
|
||||||
/* (1) Check if the current char can lead to a state
|
/* (2) Initialize local data
|
||||||
---------------------------------------------------------*/
|
---------------------------------------------------------*/
|
||||||
/* (1) Check current state choices */
|
/* (1) Check current state choices */
|
||||||
dotmem[c] = pAutomate->dCurrent;
|
dotmem[c] = pAutomate->dCurrent;
|
||||||
|
@ -69,11 +68,23 @@ unsigned int browse(struct Automate* pAutomate, const char* pString){
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
/* (3) Try paths from the current dot
|
||||||
|
---------------------------------------------------------*/
|
||||||
for( ; i < l ; i++ ){
|
for( ; i < l ; i++ ){
|
||||||
|
|
||||||
/* (3) If STRING match */
|
/* (1) If STRING match */
|
||||||
if( dotPtr.type[i] == AUTOMATE_TYPE_STRING ){
|
if( dotPtr.type[i] == DIRECT_T ){
|
||||||
|
|
||||||
|
(ADB&&0x01) && printf("%s> q%d --d0--> q%d ?\n", pad(pDepth+1), dotmem[c], dotPtr.dot[i]);
|
||||||
|
|
||||||
|
pAutomate->dCurrent = dotPtr.dot[i];
|
||||||
|
pathmem[c] = 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]);
|
||||||
|
|
||||||
ptr = pAutomate->sedge[dotPtr.edge[i]];
|
ptr = pAutomate->sedge[dotPtr.edge[i]];
|
||||||
strncpy(buffer, pString+strIndex, strlen(ptr));
|
strncpy(buffer, pString+strIndex, strlen(ptr));
|
||||||
|
@ -86,20 +97,24 @@ unsigned int browse(struct Automate* pAutomate, const char* pString){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (4) If RANGE match */
|
/* (3) If RANGE match */
|
||||||
}else if( dotPtr.type[i] == AUTOMATE_TYPE_RANGE ){
|
}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]);
|
||||||
|
|
||||||
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;
|
pathmem[c] = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (5) If LIST match */
|
/* (4) If LIST match */
|
||||||
}else if( dotPtr.type[i] == AUTOMATE_TYPE_LIST ){
|
}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]);
|
||||||
|
|
||||||
ptr = pAutomate->ledge[dotPtr.edge[i]];
|
ptr = pAutomate->ledge[dotPtr.edge[i]];
|
||||||
|
|
||||||
|
@ -112,15 +127,20 @@ unsigned int browse(struct Automate* pAutomate, const char* pString){
|
||||||
// if a char matches -> store it
|
// if a char matches -> store it
|
||||||
if( a < A ){
|
if( a < A ){
|
||||||
pAutomate->dCurrent = dotPtr.dot[i];
|
pAutomate->dCurrent = dotPtr.dot[i];
|
||||||
strIndex += 1;
|
strIndex += 1;
|
||||||
pathmem[c] = i;
|
pathmem[c] = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (6) If AUTOMATE match */
|
/* (5) If AUTOMATE match */
|
||||||
}else{
|
}else if( dotPtr.type[i] == AUTOMATE_T ){
|
||||||
|
|
||||||
recursive = browse(&pAutomate->aedge[dotPtr.edge[i]], pString+strIndex);
|
(ADB&&0x01) && printf("%s> q%d --a%d--> q%d ?\n", pad(pDepth+1), dotmem[c], dotPtr.edge[i], dotPtr.dot[i]);
|
||||||
|
|
||||||
|
recursive = browse(&pAutomate->aedge[dotPtr.edge[i]], pString+strIndex, pDepth+1);
|
||||||
|
|
||||||
|
if( pAutomate->aedge[dotPtr.edge[i]].steps > 0 )
|
||||||
|
pAutomate->steps += pAutomate->aedge[dotPtr.edge[i]].steps-1;
|
||||||
|
|
||||||
if( pAutomate->aedge[dotPtr.edge[i]].dCurrent == pAutomate->aedge[dotPtr.edge[i]].dFinal ){
|
if( pAutomate->aedge[dotPtr.edge[i]].dCurrent == pAutomate->aedge[dotPtr.edge[i]].dFinal ){
|
||||||
pAutomate->dCurrent = dotPtr.dot[i];
|
pAutomate->dCurrent = dotPtr.dot[i];
|
||||||
|
@ -134,8 +154,10 @@ unsigned int browse(struct Automate* pAutomate, const char* pString){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* (7) If no more path */
|
/* (4) Next dot or previous if locked
|
||||||
if( strIndex == indexmem[c] ){
|
---------------------------------------------------------*/
|
||||||
|
/* (1) If no char procesed && same dot && no action performed */
|
||||||
|
if( strIndex == indexmem[c] && dotmem[c] == pAutomate->dCurrent && i >= l ){
|
||||||
|
|
||||||
// {1} if not first branch -> go previous //
|
// {1} if not first branch -> go previous //
|
||||||
if( c > 0 )
|
if( c > 0 )
|
||||||
|
@ -145,12 +167,19 @@ unsigned int browse(struct Automate* pAutomate, const char* pString){
|
||||||
strIndex = indexmem[c];
|
strIndex = indexmem[c];
|
||||||
pathmem[c]++;
|
pathmem[c]++;
|
||||||
pAutomate->dCurrent = dotmem[c];
|
pAutomate->dCurrent = dotmem[c];
|
||||||
// printf("* back to q%d:%d\n", dotmem[c], pathmem[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]);
|
||||||
|
|
||||||
/* (8) Next branch + reset data (if already browsed in other path) */
|
|
||||||
|
/* (2) Next branch + reset data (if already browsed in other path) */
|
||||||
}else{
|
}else{
|
||||||
// printf("q%d -%.1s-> q%d\n", c, pString+indexmem[c], pAutomate->dCurrent);
|
(ADB&&0x01) && printf("%s< yes\n", pad(pDepth+1));
|
||||||
|
|
||||||
c++;
|
c++;
|
||||||
|
pathmem = realloc(pathmem, sizeof(char) * (c+1) );
|
||||||
|
indexmem = realloc(indexmem, sizeof(unsigned int) * (c+1) );
|
||||||
|
dotmem = realloc(dotmem, sizeof(char) * (c+1) );
|
||||||
|
|
||||||
pathmem[c] = 0;
|
pathmem[c] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +192,9 @@ unsigned int browse(struct Automate* pAutomate, const char* pString){
|
||||||
free(buffer);
|
free(buffer);
|
||||||
free(pathmem);
|
free(pathmem);
|
||||||
free(indexmem);
|
free(indexmem);
|
||||||
|
free(dotmem);
|
||||||
|
|
||||||
|
(ADB&&0x01) && printf("%s>>> [done %s = %d/%d]\n", pad(pDepth), pAutomate->name, pAutomate->dCurrent, pAutomate->dFinal);
|
||||||
return strIndex;
|
return strIndex;
|
||||||
|
|
||||||
|
|
||||||
|
@ -242,7 +273,60 @@ struct Automate buildFromRegExp(const char* pRegExp){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct Automate createAutomate(){
|
void debug(const struct Automate pAutomate){
|
||||||
|
printf("== %s ==\n", pAutomate.name);
|
||||||
|
|
||||||
|
/* [0] Initialize variables
|
||||||
|
=========================================================*/
|
||||||
|
char a, b;
|
||||||
|
|
||||||
|
|
||||||
|
/* [1] Debug dots
|
||||||
|
=========================================================*/
|
||||||
|
printf("* %d dots:\n", pAutomate.dots);
|
||||||
|
|
||||||
|
|
||||||
|
/* [2] Debug edges
|
||||||
|
=========================================================*/
|
||||||
|
for( a = 0 ; a < pAutomate.dots ; a++ ){
|
||||||
|
|
||||||
|
|
||||||
|
if( a != pAutomate.dFinal )
|
||||||
|
printf(" * q%d\n", a);
|
||||||
|
else{
|
||||||
|
printf(" * q%d final dot\n", a);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( b = 0 ; b < pAutomate.dot[a].n ; b++ ){
|
||||||
|
|
||||||
|
if( pAutomate.dot[a].type[b] == DIRECT_T )
|
||||||
|
printf(" * q%d match direct\n", pAutomate.dot[a].dot[b]);
|
||||||
|
if( pAutomate.dot[a].type[b] == STRING_T )
|
||||||
|
printf(" * q%d match string '%s'\n", pAutomate.dot[a].dot[b], pAutomate.sedge[pAutomate.dot[a].edge[b]]);
|
||||||
|
else if( pAutomate.dot[a].type[b] == LIST_T )
|
||||||
|
printf(" * q%d match list '%s'\n", pAutomate.dot[a].dot[b], pAutomate.ledge[pAutomate.dot[a].edge[b]]);
|
||||||
|
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("== END ==\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct Automate createAutomate(const char* pName){
|
||||||
|
|
||||||
/* [0] Initialize variables
|
/* [0] Initialize variables
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
|
@ -266,6 +350,8 @@ struct Automate createAutomate(){
|
||||||
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.name = malloc( strlen(pName) + 1 );
|
||||||
|
strcpy(automate.name, pName);
|
||||||
|
|
||||||
|
|
||||||
/* [3] Return initialized automate
|
/* [3] Return initialized automate
|
||||||
|
@ -274,6 +360,131 @@ struct Automate createAutomate(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mergeAutomate(struct Automate* pMaster, const char pSlaveIndex){
|
||||||
|
|
||||||
|
/* [0] Initialize variables
|
||||||
|
=========================================================*/
|
||||||
|
char a, d, e, dot, edge, edges, dotOffset, rtn, next_dot;
|
||||||
|
|
||||||
|
char sedges = pMaster->sedges;
|
||||||
|
char ledges = pMaster->ledges;
|
||||||
|
char redges = pMaster->redges;
|
||||||
|
char aedges = pMaster->aedges;
|
||||||
|
char dots = pMaster->dots;
|
||||||
|
char final = pMaster->dFinal;
|
||||||
|
struct Automate* pSlave = &pMaster->aedge[pSlaveIndex];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* [1] Merge @pSlave edges into @pMaster edges
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) String edges (sedges) */
|
||||||
|
for( a = 0 ; a < pSlave->sedges ; a++ ){
|
||||||
|
rtn = addStringTransition(pMaster, pSlave->sedge[a]);
|
||||||
|
(ADB&0x01) && printf("merge SLAVE.string.%d into MASTER.string.%d\n", a, rtn) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (2) List edges (ledges) */
|
||||||
|
for( a = 0 ; a < pSlave->ledges ; a++ ){
|
||||||
|
rtn = addListTransition(pMaster, pSlave->ledge[a]);
|
||||||
|
(ADB&0x01) && printf("merge SLAVE.list.%d into MASTER.list.%d\n", a, rtn) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (3) Range edges (redges) */
|
||||||
|
for( a = 0 ; a < pSlave->redges ; a++ ){
|
||||||
|
rtn = addRangeTransition(pMaster, pSlave->redge[a]);
|
||||||
|
(ADB&0x01) && printf("merge SLAVE.range.%d into MASTER.range.%d\n", a, rtn) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (4) Automate edges (aedges) */
|
||||||
|
for( a = 0 ; a < pSlave->aedges ; 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
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) For each fot of @pMaster */
|
||||||
|
for( dot = 0 ; dot < dots ; dot++ ){
|
||||||
|
|
||||||
|
edges = pMaster->dot[dot].n;
|
||||||
|
|
||||||
|
/* (2) For each edge of the current dot */
|
||||||
|
for( edge = 0 ; edge < edges ; edge++ ){
|
||||||
|
|
||||||
|
/* (3) If not automate || not pSlave */
|
||||||
|
if( pMaster->dot[dot].type[edge] != AUTOMATE_T || pMaster->dot[dot].edge[edge] != pSlaveIndex )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* (4) Store current dot offset in @pMaster */
|
||||||
|
dotOffset = pMaster->dots;
|
||||||
|
|
||||||
|
/* (5) Add @pSlave dots number to @pMaster */
|
||||||
|
for( d = 0 ; d < pSlave->dots ; d++ ){
|
||||||
|
rtn = addDot(pMaster);
|
||||||
|
(ADB&0x01) && printf("duplicate SLAVE.dot.%d into MASTER.dot.%d for q%d to q%d transition with a%d\n", d, rtn, dot, pMaster->dot[dot].dot[edge], pMaster->dot[dot].edge[edge]) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (6) For each @pSlave duplicated dot, add dot's edges to @pMaster */
|
||||||
|
|
||||||
|
// {1} Direct out from @pSlave replacement //
|
||||||
|
(ADB&0x01) && printf(" OUT: direct link from MASTER.dot.%d to MASTER.dot.%d\n", dotOffset+pSlave->dots-1, pMaster->dot[dot].dot[edge]) ;
|
||||||
|
linkDots(pMaster, dotOffset+pSlave->dots-1, pMaster->dot[dot].dot[edge], DIRECT_T, 0);
|
||||||
|
|
||||||
|
// {2} Direct link to @pSlave replacement //
|
||||||
|
pMaster->dot[dot].type[edge] = DIRECT_T;
|
||||||
|
pMaster->dot[dot].dot[edge] = dotOffset;
|
||||||
|
(ADB&0x01) && printf(" IN: direct link from MASTER.dot.%d to MASTER.dot.%d\n", dot, dotOffset) ;
|
||||||
|
|
||||||
|
// {3} Duplicate @pSlave dot's edges into @pMaster //
|
||||||
|
for( d = 0 ; d < pSlave->dots ; d++ ){
|
||||||
|
|
||||||
|
for( e = 0 ; e < pSlave->dot[d].n ; e++ ){
|
||||||
|
|
||||||
|
next_dot = dotOffset+pSlave->dot[d].dot[e];
|
||||||
|
|
||||||
|
if( pSlave->dot[d].type[e] == DIRECT_T ){
|
||||||
|
(ADB&0x01) && printf(" MID: direct link from MASTER.dot.%d to MASTER.dot.%d\n", dotOffset+d, next_dot) ;
|
||||||
|
linkDots(pMaster, dotOffset+d, next_dot, pSlave->dot[d].type[e], 0);
|
||||||
|
}else if( pSlave->dot[d].type[e] == STRING_T ){
|
||||||
|
(ADB&0x01) && printf(" MID: string link from MASTER.dot.%d to MASTER.dot.%d\n", dotOffset+d, next_dot) ;
|
||||||
|
linkDots(pMaster, dotOffset+d, next_dot, pSlave->dot[d].type[e], sedges+pSlave->dot[d].edge[e]);
|
||||||
|
}else if( pSlave->dot[d].type[e] == LIST_T ){
|
||||||
|
(ADB&0x01) && printf(" MID: list link from MASTER.dot.%d to MASTER.dot.%d\n", dotOffset+d, next_dot) ;
|
||||||
|
linkDots(pMaster, dotOffset+d, next_dot, pSlave->dot[d].type[e], ledges+pSlave->dot[d].edge[e]);
|
||||||
|
}else if( pSlave->dot[d].type[e] == RANGE_T ){
|
||||||
|
(ADB&0x01) && printf(" MID: range link from MASTER.dot.%d to MASTER.dot.%d\n", dotOffset+d, next_dot) ;
|
||||||
|
linkDots(pMaster, dotOffset+d, next_dot, pSlave->dot[d].type[e], redges+pSlave->dot[d].edge[e]);
|
||||||
|
}else if( pSlave->dot[d].type[e] == AUTOMATE_T ){
|
||||||
|
(ADB&0x01) && printf(" MID: automate link from MASTER.dot.%d to MASTER.dot.%d\n", dotOffset+d, next_dot) ;
|
||||||
|
linkDots(pMaster, dotOffset+d, next_dot, pSlave->dot[d].type[e], aedges+pSlave->dot[d].edge[e]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [3] Clean @pMaster
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) Remove @pSlave form @pMaster */
|
||||||
|
pMaster->aedge = realloc(pMaster->aedge, sizeof(struct Automate) * --pMaster->aedges);
|
||||||
|
|
||||||
|
/* (2) Keep old @pMaster.dFinal */
|
||||||
|
(ADB&&0x01) && printf("restauring final to %d\n", final);
|
||||||
|
pMaster->dFinal = final;
|
||||||
|
|
||||||
|
|
||||||
|
(ADB&0x01) && printf("SLAVE.%s successfully merged into MASTER.%s\n\n", pSlave->name, pMaster->name) ;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
char addDot(struct Automate* pAutomate){
|
char addDot(struct Automate* pAutomate){
|
||||||
|
|
||||||
/* [0] Initialize variables
|
/* [0] Initialize variables
|
||||||
|
@ -379,19 +590,26 @@ char addAutomateTransition(struct Automate* pAutomate, struct Automate* pAedge){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void linkDots(struct Automate* pAutomate, const char pIn, const char pOut, const char pType, const char pEdge){
|
void linkDots(struct Automate* pAutomate, const char pIn, const char pOut, const AutomateType pType, const char pEdge){
|
||||||
|
|
||||||
/* [0] Initialize variables
|
/* [0] Initialization
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
|
/* (1) Check arguments */
|
||||||
|
if( pIn >= pAutomate->dots || pOut >= pAutomate->dots ){
|
||||||
|
printf("linkDots, pIn/pOut out of range!! Exiting\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (2) Initialize variables */
|
||||||
char c; // counter
|
char c; // counter
|
||||||
char index = pAutomate->dot[pIn].n++;
|
char index = pAutomate->dot[pIn].n++;
|
||||||
|
|
||||||
|
|
||||||
/* [1] Reallocate memory for link
|
/* [1] Reallocate memory for link
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
pAutomate->dot[pIn].dot = realloc( pAutomate->dot[pIn].dot, pAutomate->dot[pIn].n );
|
pAutomate->dot[pIn].dot = realloc( pAutomate->dot[pIn].dot, pAutomate->dot[pIn].n );
|
||||||
pAutomate->dot[pIn].type = realloc( pAutomate->dot[pIn].type, pAutomate->dot[pIn].n );
|
pAutomate->dot[pIn].type = realloc( pAutomate->dot[pIn].type, sizeof(AutomateType) * pAutomate->dot[pIn].n );
|
||||||
pAutomate->dot[pIn].edge = realloc( pAutomate->dot[pIn].edge, pAutomate->dot[pIn].n );
|
pAutomate->dot[pIn].edge = realloc( pAutomate->dot[pIn].edge, pAutomate->dot[pIn].n );
|
||||||
|
|
||||||
|
|
||||||
/* [2] Create the link
|
/* [2] Create the link
|
||||||
|
@ -409,6 +627,17 @@ void linkDots(struct Automate* pAutomate, const char pIn, const char pOut, const
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
char* pad(const char depth){
|
||||||
|
char* buffer = malloc( depth+1 );
|
||||||
|
char c = 0;
|
||||||
|
|
||||||
|
for( ; c < depth ; c++ )
|
||||||
|
buffer[c] = '\t';
|
||||||
|
buffer[c] = 0;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
char* replaceAll(const char* pHaystack, const char* pNeedle, const char* pReplacement){
|
char* replaceAll(const char* pHaystack, const char* pNeedle, const char* pReplacement){
|
||||||
|
|
||||||
|
|
|
@ -11,19 +11,26 @@
|
||||||
#define _LIB_AUTOMATE_AUTOMATE_H_
|
#define _LIB_AUTOMATE_AUTOMATE_H_
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define AUTOMATE_TYPE_STRING 0x00
|
typedef enum{
|
||||||
#define AUTOMATE_TYPE_RANGE 0x01
|
DIRECT_T = 0x00,
|
||||||
#define AUTOMATE_TYPE_LIST 0x02
|
STRING_T = 0x01,
|
||||||
#define AUTOMATE_TYPE_AUTOMATE 0x03
|
RANGE_T = 0x02,
|
||||||
|
LIST_T = 0x03,
|
||||||
|
AUTOMATE_T = 0x04
|
||||||
|
} AutomateType;
|
||||||
|
|
||||||
|
|
||||||
|
#define ADB 0x00
|
||||||
|
|
||||||
struct AutomateDot{
|
struct AutomateDot{
|
||||||
char n; // number of edges
|
char n; // number of edges
|
||||||
char* type; // type of Transition (according to index) (0=string;1=range;2=list;3=automate)
|
AutomateType* type; // type of Transition (according to index) (0=direct;1=string;2=range;3=list;4=automate)
|
||||||
char* dot; // list of dot_id
|
char* dot; // list of dot_id
|
||||||
char* edge; // list of [sa]edge_id
|
char* edge; // list of [sa]edge_id
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Automate{
|
struct Automate{
|
||||||
|
@ -42,6 +49,8 @@
|
||||||
char dCurrent; // current dot index
|
char dCurrent; // current dot index
|
||||||
char dFinal; // final dot index
|
char dFinal; // final dot index
|
||||||
char steps; // number of steps
|
char steps; // number of steps
|
||||||
|
|
||||||
|
char* name; // automate name
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,13 +58,14 @@
|
||||||
*
|
*
|
||||||
* @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
|
||||||
*
|
*
|
||||||
* @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);
|
unsigned int browse(struct Automate* pAutomate, const char* pString, const char pDepth);
|
||||||
|
|
||||||
|
|
||||||
/* Builds an automate from a regexp
|
/* Builds an automate from a regexp
|
||||||
|
@ -71,14 +81,25 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void debug(const struct Automate pAutomate);
|
||||||
|
|
||||||
/* Initializes an automate
|
/* Initializes an automate
|
||||||
*
|
*
|
||||||
|
* @pName<const char*> Automate name
|
||||||
|
*
|
||||||
* @return new<struct Automate> The created automate
|
* @return new<struct Automate> The created automate
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct Automate createAutomate();
|
struct Automate createAutomate(const char* pName);
|
||||||
|
|
||||||
|
/* Merges an automate into another
|
||||||
|
*
|
||||||
|
* @pMaster<struct Automate*> Master automate that contains @pSlave
|
||||||
|
* @pSlaveIndex<const char> Slave automate index into @pMaster
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void mergeAutomate(struct Automate* pMaster, const char pSlaveIndex);
|
||||||
|
|
||||||
|
|
||||||
/* Adds a dot to an automate
|
/* Adds a dot to an automate
|
||||||
|
@ -134,14 +155,14 @@
|
||||||
* @pAutomate<struct Automate*> Current working automate
|
* @pAutomate<struct Automate*> Current working automate
|
||||||
* @pIn<const char> Input dot index
|
* @pIn<const char> Input dot index
|
||||||
* @pOut<const char> Output dot index
|
* @pOut<const char> Output dot index
|
||||||
* @pType<const char> Transition type
|
* @pType<const AutomateType> Transition type
|
||||||
* @pEdge<const char> Transition type-specific index
|
* @pEdge<const char> Transition type-specific index
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void linkDots(struct Automate* pAutomate, const char pIn, const char pOut, const char pType, const char pEdge);
|
void linkDots(struct Automate* pAutomate, const char pIn, const char pOut, const AutomateType pType, const char pEdge);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
char* pad(const char depth);
|
||||||
|
|
||||||
char* replaceAll(const char* pHaystack, const char* pNeedle, const char* pReplacement);
|
char* replaceAll(const char* pHaystack, const char* pNeedle, const char* pReplacement);
|
||||||
char getGroups(const char* pString, int* pStart, int* pEnd);
|
char getGroups(const char* pString, int* pStart, int* pEnd);
|
||||||
|
|
129
src/linter.c
129
src/linter.c
|
@ -22,105 +22,58 @@ int main(int argc, char* argv[]){
|
||||||
|
|
||||||
/** TEST **/
|
/** TEST **/
|
||||||
/** BUILD AUTOMATE **/
|
/** BUILD AUTOMATE **/
|
||||||
|
struct Automate digit = createAutomate("digit");
|
||||||
|
addDot(&digit); // q0
|
||||||
|
addDot(&digit); // q1
|
||||||
|
addRangeTransition(&digit, "09\0"); // r0
|
||||||
|
linkDots(&digit, 0, 0, RANGE_T, 0); // q0 --r0--> q0
|
||||||
|
linkDots(&digit, 0, 1, RANGE_T, 0); // q0 --r0--> q1
|
||||||
|
|
||||||
|
struct Automate positive = createAutomate("positive");
|
||||||
|
addDot(&positive); // q0
|
||||||
|
addDot(&positive); // q1
|
||||||
|
addDot(&positive); // q2
|
||||||
|
addDot(&positive); // q3
|
||||||
|
addStringTransition(&positive, ",\0"); // s0
|
||||||
|
addAutomateTransition(&positive, &digit); // a0
|
||||||
|
linkDots(&positive, 0, 1, AUTOMATE_T, 0); // q0 --a0--> q1
|
||||||
|
linkDots(&positive, 0, 2, STRING_T, 0); // q0 --s0--> q2
|
||||||
|
linkDots(&positive, 0, 3, AUTOMATE_T, 0); // q0 --a0--> q3
|
||||||
|
linkDots(&positive, 1, 2, STRING_T, 0); // q1 --s0--> q2
|
||||||
|
linkDots(&positive, 1, 3, STRING_T, 0); // q1 --s0--> q3
|
||||||
|
linkDots(&positive, 2, 3, AUTOMATE_T, 0); // q2 --a0--> q3
|
||||||
|
|
||||||
// A = a+(bc[x-z]+bc[de])
|
// A = a+(bc[x-z]+bc[de])
|
||||||
struct Automate a = createAutomate();
|
struct Automate number = createAutomate("number");
|
||||||
addDot(&a); // q0
|
addDot(&number); // q0
|
||||||
addDot(&a); // q1
|
addDot(&number); // q1
|
||||||
addDot(&a); // q2
|
addDot(&number); // q2
|
||||||
addDot(&a); // q3
|
addListTransition(&number, "+-\0"); // l0
|
||||||
addDot(&a); // q4
|
addAutomateTransition(&number, &positive); // a0
|
||||||
addDot(&a); // q5
|
|
||||||
|
|
||||||
addStringTransition(&a, "a\0"); // s0
|
linkDots(&number, 0, 1, LIST_T, 0); // q0 --l0--> q1
|
||||||
addStringTransition(&a, "b\0"); // s1
|
linkDots(&number, 0, 2, AUTOMATE_T, 0); // q0 --a0--> q2
|
||||||
addStringTransition(&a, "c\0"); // s2
|
linkDots(&number, 1, 2, AUTOMATE_T, 0); // q1 --a0--> q2
|
||||||
addListTransition(&a, "de\0"); // l0
|
|
||||||
addRangeTransition(&a, "xz\0"); // r0
|
|
||||||
|
|
||||||
linkDots(&a, 0, 1, AUTOMATE_TYPE_STRING, 0); // q0 -s0-> q1 || branch-0 path-0
|
|
||||||
linkDots(&a, 1, 1, AUTOMATE_TYPE_STRING, 0); // q1 -s0-> q1 || branch-1 path-0
|
mergeAutomate(&positive, 0);
|
||||||
linkDots(&a, 1, 2, AUTOMATE_TYPE_STRING, 1); // q1 -s1-> q2 || branch-1 path-1
|
debug(positive);
|
||||||
linkDots(&a, 2, 3, AUTOMATE_TYPE_STRING, 2); // q2 -s2-> q3 || branch-2 path-0
|
// mergeAutomate(&number, 0);
|
||||||
linkDots(&a, 3, 5, AUTOMATE_TYPE_RANGE, 0); // q2 -r0-> q5 || branch-3 path-0
|
// debug(number);
|
||||||
linkDots(&a, 1, 4, AUTOMATE_TYPE_STRING, 1); // q1 -s1-> q4 || branch-1 path-2
|
|
||||||
linkDots(&a, 4, 4, AUTOMATE_TYPE_STRING, 2); // q4 -s2-> q4 || branch-4 path-0
|
// mergeAutomate(&number, 0);
|
||||||
linkDots(&a, 4, 5, AUTOMATE_TYPE_LIST, 0); // q4 -l0-> q5 || branch-4 path-1
|
|
||||||
|
|
||||||
char string[40] = {0};
|
char string[40] = {0};
|
||||||
unsigned int browsed = 0;
|
unsigned int browsed = 0;
|
||||||
clock_t start, stop;
|
clock_t start, stop;
|
||||||
|
strcpy(string, "123,4\0");
|
||||||
strcpy(string, "abcx");
|
start = clock(); browsed = browse(&positive, string, 0); stop = clock();
|
||||||
start = clock(); browsed = browse(&a, string); stop = clock();
|
|
||||||
printf("browse '%s' : %d/%d\n", string, browsed, (int) strlen(string));
|
printf("browse '%s' : %d/%d\n", string, browsed, (int) strlen(string));
|
||||||
printf(" (*) final_state: %d/%d\n", a.dCurrent, a.dFinal);
|
printf(" (*) final_state: %d/%d\n", positive.dCurrent, positive.dFinal);
|
||||||
printf(" (*) in %d steps\n", a.steps);
|
printf(" (*) in %d steps\n", positive.steps);
|
||||||
printf(" (*) in %.3lf seconds\n\n", (double)(stop-start)/CLOCKS_PER_SEC);
|
printf(" (*) in %.3lf seconds\n\n", (double)(stop-start)/CLOCKS_PER_SEC);
|
||||||
|
|
||||||
strcpy(string, "abcy");
|
exit(0);
|
||||||
start = clock(); browsed = browse(&a, string); stop = clock();
|
|
||||||
printf("browse '%s' : %d/%d\n", string, browsed, (int) strlen(string));
|
|
||||||
printf(" (*) final_state: %d/%d\n", a.dCurrent, a.dFinal);
|
|
||||||
printf(" (*) in %d steps\n", a.steps);
|
|
||||||
printf(" (*) in %.3lf seconds\n\n", (double)(stop-start)/CLOCKS_PER_SEC);
|
|
||||||
|
|
||||||
strcpy(string, "abcz");
|
|
||||||
start = clock(); browsed = browse(&a, string); stop = clock();
|
|
||||||
printf("browse '%s' : %d/%d\n", string, browsed, (int) strlen(string));
|
|
||||||
printf(" (*) final_state: %d/%d\n", a.dCurrent, a.dFinal);
|
|
||||||
printf(" (*) in %d steps\n", a.steps);
|
|
||||||
printf(" (*) in %.3lf seconds\n\n", (double)(stop-start)/CLOCKS_PER_SEC);
|
|
||||||
|
|
||||||
strcpy(string, "abcd");
|
|
||||||
start = clock(); browsed = browse(&a, string); stop = clock();
|
|
||||||
printf("browse '%s' : %d/%d\n", string, browsed, (int) strlen(string));
|
|
||||||
printf(" (*) final_state: %d/%d\n", a.dCurrent, a.dFinal);
|
|
||||||
printf(" (*) in %d steps\n", a.steps);
|
|
||||||
printf(" (*) in %.3lf seconds\n\n", (double)(stop-start)/CLOCKS_PER_SEC);
|
|
||||||
|
|
||||||
strcpy(string, "abce");
|
|
||||||
start = clock(); browsed = browse(&a, string); stop = clock();
|
|
||||||
printf("browse '%s' : %d/%d\n", string, browsed, (int) strlen(string));
|
|
||||||
printf(" (*) final_state: %d/%d\n", a.dCurrent, a.dFinal);
|
|
||||||
printf(" (*) in %d steps\n", a.steps);
|
|
||||||
printf(" (*) in %.3lf seconds\n\n", (double)(stop-start)/CLOCKS_PER_SEC);
|
|
||||||
|
|
||||||
strcpy(string, "aaaaaaabcx");
|
|
||||||
start = clock(); browsed = browse(&a, string); stop = clock();
|
|
||||||
printf("browse '%s' : %d/%d\n", string, browsed, (int) strlen(string));
|
|
||||||
printf(" (*) final_state: %d/%d\n", a.dCurrent, a.dFinal);
|
|
||||||
printf(" (*) in %d steps\n", a.steps);
|
|
||||||
printf(" (*) in %.3lf seconds\n\n", (double)(stop-start)/CLOCKS_PER_SEC);
|
|
||||||
|
|
||||||
strcpy(string, "aaabc");
|
|
||||||
start = clock(); browsed = browse(&a, string); stop = clock();
|
|
||||||
printf("browse '%s' : %d/%d\n", string, browsed, (int) strlen(string));
|
|
||||||
printf(" (*) final_state: %d/%d\n", a.dCurrent, a.dFinal);
|
|
||||||
printf(" (*) in %d steps\n", a.steps);
|
|
||||||
printf(" (*) in %.3lf seconds\n\n", (double)(stop-start)/CLOCKS_PER_SEC);
|
|
||||||
|
|
||||||
strcpy(string, "aaabc");
|
|
||||||
start = clock(); browsed = browse(&a, string); stop = clock();
|
|
||||||
printf("browse '%s' : %d/%d\n", string, browsed, (int) strlen(string));
|
|
||||||
printf(" (*) final_state: %d/%d\n", a.dCurrent, a.dFinal);
|
|
||||||
printf(" (*) in %d steps\n", a.steps);
|
|
||||||
printf(" (*) in %.3lf seconds\n\n", (double)(stop-start)/CLOCKS_PER_SEC);
|
|
||||||
|
|
||||||
strcpy(string, "aaabd");
|
|
||||||
start = clock(); browsed = browse(&a, string); stop = clock();
|
|
||||||
printf("browse '%s' : %d/%d\n", string, browsed, (int) strlen(string));
|
|
||||||
printf(" (*) final_state: %d/%d\n", a.dCurrent, a.dFinal);
|
|
||||||
printf(" (*) in %d steps\n", a.steps);
|
|
||||||
printf(" (*) in %.3lf seconds\n\n", (double)(stop-start)/CLOCKS_PER_SEC);
|
|
||||||
|
|
||||||
strcpy(string, "bc");
|
|
||||||
start = clock(); browsed = browse(&a, string); stop = clock();
|
|
||||||
printf("browse '%s' : %d/%d\n", string, browsed, (int) strlen(string));
|
|
||||||
printf("* final_state: %d/%d\n", a.dCurrent, a.dFinal);
|
|
||||||
printf(" (*) final_state: %d/%d\n", a.dCurrent, a.dFinal);
|
|
||||||
printf(" (*) in %d steps\n", a.steps);
|
|
||||||
printf(" (*) in %.3lf seconds\n\n", (double)(stop-start)/CLOCKS_PER_SEC);
|
|
||||||
/* Build RegExp */
|
/* Build RegExp */
|
||||||
// char regex[40] = "(a([abc](b+a)(b+e)+ahd)*(b+i)c)sd";
|
// char regex[40] = "(a([abc](b+a)(b+e)+ahd)*(b+i)c)sd";
|
||||||
char regex[40] = "(a[c(e[g(i+j)h]f)d]b)";
|
char regex[40] = "(a[c(e[g(i+j)h]f)d]b)";
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
>>> [browsing number]
|
||||||
|
> q0 --l0--> q1 ?
|
||||||
|
< yes
|
||||||
|
> q1 --a0--> q2 ?
|
||||||
|
>>> [browsing positive]
|
||||||
|
> q0 --a0--> q1 ?
|
||||||
|
>>> [browsing digit]
|
||||||
|
> q0 --r0--> q0 ?
|
||||||
|
< yes
|
||||||
|
> q1 --r0--> q0 ?
|
||||||
|
< yes
|
||||||
|
> q2 --r0--> q0 ?
|
||||||
|
< yes
|
||||||
|
> q3 --r0--> q0 ?
|
||||||
|
< yes
|
||||||
|
>>> [done digit = 0/0]
|
||||||
|
automate leads us (positive) from state 0 to 1
|
||||||
|
< yes
|
||||||
|
> q1 --s0--> q2 ?
|
||||||
|
> q1 --s0--> q3 ?
|
||||||
|
< not
|
||||||
|
* back to q0:1
|
||||||
|
> q0 --s0--> q2 ?
|
||||||
|
> q0 --a0--> q3 ?
|
||||||
|
>>> [browsing digit]
|
||||||
|
> q0 --r0--> q0 ?
|
||||||
|
< yes
|
||||||
|
> q1 --r0--> q0 ?
|
||||||
|
< yes
|
||||||
|
> q2 --r0--> q0 ?
|
||||||
|
< yes
|
||||||
|
> q3 --r0--> q0 ?
|
||||||
|
< yes
|
||||||
|
>>> [done digit = 0/0]
|
||||||
|
automate leads us (positive) from state 0 to 3
|
||||||
|
< yes
|
||||||
|
< not
|
||||||
|
* back to q0:3
|
||||||
|
>>> [done positive = 0/3]
|
||||||
|
< not
|
||||||
|
* back to q0:1
|
||||||
|
> q0 --a0--> q2 ?
|
||||||
|
>>> [browsing positive]
|
||||||
|
> q0 --a0--> q1 ?
|
||||||
|
>>> [browsing digit]
|
||||||
|
> q0 --r0--> q0 ?
|
||||||
|
< not
|
||||||
|
* back to q0:1
|
||||||
|
>>> [done digit = 0/0]
|
||||||
|
automate leads us (positive) from state 0 to 1
|
||||||
|
< yes
|
||||||
|
> q1 --s0--> q2 ?
|
||||||
|
> q1 --s0--> q3 ?
|
||||||
|
< not
|
||||||
|
* back to q0:1
|
||||||
|
> q0 --s0--> q2 ?
|
||||||
|
> q0 --a0--> q3 ?
|
||||||
|
>>> [browsing digit]
|
||||||
|
> q0 --r0--> q0 ?
|
||||||
|
< not
|
||||||
|
* back to q0:1
|
||||||
|
>>> [done digit = 0/0]
|
||||||
|
automate leads us (positive) from state 0 to 3
|
||||||
|
< yes
|
||||||
|
< not
|
||||||
|
* back to q0:3
|
||||||
|
>>> [done positive = 0/3]
|
||||||
|
< not
|
||||||
|
* back to q0:2
|
||||||
|
>>> [done number = 0/2]
|
||||||
|
browse '+1234' : 0/5
|
||||||
|
(*) final_state: 0/2
|
||||||
|
(*) in 20 steps
|
||||||
|
(*) in 0.000 seconds
|
||||||
|
|
||||||
|
line/0: '<?php'
|
||||||
|
line/1: 'require_once 'blabla.php';'
|
||||||
|
line/1: 'echo "blabla";'
|
||||||
|
line/0: ''
|
||||||
|
line/1: 'function sadsad(){'
|
||||||
|
line/2: '$var = 12;'
|
||||||
|
line/1: '}'
|
Loading…
Reference in New Issue