📄 pl0pars.c
字号:
/*******************************************************************
Program : Recursive Descent Compiler for PL/0
Module : PL0PARS - Parser: syntax analysis, semantic
analysis, intermediate code
generation
File : pl0pars.c
Compiler: Borland C 3.1 - 4.5, GNU C 2.7.1
Author : H. Weber
Revision: Aug. 1998
********************************************************************/
#include <string.h>
#include <stdio.h>
#include "pl0const.h"
#include "pl0glob.h"
#include "pl0symt.h"
#include "pl0err.h"
#include "pl0code.h" /* cg */
#define maxline 100
FILE *token, *listing,
*errlist, *stlist;
FILE *intcode; /* cg */
int addr, level; /* cg */
int i, sym, num,
txcurr, levcurr;
char id[cmax];
char str[strmax];
char lline[maxline];
void statement();
void expression();
void block();
void nextline() //读取下一行
{
if (fgets(lline, maxline-2, listing) == NULL) {
fprintf(stderr, "Cannot read from listing file\n");
exit(1);
}
fputs(lline, errlist);
}
void getsym()
/* read next symbol (token) from token file */
{
int i;
i = fscanf(token, "%d", &sym);
if (i <= 0) {
fprintf(stderr, "Error reading token file\n");
exit(1);
}
if (sym == lf) { nextline(); getsym(); } //读到回车换行
else if (sym == ident) fscanf(token, "%s", id); //变量
else if (sym == number) fscanf(token, "%d", &num); //数字
else if (sym == stringsym) {
fgets(str, 3, token);
fgets(str, strmax, token);
str[strlen(str)-1] = 0;
}
}
void match(int symb, int errno)
/* check current symbol and get next symbol */
{
if (sym == symb)
getsym();
else
error(errno);
}
/* syntactic functions follow */
void constdecl(int *tx, int *txfirst, int *dindex) //常量定义
{
match(ident, 4);
match(eql, 3);
if (sym == number) {
enter(constobj, id, 0, num, tx,
txfirst, dindex);
getsym();
} else error(2);
}
void vardecl(int *tx, int *txfirst, int *dindex, int lev) //变量定义
{
int i, arrsize;
char arrid[cmax];
match(ident, 4);
enter(varobj, id, lev, 0, tx, txfirst, dindex);
}
void constpart(int *tx, int *txfirst, int *dindex) //常量部分
{
getsym();
constdecl(tx, txfirst, dindex);
while (sym == comma) {
getsym();
constdecl(tx, txfirst, dindex);
}
match(semicolon, 5);
}
void varpart(int *tx, int *txfirst, int *dindex, int lev) //变量部分
{
getsym();
vardecl(tx, txfirst, dindex, lev);
while (sym == comma) {
getsym();
vardecl(tx, txfirst, dindex, lev);
}
match(semicolon, 5);
}
void procpart(int *tx, int *txfirst, int *dindex, int lev) //过程部分
{
getsym();
if (sym == ident) {
enter(procobj, id, lev, 0, tx,
txfirst, dindex);
getsym();
} else error(4);
match(semicolon, 5);
block(*tx, lev+1);
match(semicolon, 5);
}
//F->num | (E) | id
void factor() //
{
int i, k;
if (sym == ident) { //变量
i = position(id, txcurr);
if (i == 0) error(11);
k = objkind(i);
switch (k) {
case procobj:
error(21);
break;
case constobj:
emit(LIT, 0, constsize(i)); /* cg */
break;
case varobj:
emit(LOD, levcurr-objlevel(i), objaddr(i));
/* cg */
break;
} /* switch */
getsym();
}
else if (sym == number) { //数字
emit(LIT, 0, num); /* cg */
getsym();
}
else if (sym == lparen) { //左括号
getsym();
expression(); //表达式
match(rparen, 22); //右括号
} else error(23);
}
// T->F*F | F/F
void term()
{
int symbol; /* cg */
factor();
while (sym == times || sym == slash) //乘除
{
symbol = sym; /* cg */
getsym();
factor();
if (symbol == times)
emit(MPY, 0, 0); /* cg */
else emit(DVD, 0, 0); /* cg */
}
}
//E->+T | -T | T+T | T-T
void expression()
{
int symbol; /* cg */
if (sym == plus || sym == minus) //正负
{
symbol = sym; /* cg */
getsym();
term();
if (symbol == minus) emit(NEG, 0, 0); /* cg */
}
else term();
while (sym == plus || sym == minus) //加减
{
symbol = sym; /* cg */
getsym();
term();
if (symbol == plus) emit(ADD, 0, 0); /* cg */
else emit(SUB, 0, 0); /* cg */
}
}
//条件语句
void condition()
{
if (sym == oddsym)
{
getsym();
expression();
emit(ODD, 0, 0); /* cg */
}
else
{
expression();
if (sym == eql) //等于
{
getsym();
expression();
emit(EQL, 0, 0); /* cg */
}
else if (sym == neq) //不等于
{
getsym();
expression();
emit(NEQ, 0, 0); /* cg */
}
else if (sym == lss) //小于
{
getsym();
expression();
emit(LSS, 0, 0); /* cg */
}
else if (sym == geq) //大于等于
{
getsym();
expression();
emit(GEQ, 0, 0); /* cg */
}
else if (sym == gtr) //大于
{
getsym();
expression();
emit(GTR, 0, 0); /* cg */
}
else if (sym == leq) //小于等于
{
getsym();
expression();
emit(LEQ, 0, 0); /* cg */
}
else error(20);
}
}
//赋值语句
void assignstmnt()
{
int i, k;
i = position(id, txcurr);
if (i == 0) error(11);
k = objkind(i);
if (k == constobj || k == procobj) error(12);
if (k == varobj) //变量
{
getsym();
match(becomes, 13); //:=
expression();
emit(STO, levcurr-objlevel(i), objaddr(i)); /* cg */
}
}
//调用子程序
void callstmnt()
{
int i;
getsym();
if (sym == ident) {
i = position(id, txcurr);
if (i == 0) error(11);
if (objkind(i) != procobj) error(15);
emit(CAL, levcurr-objlevel(i), objaddr(i)); /* cg */
getsym();
} else error(14);
}
//IF语句
//if C then S else S
void ifstmnt()
{
int fixup1, fixup2; /* cg */
getsym();
condition(); //条件表达式
match(thensym, 16); //then
fixup1 = cdindex(); /* cg */
emit(JPC, 0, 0); /* cg */
statement();
if (sym == elsesym) {
getsym();
fixup2 = cdindex(); /* cg */
emit(JPU, 0, 0); /* cg */
fixup(fixup1, cdindex()); /* cg */
statement();
fixup(fixup2, cdindex()); //回填
} else {
fixup(fixup1, cdindex()); /* cg */
}
}
//复合语句
void compoundstmnt()
{
getsym();
statement();
while (sym == semicolon) //;
{
getsym();
statement();
}
match(endsym, 17); //end
}
//WHILE语句
//while C do S
void whilestmnt()
{
int fixup1, fixup2; /* cg */
fixup1 = cdindex(); /* cg */
getsym();
condition();
fixup2 = cdindex(); /* cg */
emit(JPC, 0, 0); /* cg */
match(dosym, 18); //do
statement();
emit(JPU, 0, fixup1); /* cg */
fixup(fixup2, cdindex()); /* cg */
}
//读语句
void readstmnt()
{
int i, k;
getsym();
if (sym == lparen) //左括号
{
do {
getsym();
if (sym == ident) //变量
{
i = position(id, txcurr);
if (i == 0) error(11);
k = objkind(i);
if (k == constobj || k == procobj)
error(12);
else if (k == varobj) {
emit(INP, 0, 0); /* cg */
emit(STO, levcurr-objlevel(i), objaddr(i));
/* cg */
getsym();
}
} else error(33);
} while (sym == comma); //,
match(rparen, 22); //右括号
} else error(43);
}
//写语句
void writestmnt()
{
int i;
int l; /* cg */
getsym();
if (sym == lparen)
{
do {
getsym();
if (sym == stringsym) {
l = strlen(str); /* cg */
emit(PRS, 0, l); /* cg */
for (i=0; i<l; i++) { /* cg */
emit(ASC, 0, (int) str[i]); /* cg */
} /* cg */
getsym();
}
else {
expression();
emit(PRN, 0, 0); /* cg */
}
} while (sym == comma);
match(rparen, 22);
} else error(43);
}
//writeln语句
void writelnstmnt()
{
getsym();
emit(PRL, 0, 0); /* cg */
}
//语句S
void statement()
{
if (sym == ident) assignstmnt();
else if (sym == callsym) callstmnt();
else if (sym == ifsym) ifstmnt();
else if (sym == beginsym) compoundstmnt();
else if (sym == whilesym) whilestmnt();
else if (sym == readsym) readstmnt();
else if (sym == writesym) writestmnt();
else if (sym == writelnsym) writelnstmnt();
}
//
void block(int tx, int lev)
{
int ppos; /* procedure position in
symbol table */
int dindex; /* data allocation index */
int txfirst; /* index of first declaration
in block */
int oldcdi; /* saves old code index */ /* cg */
int currcdi; /* current code index */ /* cg */
txfirst = tx + 1;
ppos = tx;
dindex = 3;
oldcdi = cdindex(); /* cg */
if (lev == 0) emit(CAL, 0, 0); /* cg */
if (sym == constsym)
constpart(&tx, &txfirst, &dindex);
if (sym == varsym)
varpart(&tx, &txfirst, &dindex, lev);
while (sym == procsym)
procpart(&tx, &txfirst, &dindex, lev);
currcdi = cdindex(); /* cg */
if (lev == 0) fixup(oldcdi, currcdi); /* cg */
entersymt(ppos, currcdi, dindex); /* cg */
emit(INT, 0, dindex-3); /* cg */
txcurr = tx;
levcurr = lev;
statement();
emit(RET, 0, 0); /* cg */
printsymt(stlist, ppos, tx);
}
//程序
void program()
{
block(0, 0);
if (sym != period) error(9);
}
main(int argc, char *argv[])
/*------------------------------------------------------------------
The main function of the parser opens and closes files and
calls the function "program"
------------------------------------------------------------------*/
{
int i;
char tname[20], lname[20],
ename[20], sname[20];
char cname[20]; /* cg */
char *p;
/* check arguments */
// if (argc == 1) {
// fprintf(stderr, "Usage: %s source\n",
// argv[0]);
// exit(1);
// }
/* set up filenames */
// strcpy(tname, argv[1]);
strcpy(tname, "prim.pl0");
p = strchr(tname, '.');
if (p) *p = 0;
strcpy(lname, tname);
strcpy(ename, tname);
strcpy(sname, tname);
strcpy(cname, tname); /* cg */
strcat(tname, ".tok");
strcat(lname, ".lst");
strcat(ename, ".err");
strcat(sname, ".stb");
printf("PL/0-Compiler: Parser\n");
/* open files */
if ((token = fopen(tname, "r")) == NULL) {
fprintf(stderr, "Cannot open token file %s\n",
tname);
exit(1);
}
if ((listing = fopen(lname, "r")) == NULL) {
fprintf(stderr, "Cannot open listing file %s\n",
lname);
exit(1);
}
if ((errlist = fopen(ename, "w")) == NULL) {
fprintf(stderr,
"Cannot open error listing file %s\n",
ename);
exit(1);
}
if ((stlist = fopen(sname, "w")) == NULL) {
fprintf(stderr,
"Cannot open symbol table listing file %s\n",
sname);
exit(1);
}
/* read first 3 lines of listing and write */
for (i=0; i<3; i++) {
if (fgets(lline, maxline-2, listing) == NULL) {
fprintf(stderr, "Cannot read from listing file\n");
exit(1);
}
fputs(lline, errlist);
}
/* get first symbol and start recursive descent */
getsym();
program();
/* if we are here, the input is ok. */
/* write code array on code file */ /* cg */
strcat(cname, ".cod"); /* cg */
if ((intcode = fopen(cname, "w")) == NULL) { /* cg */
fprintf(stderr,
"Cannot open intermediate code file %s\n",
cname); /* cg */
exit(1); /* cg */
} /* cg */
writecode(); /* cg */
fclose(intcode); /* cg */
/* close files */
fclose(token);
fclose(listing);
fclose(errlist);
fclose(stlist);
/* erase listing file */
unlink(lname);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -