📄 pl0.c
字号:
{
if(sym == whilesym)
{
cx1 = cx;
getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
nxtlev[dosym] = true;
conditiondo(nxtlev,ptx,lev);
cx2 = cx;
gendo(jpc,0,0);
if(sym == dosym)
{
getsymdo;
}
else
{
error(18);
}
statementdo(fsys,ptx,lev);
gendo(jmp,0,cx1);
code[cx2].a = cx;
}
else
{
memset(nxtlev,0,sizeof(bool)*symnum);
testdo(fsys,nxtlev,19);/*<><><><><><><><>语句处理末尾*/
}
}
}
}
}
}
}
return 0;
}
/*
<表达式> ::= [+|-]<项>{<加法运算符><项>}
*/
int expression(bool* fsys,int* ptx,int lev)
{
enum symbol addop;
bool nxtlev[symnum];
if(sym == plus || sym == minus)
{
addop = sym;
getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
nxtlev[plus] = true;
nxtlev[minus] = true;
termdo(nxtlev,ptx,lev);
if(addop == minus)//“-”
{
gendo(opr,0,1);//栈顶置反放栈顶
}
}
else
{
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
nxtlev[plus] = true;
nxtlev[minus] = true;
termdo(nxtlev,ptx,lev);
}
while(sym == plus || sym == minus)
{
addop = sym;
getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
nxtlev[plus] = true;
nxtlev[minus] = true;
termdo(nxtlev,ptx,lev);
if(addop == plus)//+
{
gendo(opr,0,2);
}
else//-
{
gendo(opr,0,3);
}
}
return 0;
}
/*
<项> ::= <因子>{<乘法运算符> <因子>}
*/
int term(bool* fsys,int*ptx,int lev)
{
enum symbol mulop;
bool nxtlev[symnum];
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
nxtlev[times] = true;
nxtlev[slash] = true;
nxtlev[cossym] = true;
nxtlev[sinsym] = true;
nxtlev[tansym] = true;
nxtlev[expsym] = true;
factordo(nxtlev,ptx,lev);
while(sym == times || sym == slash)
{
mulop = sym;
getsymdo;
factordo(nxtlev,ptx,lev);
if(mulop == times)
{
gendo(opr,0,4);
}
else
{
gendo(opr,0,5);
}
}
return 0;
}
/*
<因子> ::= <标识符>|<无符号整数>|'('<表达式>')'
左右括号表示pl0程序正文中的括号,而不是EBNF元语言的括号
*/
int factor(bool* fsys,int* ptx,int lev)
{
int i;
bool nxtlev[symnum];
testdo(facbegsys,fsys,24);/*<><><><><><><><>因子处理的开始*/
while(inset(sym,facbegsys))//facbegsys = {标识符、数字、和左括号}
{
if(sym == ident)//第一种情况
{
i = position(id,*ptx);
if(i == 0)
{
error(11);
}
else
{
switch(table[i].kind)
{
case constant:
gendo(lit,0,table[i].val);
break;
case variable:
gendo(lod,lev-table[i].level,table[i].adr);
break;
case procedur://不可能是过程名
error(21);
break;
}
}
getsymdo;
}
else
{
if(sym == number)
{
if(numlen > MAX_NUM_LENGTH)
{
error(31);
num = 0;
}
gendo(lit,0,num);
getsymdo;
}
else
{
if(sym == cossym || sym == sinsym || sym == tansym || sym == expsym)//
{
enum symbol tmpsym;
tmpsym = sym;
getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
funcdo(nxtlev,ptx,lev);
if(sym == rparen)
{
if(tmpsym == cossym)
{
gen(fun,0,0);//cos
getsymdo;
}
else if(tmpsym == sinsym)
{
gen(fun,0,1);
getsymdo;
}
else if(tmpsym == tansym)
{
gen(fun,0,2);
getsymdo;
}
else
{
gen(fun,0,3);
getsymdo;
}
}
else
{
error(22);
}
}
else if(sym == lparen)//else 为什么不行呢?????
{
getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
nxtlev[rparen] = true;
expressiondo(nxtlev,ptx,lev);
if(sym == rparen)
{
getsymdo;
}
else
{
error(22);
}
}
testdo(fsys,facbegsys,23);/*<><><><><><><><>因子处理的末尾*/
}
}
}
return 0;
}
int func(bool* fsys,int* ptx,int lev)
{
bool nxtlev[symnum];
if(sym == lparen)
{
getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
nxtlev[rparen] = true;
expressiondo(nxtlev,ptx,lev);
}
else
{
printf("Standard function must be followed (\n");
}
return 0;
}
/*
<条件>::=<表达式><关系运算符><表达式>|ODD<表达式>
*/
int condition(bool* fsys,int* ptx,int lev)
{
enum symbol relop;
bool nxtlev[symnum];
if(sym == oddsym)
{
getsymdo;
expressiondo(fsys,ptx,lev);
gendo(opr,0,6);
}
else
{
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
nxtlev[eql] = true;
nxtlev[neq] = true;
nxtlev[lss] = true;
nxtlev[leq] = true;
nxtlev[gtr] = true;
nxtlev[geq] = true;
expressiondo(nxtlev,ptx,lev);
if(sym != eql && sym != neq && sym != lss && sym != leq && sym != gtr && sym != geq)
{
error(20);
}
else
{
relop = sym;
getsymdo;
expressiondo(fsys,ptx,lev);
switch(relop)
{
case eql:
gendo(opr,0,8);
break;
case neq:
gendo(opr,0,9);
break;
case lss:
gendo(opr,0,10);
break;
case geq:
gendo(opr,0,11);
break;
case gtr:
gendo(opr,0,12);
break;
case leq:
gendo(opr,0,13);
break;
}
}
}
return 0;
}
void interpret()
{
int p,b,t; /*指令指针、指令基址、栈顶指针 所谓基址就是每个过程的基址
栈顶是将要存放数据的位置,也就是说t所在位置永远都是空位置*/
struct instruction i;
double s[stacksize]; //运行栈是个局部变量
int loop = 0;//add by daka
int delay = 0;//add by daka
int nl = 0; //add by daka
double tmp;//add by daka
t = 0;
p = 0;
b = 0;
s[0] = s[1] = s[2] = 0;
for(delay=0;delay<80;delay++)
{
loop = 0;
while(loop<5000000)
loop++;
printf(">");
}
do
{
i = code[p];
p++;
switch(i.f)
{
case lit:
s[t] = (double)i.a;
t++;
break;
case opr:
switch(i.a)
{
case 0://过程调用结束后,返回调用点并退栈
t = b;//b指向静态链,于是t+1指向动态链,t+2指向返回地址。
p = (int)s[t+2];
b = (int)s[t+1];
break;
case 1://栈顶元素取反
s[t-1] = -s[t-1];
break;
case 2://次栈顶与栈顶相加,退两个栈元素,结果值进栈
t--;
s[t-1] = s[t-1] + s[t];
break;
case 3://相减
t--;
s[t-1] = s[t-1] - s[t];
break;
case 4://相乘
t--;
s[t-1] = s[t-1] * s[t];
break;
case 5://相除
t--;
s[t-1] = s[t-1] / s[t];
break;
case 6://栈顶元素奇偶判断,奇为真,偶为假,结果值在栈顶
s[t-1] = (int)s[t-1] % 2;
break;
case 8://次栈顶元素与栈顶元素是否相等,退两个栈元素结果值进栈
t--;
s[t-1] = (s[t-1] == s[t]);
break;
case 9://不相等
t--;
s[t-1] = (s[t-1] != s[t]);
break;
case 10://小于
t--;
s[t-1] = (s[t-1] < s[t]);
break;
case 11://大于等于
t--;
s[t-1] = (s[t-1] >= s[t]);
break;
case 12://大于
t--;
s[t-1] = (s[t-1] > s[t]);
break;
case 13://小于等于
t--;
s[t-1] = (s[t-1] <= s[t]);
break;
case 14://栈顶值输出至屏幕,并退栈
printf("[PL0 START]# %lf\n",s[t-1]);
fprintf(fa2,"[PL0 START]# %lf\n",s[t-1]);
t--;
break;
case 15://屏幕输出换行
printf("\n");
fprintf(fa2,"\n");
break;
case 16://从命令行读入 输入置于栈顶
printf("[PL0 START]# ");
fprintf(fa2,"[PL0 START]# ");
scanf("%lf",&(s[t]));
fprintf(fa2,"%lf\n",s[t]);
t++;
break;
}
break;
case fun:
switch(i.a)
{
case 0:
s[t-1] = cos((int)s[t-1]);
break;
case 1:
s[t-1] = sin((int)s[t-1]);
break;
case 2:
s[t-1] = tan((int)s[t-1]);
break;
case 3:
s[t-1] = exp(s[t-1]);
break;
default:
break;
}
break;
case lod://将变量取到栈顶,a为偏移量,l为层差。
s[t] = s[base(i.l,s,b)+i.a];
t++;
break;
case sto://将栈顶内容送入某变量单元中,a为偏移量,l为层差
t--;
s[base(i.l,s,b)+i.a] = s[t];//s是运行时栈,b是当前过程的基址,i.l是当前过程与被调用过程的层差。
break;
/*
PL0调用规则:
1、任意一个过程只能调用它的直接内层过程
2、只要确保不超出范围,任意一个过程可以调用它的任何外过程
3、同层过程
总结:向内调用只能逐层调用,而向外调用则可以跳跃调用。
*/
case cal://过程调用,a为过程地址,l为层差
s[t] = base(i.l,s,b);
s[t+1] = (double)b;
s[t+2] = (double)p;
b = t;
p = i.a;
printf("s[%d]=%d,s[%d]=%d,s[%d]=%d start=%d\n",t,s[t],t+1,s[t+1],t+2,s[t+2],i.a);
fprintf(fa2,"s[%d]=%d,s[%d]=%d,s[%d]=%d start=%d\n",t,s[t],t+1,s[t+1],t+2,s[t+2],i.a);
break;
case inte://在运行栈中为被调用的过程开辟a个单元的数据区。
t += i.a;
break;
case jmp://无条件跳转至a地址
p = i.a;
break;
case jpc://条件跳转,当栈顶布尔值非真时,则跳转至a地址执行,否则顺序执行。
t--;
if(s[t] == 0)
{
p = i.a;
}
break;
}
}while(p != 0);
}
/*
通过过程基址求上L层过程的基址
*/
int base(int l,double *s,int b)
{
int bl;
bl = b;
//当l<=0时,
while(l > 0)
{
bl = (int)s[bl];
l--;
}
return bl;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -