|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "tools/re2c/globals.h"
|
|
|
|
#include "tools/re2c/substr.h"
|
|
|
|
#include "tools/re2c/dfa.h"
|
|
|
|
|
|
|
|
#define octCh(c) ('0' + c%8)
|
|
|
|
|
|
|
|
void prtCh(FILE *o, uchar c){
|
|
|
|
uchar oc = talx[c];
|
|
|
|
switch(oc){
|
|
|
|
case '\'': fputs("\\'", o); break;
|
|
|
|
case '\n': fputs("\\n", o); break;
|
|
|
|
case '\t': fputs("\\t", o); break;
|
|
|
|
case '\v': fputs("\\v", o); break;
|
|
|
|
case '\b': fputs("\\b", o); break;
|
|
|
|
case '\r': fputs("\\r", o); break;
|
|
|
|
case '\f': fputs("\\f", o); break;
|
|
|
|
case '\a': fputs("\\a", o); break;
|
|
|
|
case '\\': fputs("\\\\", o); break;
|
|
|
|
default:
|
|
|
|
if(isprint(oc))
|
|
|
|
fputc(oc, o);
|
|
|
|
else
|
|
|
|
fprintf(o, "\\%c%c%c", octCh(c/64), octCh(c/8), octCh(c));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void printSpan(FILE *o, uint lb, uint ub){
|
|
|
|
if(lb > ub)
|
|
|
|
fputc('*', o);
|
|
|
|
fputc('[', o);
|
|
|
|
if((ub - lb) == 1){
|
|
|
|
prtCh(o, lb);
|
|
|
|
} else {
|
|
|
|
prtCh(o, lb);
|
|
|
|
fputc('-', o);
|
|
|
|
prtCh(o, ub-1);
|
|
|
|
}
|
|
|
|
fputc(']', o);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint
|
|
|
|
Span_show(Span *s, FILE *o, uint lb)
|
|
|
|
{
|
|
|
|
if(s->to){
|
|
|
|
printSpan(o, lb, s->ub);
|
|
|
|
fprintf(o, " %u; ", s->to->label);
|
|
|
|
}
|
|
|
|
return s->ub;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
State_out(FILE *o, const State *s){
|
|
|
|
uint lb, i;
|
|
|
|
fprintf(o, "state %u", s->label);
|
|
|
|
if(s->rule)
|
|
|
|
fprintf(o, " accepts %u", s->rule->d.RuleOp.accept);
|
|
|
|
fputs("\n", o); oline++;
|
|
|
|
lb = 0;
|
|
|
|
for(i = 0; i < s->go.nSpans; ++i)
|
|
|
|
lb = Span_show(&s->go.span[i], o, lb);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
DFA_out(FILE *o, const DFA *dfa){
|
|
|
|
State *s;
|
|
|
|
for(s = dfa->head; s; s = s->next) {
|
|
|
|
State_out(o, s);
|
|
|
|
fputs("\n\n", o); oline+=2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
State *
|
|
|
|
State_new(void)
|
|
|
|
{
|
|
|
|
State *s = malloc(sizeof(State));
|
|
|
|
s->rule = NULL;
|
|
|
|
s->link = NULL;
|
|
|
|
s->kCount = 0;
|
|
|
|
s->kernel = NULL;
|
|
|
|
s->action = NULL;
|
|
|
|
s->go.nSpans = 0;
|
|
|
|
s->go.span = NULL;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
State_delete(State *s)
|
|
|
|
{
|
|
|
|
if (s->kernel)
|
|
|
|
free(s->kernel);
|
|
|
|
if (s->go.span)
|
|
|
|
free(s->go.span);
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Ins **closure(Ins **cP, Ins *i){
|
|
|
|
while(!isMarked(i)){
|
|
|
|
mark(i);
|
|
|
|
*(cP++) = i;
|
|
|
|
if(i->i.tag == FORK){
|
|
|
|
cP = closure(cP, i + 1);
|
|
|
|
i = (Ins*) i->i.link;
|
|
|
|
} else if(i->i.tag == GOTO){
|
|
|
|
i = (Ins*) i->i.link;
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return cP;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct GoTo {
|
|
|
|
Char ch;
|
|
|
|
void *to;
|
|
|
|
} GoTo;
|
|
|
|
|
|
|
|
DFA *
|
|
|
|
DFA_new(Ins *ins, uint ni, uint lb, uint ub, Char *rep)
|
|
|
|
{
|
|
|
|
DFA *d = malloc(sizeof(DFA));
|
|
|
|
Ins **work = malloc(sizeof(Ins*)*(ni+1));
|
|
|
|
uint nc = ub - lb;
|
|
|
|
GoTo *goTo = malloc(sizeof(GoTo)*nc);
|
|
|
|
Span *span = malloc(sizeof(Span)*nc);
|
|
|
|
|
|
|
|
d->lbChar = lb;
|
|
|
|
d->ubChar = ub;
|
|
|
|
memset((char*) goTo, 0, nc*sizeof(GoTo));
|
|
|
|
d->tail = &d->head;
|
|
|
|
d->head = NULL;
|
|
|
|
d->nStates = 0;
|
|
|
|
d->toDo = NULL;
|
|
|
|
DFA_findState(d, work, closure(work, &ins[0]) - work);
|
|
|
|
while(d->toDo){
|
|
|
|
State *s = d->toDo;
|
|
|
|
|
|
|
|
Ins **cP, **iP, *i;
|
|
|
|
uint nGoTos = 0;
|
|
|
|
uint j;
|
|
|
|
|
|
|
|
d->toDo = s->link;
|
|
|
|
s->rule = NULL;
|
|
|
|
for(iP = s->kernel; (i = *iP); ++iP){
|
|
|
|
if(i->i.tag == CHAR){
|
|
|
|
Ins *j2;
|
|
|
|
for(j2 = i + 1; j2 < (Ins*) i->i.link; ++j2){
|
|
|
|
if(!(j2->c.link = goTo[j2->c.value - lb].to))
|
|
|
|
goTo[nGoTos++].ch = j2->c.value;
|
|
|
|
goTo[j2->c.value - lb].to = j2;
|
|
|
|
}
|
|
|
|
} else if(i->i.tag == TERM){
|
|
|
|
if(!s->rule || ((RegExp *)i->i.link)->d.RuleOp.accept < s->rule->d.RuleOp.accept)
|
|
|
|
s->rule = (RegExp *)i->i.link;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(j = 0; j < nGoTos; ++j){
|
|
|
|
GoTo *go = &goTo[goTo[j].ch - lb];
|
|
|
|
i = (Ins*) go->to;
|
|
|
|
for(cP = work; i; i = (Ins*) i->c.link)
|
|
|
|
cP = closure(cP, i + i->c.bump);
|
|
|
|
go->to = DFA_findState(d, work, cP - work);
|
|
|
|
}
|
|
|
|
|
|
|
|
s->go.nSpans = 0;
|
|
|
|
for(j = 0; j < nc;){
|
|
|
|
State *to = (State*) goTo[rep[j]].to;
|
|
|
|
while(++j < nc && goTo[rep[j]].to == to);
|
|
|
|
span[s->go.nSpans].ub = lb + j;
|
|
|
|
span[s->go.nSpans].to = to;
|
|
|
|
s->go.nSpans++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(j = nGoTos; j-- > 0;)
|
|
|
|
goTo[goTo[j].ch - lb].to = NULL;
|
|
|
|
|
|
|
|
s->go.span = malloc(sizeof(Span)*s->go.nSpans);
|
|
|
|
memcpy((char*) s->go.span, (char*) span, s->go.nSpans*sizeof(Span));
|
|
|
|
|
|
|
|
Action_new_Match(s);
|
|
|
|
|
|
|
|
}
|
|
|
|
free(work);
|
|
|
|
free(goTo);
|
|
|
|
free(span);
|
|
|
|
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
DFA_delete(DFA *d){
|
|
|
|
State *s;
|
|
|
|
while((s = d->head)){
|
|
|
|
d->head = s->next;
|
|
|
|
State_delete(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DFA_addState(DFA *d, State **a, State *s){
|
|
|
|
s->label = d->nStates++;
|
|
|
|
s->next = *a;
|
|
|
|
*a = s;
|
|
|
|
if(a == d->tail)
|
|
|
|
d->tail = &s->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
State *DFA_findState(DFA *d, Ins **kernel, uint kCount){
|
|
|
|
Ins **cP, **iP, *i;
|
|
|
|
State *s;
|
|
|
|
|
|
|
|
kernel[kCount] = NULL;
|
|
|
|
|
|
|
|
cP = kernel;
|
|
|
|
for(iP = kernel; (i = *iP); ++iP){
|
|
|
|
if(i->i.tag == CHAR || i->i.tag == TERM){
|
|
|
|
*cP++ = i;
|
|
|
|
} else {
|
|
|
|
unmark(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
kCount = cP - kernel;
|
|
|
|
kernel[kCount] = NULL;
|
|
|
|
|
|
|
|
for(s = d->head; s; s = s->next){
|
|
|
|
if(s->kCount == kCount){
|
|
|
|
for(iP = s->kernel; (i = *iP); ++iP)
|
|
|
|
if(!isMarked(i))
|
|
|
|
goto nextState;
|
|
|
|
goto unmarkAll;
|
|
|
|
}
|
|
|
|
nextState:;
|
|
|
|
}
|
|
|
|
|
|
|
|
s = State_new();
|
|
|
|
DFA_addState(d, d->tail, s);
|
|
|
|
s->kCount = kCount;
|
|
|
|
s->kernel = malloc(sizeof(Ins*)*(kCount+1));
|
|
|
|
memcpy(s->kernel, kernel, (kCount+1)*sizeof(Ins*));
|
|
|
|
s->link = d->toDo;
|
|
|
|
d->toDo = s;
|
|
|
|
|
|
|
|
unmarkAll:
|
|
|
|
for(iP = kernel; (i = *iP); ++iP)
|
|
|
|
unmark(i);
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|