编译原理实验词法分析器.docx
《编译原理实验词法分析器.docx》由会员分享,可在线阅读,更多相关《编译原理实验词法分析器.docx(15页珍藏版)》请在冰豆网上搜索。
编译原理实验词法分析器
洛阳理工学院实验报告
院部
计算机系
班级
B150402
学号
姓名
课程名称
编译原理
实验日期
2018.6.4
实验名称
词法分析器
成绩
实验目的:
加深对词法分析过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析;能够使自己编写的程序对简单的程序片段进行词法分析。
实验条件:
装有Windows操作系统,MicrosoftVisualC++6.0。
实验内容:
自定义一种程序设计语言,或选择已有的一种高级语言(C语言),编制它的词法分析程序。
实验要求:
1.对单词的构成规则有明确的定义
2.编写的程序能够正确识别源程序中的单词符号
3.识别出的单词以<种别码,值>的形式保存在符号表中
4.词法分析中源程序和分析后的符号表均保存在.txt文件中
5.有一定的检查错误的能力。
遇到错误时可显示“Error”,然后跳过错误部分继续显示。
6.实验报告包括以下内容
(1)编程思路、流程图、源代码
(2)上机调试时发现的问题,以及解决的过程
(3)所使用的测试数据及结果
(4)心得体会
实验步骤
1.给出目标语言的所有单词符号及种别编码、单词符号的状态转换图。
2.依次读入源程序,对源程序进行单词切分和识别,直到源程序结束。
3.对正确的单词,按照它的种别以<种别码,值>的形式保存在符号表中。
4.对不正确的单词,做出错误处理。
实验内容:
1.编程思路:
1.1、实现预处理功能
源程序中可能包含有对程序执行无意义的符号,要求将其剔除。
首先编制一个源程序的输入过程,从键盘、文件或文本框输入若干行语句,依次存入输入缓冲区(字符型数据);然后编制一个预处理子程序,去掉输入串中的回车符、换行符和跳格符等编辑性文字;把多个空白符合并为一个;去掉注释。
1.2、实现词法分析功能
输入:
所给文法的源程序字符串。
输出:
将每个单词或数字以及他对应的种别码和类型输出到文件中。
具体实现时,可以将单词的二元组用结构进行处理。
1.3、待分析的C语言子集的词法
1)关键字"char","int","if","else","var","return","break","do","while","for","double","float","short"
2)运算符和界符
+-*/<<><=>>==;()[]\|&{}\\#
3)空格由空白、制表符和换行符组成
空格一般用来分隔ID、NUM、专用符号和关键字,词法分析阶段通常被忽略。
1.4、各种单词符号对应的种别码
表1各种单词符号的种别码
单词符号
种别码
char
1
int
2
if
3
else
4
var
5
return
6
break
7
do
8
while
9
for
10
double
11
float
12
short
13
标识符
14
数字
15
符号
16-40
1.5、词法分析程序的主要算法思想
算法的基本任务是从文件中读出字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到的单词符号的第一个字符的种类,拼出相应的单词符号,并输出到文件中。
2.流程图:
2.1主程序流程图
主函数流程图
2.2分析函数流程图
分析函数流程图
3.源代码:
#include
#include
#include
#include
#include
inti,row=0,line=0;
chara[1000];//程序
intnumber[1000][100];//常数表
charmark[100][5];//标识符表
FILE*fin,*fout;
//词法分析
intwordanalysis()
{
if((a[i]>='A'&&a[i]<='Z')||(a[i]>='a'&&a[i]<='z'))//分析标识符和关键字
{
charword[10];
charkeyWord[100][100]={"char","int","if","else","var","return","break","do","while","for","double","float","short"};//关键字表
intn=0;
word[n++]=a[i++];
//若字符为A~Z或0~9,则继续读取
while((a[i]>='A'&&a[i]<='Z')||(a[i]>='0'&&a[i]<='9')||(a[i]>='a'&&a[i]<='z'))
{
word[n++]=a[i++];
}
word[n]='\0';
i--;
//判断该标识符是否为关键字
for(n=0;n<100;n++)
{
if(strcmp(word,keyWord[n])==0)
{
fprintf(fout,"%s\t(%d)\t关键字\n",keyWord[n],n+1);
return3;
}
}
//判断该标识符是否存在标识符表中
intm=0;
if(line!
=0)
{
intq=0;
while(q{
if(strcmp(word,mark[q++])==0)
{
fprintf(fout,"%s\t(14,%d)\t标识符\n",word,q);
return3;
}
}
}
//将该标识符保存到标识符表中
strcpy(mark[line],word);
fprintf(fout,"%s\t(14,%d)\t标识符\n",word,line+1);
line++;
return3;
}
elseif(a[i]>='0'&&a[i]<='9')//分析常数
{
charx[100];
intn=0,sum;
x[n++]=a[i++];
//判断字符是否是0~9
while(a[i]>='0'&&a[i]<='9')
{
x[n++]=a[i++];
}
x[n]='\0';
i--;
intnum=atoi(x);//将字符串转换成int型
//判断该常数是否存在于常数表中
if(row!
=0)
{
inty;
for(y=0;y<1000;y++)
{
intw=number[y][0];
sum=0;
intd;
for(d=1;d<=number[y][0];d++)
{
w=w-1;
sum=sum+number[y][d]*pow(2,w);
}
if(num==sum)
{
fprintf(fout,"%d\t(15,%d)\n",num,y+1);
return3;
}
}
}
intz=num,c=num;
intm=0;
do//计算是几位二进制数
{
z=z/2;
m++;
}while(z!
=0);
for(n=m;n>0;n--)//将二进制保存于常数表中
{
number[row][n]=c%2;
c=c/2;
}
number[row][0]=m;
intline=row;
fprintf(fout,"%d\t(15,%d)\n",num,line+1);
row++;
return3;
}
else//分析符号
switch(a[i])
{
case'':
case'\n':
return-1;
case'#':
return0;
case'=':
fprintf(fout,"=\t(16)\n");return3;
case'<':
i++;
if(a[i]=='=')
{
fprintf(fout,"<=\t(17)\n");
return3;
}
elseif(a[i]=='>')
{
fprintf(fout,"<>\t(18)\n");
return3;
}
else
{
i--;
fprintf(fout,"<\t(19)\n");
return3;
}
case'>':
i++;
if(a[i]=='=')
{
fprintf(fout,">=\t(20)\n");
return3;
}
else
{
i--;
fprintf(fout,">\t(21)\n");
return3;
}
case'+':
fprintf(fout,"+\t(22)\n");return3;
case'-':
fprintf(fout,"-\t(23)\n");return3;
case'*':
fprintf(fout,"*\t(24)\n");return3;
case'/':
i++;
if(a[i]!
='/'){
i--;
fprintf(fout,"/\t(25)\n");return3;
}
else{
while
(1){
if(a[i++]=='\n')
return-1;
}
fprintf(fout,"//\t(35)\n");return3;
}
case':
':
fprintf(fout,":
\t(26)\n");return3;
case';':
fprintf(fout,";\t(27)\n");return3;
case'(':
fprintf(fout,"(\t(28)\n");return3;
case')':
fprintf(fout,")\t(29)\n");return3;
case'{':
fprintf(fout,"{\t(30)\n");return3;
case'}':
fprintf(fout,"}\t(31)\n");return3;
case'[':
fprintf(fout,"[\t(32)\n");return3;
case']':
fprintf(fout,"]\t(33)\n");return3;
case'|':
fprintf(fout,"|\t(34)\n");return3;
case'"':
fprintf(fout,"\"\t(35)\n");return3;
case',':
fprintf(fout,",\t(36)\n");return3;
case'\'':
fprintf(fout,"'\t(37)\n");return3;//单引号
case'&':