|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 4758 (0x1296) Types: TextFile Notes: UNIX file Names: »dfa.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─⟦this⟧ »cmd/egrep/dfa.c«
/* * creation of the DFA */ #include "egrep.h" #include "newt.h" #include "dragon.h" #include "eclass.h" int uniq; int n_id; int n_ec; static bmsize; /* size of bitmap `d_b' */ static struct dragon d; /* prototype dragon */ static struct dragon *dragons; /* head of the dragon list */ struct dragon *member( ), *enter( ); /* * create the DFA start state */ struct dragon * initdfa( np) struct newt *np; { if (d.d_s) free( (char *)d.d_s); d.d_s = malloc( n_id*sizeof( *d.d_s)); if (d.d_s == NULL) nomem( ); d.d_s[0] = np; d.d_s[1] = NULL; bmsize = (n_id+NBCHAR-1) / NBCHAR; if (d.d_b) free( (char *)d.d_b); d.d_b = malloc( bmsize); if (d.d_b == NULL) nomem( ); dragons = NULL; ++uniq; e_closure( ); return (enter( np->n_fp)); } /* * construct the DFA * This task is done incrementally, after searching has started. * The current dragon `dp' needs a transition on the input `ec' given * the NFA `np'. The new dragon is determined, entered into `dp->d_p', * and returned. If the new dragon has never been encountered, it is * remembered. A special case arises if the current dragon is an accept * state: all transitions loop to itself. * Note that `ec' is an equivalence class, not a char. */ struct dragon * makedfa( dp, ec, np) struct dragon *dp; struct newt *np; { register struct eclass *ep; register struct dragon *p; extern struct eclass *eclasses; if (dp->d_success) { dp->d_p[ec] = dp; return (dp); } for (ep=eclasses; ep->e_class!=ec; ep=ep->e_next) ; ++uniq; gettrans( dp, ep); e_closure( ); p = member( ); if (p == NULL) p = enter( np->n_fp); dp->d_p[ec] = p; return (p); } /* * get transitions * Construct in `d.d_s' the set of newts to which there is a * transition on `ep' from some newt in `dp->d_s'. */ static gettrans( dp, ep) struct dragon *dp; struct eclass *ep; { register struct newt **pp, *np, *p, **npp; bool eqtrans( ); npp = d.d_s; pp = dp->d_s; while (np = *pp++) if ((p = np->n_cp) and (np->n_c != EPSILON) and (eqtrans( ep, np))) { *npp++ = p; p->n_uniq = uniq; } *npp = NULL; } /* * locate a dragon * The set of newts given by `d.d_s' are sought in the DFA. The * appropriate dragon is returned, else 0. The use of bitmap `d_b' allows * comparing (unsorted) `d_s' sets in time O(N). Hashing of `d_s' and * "self-organizing" the DFA also help to keep things fast. */ static struct dragon * member( ) { register struct dragon *dp; register char *p, *q; int i; dp = dragons; do { if (dp->d_hash == d.d_hash) { p = dp->d_b; q = d.d_b; i = bmsize; do { if (*p++ != *q++) break; } while (--i); if (i == 0) { if (dp == dragons) break; if (dp->d_next) dp->d_next->d_last = dp->d_last; dp->d_last->d_next = dp->d_next; dragons->d_last = dp; dp->d_next = dragons; dp->d_last = NULL; dragons = dp; break; } } } while (dp = dp->d_next); return (dp); } /* * enter the dragon * The prototype dragon `d' is used to create a dragon, which is * entered in the DFA. */ static struct dragon * enter( finalnp) struct newt *finalnp; { register struct dragon *p; register i; p = malloc( sizeof *p); if (p == NULL) nomem( ); p->d_success = FALSE; p->d_hash = d.d_hash; for (i=0; d.d_s[i]; ++i) if (d.d_s[i] == finalnp) p->d_success = TRUE; p->d_s = malloc( (i+1)*sizeof( *p->d_s)); if (p->d_s == NULL) nomem( ); for (i=0; p->d_s[i]=d.d_s[i]; ++i) ; p->d_b = malloc( bmsize); if (p->d_b == NULL) nomem( ); for (i=0; i<bmsize; ++i) p->d_b[i] = d.d_b[i]; p->d_p = malloc( n_ec*sizeof( *p->d_p)); if (p->d_p == NULL) nomem( ); for (i=0; i<n_ec; ++i) p->d_p[i] = NULL; if (dragons) dragons->d_last = p; p->d_next = dragons; dragons = p; p->d_last = NULL; return (p); } /* * perform epsilon-closure * Epsilon-transition `d.d_s' is computed and the result placed * in `d.d_s'. Ensuring a newt is not already on the list requires * time O(N), thanks to `uniq'. */ static e_closure( ) { register struct newt **nqq, *np, *p; struct newt **npp; d.d_hash = 0; for (nqq=d.d_s; *nqq++; ) ; --nqq; for (npp=d.d_s; npp<nqq; ) { np = *npp++; d.d_hash += (int)np; if ((p = np->n_cp) and (np->n_c == EPSILON) and (p->n_uniq != uniq)) { *nqq++ = p; p->n_uniq = uniq; } if ((p = np->n_ep) and (p->n_uniq != uniq)) { *nqq++ = p; p->n_uniq = uniq; } } *nqq = NULL; bmbuild( ); } /* * build bitmap * A bitmap of `d.d_s' is built in `d.d_b'. */ static bmbuild( ) { register struct newt *np; register char *p; register i; p = d.d_b; i = bmsize; do { *p++ = 0; } while (--i); i = 0; while (np = d.d_s[i++]) bitset( np->n_id, d.d_b); }