}
ch = line[++cc]; } // getch
////////////////////////////////////////////////////////////////////// // gets a symbol from input stream. void getsym(void) {
int i, k;
char a[MAXIDLEN + 1];
while (ch == ' ') getch();
if (isalpha(ch))
{ // symbol is a reserved word or an identifier. k = 0; do {
if (k < MAXIDLEN) a[k++] = ch; getch(); }
while (isalpha(ch) || isdigit(ch)); a[k] = 0;
strcpy(id, a); word[0] = id; i = NRW;
while (strcmp(id, word[i--])); if (++i)
sym = wsym[i]; // symbol is a reserved word else
sym = SYM_IDENTIFIER; // symbol is an identifier }
else if (isdigit(ch)) { // symbol is a number. k = num = 0;
sym = SYM_NUMBER; do {
num = num * 10 + ch - '0'; k++; getch(); }
30
while (isdigit(ch)); if (k > MAXNUMLEN)
error(25); // The number is too great. }
else if (ch == ':') {
getch();
if (ch == '=') {
sym = SYM_BECOMES; // := getch(); } else {
sym = SYM_NULL; // illegal? } }
else if (ch == '>') {
getch();
if (ch == '=') {
sym = SYM_GEQ; // >= getch(); } else {
sym = SYM_GTR; // > } }
else if (ch == '<') {
getch();
if (ch == '=') {
sym = SYM_LEQ; // <= getch(); }
else if (ch == '>') {
sym = SYM_NEQ; // <> getch(); } else
31
{
sym = SYM_LES; // < } } else
{ // other tokens i = NSYM; csym[0] = ch;
while (csym[i--] != ch); if (++i) {
sym = ssym[i]; getch(); } else {
printf(\ exit(1); } }
} // getsym
////////////////////////////////////////////////////////////////////// // generates (assembles) an instruction. void gen(int x, int y, int z) {
if (cx > CXMAX) {
printf(\ exit(1); }
code[cx].f = x; code[cx].l = y; code[cx++].a = z; } // gen
//////////////////////////////////////////////////////////////////////
// tests if error occurs and skips all symbols that do not belongs to s1 or s2. void test(symset s1, symset s2, int n) {
symset s;
if (! inset(sym, s1)) {
32
error(n);
s = uniteset(s1, s2); while(! inset(sym, s)) getsym(); destroyset(s); } } // test
////////////////////////////////////////////////////////////////////// int dx; // data allocation index
// enter object(constant, variable or procedre) into table. void enter(int kind) {
mask* mk;
tx++;
strcpy(table[tx].name, id); table[tx].kind = kind; switch (kind) {
case ID_CONSTANT:
if (num > MAXADDRESS) {
error(25); // The number is too great. num = 0; }
table[tx].value = num; break;
case ID_VARIABLE:
mk = (mask*) &table[tx]; mk->level = level; mk->address = dx++; break;
case ID_PROCEDURE:
mk = (mask*) &table[tx]; mk->level = level; break; } // switch } // enter
////////////////////////////////////////////////////////////////////// // locates identifier in symbol table. int position(char* id)
33
{
int i;
strcpy(table[0].name, id); i = tx + 1;
while (strcmp(table[--i].name, id) != 0); return i; } // position
////////////////////////////////////////////////////////////////////// void constdeclaration() {
if (sym == SYM_IDENTIFIER) {
getsym();
if (sym == SYM_EQU || sym == SYM_BECOMES) {
if (sym == SYM_BECOMES)
error(1); // Found ':=' when expecting '='. getsym();
if (sym == SYM_NUMBER) {
enter(ID_CONSTANT); getsym(); } else {
error(2); // There must be a number to follow '='. } } else {
error(3); // There must be an '=' to follow the identifier. } }
error(4); // There must be an identifier to follow 'const', 'var', 'procedure'.
} // constdeclaration
////////////////////////////////////////////////////////////////////// void vardeclaration(void) {
if (sym == SYM_IDENTIFIER) {
enter(ID_VARIABLE);
34
or