编译原理实验一词法分析器.docx
《编译原理实验一词法分析器.docx》由会员分享,可在线阅读,更多相关《编译原理实验一词法分析器.docx(17页珍藏版)》请在冰豆网上搜索。
![编译原理实验一词法分析器.docx](https://file1.bdocx.com/fileroot1/2022-12/12/fac4c69b-646e-438f-86e3-acdb48e37634/fac4c69b-646e-438f-86e3-acdb48e376341.gif)
编译原理实验一词法分析器
实验报告
课程名称编译原理
实验名称词法分析器
实验类型设计型
实验地点405机房实验日期2015/12
指导教师
专业软件工程
班级
学号
姓名
成绩
辽宁石油化工大学计算机与通信工程学院
实验报告说明
1、封面内容
(1)课程名称:
实验所属的课程的名称。
(2)实验名称:
要用最简练的语言反映实验的内容。
要求与实验指导书中相一致。
(3)实验类型:
说明是验证型实验、设计型实验、创新型实验还是综合型实验。
2、正文内容
实验报告的正文内容须包括以下内容:
(1)实验目的:
目的要明确,要抓住重点,符合实验指导书中的要求。
(2)实验内容:
说明本实验的主要内容。
(3)实验原理:
简要说明本实验项目所涉及的理论知识。
(4)实验环境:
实验用的软硬件环境(配置)。
(5)实验方案:
对于验证性型实验,写明依据何种原理、操作方法进行实验;对于设计型和综合型实验,写明依据何种原理、操作方法进行实验,并画出硬件组成图、软件流程图、设计思路和设计方法,再配以相应的文字说明;对于创新型实验,除符合设计型和综合型实验要求外,还应注明其创新点、特色。
(6)实验步骤:
写明实验的实施步骤,包括实验过程中的记录、数据。
(7)实验结果与分析:
写明实验的最终结果,并对结果进行分析,做出结论。
(8)实验中遇到的问题及解决方法:
写明实验过程中遇到的问题及所采取的解决方法。
(9)实验总结(在封底上):
写出对本次实验的心得体会、思考和建议。
一、实验目的
设计,编制,调试一个词法分析程序-识别单词,加深对词法分析原理的理解。
二、实验要求
构造一个自己设计的小语言的词法分析器:
1、这个小语言能说明一些简单的变量
识别诸如begin,end,if,while等保留字;识别非保留字的一般标识符(有下划线、字符、数字,且第一个字符不能是数字)。
识别数字序列(整数和小数);识别:
=,<=,>=之类的特殊符号以及;,(,)等界符。
2、相关过程(函数):
Scanner()词法扫描程序,提取标识符并填入display表中
3、这个小语言有顺序结构的语句
4、这个小语言能表达分支结构的语句
5、这个小语言能够输出结果;
三、算法设计
单词种别码设计:
状态
种别编码
种类
解释
0
初态
1
2
1
关键字
3
2
变量标识符
由字母下划线数字组成,且第一位不能是数字
4
读入了数字
5
3
整数
6
4
小数
7
小数点个数出错,大于1
8
读入了<
9
6
双目运算<>、<=
10
5
单目运算<
11
读入了>
12
6
双目运算>=
13
5
单目运算>
14
5
单目运算+、—、*、/、=、#
用default实现
15
读入了:
16
6
双目运算:
=
17
7
界符(、)、,、;、—、[、]、:
、{、}、‘’
用变量errorflag实现
四、程序源代码
1使用环境:
vc++6.0,win8;
2源代码:
#include
#include
#include
#include
#include
#include
usingnamespacestd;
#defineMax655
#defineWordMaxNum256//变量最大个数
#defineDigitNum256//常量最大个数
#defineMaxKeyWord32//关键字数量
#defineMaxOptANum8//运算符最大个数
#defineMaxOptBNum4//运算符最大个数
#defineMaxEndNum11//界符最大个数
typedefstructDisplayTable
{
intIndex;//标识符所在表的下标
inttype;//标识符的类型
intline;//标识符所在表的行数
charsymbol[20];//标识符所在表的名称
}Table;
intTableNum=0;//display表的下标
charWord[WordMaxNum][20];//标识符表
charDigit[WordMaxNum][20];//数字表
intWordNum=0;//变量表的下标
intDigNum=0;//常量表的下标
boolerrorFlag=0;//错误标志
constchar*constKeyWord[MaxKeyWord]={"and","array","begin","case","char""constant","do","else","end","false","for","if","input","integer","not","of","or","output","packed","procedure","program","read","real","repeat","set","then","to","type","until","var","while","with","prn"};//关键字
constcharOptA[]={'+','-','*','/','=','#','<','>'};//单目运算
constchar*OptB[]={"<=",">=",":
=","<>"};//双目运算符
constcharEnd[]={'(',')',',',';','.','[',']',':
','{','}','"'};//界符
voiderror(charstr[20],intnLine,interrorType)
{
cout<<"\nError:
";
switch(errorType)
{
case1:
cout<<"第"<\n";
errorFlag=1;
break;
case2:
cout<<"第"<\n";
errorFlag=1;
break;
case3:
cout<<"第"<\n";
errorFlag=1;
break;
}
}//error
voidScanner(charch[],intchLen,Tabletable[Max],intnLine)
{
intchIndex=0;
while(chIndex{
while(ch[chIndex]==''||ch[chIndex]==9)
{chIndex++;}
while(ch[chIndex]==10)//遇到换行符,行数加1
{nLine++;chIndex++;}
if(isalpha(ch[chIndex]))
{
charstr[256];
intstrLen=0;
while(isalpha(ch[chIndex])||ch[chIndex]=='_')//是字母、下划线
{
str[strLen++]=ch[chIndex];
chIndex++;
while(isdigit(ch[chIndex]))//不是第一位,可以为数字
{
str[strLen++]=ch[chIndex];
chIndex++;
}
}
str[strLen]=0;//字符串结束符
if(strlen(str)>20)//标识符超过规定长度,报错处理
{
error(str,nLine,1);
}
else{inti;
for(i=0;iif(strcmp(str,KeyWord[i])==0)
{
strcpy(table[TableNum].symbol,str);
table[TableNum].type=1;
table[TableNum].line=nLine;
table[TableNum].Index=i;
TableNum++;
break;
}
if(i>=MaxKeyWord)
{
table[TableNum].Index=WordNum;
strcpy(Word[WordNum++],str);
table[TableNum].type=2;//变量标识符
strcpy(table[TableNum].symbol,str);
table[TableNum].line=nLine;
TableNum++;
}
}
}
elseif(isdigit(ch[chIndex]))
{
intflag=0;
charstr[256];
intstrLen=0;
while(isdigit(ch[chIndex])||ch[chIndex]=='.')
{
if(ch[chIndex]=='.')
flag++;
str[strLen++]=ch[chIndex];
chIndex++;
}
str[strLen]=0;
if(strlen(str)>20)
{
error(str,nLine,3);
}
if(flag==0)
{
table[TableNum].type=3;//整数
}
if(flag==1)
{
table[TableNum].type=4;//小数
}
if(flag>1)
{
error(str,nLine,2);
}
table[TableNum].Index=DigNum;
strcpy(Digit[DigNum++],str);
strcpy(table[TableNum].symbol,str);
table[TableNum].line=nLine;
TableNum++;
}
/*******************************运算符************************************/
else
{
interrorFlag;//用来区分是不是无法识别的标识符,0为运算符,1为界符
charstr[3];
str[0]=ch[chIndex];
str[1]=ch[chIndex+1];
str[3]=0;
for(inti=0;iif(strcmp(str,OptB[i])==0)
{
errorFlag=0;
table[TableNum].type=6;
strcpy(table[TableNum].symbol,str);
table[TableNum].line=nLine;
table[TableNum].Index=i;
TableNum++;
chIndex=chIndex+2;
break;
}
if(i>=MaxOptBNum)
{
for(intk=0;kif(OptA[k]==ch[chIndex])
{
errorFlag=0;
table[TableNum].type=5;
table[TableNum].symbol[0]=ch[chIndex];
table[TableNum].symbol[1]=0;
table[TableNum].line=nLine;
table[TableNum].Index=k;
TableNum++;
chIndex++;
break;
}
/*************************界符*****************************************/
for(intj=0;jif(End[j]==ch[chIndex])
{
errorFlag=1;
table[TableNum].line=nLine;
table[TableNum].symbol[0]=ch[chIndex];
table[TableNum].symbol[1]=0;
table[TableNum].Index=j;
table[TableNum].type=7;
TableNum++;
chIndex++;
}
/********************其他无法识别字符*************************************/
if(errorFlag!
=0&&errorFlag!
=1)//开头的不是字母、数字、运算符、界符
{
charstr[256];
intstrLen=-1;
str[strLen++]=ch[chIndex];
chIndex++;
while(*ch!
=''||*ch!
=9||ch[chIndex]!
=10)//
{
str[strLen++]=ch[chIndex];
chIndex++;
}
str[strLen]=0;
table[TableNum].type=8;
strcpy(table[TableNum].symbol,str);
table[TableNum].line=nLine;
table[TableNum].Index=-2;
TableNum++;
}
}
}
}
}
voidTrans(doublex,intp)//把十进制小数转为16进制
{
inti=0;//控制保留的有效位数
while(i
{
if(x==0)//如果小数部分是0
break;//则退出循环
else
{
intk=int(x*16);//取整数部分
x=x*16-int(k);//得到小数部分
if(k<=9)
cout<else
cout<};
i++;
};
};
intmain()
{
ifstreamin;
ofstreamout,outVar,outCon;
charin_file_name[26],out_file_name[26];//读入文件和写入文件的名称
charch[Max];//存放输入代码的缓冲区
intnLine=1;//初始化行数
Table*table=newTable[Max];
intchoice;
cout<<"请输入读入方式:
1:
从文件中读,2:
从键盘读(输入结束标志位#):
\n";
cin>>choice;
switch(choice)
{
inti;
/****************************从文件读取***************************/
case1:
cout<<"Entertheinputfilename:
\n";
cin>>in_file_name;
in.open(in_file_name);
if(in.fail())//打开display表读文件失败
{
cout<<"Inputputfileopeningfailed.\n";
exit
(1);
}
cout<<"Entertheoutputfilename:
\n";
cin>>out_file_name;
out.open(out_file_name);
outVar.open("变量表.txt");
outCon.open("常量表.txt");
if(out.fail())//打开display表写文件失败
{
cout<<"Outputfileopeningfailed.\n";
exit
(1);
}
if(outVar.fail())//打开变量表写文件失败
{
cout<<"VarOutputfileopeningfailed.\n";
exit
(1);
}
if(outCon.fail())//打开常量表写文件失败
{
cout<<"ConstOutputfileopeningfailed.\n";
exit
(1);
}
in.getline(ch,Max,'#');
Scanner(ch,strlen(ch),table,nLine);//调用扫描函数
if(errorFlag==1)//出错处理
return0;
/*******************************把结果打印到各个表中***********************/
out<<"类型"<<""<<"下标"<for(i=0;iout<<"(0x"<outCon<<"下标"<<""<<"常量值"<for(i=0;i{
if(table[i].type==3)
{
longnum1;
num1=atoi(table[i].symbol);
outCon<<"(0x"<}
if(table[i].type==4)
{
doublenum2;
num2=atof(table[i].symbol);
outCon<<"(0x"<}
}
outVar<<"类型"<<""<<"变量名称"<for(i=0;ioutVar<<"(0x"<in.close();//关闭文件
out.close();
outVar.close();
outCon.close();
break;
/***********************************从键盘输入****************************/
case2:
cin.getline(ch,Max,'#');
Scanner(ch,strlen(ch),table,nLine);//调用扫描函数
if(errorFlag==1)
return0;
cout<<"\nDisplay表:
\n";
cout<<"类型"<<""<<"下标"<for(i=0;icout<<"(0x"<cout<<"\n常量表:
\n"<<"下标"<<""<<"常量值"<for(i=0;i{
if(table[i].type==3)
{
longnum1;
num1=atoi(table[i].symbol);
cout<<"(0x"<}
if(table[i].typ