home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / C / LEX.ZIP / DFA.C < prev    next >
Encoding:
C/C++ Source or Header  |  1980-01-01  |  5.2 KB  |  194 lines

  1. /*
  2.  * Copyright (c) 1978 Charles H. Forsyth
  3.  *
  4.  * Modified 02-Dec-80 Bob Denny -- Conditionalize debug code for reduced size
  5.  * Modified 29-May-81 Bob Denny -- Clean up overlay stuff for RSX.
  6.  * More     19-Mar-82 Bob Denny -- New C library & compiler
  7.  * More     03-May-82 Bob Denny -- Final touches, remove unreferenced autos
  8.  * More     29-Aug-82 Bob Denny -- Clean up -d printouts
  9.  * More     29-Aug-82 Bob Denny -- Reformat for readability and comment
  10.  *                                 while learning about LEX.
  11.  * More        20-Nov-83 Scott Guthery -- Adapt for IBM PC & DeSmet C
  12.  */
  13.  
  14. /*
  15.  *    *********
  16.  *    * DFA.C *
  17.  *    *********
  18.  *
  19.  * LEX -- DFA construction routines
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include "lexlex.h"
  24.  
  25. extern struct set *eclosure();          /* Used only by DFA */
  26. extern struct dfa *defalt();            /* Used only by DFA */
  27. extern struct move *stbase();           /* Used only by DFA */
  28.  
  29. /*
  30.  * Build the DFA from the NFA
  31.  */
  32. dfabuild()
  33.    {
  34.    struct trans *trp;
  35.    struct nfa **vec, **tp, *np, *temp[MAXNFA+1];
  36.    int a, i;
  37.    struct set **sp, *stack[MAXDFA], **spp, *xp;  /* DFA set stack */
  38.    struct dfa *state;                  /* --> current DFA state */
  39.    struct xset *xs, *xse;
  40.  
  41.   /*
  42.    * Simulate an epsilon transition from nfa state 0 to
  43.    * the initial states of the machines for each
  44.    * translation.
  45.    */
  46.    nfa[0].n_char = EPSILON;            /* Set NFA state 0 transition EPSILON */
  47.    /*
  48.     * Allocate a state vector, each node of which will
  49.     * point to an NFA starting state.  Each translation
  50.     * generates an NFA, so the number of translations
  51.     * equals the number of NFA start states.
  52.     */
  53.    vec = lalloc(i = (transp-trans)+1, sizeof(*vec), "dfabuild");
  54.    /*
  55.     * Fill in the start state vector
  56.     */
  57.    vec[0] = nfa;                       /* vec[0] always --> NFA state 0 */
  58.    for (a = 1, trp = trans; trp < transp; trp++)  /* For each translation */
  59.       vec[a++] = trp->t_start;         /* Pick up the NFA start state */
  60.    /*
  61.     * Now build the set sp --> e-CLOSURE(vec)
  62.     */
  63.    sp = eclosure(newset(vec, i, 1));
  64.  
  65.    free(vec);                          /* Deallocate the start state vector */
  66.  
  67.    /*
  68.     * At this point state 0 of the DFA is constructed.
  69.     * This is the start state of the DFA.
  70.     * Mark it "added" and push it on to the stack.
  71.     */
  72.    sp->s_flag |= ADDED;
  73.    spp = stack;
  74.    *spp++ = sp;
  75.    /*
  76.     * From state 0, which is now stacked, all further DFA
  77.     * states will be derived.
  78.     */
  79.    while (spp > stack)
  80.       {
  81.       sp = *--spp;
  82.       for (a = 0; a < NCHARS; a++)
  83.          insets[a] = 0;
  84.       xse = sets;
  85.       for (i = 0; i < sp->s_len; i++)
  86.          xse = addset(sp->s_els[i], xse);
  87.       state = newdfa();
  88.       sp->s_state = state;
  89.       state->df_name = sp;
  90. #ifdef DEBUG
  91.       if (lldebug)
  92.          {
  93.          fprintf(lexlog, "build state %d ", state-dfa);
  94.          pset(sp, 1);
  95.          fprintf(lexlog, "\n");
  96.          }
  97. #endif
  98.       state->df_ntrans = xse-sets;
  99.       for (xs = sets; xs < xse; xs++)
  100.          {
  101.          a = xs->x_char&0377;
  102.          tp = temp;
  103.          for (i = 0; i < sp->s_len; i++)
  104.             if ((np = sp->s_els[i])->n_char==a ||
  105.                 np->n_char==CCL &&
  106.                 np->n_ccl[a/NBPC]&(1<<(a%NBPC)))
  107.                add(temp, &tp, np->n_succ[0]);
  108.          xp = newset(temp, tp-temp, 1);
  109.          xp = eclosure(xp);
  110. #ifdef DEBUG
  111.          if (lldebug)
  112.             {
  113.             putc('\t', lexlog);
  114.             chprint(a);
  115.             putc('\t', lexlog);
  116.             pset(xp, 1);
  117.             fprintf(lexlog, "\n");
  118.             }
  119. #endif
  120.          xs->x_set = xp;
  121.          if (xp->s_state==0 && (xp->s_flag&ADDED)==0)
  122.             {
  123.             xp->s_flag |= ADDED;
  124.             if (spp >= stack+MAXDFA)
  125.                {
  126.                error("dfabuild: stack overflow");
  127.  
  128.                exit(1);
  129.                }
  130.             *spp++ = xp;
  131.             }
  132.          }
  133.       state->df_default = defalt(state, &xse);
  134.       setbase(state, stbase(xse), xse);
  135.       }
  136.    }
  137.  
  138. /*
  139.  * If an nfa state is not already a member of the vector `base', add it.
  140.  */
  141. add(base, tpp, np)
  142. struct nfa ***tpp, **base, *np;
  143.    {
  144.    register struct nfa **tp;
  145.  
  146.    for (tp = base; tp < *tpp; tp++)
  147.       if (*tp == np)
  148.          return;
  149.    *(*tpp)++ = np;
  150.    }
  151.  
  152. /*
  153.  * Add the character(s) on which state `np' branches to the transition vector.
  154.  */
  155. addset(np, xse)
  156. register struct nfa *np;
  157. struct xset *xse;
  158.    {
  159.    register a;
  160.    register char *ccl;
  161.  
  162.    if ((a = np->n_char) < NCHARS)
  163.       xse = addxset(a, xse);
  164.    if (a != CCL)
  165.       return(xse);
  166.    ccl = np->n_ccl;
  167.    for (a = 0; a < NCHARS; a++)
  168.       if (ccl[a/NBPC]&(1<<(a%NBPC)))
  169.          xse = addxset(a, xse);
  170.    return(xse);
  171.    }
  172.  
  173. /*
  174.  * Add a character to the transition vector, if it isn't there already.
  175.  */
  176. addxset(a, xse)
  177. register a;
  178. struct xset *xse;
  179.    {
  180.    register struct xset *xs;
  181.    register int temp;
  182.    /*
  183.    * VMS native doesn't do this correctly:
  184.    *    if (insets[a]++)
  185.    */
  186.    temp = insets[a];
  187.    insets[a] += 1;
  188.    if (temp)
  189.       return(xse);
  190.    xs = xse++;
  191.    xs->x_char = a;
  192.    xs->x_set = NULL;
  193.    xs->x_defsame = 0;
  194.    return(xse);
  195.    }
  196.