📄 pl0.c
字号:
{ 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 //增加的地方 test(fsys, phi, 19);} // statement //////////////////////////////////////////////////////////////////////void block(symset fsys){ int cx0; // initial code index mask* mk; int block_dx; int savedTx; 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; // 修改的地方 } // 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; //删除的地方 set1 = createset(SYM_SEMICOLON, SYM_NULL); set = uniteset(set1, fsys); block(set); destroyset(set1); destroyset(set); tx = savedTx; //删除的地方 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; printf("base(currentLevel=%d, levelDiff=%d)\n", currentLevel,levelDiff);#if 0 //修改的地方,测试栈是否为空 while (levelDiff--)#else if (levelDiff>0) while (levelDiff--) #endif 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
// int mm; printf("Begin executing PL/0 program.\n"); fprintf(outfile, "Begin executing PL/0 program.\n"); pc = 0; b = 1; top = 0; stack[1] = 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]; break; // 增加的地方 case OPR_LES: top--; stack[top] = stack[top] < stack[top + 1]; break; case OPR_GEQ: top--; stack[top] = stack[top] >= stack[top + 1]; break; // 增加的地方 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);删除的地方strcpy(s, "test.txt"); if ((infile = fopen(s, "r")) == NULL) { printf("File %s can't be opened.\n", s); exit(1); }#if 1 // 增加的地方 // 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.
//**************************修改的地方
else
{
while(1) {
while(cc<ll&&line[cc]!=-1)
{
if(line[cc]!=' '&& line[cc]!='\t')
{
error (28);//"Follow the period is an incorrect symbol."
break;
}
cc++;
}
if (feof(infile)) break;
else getch();
}
}
//*********************************** 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); // 增加的地方,关闭所有文件流 fclose(infile); fclose(outfile);} // main//////////////////////////////////////////////////////////////////////// eof pl0.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -