词法分析器计算器设计及实现实验报告.docx
《词法分析器计算器设计及实现实验报告.docx》由会员分享,可在线阅读,更多相关《词法分析器计算器设计及实现实验报告.docx(23页珍藏版)》请在冰点文库上搜索。
![词法分析器计算器设计及实现实验报告.docx](https://file1.bingdoc.com/fileroot1/2023-6/27/70800ad0-9aea-4eb4-9855-573e3c04e772/70800ad0-9aea-4eb4-9855-573e3c04e7721.gif)
词法分析器计算器设计及实现实验报告
辅导教师张静成绩
实验日期
实验时间
1实验名称:
词法分析器的设计与实现
2、实验目的
(1)掌握C语言单词符号的划分、正规式、状态转换图及词法分析器的实现。
(2)掌握词法分析程序的作用。
3、实验要求
(1)对任给的一个C语言源程序,能够滤掉空格、回车换行符、tab键及注释。
(2)识别各类单词符号,如关键字、标识符、运算符、常数、界符,结果以二元式形式输出,并构造符号表。
(3)输出有词法错误的单词及所在行号。
(在此阶段只能识别有限的词法错误)
4、实验原理
根据扫描到的单词符号的第一个字符的种类,分别转到相应的程序进行处理。
这些程序的功能就是识别以相应字符开头的各类单词符号。
5、实验步骤
(1)根据C语言各类单词的正规式,构造能识别各类单词的状态转换图。
(2)根据状态转换图,构造识别各类单词的词法分析器。
6、状态转换图及词法分析程序
状态转换图:
词法分析程序:
#include
#include
#include
#include
usingnamespacestd;
stringkeywords[20]={"include","void","main","int","char","float","double","if","else","then","break","continue","for","do","while","printf","scanf","begin","end","return"};
charrz[99999]="";
stringid[10000];
intpp=0;
stringnu[10000];
intqq=0;
intchoice1(chara)//判断是否是字母
{
if((a>='a'&&a<='z')||(a>='A'&&a<='Z'))
return1;
elsereturn0;
}
intchoice2(chara)//判断是否是数字
{
if(a>='0'&&a<='9')
return1;
elsereturn0;
}
intalpha(intst)//识别保留字和标识符
{
charwordbuf[20]="";
intn=0;
for(;;)
{
wordbuf[n]=rz[st];
st++;
n++;
if((choice2(rz[st])==1)||(choice1(rz[st])==1)||(rz[st]=='_'))
wordbuf[n]=rz[st];
elsebreak;
}
intflag=0;
for(intk=0;k<20;k++)
{
if(strcmp(keywords[k].c_str(),wordbuf)==0)flag=1;
}
if(flag==0)
{
intflagg=-1;
for(intt=0;t{
if(strcmp(id[t].c_str(),wordbuf)==0)
{
flagg=t;
}
}
if(flagg!
=-1)printf("(id,%d)",flagg);
else
{
id[pp]=wordbuf;
printf("(id,%d)",pp);
pp++;
}
}
else
{
printf("(");
for(inti=0;i{
printf("%c",wordbuf[i]);
}
printf(",-)");
}
returnst;
}
intnumber(intst)//识别整数
{
charnumbuf[20]="";
intn=0;
intk=0;
intflag=0;
for(;;)
{
numbuf[n]=rz[st];
st++;
n++;
if(choice2(rz[st])==1)
{
numbuf[n]=rz[st];
}
elseif((k==0)&&(rz[st]=='.'))
{
numbuf[n]=rz[st];
k++;
}
elseif(choice1(rz[st])==1)
{
numbuf[n]=rz[st];
flag=1;
continue;
}
elsebreak;
}
if(flag==0)
{
intflagg=-1;
for(intt=0;tif(strcmp(nu[t].c_str(),numbuf)==0)
flagg=t;
if(flagg!
=-1)printf("(nu,%d)",flagg);
else
{
nu[qq]=numbuf;
printf("(nu,%d)",qq);
qq++;
}
}
else
{
printf("(");
for(inti=0;iprintf(",errordigital!
)");
}
returnst;
}
intanotation(intst)//处理除号/和注释
{
chartabuf[9999]="";
intn=0;
st++;
if(rz[st]=='/')
{
printf("(//,-)");
st++;
while(rz[st]!
=10)
{
tabuf[n]=rz[st];
st++;
n++;
}
printf("\n注释");
for(inti=0;iprintf("%c",tabuf[i]);
}
elseif(rz[st]=='*')
{
printf("(/*,-)");
st++;
intstt=st+1;
while
(1)
{
if(rz[st]=='*'&&rz[st+1]=='/')break;
tabuf[n]=rz[st];
st++;
n++;
if(rz[st+1]=='\0')
{
printf("(/*error!
!
\n)");
returnst+1;
}
}printf("\n注释");
for(inti=0;iprintf("%c",tabuf[i]);
printf("(*/,-)");
st=st+2;
}
elseif(rz[st]=='=')
{
st++;
printf("(/*,-)");
}
elseprintf("(/,-)");
returnst;
}
intother(intst)//函数识别其他特殊字符
{
switch(rz[st])
{
case'=':
st++;
if(rz[st]=='=')
{
st++;
printf("(rlop,==)");
}
elseprintf("(rlop,=)");
break;
case'+':
st++;
if(rz[st]=='=')
{
st++;
printf("(+=,-)");
}
elseif(rz[st]=='+')
{
st++;
printf("(++,-)");
}
elseprintf("(+,-)");
break;
case'-':
st++;
if(rz[st]=='=')
{
st++;
printf("(-=,-)");
}
elseif(rz[st]=='-')
{
st++;
printf("(--,-)");
}
elseprintf("(-,-)");
break;
case'*':
st++;
if(rz[st]=='=')
{
st++;
printf("(*=,-)");
}
elseprintf("(*,-)");
break;
case'>':
st++;
if(rz[st]=='=')
{
st++;
printf("(rlop,>=)");
}
elseprintf("(rlop,>)");
break;
case'<':
st++;
if(rz[st]=='=')
{
st++;
printf("(rlop,<=)");
}
elseprintf("(rlop,<)");
break;
case'%':
st++;
if(rz[st]=='=')
{
st++;
printf("(\%=,-)");
}
elseprintf("(\%,-)");
break;
case'!
':
st++;
if(rz[st]=='=')
{
st++;
printf("(!
=,-)");
}
elseprintf("(!
wrongthing!
)");
break;
case'&':
st++;
if(rz[st]=='&')
{
st++;
printf("(&&,-)");
}
elseprintf("(&,worngword!
)");
break;
case'|':
st++;
if(rz[st]=='|')
{
st++;
printf("(||,-)");
}
elseprintf("(|,worngword!
)");
break;
case'{':
st++;
printf("({,-)");
break;
case'}':
st++;
printf("(},-)");
break;
case'(':
st++;
printf("((,-)");
break;
case')':
st++;
printf("(),-)");
break;
case'[':
st++;
printf("([,-)");
break;
case']':
st++;
printf("(],-)");
break;
case':
':
st++;
printf("(:
-)");
break;
case'#':
st++;
printf("(#,-)");
break;
case';':
st++;
printf("(;,-)");
break;
case'.':
st++;
printf("(.,-)");
break;
case',':
st++;
printf("(,,-)");
break;
case'':
st++;
break;
case'':
st++;
break;
case10:
st++;
printf("\n");
break;
case34:
st++;
printf("(\",-)");
break;
case39:
st++;
printf("(',-)");
break;
default:
printf("(%c,worngthing)",rz[st]);
st++;
}
returnst;
}
intchoice(intst)//根据读入的单词的第一个字符确定调用不同的单词识别函数
{
if(choice1(rz[st])==1)
st=alpha(st);
elseif(choice2(rz[st])==1)
st=number(st);
elseif(rz[st]=='/')
st=anotation(st);
elsest=other(st);
returnst;
}
intmain()
{
inti=0;
FILE*fp;
charname[10];
printf("请输入文件名:
\n");
scanf("%s",&name);
if((fp=fopen(name,"r"))==NULL)
{
printf("Openerror!
");
exit(0);
}
charch=fgetc(fp);
while(ch!
=EOF)
{
rz[i]=ch;
i++;
ch=fgetc(fp);
}
fclose(fp);
intj=0;
while(rz[j]!
='\0')
j=choice(j);
cout<for(inti=0;icout<
cout<<"程序中数字如下"<for(intj=0;jcout<system("pause");
}
7、测试及结果
测试代码:
intchoice(intst)//根据读入的单词的第一个字符确定调用不同的单词识别函数
{
if(choice1(rz[st])==1)
st=alpha(st);
elseif(choice2(rz[st])==1)
st=number(st);
elseif(rz[st]=='/')
st=anotation(st);
elsest=other(st);
returnst;
}
测试结果:
8、心得
通过本次的实验,使我真正的了解词法分析器的实现过程,让我更加深刻领悟词法分析器的实现原理。
虽然在本次实验中遇到了各种各样的困难和错误,但在同学们的帮助下我都一一克服了,使得词法分析器能够正确的识别相应的词法和表达式。
在做实验的过程中,总是会忽略各种细节,从而导致经常修改一些很小的低级错误才能使程序正常运行,不仅浪费时间,还影响对其他地方的修改,并且在很多步骤处理上,方法不正确。
使结果不能符合要求,深刻体会到了自己在编程方面与别人的差距,在今后的学习中,我会注意改正自己在这方面的缺点,促使自己的编程水平不断进步。
编译原理是一门专业学科,对于现阶段的我来说,只能掌握它的一些基本原理和概念,对于一些更深层的知识还是有很多难以理解的地方。
但在这次实验过程中,锻炼了自己的思考能力,也锻炼了自己的动手编程能力,对于将知识的转化有了很大的帮助。
辅导教师张静成绩
实验日期
实验时间
1实验名称计算器的设计与实现
2、实验目的
掌握自上而下语法分析方法、自下而上语法分析方法
3、实验要求
(1)实验内容
设计及实现计算表达式的计算器。
表达式中可包含+、-、*、/、(、)等运算符。
(2)实验要求:
对已给的一个二元式形式表达式,能够检查有无语法错误。
并指定出错位置。
将表达式的语法树输出(或将语法分析过程输出)。
4、实验原理
根据算符优先分析思想实现语法分析程序。
5、实验步骤
(1)根据文法构造语法分析表。
(2)编写总控程序实现语法分析。
6、算符优先分析表及语法分析程序
算符优先分析表:
语法分析程序:
#include
#include
#defineMaxSize99
voidtranslate(charstr[],charexp[])/*将算术表达式转换成后缀表达式*/
{
struct
{
chardata[MaxSize];
inttop;/*top为栈顶*/
}op;/*定义一个含data和top的结构体*/
charch;
inti=0,t=0;
op.top=-1;
ch=str[i];/*将str的每一个数转换成ch*/
i++;
while(ch!
='\0')/*ch对应不同的符号的时候对应的转换情况*/
{
switch(ch)
{
case'(':
/*当是的时候将此括号存入栈op*/
op.top++;op.data[op.top]=ch;
break;
case')':
while(op.data[op.top]!
='(')/*括号内的转换优先级最高故先提
取表达式*/
{
exp[t]=op.data[op.top];
op.top--;
t++;
}
op.top--;
break;
case'+':
case'-':
while(op.top!
=-1&&op.data[op.top]!
='('){
exp[t]=op.data[op.top];
op.top--;
t++;
}
op.top++;/*恢复可插入位置*/
op.data[op.top]=ch;
break;
case'*':
case'/':
while(op.top=='/'||op.top=='*')/*优先级*/
{
exp[t]=op.data[op.top];
op.top--;
t++;
}
op.top++;
op.data[op.top]=ch;
break;
case'':
/*忽略空格排除误操作*/
break;
default:
while(ch>='0'&&ch<='9')
{
exp[t]=ch;t++;
ch=str[i];i++;
}
i--;
exp[t]='#';/*分隔操作数为了美观也为了以后好
分隔操作数*/
t++;
}
ch=str[i];
i++;
}
while(op.top!
=-1)/*得到剩下的部分*/
{
exp[t]=op.data[op.top];
t++;
op.top--;
}
exp[t]='\0';/*表达式结束*/
}
floatcal_value(charexp[]){
struct
{
floatdata[MaxSize];
inttop;
}st;/*操作数栈*/
floatd;
charch;
intt=0;
st.top=-1;
ch=exp[t];
t++;
while(ch!
='\0')
{
switch(ch)/*运算主体*/
{
case'+':
st.data[st.top-1]=st.data[st.top-1]+st.data[st.top];
st.top--;
break;
case'-':
st.data[st.top-1]=st.data[st.top-1]-st.data[st.top];
st.top--;
break;
case'*':
st.data[st.top-1]=st.data[st.top-1]*st.data[st.top];
st.top--;
break;
case'/':
if(st.data[st.top]!
=0)
st.data[st.top-1]=st.data[st.top-1]/st.data[st.top];
else
{
printf("\n\t除0是错误的");
}
st.top--;
break;
default:
d=0;
while(ch>='0'&&ch<='9')/*从后缀表达式中获取操作数
#作用在此体现*/
{
d=10*d+ch-'0';
ch=exp[t];t++;
}
st.top++;
st.data[st.top]=d;
}
ch=exp[t];
t++;
}
returnst.data[st.top];
}
intmain()/*可以提到前面去*/
{
charstr[MaxSize],exp[MaxSize];/*str为算术表达式,exps为后缀表达式*/
printf("请输入一个求值表达式\n");
gets(str);/*输入一个算术表达式*/
printf("原表达式是:
%s\n",str);
translate(str,exp);/*将算术表达式转换成后缀表达式*/
printf("后缀表达式%s\n",exp);
printf("计算结果:
%g\n",cal_value(exp));/*通过后缀表达式来求值*/
system("pause");
return0;
}
7、测试及结果
8、心得
此次实验,经过对计算器的设计与实现,让我对编译原理的基本知识有了深入的了解,加强了对语法分析的认识,掌握了自上而下语法分析方法、自下而上语法分析方法。
熟悉了算符优