编译原理实验一.docx
《编译原理实验一.docx》由会员分享,可在线阅读,更多相关《编译原理实验一.docx(43页珍藏版)》请在冰豆网上搜索。
![编译原理实验一.docx](https://file1.bdocx.com/fileroot1/2022-10/20/8ae97ef6-5ef2-42f8-bc3c-3e8feb09c297/8ae97ef6-5ef2-42f8-bc3c-3e8feb09c2971.gif)
编译原理实验一
实验一编译程序的分析与验证
一、实验目的
了解编译程序中LR分析表的作用以及语义加工程序的功能
二、实验内容
(1)验证下述程序的正确性
while(a<=b)do
begin
ifm>=nthena:
=a+1
else
ifj>itheni=i+j
else
whilek=hdox:
=x+2;
m:
=n+m+x+y+n*m+x*y
end#~
三、编译程序理解
输入文件名,取一个字符,程序扫描,词法分析结果打印,变量名表打印,语句分析栈初始化,符号栈初始化,四元式空白初始化,状态栈加工过程及归约顺序,读结果缓冲区中字符到当前字符中,语句分析,四元式分析结果打印,程序运行结束。
具体函数功能介绍:
charch='\0';//可用于存放读出的一个字符
intcount=0;//词法分析结果缓冲区计数器
staticcharspelling[10]={""};//存放是别的字
staticcharline[81]={""};//一行字符缓冲区
char*pline;//line的指针
staticcharntab1[100][10];//变量类型名表
structntab
{
inttc;//真
intfc;//假
}ntab2[200];//用于存放布尔表达式的值
intlabel=0;//指向ntab2的指针
structrwords
{
charsp[10];
intsy;
};//匹配表结构体
structrwordsreswords[10]={{"if",sy_if},
{"do",sy_do},
{"else",sy_else},
{"while",sy_while},
{"then",sy_then},
{"begin",sy_begin},
{"end",sy_end},
{"and",op_and},
{"or",op_or},
{"not",op_not}};//初始化匹配表,用于关键字的匹配
structaa
{
intsy1;//存放变量的类型名
intpos;//存放该变量在自己表中的位置
}buf[1000],//词法分析结果缓冲区
n,//存放二元式当前字符
n1,//表达式当前的字符
E,//非终结符
sstack[100],//算术表达式和布尔表达式的符号栈
ibuf[100],//算术表达式和布尔表达式的缓冲区
stack[1000];//语法分析的符号栈
structaaoth;//四元式中没有填写的空白位置
structfourexp//四元式结构体
{
charop[10];
structaaarg1;
structaaarg2;
intresult;
}fexp[200];
intssp=0;//指向sstack的指针
structaa*pbuf=buf;//词法分析结果缓冲区的指针
intnlength=0;//词法分析中记录单词的长度
intlnum=0;//行数计数源程序
inttt1=0;//变量类型名表的指针
FILE*c源程序文件
/********************************************************/
intnewt=0;//临时变量计数器
intnxq=100;//总是指向下一个要形成的四元式每次执行gen()
intlr;//用于存放action1中的当前状态
intlr1;//用于存放action2,3中的当前状态
intsp=0;//LR分析表栈顶指针
intstack1[100];//状态栈1
intsp1=0;//状态栈的指针
intnum=0;//算术表达式或布尔表达式的指针
structll
{
intnxq1;//指向下一条四元式的指针
inttc1;//真值链
intfc1;//假值链
}labelmark[10];//记录嵌套中每层布尔表达式e的首地址
intlabeltemp[10];//记录每层else之前四元式的地址
intpointmark=-1,pointtemp=-1;//labelmark的指针,labelmark的指针
intsign=0;//sign=1赋值语句,sign=2while语句,sign=3if语句
构造程序语句的LR分析表
算术表达式的LR分析表
布尔表达式的LR分析表
readline()//读一行
{
charch1;
pline=line;
ch1=fgetc(c从文件中取一个
while((ch1!
='\n')&&(ch1!
=EOF))//把字符缓冲区填满
{
*pline=ch1;
pline++;
ch1=fgetc(cfile);
}
*pline='\0';//结尾终结符
pline=line;//字符缓冲区指针重新回到字符缓冲区的第一个字符位置
}
/**********************从缓冲区读取一个字符*********************/
readch()//读一个
{
if(ch=='\0')//读到尾姐再来一行,行数加一
{
readline();
lnum++;
}
ch=*pline;//从行缓冲区读取一个字符
pline++;//字符缓冲区指针后移
}
/***********************标识符和关键字的识别********************/
find(charspel[])//在变量表中查询
{
intss1=0;//是否查到的变量的标志(1为查到,0为没查到)
intii=0;//记录查到变量表第几条
while((ss1==0)&&(ii{
if(!
strcmp(spel,ntab1[ii]))
ss1=1;
ii++;
}
if(ss1==1)//查到了
returnii-1;//返回在表量表的地址(-1的原因是上面的ii++最后多加了一次)
elsereturn-1;//没查到,返回-1
}
identifier()//关键字或变量或常量查询
{
intiii=0,j,k;//iii关键字表中的指针位置
intss=0;//关键字是否匹配到的标识
k=0;//存放的识别的字的指针(spelling[k])
do//将取出的字符放入识别的字spelling数组中
{
spelling[k]=ch;
k++;
readch();//取一个字符
}while(((ch>='a')&&(ch<='z'))||((ch>='0')&&(ch<='9')));//数字或小写字母
pline--;//取字时多加的一个,-1可使*pline指向字符缓冲区行尾
spelling[k]='\0';
while((ss==0)&&(iii<10))
{
if(!
strcmp(spelling,reswords[iii].sp))//在关键字表中查询
ss=1;//查到标志置1
iii++;
}
/*关键字匹配*/
if(ss==1)//在关键字表中查到
{
buf[count].sy1=reswords[iii-1].sy;//关键字名字放入结果缓冲区
}
else//没查到
{
buf[count].sy1=ident;//将变量名置入结果缓冲区
j=find(spelling);//变量表查询,查到就把变量在变量表的地址赋给j
if(j==-1)//没查到就新建一个变量
{
buf[count].pos=tt1;//将其在变量表中的地址放入结果缓冲区中的地址栏
strcpy(ntab1[tt1],spelling);//将识别的变量名放入变量名表
tt1++;
nlength++;//变量名表长加一
}
elsebuf[count].pos=j;//查到后,将变量名表中变量的地址放入结果缓冲区该变量的地址栏中
}
count++;//指向结果缓冲区下一位置
for(k=0;k<10;k++)spelling[k]='';//以识别的临时字符清空
}
/**********************数字识别*************************/
number()
{
intivalue=0;
intdigit;
do
{
digit=ch-'0';//取出的字符转换为数字
ivalue=ivalue*10+digit;//数字地址从10后开始记录
readch();//取一个字符
}while((ch>='0')&&(ch<='9'));
buf[count].sy1=intconst;//常量名存入结果缓冲区
buf[count].pos=ivalue;//该常量地址存入结果缓冲区
count++;//向结果缓冲区下一位置
pline--;//指向行缓冲区尾字符
}
scan()//扫描主程序
readnu()//读取当前结果缓冲区的二元式存入structaan中,pbuf指向结果缓冲区中下一位置的指针
newtemp()//返回目前临时变量数
gen(charop1[],structaaarg11,structaaarg22,intresult1)//op1算符,arg11操作数1,arg22操作数2,result1结果
merg(intp1,intp2)//将链首“指针”分别为p1和p2的两条链合并为一条,并返回新链的链首“指针”(此处的“指针”实际上是四元式的序号,应为整型值)
backpatch(intp,intt)//用四元式序号t回填以p为首的链,将链中每个四元式的Result域改写为t的值。
change1(intchan)//action1的符号查找排序(i,+,*,(,),#,E,-,/)
change2(intchan)//action2的符号查找排序
lrparse1(intnum)//算数表达式语义分析
lrparse2(intnum)//布尔表达式的分析
test(intvalue)//测试字符是否为表达式中的值(不包括":
")
lrparse()//程序语句分析
disp1()//打印词法分析结果
disp2()//打印四元式分析结果
disp3()//打印变量表名
main()//主函数
四、A语言程序分析与验证
五、源码(带注释)
#include"stdio.h"
#include"string.h"
#defineACC-2
/**************************************/
#definesy_if0
#definesy_then1
#definesy_else2
#definesy_while3
#definesy_begin4
#definesy_do5
#definesy_e