home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_07_02 / v7n2032a.txt < prev    next >
Text File  |  1988-11-21  |  6KB  |  183 lines

  1. /*
  2.  *  stgen.c - C++ program to GENerate State Tables.
  3.  */
  4.  
  5. #include <stream.hpp>   /* Zortech uses ".hpp", not ".h" */
  6. #include <stdlib.h>
  7. #include <ctype.h>
  8.  
  9. const   MAXSYM  = 32+1; /* Maximum length of symbol     */
  10. const   MAXSYMS = 100;  /* Max # of inputs or actions   */
  11.  
  12. enum toktype {
  13.     END,    NAME,   NUMBER,     LPAREN = '(',   RPAREN = ')',
  14.     COLON = ':',    NWLN = '\n'
  15.     };
  16.  
  17. struct  symtab  {
  18.     char    table[MAXSYMS][MAXSYM];
  19.     int     n;      /* # of symbols in table */
  20.     int     find(char *sym) {   /* find symbol in table */
  21.         for(int i = 0; i < n; ++i)
  22.             if(!strcmp(table[i], sym))
  23.                 return i;
  24.         return -1;
  25.         }
  26.     };
  27.  
  28. int     linumb = 1;     /* current line number in input file */
  29.  
  30. main(int argc, char **argv) {
  31.     void    getinpact(symtab *, symtab *);
  32.     void    doheader(char *, symtab *, symtab *, char *, int);
  33.     int     dostate(char *, symtab *, symtab *, symtab *, char *);
  34.     void    synerr(char *);
  35.     toktype lex(char *);
  36.     char    tok[MAXSYM], matrix[MAXSYM], defact[MAXSYM];
  37.     int     nstates;
  38.     toktype tt;
  39.     static  symtab  inputs, actions, allinputs;    /* too big for stack */
  40.  
  41.     while((tt=lex(matrix)) == NWLN) /* eat empty lines */
  42.         ;
  43.     if(tt != NAME)
  44.         synerr( "Expecting name of state transition matrix." );
  45.     if(lex(tok) != LPAREN)
  46.         synerr( "Expecting left paren." );
  47.     if(lex(defact) != NAME)
  48.         synerr( "Expecting name of default action." );
  49.     if(lex(tok) != RPAREN)
  50.         synerr( "Expecting right paren after default action." );
  51.     if(lex(tok) != NUMBER)
  52.         synerr( "Expecting # of states after right paren." );
  53.     else
  54.         nstates = atoi(tok);
  55.     if(lex(tok) != NWLN)
  56.         synerr( "Expecting newline after # of states." );
  57.     getinpact(&allinputs, &actions);
  58.     doheader(matrix, &allinputs, &actions, defact, nstates);
  59.     while((tt=lex(tok)) == NWLN)    /* eat empty lines */
  60.         ;
  61.     if(tt != NAME || lex(tok) != NWLN)
  62.         synerr( "Expecting definition for state." );
  63.     while(nstates-- && dostate(tok, &inputs, &actions, &allinputs, defact))
  64.         ;
  65.     if(nstates >= 0)
  66.         synerr( "Expecting more states." );
  67.     else
  68.         cout << "};\n";
  69.     }
  70.  
  71.  
  72. toktype lex(char *buf) {    /* return next lexical token    */
  73.     char    c;
  74.  
  75.     while(cin.get(c))   /* while not EOF */
  76.         if(c == ')' || c == '(' || c == ':' || c == '\n') {
  77.             if(c == '\n')
  78.                 ++linumb;
  79.             return( c );
  80.             }
  81.         else if(c == '\\') {    /* delete backslash newline */
  82.             if(cin.get(c))
  83.                 if(c != '\n')
  84.                     cin.putback(c);
  85.                 else
  86.                     ++linumb;
  87.             }
  88.         else if(c == '/') {     /* eat comment  */
  89.             while(cin >> c)
  90.                 if(c == '*' && (cin >> c) && c == '/')
  91.                     break;
  92.             }
  93.         else if(isdigit(c)) {
  94.             for(*buf++ = c; cin.get(c) && isdigit(c); *buf++ = c)
  95.                 ;
  96.             *buf++  = '\0'; /* terminate the string */
  97.             cin.putback(c); /* put back char that stopped scan */
  98.             return NUMBER;
  99.             }
  100.         else if( isalpha(c) || c == '_' ) {
  101.             for(*buf++ = c; cin.get(c) && (isalnum(c) || c=='_'); *buf++ = c)
  102.                 ;
  103.             *buf++  = '\0'; /* terminate the string */
  104.             cin.putback(c); /* put back char that stopped scan */
  105.             return NAME;
  106.             }
  107.     return END;
  108.     }
  109.  
  110. void    synerr(char * msg) {
  111.     cerr << "Line " << linumb << ": " << msg << "\n";
  112.     exit( EXIT_FAILURE );   /* defined in stdlib.h  */
  113.     }
  114.  
  115. /*
  116.  *  getinpact - read list of inputs and actions in the form:
  117.  *      inp1 ... inpN : act1 ... actN
  118.  */
  119. void    getinpact(symtab *inp, symtab *act) {
  120.     toktype getlist(symtab *table);
  121.  
  122.     if(getlist(inp) != COLON)
  123.         synerr( "Expecting colon after list of inputs." );
  124.     else if(getlist(act) != NWLN)
  125.         synerr( "Expecting newline after list of actions." );
  126.     }
  127.  
  128. toktype getlist(symtab *t) { /* read list of names   */
  129.     toktype tt;
  130.  
  131.     for(t->n = 0; (tt=lex(t->table[t->n])) == NAME; ++t->n)
  132.         ;
  133.     return tt;
  134.     }
  135.  
  136. void    doheader(char *matname, symtab *inp, symtab *act,
  137.                 char *defact, int nstates) {
  138.     cout << "/* Define machine inputs */\n";
  139.     for(int i = 0; i < inp->n; ++i)
  140.         cout << "#define " << inp->table[i] << " " << i << "\n";
  141.     cout << "/* Define machine actions */\n";
  142.     for(i = 0; i < act->n; ++i)
  143.         cout << "#define " << act->table[i] << " "<< i << "\n";
  144.     cout << "#define " << defact << " " << i << "  /* default */\n";
  145.     cout << "\n" << matname << "[" << nstates << "][" 
  146.             << inp->n << "] = {\n";
  147.     }
  148.  
  149. int     dostate(char *buf, symtab *inp, symtab *act,
  150.                     symtab *allinp, char *defact) {
  151.     char    state[MAXSYM];
  152.     toktype tt;
  153.     static  symtab  temp;
  154.         
  155.     strcpy(state, buf); /* remember state   */
  156.     for(int i=0; i < MAXSYMS; ++i)  /* init with default action */
  157.         strcpy(temp.table[i], defact);
  158.     for(int lines=0; ; ++lines) {
  159.         tt  = getlist(inp);
  160.         if(inp->n <= 0 || (tt == NWLN && inp->n == 1))
  161.             break;
  162.         if(((tt=getlist(act)) != NWLN && tt != END) || act->n <= 0)
  163.             synerr( "Expecting list of inputs : action." );
  164.         if(act->n > 1)
  165.             synerr( "Can't have more than one action per input." );
  166.         for(i=0; i < inp->n; ++i) {
  167.             int j = allinp->find(inp->table[i]);
  168.             if(strcmp(temp.table[j], defact))
  169.                 synerr( "Can't have more than one action per input." );
  170.             else
  171.                 strcpy(temp.table[j], inp->table[i]);
  172.             }
  173.         }
  174.     strcpy(buf, inp->table[0]); /* name of next state */
  175.     if(!lines)
  176.         return( 0 );
  177.     cout << "/* State '" << state << "' */\n{ ";
  178.     for(i = 0; i < allinp->n; ++i)
  179.         cout << (i?", ":"") << temp.table[i];
  180.     cout << " },\n";
  181.     return( 1 );
  182.     }
  183.