/* * Copyright (c) 1978 Charles H. Forsyth * * Modified 02-Dec-80 Bob Denny -- Conditionalize debug code for reduced size * Modified 29-May-81 Bob Denny -- Clean up overlay stuff for RSX. * More 19-Mar-82 Bob Denny -- New C library & compiler * More 03-May-82 Bob Denny -- Final touches, remove unreferenced autos * More 29-Aug-82 Bob Denny -- Clean up -d printouts * More 29-Aug-82 Bob Denny -- Reformat for readability and comment * while learning about LEX. */ /* * ********* * * DFA.C * * ********* * * LEX -- DFA construction routines */ #include #include "lexlex.h" extern struct set *eclosure(); /* Used only by DFA */ extern struct dfa *defalt(); /* Used only by DFA */ extern struct move *stbase(); /* Used only by DFA */ /* * Build the DFA from the NFA */ dfabuild() { struct trans *trp; struct nfa **vec, **tp, *np, *temp[MAXNFA+1]; int a, i; struct set **sp, *stack[MAXDFA], **spp, *xp; /* DFA set stack */ struct dfa *state; /* --> current DFA state */ struct xset *xs, *xse; /* * Simulate an epsilon transition from nfa state 0 to * the initial states of the machines for each * translation. */ nfa[0].n_char = EPSILON; /* Set NFA state 0 transition EPSILON */ /* * Allocate a state vector, each node of which will * point to an NFA starting state. Each translation * generates an NFA, so the number of translations * equals the number of NFA start states. */ vec = lalloc(i = (transp-trans)+1, sizeof(*vec), "dfabuild"); /* * Fill in the start state vector */ vec[0] = nfa; /* vec[0] always --> NFA state 0 */ for (a = 1, trp = trans; trp < transp; trp++) /* For each translation */ vec[a++] = trp->t_start; /* Pick up the NFA start state */ /* * Now build the set sp --> e-CLOSURE(vec) */ sp = eclosure(newset(vec, i, 1)); free(vec); /* Deallocate the start state vector */ /* * At this point state 0 of the DFA is constructed. * This is the start state of the DFA. * Mark it "added" and push it on to the stack. */ sp->s_flag |= ADDED; spp = stack; *spp++ = sp; /* * From state 0, which is now stacked, all further DFA * states will be derived. */ while (spp > stack) { sp = *--spp; for (a = 0; a < NCHARS; a++) insets[a] = 0; xse = sets; for (i = 0; i < sp->s_len; i++) xse = addset(sp->s_els[i], xse); state = newdfa(); sp->s_state = state; state->df_name = sp; #ifdef DEBUG if (lldebug) { fprintf(lexlog, "build state %d ", state-dfa); pset(sp, 1); fprintf(lexlog, "\n"); } #endif state->df_ntrans = xse-sets; for (xs = sets; xs < xse; xs++) { a = xs->x_char&0377; tp = temp; for (i = 0; i < sp->s_len; i++) if ((np = sp->s_els[i])->n_char==a || np->n_char==CCL && np->n_ccl[a/NBPC]&(1<<(a%NBPC))) add(temp, &tp, np->n_succ[0]); xp = newset(temp, tp-temp, 1); xp = eclosure(xp); #ifdef DEBUG if (lldebug) { putc('\t', lexlog); chprint(a); putc('\t', lexlog); pset(xp, 1); fprintf(lexlog, "\n"); } #endif xs->x_set = xp; if (xp->s_state==0 && (xp->s_flag&ADDED)==0) { xp->s_flag |= ADDED; if (spp >= stack+MAXDFA) { error("dfabuild: stack overflow"); exit(1); } *spp++ = xp; } } state->df_default = defalt(state, &xse); setbase(state, stbase(xse), xse); } } /* * If an nfa state is not * already a member of the vector * `base', add it. */ add(base, tpp, np) struct nfa ***tpp, **base, *np; { register struct nfa **tp; for (tp = base; tp < *tpp; tp++) if (*tp == np) return; *(*tpp)++ = np; } /* * Add the character(s) * on which state `np' * branches to the transition * vector. */ addset(np, xse) register struct nfa *np; struct xset *xse; { register a; register char *ccl; if ((a = np->n_char) < NCHARS) xse = addxset(a, xse); if (a != CCL) return(xse); ccl = np->n_ccl; for (a = 0; a < NCHARS; a++) if (ccl[a/NBPC]&(1<<(a%NBPC))) xse = addxset(a, xse); return(xse); } /* * Add a character to the * transition vector, if it * isn't there already. */ addxset(a, xse) register a; struct xset *xse; { register struct xset *xs; register int temp; /* * VMS native doesn't do this correctly: * if (insets[a]++) */ temp = insets[a]; insets[a] += 1; if (temp) return(xse); xs = xse++; xs->x_char = a; xs->x_set = NULL; xs->x_defsame = 0; return(xse); }