home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / OS2_LEX.ZIP / DFA.C < prev    next >
C/C++ Source or Header  |  1989-10-07  |  5KB  |  191 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 <stdlib.h>
  23. #include <stdio.h>
  24. #include "lexlex.h"
  25. #include "lextern.h"
  26.  
  27. struct xset *addxset(int, struct xset *);
  28. struct xset *addset(struct nfa *, struct xset *);
  29. void add(struct nfa **, struct nfa ***, struct nfa *);
  30.  
  31. /*
  32.  * Build the DFA from the NFA
  33.  */
  34. void dfabuild(void)
  35.    {
  36.    struct trans *trp;
  37.    struct nfa **vec, **tp, *np, *temp[MAXNFA+1];
  38.    int a, i;
  39.    struct set *sp, *stack[MAXDFA], **spp, *xp;  /* DFA set stack */
  40.    struct dfa *state;                  /* --> current DFA state */
  41.    struct xset *xs, *xse;
  42.  
  43.   /*
  44.    * Simulate an epsilon transition from nfa state 0 to
  45.    * the initial states of the machines for each
  46.    * translation.
  47.    */
  48.    nfa[0].n_char = EPSILON;            /* Set NFA state 0 transition EPSILON */
  49.    /*
  50.     * Allocate a state vector, each node of which will
  51.     * point to an NFA starting state.  Each translation
  52.     * generates an NFA, so the number of translations
  53.     * equals the number of NFA start states.
  54.     */
  55.    vec = (struct nfa **)lalloc(i = (transp-trans)+1, sizeof(*vec), "dfabuild");
  56.    /*
  57.     * Fill in the start state vector
  58.     */
  59.    vec[0] = nfa;                       /* vec[0] always --> NFA state 0 */
  60.    for (a = 1, trp = trans; trp < transp; trp++)  /* For each translation */
  61.       vec[a++] = trp->t_start;         /* Pick up the NFA start state */
  62.    /*
  63.     * Now build the set sp --> e-CLOSURE(vec)
  64.     */
  65.    sp = eclosure(newset(vec, i, 1));
  66.    free(vec);                          /* Deallocate the start state vector */
  67.  
  68.    /*
  69.     * At this point state 0 of the DFA is constructed.
  70.     * This is the start state of the DFA.
  71.     * Mark it "added" and push it on to the stack.
  72.     */
  73.    sp->s_flag |= ADDED;
  74.    spp = stack;
  75.    *spp++ = sp;
  76.    /*
  77.     * From state 0, which is now stacked, all further DFA
  78.     * states will be derived.
  79.     */
  80.    while (spp > stack)
  81.       {
  82.       sp = *--spp;
  83.       for (a = 0; a < NCHARS; a++)
  84.          insets[a] = 0;
  85.       xse = sets;
  86.       for (i = 0; i < sp->s_len; i++)
  87.          xse = addset(sp->s_els[i], xse);
  88.       state = newdfa();
  89.       sp->s_state = state;
  90.       state->df_name = sp;
  91. #ifdef DEBUG
  92.       if (lldebug)
  93.          {
  94.          fprintf(lexlog, "build state %d ", state-dfa);
  95.          pset(sp, 1);
  96.          fprintf(lexlog, "\n");
  97.          }
  98. #endif
  99.       state->df_ntrans = xse-sets;
  100.       for (xs = sets; xs < xse; xs++)
  101.          {
  102.          a = xs->x_char&0377;
  103.          tp = temp;
  104.          for (i = 0; i < sp->s_len; i++)
  105.             if ((np = sp->s_els[i])->n_char==a ||
  106.                 np->n_char==CCL &&
  107.                 np->n_ccl[a/NBPC]&(1<<(a%NBPC)))
  108.                add(temp, &tp, np->n_succ[0]);
  109.          xp = newset(temp, tp-temp, 1);
  110.          xp = eclosure(xp);
  111. #ifdef DEBUG
  112.          if (lldebug)
  113.             {
  114.             putc('\t', lexlog);
  115.             chprint(a);
  116.             putc('\t', lexlog);
  117.             pset(xp, 1);
  118.             fprintf(lexlog, "\n");
  119.             }
  120. #endif
  121.          xs->x_set = xp;
  122.          if (xp->s_state==0 && (xp->s_flag&ADDED)==0)
  123.             {
  124.             xp->s_flag |= ADDED;
  125.             if (spp >= stack+MAXDFA)
  126.                {
  127.                error("dfabuild: stack overflow");
  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. void add(struct nfa **base, struct nfa ***tpp, struct nfa *np)
  142.    {
  143.    register struct nfa **tp;
  144.  
  145.    for (tp = base; tp < *tpp; tp++)
  146.       if (*tp == np)
  147.          return;
  148.    *(*tpp)++ = np;
  149.    }
  150.  
  151. /*
  152.  * Add the character(s) on which state `np' branches to the transition vector.
  153.  */
  154. struct xset *addset(struct nfa *np, struct xset *xse)
  155.    {
  156.    register a;
  157.    register char *ccl;
  158.  
  159.    if ((a = np->n_char) < NCHARS)
  160.       xse = addxset(a, xse);
  161.    if (a != CCL)
  162.       return(xse);
  163.    ccl = np->n_ccl;
  164.    for (a = 0; a < NCHARS; a++)
  165.       if (ccl[a/NBPC]&(1<<(a%NBPC)))
  166.          xse = addxset(a, xse);
  167.    return(xse);
  168.    }
  169.  
  170. /*
  171.  * Add a character to the transition vector, if it isn't there already.
  172.  */
  173. struct xset *addxset(int a, struct xset *xse)
  174.    {
  175.    register struct xset *xs;
  176.    register int temp;
  177.    /*
  178.    * VMS native doesn't do this correctly:
  179.    *    if (insets[a]++)
  180.    */
  181.    temp = insets[a];
  182.    insets[a] += 1;
  183.    if (temp)
  184.       return(xse);
  185.    xs = xse++;
  186.    xs->x_char = a;
  187.    xs->x_set = NULL;
  188.    xs->x_defsame = 0;
  189.    return(xse);
  190.    }
  191.