📄 sxb2.c
字号:
// pl0 compiler source code#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "set.h"#include "sxb2.h"//////////////////////////////////////////////////////////////////////// print error message.void error(n){ int i; printf(" "); for (i = 1; i <= cc - 1; i++)
printf(" "); fprintf(outfile, " "); fprintf(outfile, "^\n"); printf("^\n"); fprintf(outfile, "Error %3d: %s\n", n, err_msg[n]); printf("Error %3d: %s\n", n, err_msg[n]); err++;} // error//////////////////////////////////////////////////////////////////////void getch(void){ if (cc == ll) { if (feof(infile)) { printf("\nPROGRAM INCOMPLETE\n"); exit(1); } ll = cc = 0; fprintf(outfile, "%5d ", cx); printf("%5d ", cx); while ( (!feof(infile)) // added & modified by alex 01-02-09 && ((ch = getc(infile)) != '\n')) { fprintf(outfile, "%c", ch); printf("%c", ch); line[++ll] = ch; } // while fprintf(outfile, "\n"); printf("\n"); line[++ll] = ' '; } ch = line[++cc];} // getch//////////////////////////////////////////////////////////////////////// gets a symbol from input stream.void getsym(void){ int i, k; char a[MAXIDLEN + 1]; while (ch == ' '|| ch == '\t') // modified by yzhang 02-03-12,add some white space 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(); } 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 { sym = SYM_LES; // < } } else { // other tokens i = NSYM; csym[0] = ch; while (csym[i--] != ch); if (++i) { sym = ssym[i]; getch(); } else { printf("Fatal Error: Unknown character.\n"); fprintf(outfile, "Fatal Error: Unknown character.\n"); exit(1); } }} // getsym//////////////////////////////////////////////////////////////////////// generates (assembles) an instruction.void gen(int x, int y, int z){ if (cx > CXMAX) { fprintf(outfile, "Fatal Error: Program too long.\n"); printf("Fatal Error: Program too long.\n"); 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)) { showset(s1); showset(s2); printf("sym=%d, id=%s\n", sym, id); 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;// added by yzhang 02-02-28// if ( position(id)> 0 ){// error(26); //Redeclared identifier.// }// end 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){ 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. } } else //added by yzhang 02-02-28 error(4); // There must be an identifier to follow 'const', 'var', or 'procedure'.} // constdeclaration//////////////////////////////////////////////////////////////////////void vardeclaration(void){ if (sym == SYM_IDENTIFIER) { enter(ID_VARIABLE); getsym(); } else { error(4); // There must be an identifier to follow 'const', 'var', or 'procedure'. }} // vardeclaration//////////////////////////////////////////////////////////////////////void listcode(int from, int to){ int i; printf("\n"); fprintf(outfile, "\n"); for (i = from; i < to; i++) { printf("%5d %s\t%d\t%d\n", i, mnemonic[code[i].f], code[i].l, code[i].a); fprintf(outfile, "%5d %s\t%d\t%d\n", i, mnemonic[code[i].f], code[i].l, code[i].a); } printf("\n"); fprintf(outfile, "\n");} // listcode//////////////////////////////////////////////////////////////////////void factor(symset fsys){ void expression(); int i; symset set; test(facbegsys, fsys, 24); // The symbol can not be as the beginning of an expression.
while (inset(sym, facbegsys)) { if (sym == SYM_IDENTIFIER) { if ((i = position(id)) == 0) { error(11); // Undeclared identifier. } else { switch (table[i].kind) { mask* mk; case ID_CONSTANT: gen(LIT, 0, table[i].value); break; case ID_VARIABLE: mk = (mask*) &table[i]; gen(LOD, level - mk->level, mk->address); break; case ID_PROCEDURE: error(21); // Procedure identifier can not be in an expression. break; } // switch } getsym(); } else if (sym == SYM_NUMBER) { if (num > MAXADDRESS) { error(25); // The number is too great. num = 0; } gen(LIT, 0, num); getsym(); } else if (sym == SYM_LPAREN) { getsym(); set = uniteset(createset(SYM_RPAREN, SYM_NULL), fsys); expression(set); destroyset(set); if (sym == SYM_RPAREN) { getsym(); } else { error(22); // Missing ')'. } } else // added by yzhang 02-02-28 test(fsys, createset(SYM_LPAREN, SYM_NULL), 23); } // while} // factor//////////////////////////////////////////////////////////////////////void term(symset fsys){ int mulop; symset set; set = uniteset(fsys, createset(SYM_TIMES, SYM_SLASH, SYM_NULL)); factor(set); while (sym == SYM_TIMES || sym == SYM_SLASH) { mulop = sym; getsym(); factor(set); if (mulop == SYM_TIMES) { gen(OPR, 0, OPR_MUL); } else { gen(OPR, 0, OPR_DIV); } } // while destroyset(set);} // term//////////////////////////////////////////////////////////////////////void expression(symset fsys){ int addop; symset set; set = uniteset(fsys, createset(SYM_PLUS, SYM_MINUS, SYM_NULL)); if (sym == SYM_PLUS || sym == SYM_MINUS) { addop = sym; getsym(); term(set); if (addop == SYM_MINUS) { gen(OPR, 0, OPR_NEG); } } else { term(set); } while (sym == SYM_PLUS || sym == SYM_MINUS) { addop = sym; getsym(); term(set); if (addop == SYM_PLUS) { gen(OPR, 0, OPR_ADD); } else { gen(OPR, 0, OPR_MIN); } } // while destroyset(set);} // expression//////////////////////////////////////////////////////////////////////void condition(symset fsys){ int relop; symset set; if (sym == SYM_ODD) { getsym(); expression(fsys); gen(OPR, 0, 6); } else { set = uniteset(relset, fsys); expression(set); destroyset(set); if (! inset(sym, relset)) { error(20); } else { relop = sym; getsym(); expression(fsys); switch (relop) { case SYM_EQU: gen(OPR, 0, OPR_EQU); break; case SYM_NEQ: gen(OPR, 0, OPR_NEQ); break; case SYM_LES: gen(OPR, 0, OPR_LES); break; case SYM_GEQ: gen(OPR, 0, OPR_GEQ); break; case SYM_GTR: gen(OPR, 0, OPR_GTR); break; case SYM_LEQ: gen(OPR, 0, OPR_LEQ); break; } // switch } // else } // else} // condition//////////////////////////////////////////////////////////////////////void statement(symset fsys){ int i, cx1, cx2; symset set1, set; if (sym == SYM_IDENTIFIER) { // variable assignment mask* mk; if (! (i = position(id))) { error(11); // Undeclared identifier. } else if (table[i].kind != ID_VARIABLE) { error(12); // Illegal assignment. i = 0; } getsym(); if (sym == SYM_BECOMES) { getsym(); } else { error(13); // ':=' expected. } expression(fsys); mk = (mask*) &table[i]; if (i) { gen(STO, level - mk->level, mk->address); } } else if (sym == SYM_CALL) { // procedure call getsym(); if (sym != SYM_IDENTIFIER) { error(14); // There must be an identifier to follow the 'call'. } else { if (! (i = position(id))) { error(11); // Undeclared identifier. } else if (table[i].kind == ID_PROCEDURE) { mask* mk; mk = (mask*) &table[i]; gen(CAL, level - mk->level, mk->address); } else { error(15); // A constant or variable can not be called. } getsym(); } // else } else if (sym == SYM_IF)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -