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 >
Wrap
Text File
|
1988-11-21
|
6KB
|
183 lines
/*
* stgen.c - C++ program to GENerate State Tables.
*/
#include <stream.hpp> /* Zortech uses ".hpp", not ".h" */
#include <stdlib.h>
#include <ctype.h>
const MAXSYM = 32+1; /* Maximum length of symbol */
const MAXSYMS = 100; /* Max # of inputs or actions */
enum toktype {
END, NAME, NUMBER, LPAREN = '(', RPAREN = ')',
COLON = ':', NWLN = '\n'
};
struct symtab {
char table[MAXSYMS][MAXSYM];
int n; /* # of symbols in table */
int find(char *sym) { /* find symbol in table */
for(int i = 0; i < n; ++i)
if(!strcmp(table[i], sym))
return i;
return -1;
}
};
int linumb = 1; /* current line number in input file */
main(int argc, char **argv) {
void getinpact(symtab *, symtab *);
void doheader(char *, symtab *, symtab *, char *, int);
int dostate(char *, symtab *, symtab *, symtab *, char *);
void synerr(char *);
toktype lex(char *);
char tok[MAXSYM], matrix[MAXSYM], defact[MAXSYM];
int nstates;
toktype tt;
static symtab inputs, actions, allinputs; /* too big for stack */
while((tt=lex(matrix)) == NWLN) /* eat empty lines */
;
if(tt != NAME)
synerr( "Expecting name of state transition matrix." );
if(lex(tok) != LPAREN)
synerr( "Expecting left paren." );
if(lex(defact) != NAME)
synerr( "Expecting name of default action." );
if(lex(tok) != RPAREN)
synerr( "Expecting right paren after default action." );
if(lex(tok) != NUMBER)
synerr( "Expecting # of states after right paren." );
else
nstates = atoi(tok);
if(lex(tok) != NWLN)
synerr( "Expecting newline after # of states." );
getinpact(&allinputs, &actions);
doheader(matrix, &allinputs, &actions, defact, nstates);
while((tt=lex(tok)) == NWLN) /* eat empty lines */
;
if(tt != NAME || lex(tok) != NWLN)
synerr( "Expecting definition for state." );
while(nstates-- && dostate(tok, &inputs, &actions, &allinputs, defact))
;
if(nstates >= 0)
synerr( "Expecting more states." );
else
cout << "};\n";
}
toktype lex(char *buf) { /* return next lexical token */
char c;
while(cin.get(c)) /* while not EOF */
if(c == ')' || c == '(' || c == ':' || c == '\n') {
if(c == '\n')
++linumb;
return( c );
}
else if(c == '\\') { /* delete backslash newline */
if(cin.get(c))
if(c != '\n')
cin.putback(c);
else
++linumb;
}
else if(c == '/') { /* eat comment */
while(cin >> c)
if(c == '*' && (cin >> c) && c == '/')
break;
}
else if(isdigit(c)) {
for(*buf++ = c; cin.get(c) && isdigit(c); *buf++ = c)
;
*buf++ = '\0'; /* terminate the string */
cin.putback(c); /* put back char that stopped scan */
return NUMBER;
}
else if( isalpha(c) || c == '_' ) {
for(*buf++ = c; cin.get(c) && (isalnum(c) || c=='_'); *buf++ = c)
;
*buf++ = '\0'; /* terminate the string */
cin.putback(c); /* put back char that stopped scan */
return NAME;
}
return END;
}
void synerr(char * msg) {
cerr << "Line " << linumb << ": " << msg << "\n";
exit( EXIT_FAILURE ); /* defined in stdlib.h */
}
/*
* getinpact - read list of inputs and actions in the form:
* inp1 ... inpN : act1 ... actN
*/
void getinpact(symtab *inp, symtab *act) {
toktype getlist(symtab *table);
if(getlist(inp) != COLON)
synerr( "Expecting colon after list of inputs." );
else if(getlist(act) != NWLN)
synerr( "Expecting newline after list of actions." );
}
toktype getlist(symtab *t) { /* read list of names */
toktype tt;
for(t->n = 0; (tt=lex(t->table[t->n])) == NAME; ++t->n)
;
return tt;
}
void doheader(char *matname, symtab *inp, symtab *act,
char *defact, int nstates) {
cout << "/* Define machine inputs */\n";
for(int i = 0; i < inp->n; ++i)
cout << "#define " << inp->table[i] << " " << i << "\n";
cout << "/* Define machine actions */\n";
for(i = 0; i < act->n; ++i)
cout << "#define " << act->table[i] << " "<< i << "\n";
cout << "#define " << defact << " " << i << " /* default */\n";
cout << "\n" << matname << "[" << nstates << "]["
<< inp->n << "] = {\n";
}
int dostate(char *buf, symtab *inp, symtab *act,
symtab *allinp, char *defact) {
char state[MAXSYM];
toktype tt;
static symtab temp;
strcpy(state, buf); /* remember state */
for(int i=0; i < MAXSYMS; ++i) /* init with default action */
strcpy(temp.table[i], defact);
for(int lines=0; ; ++lines) {
tt = getlist(inp);
if(inp->n <= 0 || (tt == NWLN && inp->n == 1))
break;
if(((tt=getlist(act)) != NWLN && tt != END) || act->n <= 0)
synerr( "Expecting list of inputs : action." );
if(act->n > 1)
synerr( "Can't have more than one action per input." );
for(i=0; i < inp->n; ++i) {
int j = allinp->find(inp->table[i]);
if(strcmp(temp.table[j], defact))
synerr( "Can't have more than one action per input." );
else
strcpy(temp.table[j], inp->table[i]);
}
}
strcpy(buf, inp->table[0]); /* name of next state */
if(!lines)
return( 0 );
cout << "/* State '" << state << "' */\n{ ";
for(i = 0; i < allinp->n; ++i)
cout << (i?", ":"") << temp.table[i];
cout << " },\n";
return( 1 );
}