📄 yacc.cpp
字号:
#include "compile.h"
//******************************************************************/
//函数原型:void enterTable(int k)
//参数说明:k: 标识符类型
//函数功能:把标识符放入符号表
//返回值 :无
//******************************************************************/
void enterTable(int k)
{
tableCount++;//注:table[0]不存放内容。当position()函数返回0时,表示未找到。
table[tableCount].kind=k;
table[tableCount].offSet=stackCount;
strcpy( table[tableCount].name, ident);//ident是词法分析中填入的当前标识符
dataStack[stackCount++]=0;//初始化变量的植为0
return;
}
//******************************************************************/
//函数原型:int position(char *id)
//参数说明:id: 被查找的标识符
//函数功能:查找标识符id在table中的位置
//返回值 :如果找到,返回该标识符在table中的下标;否则返回0
//******************************************************************/
int position(char *id)
{
int i=tableCount;
while(i>0)
{
if( strcmp(table[i].name,id) == 0 )//发现匹配
break;
else
i--;
}
return i;
}
//******************************************************************/
//函数原型:void gen(int i, int j)
//参数说明:i: 目标代码类型
// j: 目标代码参数,一般代表位移
//函数功能:产生一条目标代码
//返回值 :无
//******************************************************************/
void gen(int i, int j)
{
code[codeCount].funCode=i;
code[codeCount++].offset=j;
}
//******************************************************************/
//函数原型:void yacc_prog()
//参数说明:无
//函数功能:语法分析分程序之prog
//返回值 :无
//******************************************************************/
void yacc_prog()
{
if(sym != PROGRAM)
errorOccur(1);//缺少关键字program
else
getSym();
yacc_ds();
if(sym != BEGIN)
errorOccur(2);//缺少关键字begin
else
getSym();
yacc_ss();
if(sym != END)
errorOccur(3);//缺少关键字end
else
printf("yacc completed\n");
return;
}
//******************************************************************/
//函数原型:void yacc_ds()
//参数说明:无
//函数功能:语法分析分程序之ds
//返回值 :无
//******************************************************************/
void yacc_ds()
{
yacc_d();
while(sym == SEMICOLON)
{
getSym();
yacc_d();
}
gen(INT,stackCount);//stackCount表示当前数据栈的大小,也就是变量的个数,需要为这些变量预留空间
return;
}
//******************************************************************/
//函数原型:void yacc_ss()
//参数说明:无
//函数功能:语法分析分程序之ss
//返回值 :无
//******************************************************************/
void yacc_ss()
{
yacc_s();
while(sym == SEMICOLON)
{
getSym();
yacc_s();
}
return;
}
//******************************************************************/
//函数原型:void yacc_d()
//参数说明:无
//函数功能:语法分析分程序之d
//返回值 :无
//******************************************************************/
void yacc_d()
{
switch(sym)
{
case INTEGER:
getSym();
if(sym != IDENT)
errorOccur(4);//缺少一个标识符,语法分析中止
else
{
enterTable(INTEGER);
getSym();
while(sym == COMMA)
{
getSym();
if(sym != IDENT)
errorOccur(4);//缺少一个标识符,语法分析中止
else
{
enterTable(INTEGER);
getSym();
}
}
}
break;
case LOGICAL:
getSym();
if(sym != IDENT)
errorOccur(4);//缺少一个标识符,语法分析中止
else
{
enterTable(LOGICAL);
getSym();
while(sym == COMMA)
{
getSym();
if(sym != IDENT)
errorOccur(4);//缺少一个标识符,语法分析中止
else
{
enterTable(LOGICAL);
getSym();
}
}
}
break;
}
return;
}
//******************************************************************/
//函数原型:void yacc_s()
//参数说明:无
//函数功能:语法分析分程序之s
//返回值 :无
//******************************************************************/
void yacc_s()
{
int i;
int temp,temp2;
switch(sym)
{
/********************* IDENT *********************/
case IDENT:
i=position(ident);//ident是词法分析中填入的当前标识符
if(i == 0)
errorOccur(5);//标识符未定义,定义后才可以使用
/************ INTEGER *************/
if(table[i].kind == INTEGER)
{
temp=table[i].offSet;
getSym();
if(sym != BECOMES)
errorOccur(6);//此处需要有:=
else
getSym();
yacc_ae();
gen(STO,temp);
}
/************ LOGICAL *************/
else
{
temp=table[i].offSet;
getSym();
if(sym != BECOMES)
errorOccur(6);//此处需要有:=
else
getSym();
yacc_be();
gen(STO,temp);
}
break;
/********************** IF ***********************/
case IF:
getSym();
yacc_be();
temp=codeCount;//记下目标代码的序号,也即下面gen()产生的跳转指令的序号,用于以后回填
gen(JPC,0);
if(sym != THEN)
errorOccur(7);//缺少关键字then
else
getSym();
yacc_ss();
if(sym == ELSE)
{
//ELSE
code[temp].offset=codeCount;//回填if语句的假出口
getSym();
yacc_ss();
}
//END
if(sym != END)
errorOccur(3);//缺少关键字end
else
{
if(code[temp].offset == 0)
{
//假如条件成立,表示该if语句没有else分句,
//所以上面的回填没有执行,需要在此处回填
code[temp].offset=codeCount;
}
getSym();
}
break;
/********************* WHILE *********************/
case WHILE:
getSym();
temp2=codeCount;//记下目标代码的序号,也即条件判断语句的起始序号,用于一次循环后跳转回来
yacc_be();
temp=codeCount;//记下目标代码的序号,也即下面gen()产生的跳转指令的序号,用于以后回填
gen(JPC,0);
if(sym != DO)
errorOccur(8);//缺少关键字do
else
getSym();
yacc_ss();
if(sym != END)
errorOccur(3);//缺少关键字end
else
{
gen(JMP,temp2);//跳转到条件判断语句的起始序号
code[temp].offset=codeCount;//回填while语句的出口
getSym();
}
break;
/********************* REPEAT ********************/
case REPEAT:
getSym();
temp=codeCount;//记下目标代码的序号,也即循环体的起始序号,用于一次循环后跳转回来
yacc_ss();
if(sym != UNTIL)
errorOccur(9);//缺少关键字until
else
getSym();
yacc_be();
gen(JPC,temp);//假如判断失败,则跳回至上面的循环体;否则顺序执行下去
break;
/********************* WRITE *********************/
case WRITE:
getSym();
yacc_ae();
gen(WRT,0);
break;
default:
errorOccur(10);//此处需要aident,bident,if,while,repeat,write中的一个
break;
}
return;
}
//******************************************************************/
//函数原型:void yacc_ae()
//参数说明:无
//函数功能:语法分析分程序之ae
//返回值 :无
//******************************************************************/
void yacc_ae()
{
if(sym == MINUS)
{
getSym();
yacc_at();
while(sym == MINUS || sym == PLUS)
{
if(sym == MINUS)
{
getSym();
yacc_at();
gen(OPR,OPR_MINUS);
}
else
{
getSym();
yacc_at();
gen(OPR,OPR_PLUS);
}
}
gen(OPR,OPR_OPPO);
}
else
{
yacc_at();
while(sym == MINUS || sym == PLUS)
{
if(sym == MINUS)
{
getSym();
yacc_at();
gen(OPR,OPR_MINUS);
}
else
{
getSym();
yacc_at();
gen(OPR,OPR_PLUS);
}
}
}
return;
}
//******************************************************************/
//函数原型:void yacc_at()
//参数说明:无
//函数功能:语法分析分程序之at
//返回值 :无
//******************************************************************/
void yacc_at()
{
yacc_af();
while(sym == TIMES || sym == SLASH)
{
if(sym == TIMES)
{
getSym();
yacc_af();
gen(OPR,OPR_TIMES);
}
else
{
getSym();
yacc_af();
gen(OPR,OPR_SLASH);
}
}
return;
}
//******************************************************************/
//函数原型:void yacc_af()
//参数说明:无
//函数功能:语法分析分程序之af
//返回值 :无
//******************************************************************/
void yacc_af()
{
int i;
switch(sym)
{
/********************* IDENT *********************/
case IDENT:
i=position(ident);//ident是词法分析中填入的当前标识符
if(i == 0)
errorOccur(5);//标识符未定义,定义后才可以使用
if(table[i].kind == INTEGER)
{
gen(LOD,table[i].offSet);
getSym();
}
else
{
errorOccur(11);//此处需要aident,不能是bident
}
break;
/********************* NUMBER ********************/
case NUMBER:
gen(LIT,num);//num,全局变量,存放当前被取到的常数
getSym();
break;
/********************* LPAREN ********************/
case LPAREN:
getSym();
yacc_ae();
if(sym != RPAREN)
errorOccur(12);//此处需要有)
else
getSym();
break;
default:
errorOccur(13);//此处需要aident,NUMBER,LPAREN中的一个
break;
}
return;
}
//******************************************************************/
//函数原型:void yacc_be()
//参数说明:无
//函数功能:语法分析分程序之be
//返回值 :无
//******************************************************************/
void yacc_be()
{
yacc_bt();
while(sym == OR)
{
getSym();
yacc_bt();
gen(OPR,OPR_OR);
}
return;
}
//******************************************************************/
//函数原型:void yacc_bt()
//参数说明:无
//函数功能:语法分析分程序之bt
//返回值 :无
//******************************************************************/
void yacc_bt()
{
yacc_bf();
while(sym == AND)
{
getSym();
yacc_bf();
gen(OPR,OPR_AND);
}
return;
}
//******************************************************************/
//函数原型:void yacc_bf()
//参数说明:无
//函数功能:语法分析分程序之bf
//返回值 :无
//******************************************************************/
void yacc_bf()
{
int i;
switch(sym)
{
/********************* IDENT *********************/
case IDENT:
i=position(ident);//ident是词法分析中填入的当前标识符
if(i == 0)
errorOccur(5);//标识符未定义,定义后才可以使用
if(table[i].kind == LOGICAL)
{
gen(LOD,table[i].offSet);
getSym();
}
else
{
yacc_re();//如果不是bident,可能是aident,可以进入到re过程继续进行分析
}
break;
/********************* TRUE **********************/
case TRUE:
gen(LIT,TRUE);
getSym();
break;
/********************* FALSE *********************/
case FALSE:
gen(LIT,FALSE);
getSym();
break;
/********************** NOT **********************/
case NOT:
getSym();
yacc_bf();
gen(OPR,OPR_OPPO);
break;
/********************* LPAREN ********************/
case LPAREN:
getSym();
yacc_be();
if(sym != RPAREN)
errorOccur(12);//此处需要有)
else
getSym();
break;
/******************** yacc_re() ******************/
default:
yacc_re();
break;
}
return;
}
//******************************************************************/
//函数原型:void yacc_re()
//参数说明:无
//函数功能:语法分析分程序之re
//返回值 :无
//******************************************************************/
void yacc_re()
{
int i;
switch(sym)
{
/********************* IDENT *********************/
case IDENT:
i=position(ident);//ident是词法分析中填入的当前标识符
if(i == 0)
errorOccur(5);//标识符未定义,定义后才可以使用
if(table[i].kind == INTEGER)
{
gen(LOD,table[i].offSet);
getSym();
}
else
{
errorOccur(11);//此处需要aident,不能是bident
}
break;
/********************* NUMBER ********************/
case NUMBER:
gen(LIT,num);//num,全局变量,存放当前被取到的常数
getSym();
break;
default:
errorOccur(14);//此处需要aident,NUMBER中的一个
break;
}
switch(sym)
{
case EQL:
getSym();
yacc_ae();
gen(OPR,OPR_EQL);
break;
case GTR:
getSym();
yacc_ae();
gen(OPR,OPR_GTR);
break;
case GEQ:
getSym();
yacc_ae();
gen(OPR,OPR_GEQ);
break;
case LSS:
getSym();
yacc_ae();
gen(OPR,OPR_LSS);
break;
case LEQ:
getSym();
yacc_ae();
gen(OPR,OPR_LEQ);
break;
default:
errorOccur(15);//此处需要=,>,>=,<,<=中的一个
}
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -