📄 pl0.c
字号:
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) { // if statement getsym(); set1 = createset(SYM_THEN, SYM_DO, SYM_NULL); set = uniteset(set1, fsys); condition(set); destroyset(set1); destroyset(set); if (sym == SYM_THEN) { getsym(); } else { error(16); // 'then' expected. } cx1 = cx; gen(JPC, 0, 0); statement(fsys); code[cx1].a = cx; } else if (sym == SYM_BEGIN) { // block getsym(); set1 = createset(SYM_SEMICOLON, SYM_END, SYM_NULL); set = uniteset(set1, fsys); statement(set); while (sym == SYM_SEMICOLON || inset(sym, statbegsys)) { if (sym == SYM_SEMICOLON) { getsym(); } else { error(10); } statement(set); } // while destroyset(set1); destroyset(set); if (sym == SYM_END) { getsym(); } else { error(17); // ';' or 'end' expected. } } else if (sym == SYM_WHILE) { // while statement cx1 = cx; getsym(); set1 = createset(SYM_DO, SYM_NULL); set = uniteset(set1, fsys); condition(set); destroyset(set1); destroyset(set); cx2 = cx; gen(JPC, 0, 0); if (sym == SYM_DO) { getsym(); } else { error(18); // 'do' expected. } statement(fsys); gen(JMP, 0, cx1); code[cx2].a = cx; } else //added by yzhang 02-02-28 test(fsys, phi, 19);} // statement //////////////////////////////////////////////////////////////////////void block(symset fsys){ int cx0; // initial code index mask* mk; int block_dx; //int savedTx; /*Deleted by XSun&HYC.........25/04/2004*/ symset set1, set; dx = 3; block_dx = dx; mk = (mask*) &table[tx]; mk->address = cx; gen(JMP, 0, 0); if (level > MAXLEVEL) { error(32); // There are too many levels. } do { if (sym == SYM_CONST) { // constant declarations getsym(); do { constdeclaration(); while (sym == SYM_COMMA) { getsym(); constdeclaration(); } if (sym == SYM_SEMICOLON) { getsym(); } else { error(5); // Missing ',' or ';'. } } while (sym == SYM_IDENTIFIER); } // if if (sym == SYM_VAR) { // variable declarations getsym(); do { vardeclaration(); while (sym == SYM_COMMA) { getsym(); vardeclaration(); } if (sym == SYM_SEMICOLON) { getsym(); } else { error(5); // Missing ',' or ';'. } } while (sym == SYM_IDENTIFIER); block_dx = dx; // modified by yzhang 02-03-15 } // if while (sym == SYM_PROCEDURE) { // procedure declarations getsym(); if (sym == SYM_IDENTIFIER) { enter(ID_PROCEDURE); getsym(); } else { error(4); // There must be an identifier to follow 'const', 'var', or 'procedure'. } if (sym == SYM_SEMICOLON) { getsym(); } else { error(5); // Missing ',' or ';'. } level++; //savedTx = tx; /* deleted by XSun&HYC......25/04/2004*/ set1 = createset(SYM_SEMICOLON, SYM_NULL); set = uniteset(set1, fsys); block(set); destroyset(set1); destroyset(set); //tx = savedTx; /* deleted by XSun&HYC......25/04/2004*/ level--; if (sym == SYM_SEMICOLON) { getsym(); set1 = createset(SYM_IDENTIFIER, SYM_PROCEDURE, SYM_NULL); set = uniteset(statbegsys, set1); test(set, fsys, 6); destroyset(set1); destroyset(set); } else { error(5); // Missing ',' or ';'. } } // while set1 = createset(SYM_IDENTIFIER, SYM_NULL); set = uniteset(statbegsys, set1); test(set, declbegsys, 7); destroyset(set1); destroyset(set); } while (inset(sym, declbegsys)); code[mk->address].a = cx; mk->address = cx; cx0 = cx; gen(INT, 0, block_dx); set1 = createset(SYM_SEMICOLON, SYM_END, SYM_NULL); set = uniteset(set1, fsys); statement(set); destroyset(set1); destroyset(set); gen(OPR, 0, OPR_RET); // return test(fsys, phi, 8); // test for error: Follow the statement is an incorrect symbol. listcode(cx0, cx);} // block//////////////////////////////////////////////////////////////////////int base(int stack[], int currentLevel, int levelDiff){ int b = currentLevel;
if(levelDiff>0) /*Added by XSun&HYC..........25/04/2004*/
while (levelDiff--)
{
b = stack[b];
} return b;} // base//////////////////////////////////////////////////////////////////////// interprets and executes codes.void interpret(){ int pc; // program counter int stack[STACKSIZE]; int top; // top of stack int b; // program, base, and top-stack register instruction i; // instruction register printf("Begin executing PL/0 program.\n"); fprintf(outfile, "Begin executing PL/0 program.\n"); pc = 0; b = 1; top = 3; stack[1] = stack[2] = stack[3] = 0; do { i = code[pc++]; switch (i.f) { case LIT: stack[++top] = i.a; break; case OPR: switch (i.a) // operator { case OPR_RET: top = b - 1; pc = stack[top + 3]; b = stack[top + 2]; break; case OPR_NEG: stack[top] = -stack[top]; break; case OPR_ADD: top--; stack[top] += stack[top + 1]; break; case OPR_MIN: top--; stack[top] -= stack[top + 1]; break; case OPR_MUL: top--; stack[top] *= stack[top + 1]; break; case OPR_DIV: top--; if (stack[top + 1] == 0) { fprintf(stderr, "Runtime Error: Divided by zero.\n"); fprintf(stderr, "Program terminated.\n"); continue; } stack[top] /= stack[top + 1]; break; case OPR_ODD: stack[top] %= 2; break; case OPR_EQU: top--; stack[top] = stack[top] == stack[top + 1]; break; case OPR_NEQ: top--; stack[top] = stack[top] != stack[top + 1]; case OPR_LES: top--; stack[top] = stack[top] < stack[top + 1]; break; case OPR_GEQ: top--; stack[top] = stack[top] >= stack[top + 1]; case OPR_GTR: top--; stack[top] = stack[top] > stack[top + 1]; break; case OPR_LEQ: top--; stack[top] = stack[top] <= stack[top + 1]; } // switch break; case LOD: stack[++top] = stack[base(stack, b, i.l) + i.a]; break; case STO: stack[base(stack, b, i.l) + i.a] = stack[top]; printf("%d\n", stack[top]); fprintf(outfile, "%d\n", stack[top]); top--; break; case CAL: stack[top + 1] = base(stack, b, i.l); // generate new block mark stack[top + 2] = b; stack[top + 3] = pc; b = top + 1; pc = i.a; break; case INT: top += i.a; break; case JMP: pc = i.a; break; case JPC: if (stack[top] == 0) pc = i.a; top--; break; } // switch } while (pc); printf("End executing PL/0 program.\n"); fprintf(outfile, "End executing PL/0 program.\n");} // interpret//////////////////////////////////////////////////////////////////////void main (){ FILE* hbin; char s[80],*finddot; int i; symset set, set1, set2; printf("Please input source file name: "); // get file name to be compiled scanf("%s", s); if ((infile = fopen(s, "r")) == NULL) { printf("File %s can't be opened.\n", s); exit(1); }#if 1 // added by yzhang 02-02-28 // open the output file finddot = strchr(s,'.'); if (finddot!=NULL){ strcpy(finddot, ".out"); }else{ strcat(s, ".out"); printf("%s\n", s); } printf("Output File is %s\n", s); if ((outfile = fopen(s, "w")) == NULL) { printf("File %s can't be opened.\n", s); exit(1); }#endif phi = createset(SYM_NULL); relset = createset(SYM_EQU, SYM_NEQ, SYM_LES, SYM_LEQ, SYM_GTR, SYM_GEQ, SYM_NULL); // create begin symbol sets declbegsys = createset(SYM_CONST, SYM_VAR, SYM_PROCEDURE, SYM_NULL); statbegsys = createset(SYM_BEGIN, SYM_CALL, SYM_IF, SYM_WHILE, SYM_NULL); facbegsys = createset(SYM_IDENTIFIER, SYM_NUMBER, SYM_LPAREN, SYM_NULL); err = cc = cx = ll = 0; // initialize global variables ch = ' '; kk = MAXIDLEN; getsym(); set1 = createset(SYM_PERIOD, SYM_NULL); set2 = uniteset(declbegsys, statbegsys); set = uniteset(set1, set2); block(set); destroyset(set1); destroyset(set2); destroyset(set); destroyset(phi); destroyset(relset); destroyset(declbegsys); destroyset(statbegsys); destroyset(facbegsys); if (sym != SYM_PERIOD) error(9); // '.' expected. if (err == 0) { hbin = fopen("hbin.txt", "w"); for (i = 0; i < cx; i++) fwrite(&code[i], sizeof(instruction), 1, hbin); fclose(hbin); } if (err == 0) interpret(); else printf("There are %d error(s) in PL/0 program.\n", err); listcode(0, cx); // close all files, added by yzhang, 02-02-28 fclose(infile); fclose(outfile);} // main//////////////////////////////////////////////////////////////////////// eof pl0.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -