home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / progrmng / flextc.sit / dfa.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-01-03  |  22.0 KB  |  978 lines  |  [TEXT/KAHL]

  1. /* dfa - DFA construction routines */
  2.  
  3. /*
  4.  * Copyright (c) 1989 The Regents of the University of California.
  5.  * All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * Vern Paxson.
  9.  *
  10.  * The United States Government has rights in this work pursuant to
  11.  * contract no. DE-AC03-76SF00098 between the United States Department of
  12.  * Energy and the University of California.
  13.  *
  14.  * Redistribution and use in source and binary forms are permitted
  15.  * provided that the above copyright notice and this paragraph are
  16.  * duplicated in all such forms and that any documentation,
  17.  * advertising materials, and other materials related to such
  18.  * distribution and use acknowledge that the software was developed
  19.  * by the University of California, Berkeley.  The name of the
  20.  * University may not be used to endorse or promote products derived
  21.  * from this software without specific prior written permission.
  22.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  23.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  24.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  25.  */
  26.  
  27. #ifndef lint
  28.  
  29. static char copyright[] =
  30. "@(#) Copyright (c) 1989 The Regents of the University of California.\n";
  31. static char CR_continuation[] = "@(#) All rights reserved.\n";
  32.  
  33. static char rcsid[] =
  34. "@(#) $Header: dfa.c,v 2.0 89/06/20 15:49:30 vern Locked $ (LBL)";
  35.  
  36. #endif
  37.  
  38. #include "flexdef.h"
  39. #ifdef THINK_C
  40. #include <stdlib.h>
  41. #endif
  42.  
  43.  
  44. /* check_for_backtracking - check a DFA state for backtracking
  45.  *
  46.  * synopsis
  47.  *       int ds, state[numecs];
  48.  *       check_for_backtracking( ds, state );
  49.  *
  50.  * ds is the number of the state to check and state[] is its out-transitions,
  51.  * indexed by equivalence class, and state_rules[] is the set of rules
  52.  * associated with this state
  53.  */
  54.  
  55. check_for_backtracking( ds, state )
  56. int ds;
  57. int state[];
  58.  
  59. {
  60.     if ( (reject && ! dfaacc[ds].dfaacc_set) || ! dfaacc[ds].dfaacc_state )
  61.     { /* state is non-accepting */
  62.         ++num_backtracking;
  63.  
  64.         if ( backtrack_report )
  65.         {
  66.             fprintf( backtrack_file, "State #%d is non-accepting -\n", ds );
  67.  
  68.             /* identify the state */
  69.             dump_associated_rules( backtrack_file, ds );
  70.  
  71.             /* now identify it further using the out- and jam-transitions */
  72.             dump_transitions( backtrack_file, state );
  73.  
  74.             putc( '\n', backtrack_file );
  75.         }
  76.     }
  77. }
  78.  
  79.  
  80. /* check_trailing_context - check to see if NFA state set constitutes
  81.  *                            "dangerous" trailing context
  82.  *
  83.  * synopsis
  84.  *      int nfa_states[num_states+1], num_states;
  85.  *      int accset[nacc+1], nacc;
  86.  *      int check_trailing_context();
  87.  *      true/false = check_trailing_context( nfa_states, num_states,
  88.  *                                           accset, nacc );
  89.  *
  90.  * NOTES
  91.  *      Trailing context is "dangerous" if both the head and the trailing
  92.  *    part are of variable size \and/ there's a DFA state which contains
  93.  *    both an accepting state for the head part of the rule and NFA states
  94.  *    which occur after the beginning of the trailing context.
  95.  *    When such a rule is matched, it's impossible to tell if having been
  96.  *    in the DFA state indicates the beginning of the trailing context
  97.  *    or further-along scanning of the pattern.  In these cases, a warning
  98.  *    message is issued.
  99.  *
  100.  *      nfa_states[1 .. num_states] is the list of NFA states in the DFA.
  101.  *      accset[1 .. nacc] is the list of accepting numbers for the DFA state.
  102.  */
  103.  
  104. int check_trailing_context( nfa_states, num_states, accset, nacc )
  105. int *nfa_states, num_states;
  106. int *accset;
  107. register int nacc;
  108.  
  109. {
  110.     register int i, j;
  111.  
  112.     for ( i = 1; i <= num_states; ++i )
  113.     {
  114.         int ns = nfa_states[i];
  115.         register int type = state_type[ns];
  116.         register int ar = assoc_rule[ns];
  117.  
  118.         if ( type == STATE_NORMAL || rule_type[ar] != RULE_VARIABLE )
  119.         { /* do nothing */
  120.         }
  121.  
  122.         else
  123.             if ( type == STATE_TRAILING_CONTEXT )
  124.             {
  125.                 /* potential trouble.  Scan set of accepting numbers for
  126.                  * the one marking the end of the "head".  We assume that
  127.                  * this looping will be fairly cheap since it's rare that
  128.                  * an accepting number set is large.
  129.                  */
  130.                 for ( j = 1; j <= nacc; ++j )
  131.                     if ( accset[j] & YY_TRAILING_HEAD_MASK )
  132.                     {
  133.                         fprintf( stderr,
  134.                         "flex: Dangerous trailing context in rule at line %d\n",
  135.                         rule_linenum[ar] );
  136.                         return;
  137.                     }
  138.             }
  139.     }
  140. }
  141.  
  142.  
  143. /* dump_associated_rules - list the rules associated with a DFA state
  144.  *
  145.  * synopisis
  146.  *       int ds;
  147.  *       FILE *file;
  148.  *       dump_associated_rules( file, ds );
  149.  *
  150.  * goes through the set of NFA states associated with the DFA and
  151.  * extracts the first MAX_ASSOC_RULES unique rules, sorts them,
  152.  * and writes a report to the given file
  153.  */
  154.  
  155. dump_associated_rules( file, ds )
  156. FILE *file;
  157. int ds;
  158.  
  159. {
  160.     register int i, j;
  161.     register int num_associated_rules = 0;
  162.     int rule_set[MAX_ASSOC_RULES + 1];
  163.     int *dset = dss[ds];
  164.     int size = dfasiz[ds];
  165.  
  166.     for ( i = 1; i <= size; ++i )
  167.     {
  168.         register rule_num = rule_linenum[assoc_rule[dset[i]]];
  169.  
  170.         for ( j = 1; j <= num_associated_rules; ++j )
  171.             if ( rule_num == rule_set[j] )
  172.                 break;
  173.  
  174.         if ( j > num_associated_rules )
  175.         { /* new rule */
  176.             if ( num_associated_rules < MAX_ASSOC_RULES )
  177.                 rule_set[++num_associated_rules] = rule_num;
  178.         }
  179.     }
  180.  
  181.     bubble( rule_set, num_associated_rules );
  182.  
  183.     fprintf( file, " associated rules:" );
  184.  
  185.     for ( i = 1; i <= num_associated_rules; ++i )
  186.     {
  187.         if ( i % 8 == 1 )
  188.             putc( '\n', file );
  189.  
  190.         fprintf( file, "\t%d", rule_set[i] );
  191.     }
  192.  
  193.     putc( '\n', file );
  194. }
  195.  
  196.  
  197. /* dump_transitions - list the transitions associated with a DFA state
  198.  *
  199.  * synopisis
  200.  *       int state[numecs];
  201.  *       FILE *file;
  202.  *       dump_transitions( file, state );
  203.  *
  204.  * goes through the set of out-transitions and lists them in human-readable
  205.  * form (i.e., not as equivalence classes); also lists jam transitions
  206.  * (i.e., all those which are not out-transitions, plus EOF).  The dump
  207.  * is done to the given file.
  208.  */
  209.  
  210. dump_transitions( file, state )
  211. FILE *file;
  212. int state[];
  213.  
  214. {
  215.     register int i, ec;
  216.     int out_char_set[CSIZE + 1];
  217.  
  218.     for ( i = 1; i <= CSIZE; ++i )
  219.     {
  220.         ec = ecgroup[i];
  221.  
  222.         if ( ec < 0 )
  223.             ec = -ec;
  224.  
  225.         out_char_set[i] = state[ec];
  226.     }
  227.  
  228.     fprintf( file, " out-transitions: " );
  229.  
  230.     list_character_set( file, out_char_set );
  231.  
  232.     /* now invert the members of the set to get the jam transitions */
  233.     for ( i = 1; i <= CSIZE; ++i )
  234.         out_char_set[i] = ! out_char_set[i];
  235.  
  236.     fprintf( file, "\n jam-transitions: EOF " );
  237.  
  238.     list_character_set( file, out_char_set );
  239.  
  240.     putc( '\n', file );
  241. }
  242.  
  243.  
  244. /* epsclosure - construct the epsilon closure of a set of ndfa states
  245.  *
  246.  * synopsis
  247.  *      int t[current_max_dfa_size], numstates, accset[num_rules + 1], nacc;
  248.  *      int hashval;
  249.  *      int *epsclosure();
  250.  *      t = epsclosure( t, &numstates, accset, &nacc, &hashval );
  251.  *
  252.  * NOTES
  253.  *      the epsilon closure is the set of all states reachable by an arbitrary
  254.  *    number of epsilon transitions which themselves do not have epsilon
  255.  *    transitions going out, unioned with the set of states which have non-null
  256.  *    accepting numbers.    t is an array of size numstates of nfa state numbers.
  257.  *    Upon return, t holds the epsilon closure and numstates is updated.    accset
  258.  *    holds a list of the accepting numbers, and the size of accset is given
  259.  *    by nacc.  t may be subjected to reallocation if it is not large enough
  260.  *    to hold the epsilon closure.
  261.  *
  262.  *      hashval is the hash value for the dfa corresponding to the state set
  263.  */
  264.  
  265. int *epsclosure( t, ns_addr, accset, nacc_addr, hv_addr )
  266. int *t, *ns_addr, accset[], *nacc_addr, *hv_addr;
  267.  
  268. {
  269.     register int stkpos, ns, tsp;
  270.     int numstates = *ns_addr, nacc, hashval, transsym, nfaccnum;
  271.     int stkend, nstate;
  272.     static int did_stk_init = false, *stk;
  273.  
  274. #define MARK_STATE(state) \
  275.     trans1[state] = trans1[state] - MARKER_DIFFERENCE;
  276.  
  277. #define IS_MARKED(state) (trans1[state] < 0)
  278.  
  279. #define UNMARK_STATE(state) \
  280.     trans1[state] = trans1[state] + MARKER_DIFFERENCE;
  281.  
  282. #define CHECK_ACCEPT(state) \
  283.     {    \
  284.     nfaccnum = accptnum[state];    \
  285.     if ( nfaccnum != NIL ) \
  286.         accset[++nacc] = nfaccnum;    \
  287.         }
  288.  
  289. #define DO_REALLOCATION \
  290.     {    \
  291.     current_max_dfa_size += MAX_DFA_SIZE_INCREMENT;    \
  292.     ++num_reallocs;    \
  293.     t = reallocate_integer_array( t, current_max_dfa_size );    \
  294.     stk = reallocate_integer_array( stk, current_max_dfa_size );    \
  295.         }
  296.  
  297. #define PUT_ON_STACK(state) \
  298.     {    \
  299.     if ( ++stkend >= current_max_dfa_size ) \
  300.         DO_REALLOCATION \
  301.     stk[stkend] = state;    \
  302.     MARK_STATE(state) \
  303.         }
  304.  
  305. #define ADD_STATE(state) \
  306.     {    \
  307.     if ( ++numstates >= current_max_dfa_size ) \
  308.         DO_REALLOCATION \
  309.     t[numstates] = state;    \
  310.     hashval = hashval + state;    \
  311.         }
  312.  
  313. #define STACK_STATE(state) \
  314.     {    \
  315.     PUT_ON_STACK(state) \
  316.     CHECK_ACCEPT(state) \
  317.     if ( nfaccnum != NIL || transchar[state] != SYM_EPSILON ) \
  318.         ADD_STATE(state) \
  319.         }
  320.  
  321.     if ( ! did_stk_init )
  322.     {
  323.         stk = allocate_integer_array( current_max_dfa_size );
  324.         did_stk_init = true;
  325.     }
  326.  
  327.     nacc = stkend = hashval = 0;
  328.  
  329.     for ( nstate = 1; nstate <= numstates; ++nstate )
  330.     {
  331.         ns = t[nstate];
  332.  
  333.         /* the state could be marked if we've already pushed it onto
  334.          * the stack
  335.          */
  336.         if ( ! IS_MARKED(ns) )
  337.             PUT_ON_STACK(ns)
  338.                 CHECK_ACCEPT(ns)
  339.                     hashval = hashval + ns;
  340.             }
  341.  
  342.             for ( stkpos = 1; stkpos <= stkend; ++stkpos )
  343.             {
  344.                 ns = stk[stkpos];
  345.                 transsym = transchar[ns];
  346.  
  347.                 if ( transsym == SYM_EPSILON )
  348.                 {
  349.                     tsp = trans1[ns] + MARKER_DIFFERENCE;
  350.  
  351.                     if ( tsp != NO_TRANSITION )
  352.                     {
  353.                         if ( ! IS_MARKED(tsp) )
  354.                             STACK_STATE(tsp)
  355.                                 tsp = trans2[ns];
  356.  
  357.                             if ( tsp != NO_TRANSITION )
  358.                                 if ( ! IS_MARKED(tsp) )
  359.                                     STACK_STATE(tsp)
  360.                                     }
  361.                                 }
  362.                             }
  363.  
  364.                             /* clear out "visit" markers */
  365.  
  366.                             for ( stkpos = 1; stkpos <= stkend; ++stkpos )
  367.                             {
  368.                                 if ( IS_MARKED(stk[stkpos]) )
  369.                                 {
  370.                                     UNMARK_STATE(stk[stkpos])
  371.                                     }
  372.                                     else
  373.                                         flexfatal( "consistency check failed in epsclosure()" );
  374.                             }
  375.  
  376.                             *ns_addr = numstates;
  377.                             *hv_addr = hashval;
  378.                             *nacc_addr = nacc;
  379.  
  380.                             return ( t );
  381.                         }
  382.  
  383.  
  384. /* increase_max_dfas - increase the maximum number of DFAs */
  385.  
  386. increase_max_dfas()
  387.  
  388. {
  389.     current_max_dfas += MAX_DFAS_INCREMENT;
  390.  
  391.     ++num_reallocs;
  392.  
  393.     base = reallocate_integer_array( base, current_max_dfas );
  394.     def = reallocate_integer_array( def, current_max_dfas );
  395.     dfasiz = reallocate_integer_array( dfasiz, current_max_dfas );
  396.     accsiz = reallocate_integer_array( accsiz, current_max_dfas );
  397.     dhash = reallocate_integer_array( dhash, current_max_dfas );
  398.     dss = reallocate_int_ptr_array( dss, current_max_dfas );
  399.     dfaacc = reallocate_dfaacc_union( dfaacc, current_max_dfas );
  400. }
  401.  
  402.  
  403. /* ntod - convert an ndfa to a dfa
  404.  *
  405.  * synopsis
  406.  *      ntod();
  407.  *
  408.  *    creates the dfa corresponding to the ndfa we've constructed.  the
  409.  *    dfa starts out in state #1.
  410.  */
  411. ntod()
  412.  
  413. {
  414.     int *accset, ds, nacc, newds;
  415.     int duplist[CSIZE + 1], sym, hashval, numstates, dsize;
  416.     int targfreq[CSIZE + 1], targstate[CSIZE + 1], state[CSIZE + 1];
  417.     int *nset, *dset;
  418.     int targptr, totaltrans, i, comstate, comfreq, targ;
  419.     int *epsclosure(), snstods(), symlist[CSIZE + 1];
  420.     int num_start_states;
  421.     int todo_head, todo_next;
  422.  
  423.     /* this is so find_table_space(...) will know where to start looking in
  424.      * chk/nxt for unused records for space to put in the state
  425.      */
  426.     if ( fullspd )
  427.         firstfree = 0;
  428.  
  429.     accset = allocate_integer_array( num_rules + 1 );
  430.     nset = allocate_integer_array( current_max_dfa_size );
  431.  
  432.     /* the "todo" queue is represented by the head, which is the DFA
  433.      * state currently being processed, and the "next", which is the
  434.      * next DFA state number available (not in use).  We depend on the
  435.      * fact that snstods() returns DFA's \in increasing order/, and thus
  436.      * need only know the bounds of the dfas to be processed.
  437.      */
  438.     todo_head = todo_next = 0;
  439.  
  440.     for ( i = 0; i <= CSIZE; ++i )
  441.     {
  442.         duplist[i] = NIL;
  443.         symlist[i] = false;
  444.     }
  445.  
  446.     for ( i = 0; i <= num_rules; ++i )
  447.         accset[i] = NIL;
  448.  
  449.     if ( trace )
  450.     {
  451.         dumpnfa( scset[1] );
  452.         fputs( "\n\nDFA Dump:\n\n", stderr );
  453.     }
  454.  
  455.     inittbl();
  456.  
  457.     if ( fullspd )
  458.     {
  459.         for ( i = 0; i <= numecs; ++i )
  460.             state[i] = 0;
  461.         place_state( state, 0, 0 );
  462.     }
  463.  
  464.     if ( fulltbl )
  465.     {
  466.         /* declare it "short" because it's a real long-shot that that
  467.          * won't be large enough
  468.          */
  469.         printf( "static short int %s[][%d] =\n    {\n", NEXTARRAY,
  470.         numecs + 1 ); /* '}' so vi doesn't get too confused */
  471.  
  472.         /* generate 0 entries for state #0 */
  473.         for ( i = 0; i <= numecs; ++i )
  474.             mk2data( 0 );
  475.  
  476.         /* force ',' and dataflush() next call to mk2data */
  477.         datapos = NUMDATAITEMS;
  478.  
  479.         /* force extra blank line next dataflush() */
  480.         dataline = NUMDATALINES;
  481.     }
  482.  
  483.     /* create the first states */
  484.  
  485.     num_start_states = lastsc * 2;
  486.  
  487.     for ( i = 1; i <= num_start_states; ++i )
  488.     {
  489.         numstates = 1;
  490.  
  491.         /* for each start condition, make one state for the case when
  492.          * we're at the beginning of the line (the '%' operator) and
  493.          * one for the case when we're not
  494.          */
  495.         if ( i % 2 == 1 )
  496.             nset[numstates] = scset[(i / 2) + 1];
  497.         else
  498.             nset[numstates] = mkbranch( scbol[i / 2], scset[i / 2] );
  499.  
  500.         nset = epsclosure( nset, &numstates, accset, &nacc, &hashval );
  501.  
  502.         if ( snstods( nset, numstates, accset, nacc, hashval, &ds ) )
  503.         {
  504.             numas += nacc;
  505.             totnst += numstates;
  506.             ++todo_next;
  507.  
  508.             if ( variable_trailing_context_rules && nacc > 0 )
  509.                 check_trailing_context( nset, numstates, accset, nacc );
  510.         }
  511.     }
  512.  
  513.     if ( ! fullspd )
  514.     {
  515.         if ( ! snstods( nset, 0, accset, 0, 0, &end_of_buffer_state ) )
  516.             flexfatal( "could not create unique end-of-buffer state" );
  517.  
  518.         ++numas;
  519.         ++num_start_states;
  520.         ++todo_next;
  521.     }
  522.  
  523.     while ( todo_head < todo_next )
  524.     {
  525.         targptr = 0;
  526.         totaltrans = 0;
  527.  
  528.         for ( i = 1; i <= numecs; ++i )
  529.             state[i] = 0;
  530.  
  531.         ds = ++todo_head;
  532.  
  533.         dset = dss[ds];
  534.         dsize = dfasiz[ds];
  535.  
  536.         if ( trace )
  537.             fprintf( stderr, "state # %d:\n", ds );
  538.  
  539.         sympartition( dset, dsize, symlist, duplist );
  540.  
  541.         for ( sym = 1; sym <= numecs; ++sym )
  542.         {
  543.             if ( symlist[sym] )
  544.             {
  545.                 symlist[sym] = 0;
  546.  
  547.                 if ( duplist[sym] == NIL )
  548.                 { /* symbol has unique out-transitions */
  549.                     numstates = symfollowset( dset, dsize, sym, nset );
  550.                     nset = epsclosure( nset, &numstates, accset,
  551.                     &nacc, &hashval );
  552.  
  553.                     if ( snstods( nset, numstates, accset,
  554.                     nacc, hashval, &newds ) )
  555.                     {
  556.                         totnst = totnst + numstates;
  557.                         ++todo_next;
  558.                         numas += nacc;
  559.  
  560.                         if ( variable_trailing_context_rules && nacc > 0 )
  561.                             check_trailing_context( nset, numstates,
  562.                             accset, nacc );
  563.                     }
  564.  
  565.                     state[sym] = newds;
  566.  
  567.                     if ( trace )
  568.                         fprintf( stderr, "\t%d\t%d\n", sym, newds );
  569.  
  570.                     targfreq[++targptr] = 1;
  571.                     targstate[targptr] = newds;
  572.                     ++numuniq;
  573.                 }
  574.  
  575.                 else
  576.                 {
  577.                     /* sym's equivalence class has the same transitions
  578.                      * as duplist(sym)'s equivalence class
  579.                      */
  580.                     targ = state[duplist[sym]];
  581.                     state[sym] = targ;
  582.  
  583.                     if ( trace )
  584.                         fprintf( stderr, "\t%d\t%d\n", sym, targ );
  585.  
  586.                     /* update frequency count for destination state */
  587.  
  588.                     i = 0;
  589.                     while ( targstate[++i] != targ );
  590.  
  591.                     ++targfreq[i];
  592.                     ++numdup;
  593.                 }
  594.  
  595.                 ++totaltrans;
  596.                 duplist[sym] = NIL;
  597.             }
  598.         }
  599.  
  600.         numsnpairs = numsnpairs + totaltrans;
  601.  
  602.         if ( caseins && ! useecs )
  603.         {
  604.             register int j;
  605.  
  606.             for ( i = 'A', j = 'a'; i <= 'Z'; ++i, ++j )
  607.                 state[i] = state[j];
  608.         }
  609.  
  610.         if ( ds > num_start_states )
  611.             check_for_backtracking( ds, state );
  612.  
  613.         if ( fulltbl )
  614.         {
  615.             /* supply array's 0-element */
  616.             if ( ds == end_of_buffer_state )
  617.                 mk2data( -end_of_buffer_state );
  618.             else
  619.                 mk2data( end_of_buffer_state );
  620.  
  621.             for ( i = 1; i <= numecs; ++i )        /* jams are marked by negative of state number */
  622.                 mk2data( state[i] ? state[i] : -ds );
  623.  
  624.             /* force ',' and dataflush() next call to mk2data */
  625.             datapos = NUMDATAITEMS;
  626.  
  627.             /* force extra blank line next dataflush() */
  628.             dataline = NUMDATALINES;
  629.         }
  630.  
  631.         else
  632.             if ( fullspd )
  633.                 place_state( state, ds, totaltrans );
  634.  
  635.         else
  636.             if ( ds == end_of_buffer_state )        /* special case this state to make sure it does what it's
  637.              * supposed to, i.e., jam on end-of-buffer
  638.              */
  639.                 stack1( ds, 0, 0, JAMSTATE );
  640.  
  641.         else /* normal, compressed state */
  642.         {
  643.             /* determine which destination state is the most common, and
  644.              * how many transitions to it there are
  645.              */
  646.  
  647.             comfreq = 0;
  648.             comstate = 0;
  649.  
  650.             for ( i = 1; i <= targptr; ++i )
  651.                 if ( targfreq[i] > comfreq )
  652.                 {
  653.                     comfreq = targfreq[i];
  654.                     comstate = targstate[i];
  655.                 }
  656.  
  657.             bldtbl( state, ds, totaltrans, comstate, comfreq );
  658.         }
  659.     }
  660.  
  661.     if ( fulltbl )
  662.         dataend();
  663.  
  664.     else
  665.         if ( ! fullspd )
  666.         {
  667.             cmptmps();    /* create compressed template entries */
  668.  
  669.             /* create tables for all the states with only one out-transition */
  670.             while ( onesp > 0 )
  671.             {
  672.                 mk1tbl( onestate[onesp], onesym[onesp], onenext[onesp],
  673.                 onedef[onesp] );
  674.                 --onesp;
  675.             }
  676.  
  677.             mkdeftbl();
  678.         }
  679. }
  680.  
  681.  
  682. /* snstods - converts a set of ndfa states into a dfa state
  683.  *
  684.  * synopsis
  685.  *      int sns[numstates], numstates, newds, accset[num_rules + 1], nacc, hashval;
  686.  *      int snstods();
  687.  *      is_new_state = snstods( sns, numstates, accset, nacc, hashval, &newds );
  688.  *
  689.  * on return, the dfa state number is in newds.
  690.  */
  691.  
  692. int snstods( sns, numstates, accset, nacc, hashval, newds_addr )
  693. int sns[], numstates, accset[], nacc, hashval, *newds_addr;
  694.  
  695. {
  696.     int didsort = 0;
  697.     register int i, j;
  698.     int newds, *oldsns;
  699. #ifndef THINK_C
  700.     char *malloc();
  701. #endif
  702.  
  703.     for ( i = 1; i <= lastdfa; ++i )
  704.         if ( hashval == dhash[i] )
  705.         {
  706.             if ( numstates == dfasiz[i] )
  707.             {
  708.                 oldsns = dss[i];
  709.  
  710.                 if ( ! didsort )
  711.                 {
  712.                     /* we sort the states in sns so we can compare it to
  713.                      * oldsns quickly.    we use bubble because there probably
  714.                      * aren't very many states
  715.                      */
  716.                     bubble( sns, numstates );
  717.                     didsort = 1;
  718.                 }
  719.  
  720.                 for ( j = 1; j <= numstates; ++j )
  721.                     if ( sns[j] != oldsns[j] )
  722.                         break;
  723.  
  724.                 if ( j > numstates )
  725.                 {
  726.                     ++dfaeql;
  727.                     *newds_addr = i;
  728.                     return ( 0 );
  729.                 }
  730.  
  731.                 ++hshcol;
  732.             }
  733.  
  734.             else
  735.                 ++hshsave;
  736.         }
  737.  
  738.     /* make a new dfa */
  739.  
  740.     if ( ++lastdfa >= current_max_dfas )
  741.         increase_max_dfas();
  742.  
  743.     newds = lastdfa;
  744.  
  745.     dss[newds] = (int *) malloc( (unsigned) ((numstates + 1) * sizeof( int )) );
  746.  
  747.     if ( ! dss[newds] )
  748.         flexfatal( "dynamic memory failure in snstods()" );
  749.  
  750.     /* if we haven't already sorted the states in sns, we do so now, so that
  751.      * future comparisons with it can be made quickly
  752.      */
  753.  
  754.     if ( ! didsort )
  755.         bubble( sns, numstates );
  756.  
  757.     for ( i = 1; i <= numstates; ++i )
  758.         dss[newds][i] = sns[i];
  759.  
  760.     dfasiz[newds] = numstates;
  761.     dhash[newds] = hashval;
  762.  
  763.     if ( nacc == 0 )
  764.     {
  765.         if ( reject )
  766.             dfaacc[newds].dfaacc_set = (int *) 0;
  767.         else
  768.             dfaacc[newds].dfaacc_state = 0;
  769.  
  770.         accsiz[newds] = 0;
  771.     }
  772.  
  773.     else
  774.         if ( reject )
  775.         {
  776.             /* we sort the accepting set in increasing order so the disambiguating
  777.              * rule that the first rule listed is considered match in the event of
  778.              * ties will work.    We use a bubble sort since the list is probably
  779.              * quite small.
  780.              */
  781.  
  782.             bubble( accset, nacc );
  783.  
  784.             dfaacc[newds].dfaacc_set =
  785.                 (int *) malloc( (unsigned) ((nacc + 1) * sizeof( int )) );
  786.  
  787.             if ( ! dfaacc[newds].dfaacc_set )
  788.                 flexfatal( "dynamic memory failure in snstods()" );
  789.  
  790.             /* save the accepting set for later */
  791.             for ( i = 1; i <= nacc; ++i )
  792.                 dfaacc[newds].dfaacc_set[i] = accset[i];
  793.  
  794.             accsiz[newds] = nacc;
  795.         }
  796.  
  797.     else
  798.     { /* find lowest numbered rule so the disambiguating rule will work */
  799.         j = num_rules + 1;
  800.  
  801.         for ( i = 1; i <= nacc; ++i )
  802.             if ( accset[i] < j )
  803.                 j = accset[i];
  804.  
  805.         dfaacc[newds].dfaacc_state = j;
  806.     }
  807.  
  808.     *newds_addr = newds;
  809.  
  810.     return ( 1 );
  811. }
  812.  
  813.  
  814. /* symfollowset - follow the symbol transitions one step
  815.  *
  816.  * synopsis
  817.  *      int ds[current_max_dfa_size], dsize, transsym;
  818.  *      int nset[current_max_dfa_size], numstates;
  819.  *      numstates = symfollowset( ds, dsize, transsym, nset );
  820.  */
  821.  
  822. int symfollowset( ds, dsize, transsym, nset )
  823. int ds[], dsize, transsym, nset[];
  824.  
  825. {
  826.     int ns, tsp, sym, i, j, lenccl, ch, numstates;
  827.     int ccllist;
  828.  
  829.     numstates = 0;
  830.  
  831.     for ( i = 1; i <= dsize; ++i )
  832.     { /* for each nfa state ns in the state set of ds */
  833.         ns = ds[i];
  834.         sym = transchar[ns];
  835.         tsp = trans1[ns];
  836.  
  837.         if ( sym < 0 )
  838.         { /* it's a character class */
  839.             sym = -sym;
  840.             ccllist = cclmap[sym];
  841.             lenccl = ccllen[sym];
  842.  
  843.             if ( cclng[sym] )
  844.             {
  845.                 for ( j = 0; j < lenccl; ++j )
  846.                 { /* loop through negated character class */
  847.                     ch = ccltbl[ccllist + j];
  848.  
  849.                     if ( ch > transsym )
  850.                         break;    /* transsym isn't in negated ccl */
  851.  
  852.                     else
  853.                         if ( ch == transsym )             /* next 2 */
  854.                             goto bottom;
  855.                 }
  856.  
  857.                 /* didn't find transsym in ccl */
  858.                 nset[++numstates] = tsp;
  859.             }
  860.  
  861.             else
  862.                 for ( j = 0; j < lenccl; ++j )
  863.                 {
  864.                     ch = ccltbl[ccllist + j];
  865.  
  866.                     if ( ch > transsym )
  867.                         break;
  868.  
  869.                     else
  870.                         if ( ch == transsym )
  871.                         {
  872.                             nset[++numstates] = tsp;
  873.                             break;
  874.                         }
  875.                 }
  876.         }
  877.  
  878.         else
  879.             if ( sym >= 'A' && sym <= 'Z' && caseins )
  880.                 flexfatal( "consistency check failed in symfollowset" );
  881.  
  882.         else
  883.             if ( sym == SYM_EPSILON )
  884.             { /* do nothing */
  885.             }
  886.  
  887.         else
  888.             if ( ecgroup[sym] == transsym )
  889.                 nset[++numstates] = tsp;
  890.  
  891. bottom:;
  892.     }
  893.  
  894.     return ( numstates );
  895. }
  896.  
  897.  
  898. /* sympartition - partition characters with same out-transitions
  899.  *
  900.  * synopsis
  901.  *      integer ds[current_max_dfa_size], numstates, duplist[numecs];
  902.  *      symlist[numecs];
  903.  *      sympartition( ds, numstates, symlist, duplist );
  904.  */
  905.  
  906. sympartition( ds, numstates, symlist, duplist )
  907. int ds[], numstates, duplist[];
  908. int symlist[];
  909.  
  910. {
  911.     int tch, i, j, k, ns, dupfwd[CSIZE + 1], lenccl, cclp, ich;
  912.  
  913.     /* partitioning is done by creating equivalence classes for those
  914.      * characters which have out-transitions from the given state.    Thus
  915.      * we are really creating equivalence classes of equivalence classes.
  916.      */
  917.  
  918.     for ( i = 1; i <= numecs; ++i )
  919.     { /* initialize equivalence class list */
  920.         duplist[i] = i - 1;
  921.         dupfwd[i] = i + 1;
  922.     }
  923.  
  924.     duplist[1] = NIL;
  925.     dupfwd[numecs] = NIL;
  926.  
  927.     for ( i = 1; i <= numstates; ++i )
  928.     {
  929.         ns = ds[i];
  930.         tch = transchar[ns];
  931.  
  932.         if ( tch != SYM_EPSILON )
  933.         {
  934.             if ( tch < -lastccl || tch > CSIZE )
  935.                 flexfatal( "bad transition character detected in sympartition()" );
  936.  
  937.             if ( tch > 0 )
  938.             { /* character transition */
  939.                 mkechar( ecgroup[tch], dupfwd, duplist );
  940.                 symlist[ecgroup[tch]] = 1;
  941.             }
  942.  
  943.             else
  944.             { /* character class */
  945.                 tch = -tch;
  946.  
  947.                 lenccl = ccllen[tch];
  948.                 cclp = cclmap[tch];
  949.                 mkeccl( ccltbl + cclp, lenccl, dupfwd, duplist, numecs );
  950.  
  951.                 if ( cclng[tch] )
  952.                 {
  953.                     j = 0;
  954.  
  955.                     for ( k = 0; k < lenccl; ++k )
  956.                     {
  957.                         ich = ccltbl[cclp + k];
  958.  
  959.                         for ( ++j; j < ich; ++j )
  960.                             symlist[j] = 1;
  961.                     }
  962.  
  963.                     for ( ++j; j <= numecs; ++j )
  964.                         symlist[j] = 1;
  965.                 }
  966.  
  967.                 else
  968.                     for ( k = 0; k < lenccl; ++k )
  969.                     {
  970.                         ich = ccltbl[cclp + k];
  971.                         symlist[ich] = 1;
  972.                     }
  973.             }
  974.         }
  975.     }
  976. }
  977.  
  978.