编译原理实验报告.doc
《编译原理实验报告.doc》由会员分享,可在线阅读,更多相关《编译原理实验报告.doc(15页珍藏版)》请在冰豆网上搜索。
![编译原理实验报告.doc](https://file1.bdocx.com/fileroot1/2022-10/19/61835c2d-4edc-4d08-a416-2eb410cafaf4/61835c2d-4edc-4d08-a416-2eb410cafaf41.gif)
编译方法实验报告
实验1:
扫描器的设计
一、实验目的
熟悉并实现一个扫描器(词法分析程序)。
二、实验要求
(1)设计扫描器的有限自动机(识别器);
(2)设计翻译、生成Token的算法(翻译器);
(3)编写代码并上机调试运行通过。
·输入——源程序文件或源程序字符串;
·输出——相应的Token序列;
关键字表和界符表;
符号表和常数表;
三、实验步骤
流程:
初始化;
打开用户源程序文件;
while(文件未结束)
{读入一行到w[i],i=0;
do//处理一行,每次处理一个单词
{滤空格,直到第一个非空的w[i];
i--;
s=1;//处理一个单词开始
while(s!
=0)//拼单词并生成相应Token
{
act(s);//执行qs
if(s>=11&&s<=14)//一个单词处理结束
break;
i++;//getchar()
s=find(s,w[i]);
}
if(s==0)
词法错误;
}while(w[i]!
=换行符);
}
关闭用户源程序文件;
生成Token文件;
输出关键字表;
输出Token序列;
输出符号表;
输出常数表;
有限自动机的状态转换图:
e
ddd
+|--1/+/-
11
+①d②.③d④e⑤⑥d⑦
d-
-1/+/-
l/d-1/+/-
12
-1
l⑧-
13
-1
b⑨b⑩-
14
-1
-
15
-1
-
其中:
d为数字,l为字母,b为界符,-1代表其它符号(如在状态8处遇到了非字母或数字的其它符号,会变换到状态12)。
关键字表和界符表:
Program
;
Begin
:
End
(
Var
)
While
Do
:
=
Repeat
+
Until
-
For
*
To
/
If
>
Then
>=
Else
==
<
<=
四、主要数据结构
①状态转换矩阵:
intaut[10][7]={2,0,0,0,8,9,15,
2,3,5,11,0,0,11,
4,0,0,0,0,0,0,
4,0,5,11,0,0,11,
7,0,0,6,0,0,0,
7,0,0,0,0,0,0,
7,0,0,11,0,0,11,
8,0,0,0,8,0,12,
0,0,0,0,0,10,14,
0,0,0,0,0,0,13};
②关键字表:
charkeywords[30][12]={“program”,”begin”,”end”,”var”,”while”,”do”,
”repeat”,”until”,”for”,”to”,”if”,”then”,”else”,“;”,”:
”,”(“,”)”,”,”,”:
=”,”+”,”-“,”*”,”/”,
”>”,”>=”,”==”,“<”,“<=”};
③符号表:
charID[50][12];//表中存有源程序中的标识符
④常数表:
floatC[20];
⑤其它变量:
structtoken
{intcode;
intvalue};//Token结构
structtokentok[100];//Token数组
ints;//当前状态
intn,p,m,e,t;//尾数值,指数值,小数位数,指数符号,类型
floatnum;//常数值
charw[50];//源程序缓冲区
inti;//源程序指针,当前字符为w[i]
charstrTOKEN[12];//当前已经识别出的单词
五、实验核心代码
intmain(intargc,char*argv[])
{
FILE*fp;
ints;//当前状态*有限自动机中的状态
fp=fopen("exa.txt","r");
while(!
feof(fp))
{
fgets(w,50,fp);
i=0;
//*处理一行
do
{
printf("%c",w[i]);//测试显示每个token的首字母
//*处理一个token
while(w[i]=='')//滤空格
i++;
if(w[i]>='a'&&w[i]<='z')//判定单词类别*是字母(关键字或标识符)
{
ptr=col2;num_map=2;
}
elseif(w[i]>='0'&&w[i]<='9')//*是数字(常量的开头)
{
ptr=col1;num_map=4;
}
elseif(strchr(col3[0].str,w[i])==NULL)//*其他字符算为非法字符
{
printf("非法字符%c\n",w[i]);
i++;
continue;
}
else//界符
{
ptr=col3;num_map=1;
}
i--;//*向后退一个字符
s=1;//开始处理一个单词
while(s!
=0)
{
act(s);
if(s>=11&&s<=14)//*判断是否是终止状态*是终止状态,则形成一个token
break;
i++;//getchar()*读取下一个字符
s=find(s,w[i]);//状态转换
}
if(s==0)
{
strTOKEN[i_str]='\0';
printf("词法错误:
%s\n",strTOKEN);
}
}while(w[i]!
=10);
}
printf("关键字表:
");//输出结果
for(i=0;i<30;i++)
printf("%s",keywords[i]);
printf("\n");
printf("Token序列:
");
for(i=0;i printf("(%d,%d)",tok[i].code,tok[i].value);
printf("\n");
printf("符号表:
");
for(i=0;i printf("%s",ID[i]);
printf("\n");
printf("常数表:
");
for(i=0;i printf("%d",C[i]);
printf("\n");
fclose(fp);
printf("HelloWorld!
\n");
return0;
}
//*状态转换后,达到新的状态之后,记录的变化
voidact(ints)
{
intcode;
switch(s)
{
case1:
n=0;m=0;p=0;t=0;e=1;num=0;i_str=0;
strTOKEN[i_str]='\0';//其它变量初始化
break;
case2:
n=10*n+w[i]-48;
break;
case3:
t=1;
break;
case4:
n=10*n+w[i]-48;m++;
break;
case5:
t=1;
break;
case6:
if(w[i]=='-')