语法分析实验报告.docx
《语法分析实验报告.docx》由会员分享,可在线阅读,更多相关《语法分析实验报告.docx(23页珍藏版)》请在冰豆网上搜索。
![语法分析实验报告.docx](https://file1.bdocx.com/fileroot1/2022-12/14/81a273ad-3cb0-4b64-9d7a-0cbac39f731c/81a273ad-3cb0-4b64-9d7a-0cbac39f731c1.gif)
语法分析实验报告
编译原理实验报告
实验题目:
语法分析器构造
指导教师:
姓名:
班级:
学号:
实验成绩:
实验题目
语法分析器
实验目的和要求
实验目的:
在语法分析器原理学习和词法分析器实验基础上,学生自行设计实现一个高级语言语法分析器。
通过实验使学生能够把原理和实现方法应用到如搜索引擎、描述语言语法分析等词法分析器的设计中去。
借助于词法分析程序提供的分析结果,设计一个算符优先语法分析程序,程序能进行语法结构分析和错误检查并产生相应的归约信息。
同时给出出错信息和错误类型,从而加深对语法分析的理解。
实验要求:
实验结束写出实验报告。
内容包括:
实验课题名称、实验目的和要求,实验的实现(包括主要设计思想、实现算法、主要技术问题的处理方法及实验结果)结论分析。
设计思想与框架
设计思想与框架:
通过课堂教学详细讲解语法分析器的基本原理,以及设计实现的基本方法,并通过一个实际语法分析器的案例分析,示范设计实现过程中的关键技术和技术难点,一般不规定具体的实现语言。
首先规定算符,这里是文法的终极符之间的优先关系,然后根据这种优先关系,通过比较相邻算符的优先次序来确定句型中的“句柄”,然后进行归约。
算符优先分析法的关键:
算符优先分析法的关键就是寻找当前句型中的最左素短语,并归约它。
核心算法
核心算法:
语法分析前首先要对输入的文法和句子进行词法分析,去除多余的字符(空格、回车符等),并将产生式和终结符、非终结符填入有关数组,为语法分析做前期准备。
用于构建输入文法的算符优先表,并在构建过程中检查该文法是否为算符优先文法,如果在构建过程中对同一对终结符计算出两次不一样的优先关系,则报错并停止接下来的任何步骤。
源程序及注释
本语法分析器所分析的源程序为:
#include
intmain()
{
inta,b,c;
a=1;
b=2;
c=a+b;
c=2*(a+b);
printf("c=%d\n",c);
}
语法分析程序为:
#include
#include
#include
////////////////////////////存放归约步骤的一个整形数组///////////////////////////////
intstep_result[1000];//存放归约步骤的一个全局数组
intstep_result_len=0;//统计全局数组的长度每次清零应该
////////////////////////////////定义文法符号优先表用int型矩阵表示///////////////////
intMatux[8][8]={{1,1,-1,-1,-1,1,-1,1},{1,1,-1,-1,-1,1,-1,1},{1,1,1,1,-1,1,-1,1},{1,1,1,1,-1,1,-1,1},
{-1,-1,-1,-1,-1,0,-1,-3},{1,1,1,1,-2,1,-2,1},{1,1,1,1,-2,1,-2,1},{-1,-1,-1,-1,-1,-4,-1,0}};
char*STR[6]={"N+N","N-N","N*N","N/N","(N)","i"};//定义文法可规约可归约字符串
charstack[100];//定义符号栈
intstack_len=0;//定义初始化符号栈的长度为0
intGetchar_len=0;//定义取得字符的全局在窜中的变量
////////////////////////////////////////////////////////////////////////////////////////
boolIsLetter(charch)//判断当前ch是否为字符///////////////////////////////////////////
{
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
{
return1;//如果ch是字母则返回1
}
else
{
return0;//如果不是字母则返回0
}
}
boolIsDigit(charch)//判断当前ch是否为数字/////////////////////////////////////////////
{
if(ch>='0'&&ch<='9')
{
return1;//如果ch是数字则返回1
}
else
{
return0;//如果不是数字则返回0
}
}
/////////////////////求出终结符对应的优先表矩阵中的行列位置的函数//////////////////////
intFind_two_table(charch)//求出对应的优先表的行数和列数的一个函数
{
switch(ch)
{
case'+':
return0;
case'-':
return1;
case'*':
return2;
case'/':
return3;
case'(':
return4;
case')':
return5;
case'i':
return6;
case'#':
return7;
default:
return-1;
}
}
////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////根据预处理求出算数分析的表达式存放在一个二维数组里面的一个函数///////////////
intFind_num_string(charnum_string[100][100])
{
inti,j,flag;
charch,old_ch='',string[20];
FILE*fp;
printf("您好!
请您输入预处理程序的文件名称:
");
gets(string);
if((fp=fopen(string,"r"))==NULL)//打开文件,如果打开失败则提示
{
printf("您打开的文件不存在,请您重新打开文件\n");//文件打开失败提示打开的文件不存在
}
i=0;
while(!
feof(fp))
{
j=0;
ch=fgetc(fp);
while(ch!
='='&&!
feof(fp))
{
old_ch=ch;
ch=fgetc(fp);
}
if(old_ch!
='>'&&old_ch!
='<'&&old_ch!
='!
')
{
ch=fgetc(fp);
if(ch!
='=')
{
while(ch!
=';'&&!
feof(fp))
{
num_string[i][j]=ch;
ch=fgetc(fp);
j++;
}
i++;
num_string[i][j]='\0';
}
}
}
flag=i-1;
fclose(fp);
returnflag;
}
/////////////////////////将求出的算术表达式转化成可输入串的函数/////////////////////////
voidConvert_input_string(charnum_string[100],charinput_string[100])
{
inti=0,i_input_str=0;
charch,flag_ch;
/////////////////////begin////////////////////////////////
ch=num_string[i];
while(ch!
='\0')
{
if(IsDigit(ch))
{
flag_ch='0';
}
else
{
if(IsLetter(ch))
{
flag_ch='a';
}
else
{
flag_ch=ch;
}
}
switch(flag_ch)
{
case'a':
{
while((IsLetter(ch)||IsDigit(ch)||ch=='_')&&ch!
='\0')
{
i++;
ch=num_string[i];
}
input_string[i_input_str]='i';
i--;
break;
}
case'0':
{
while((IsDigit(ch)||ch=='.')&&ch!
='\0')
{
i++;
ch=num_string[i];
}
input_string[i_input_str]='i';
i--;
break;
}
case'':
{
break;
}
default:
{
input_string[i_input_str]=ch;
break;
}
}
i++;
ch=num_string[i];
if(ch!
='')
{
i_input_str++;
}
}
input_string[i_input_str]='#';
//////////////////////end///////////////////////
return;
}
////////////////////自动取得是规约串中字符的一个函数///////////////////
charGetchar(charinput_string[100])
{
charch;
inti,len;
charinput_string_temp[100]={'\0'};
len=strlen(input_string);
ch=input_string[0];
for(i=1;i{
input_string_temp[i-1]=input_string[i];
if(input_string[i-1]=='#')
{
break;
}
}
strcpy(input_string,input_string_temp);
returnch;
}
//////////////////////判断是否是终结符///////////////////////////////
boolChar_IsVt(charch)
{
if(Find_two_table(ch)>=0&&Find_two_table(ch)<=9)
{
return1;
}
else
{
return0;
}
}
///////////////////////判断终结符之间的优先关系的一个函数////////////////
intFind_relaion(charstack_ch,charch)//找出终结符之间的优先关系的一个函数
{
introw,lie,result;
row=Find_two_table(stack_ch);
lie=Find_two_table(ch);
if((lie<0||lie>7)&&ch!
='N')
{
//printf("非法标识符%c",ch);
return-10;
}
result=Matux[row][lie];
returnresult;//返回终结符对应的行数或者是列数
}
////////////////////////////出错处理子程序///////////////////////////////
voidProcess_Error(intreturn_num)
{
if(return_num==-2)//出错处理函数,一共有三种错误情况
{
printf("Error!
算术表达式缺少运算符,请查看更改!
\n");
}
else
{
if(return_num==-3)
{
printf("Error!
算术表达式缺少右括号,请查看更改!
\n");
}
else
{
if(return_num==-4)
{
printf("Error!
算术表达式缺少左括号,请查看更改!
\n");
}
}
}
return;//函数结束
}
////////////////////处理一个算术表达式的规约过程的函数///////////////////
voidmain_analyous(charinput_string[100])
{
intk,step=1,i,j,flag=0,p;intflag_temp=0,input_string_len;
charch,q_ch;
charstack[100]={'\0'},temp_str[20]={'\0'};
k=1;
stack[k]='#';
printf("步骤号动作优先关系当前分析符符号栈剩余输入串\n");
printf("1预备<#%s\n",input_string);
ch=Getchar(input_string);
charstack_pop='';
while(stack_pop!
='#')
{
if(Char_IsVt(ch))
{
j=k;
}
else
{
j=k-1;
}
interror;
//////////////////判断输入串中是不是存在非法符号的存在则返回-10/////////////
error=Find_relaion(stack[j],ch);
if(error==(-10))
{
printf("输入串中存在非法符号%c,输入串分析结束!
\n",ch);
return;
}
///////////////////////////////////////////////////////////////////////////
while(Find_relaion(stack[j],ch)==1)
{
for(inth=0;h<20;h++)//每次规约过程中存放可归约变量清零
{
temp_str[h]='\0';
}
flag=0;//////////////////每次规约flag清零//////////////////
do
{
q_ch=stack[j];
if(Char_IsVt(stack[j-1]))
{
j=j-1;
}
else
{
j=j-2;
}
}while((Find_relaion(stack[j],q_ch)==1)||(Find_relaion(stack[j],q_ch)==0));
/////////////////////////////////////////////////////////////////////////
p=j+1;
temp_str[flag]=stack[p];//将stack[j+1]的字符给临时数组temp+str中进行和产生式右部进行比较
while(p{
p=p+1;
flag++;
temp_str[flag]=stack[p];
}
for(i=0;i<6;i++)
{
if(strcmp(temp_str,STR[i])==0)
{
while(p{
p=p+1;
stack[p]='\0';
}
k=j+1;
stack[k]='N';
/////////////////////////////输出归约过程的一行的代码/////////////////////////////////////////////////////
step++;
step_result[step_result_len]=step;
step_result_len++;
printf("%4d",step);
printf("归约");
printf(">");
printf("%7c",ch);
printf("");
for(intr=1;r<=k;r++)
{
printf("%c",stack[r]);
}
for(r=0;r<12-k;r++)
{
printf("");
}
input_string_len=strlen(input_string);
for(r=0;r<=input_string_len;r++)
{
printf("%c",input_string[r]);
}
printf("\n");
//////////////////////////////////////////////////////////////////////////////////////////////////////////
flag_temp=1;
break;
}
}
if(flag_temp==0)
{
printf("Error!
没有这样的产生式!
\n");
}
}
///////////////////stack[j+1]到stack[k]规约过程结束//////////////////
if((Find_relaion(stack[j],ch)==-1)||(Find_relaion(stack[j],ch)==0))
{
k=k+1;
stack[k]=ch;
}
else
{
interror;
error=Find_relaion(stack[j],ch);
Process_Error(error);
return;
}
//////////////////////////输出归约过程的一行的代码////////////////////////////////
step++;
printf("%4d",step);
printf("移进");
if(Find_relaion(stack[j],ch)==-1)
{
printf("<");
}
if(Find_relaion(stack[j],ch)==0)
{
printf("=");
}
printf("%7c",ch);
printf("");
for(intr=1;r<=k;r++)
{
printf("%c",stack[r]);
}
for(r=0;r<12-k;r++)
{
printf("");
}
input_string_len=strlen(input_string);
for(r=0;r<=input_string_len;r++)
{
printf("%c",input_string[r]);
}
printf("\n");
/////////////////////////////////////////////////////////////////////////////////////////
ch=Getchar(input_string);
stack_pop=stack[k];
}
////////////////////判断最终规约后的符号栈中是否是#N#形式,如果是那么久分析正确////
if((stack[1]=='#')&&(stack[2]=='N')&&(stack[3]=='#'))
{
printf("输入的算术表达式正确!
\n");
}
else
{
printf("您输入的算术表达式有错误,请检查!
\n");
}
return;
}
/////////////////////////打印每个算术表达式求解的归约过程的一个函数/////////////////////
voidPrint_step()
{
inti;
for(i=0;i{
printf("%d",step_result[i]);
}
printf("\n");
step_result_len=0;
}
////////////////////main()/////////////////////////////
intmain()
{
inti,j,len,result;
charnum_string[100][100]={'\0'};
charresult_string[100];
printf("******************************算符优先语法分析程序***************************\n");
printf("*E->E+T|E-T|T分析的是四则混合运算的文法*\n");
printf("*T->T*F|T/F|F其中:
E表示算术表达式;T表示项;*\n");
printf("*F->(E)|ii表示变量或常数;*\n");
printf("*****************************************************************************\n");
printf("*终结符优先表*\n");
printf("*+-*/(