编译实验词法分析.docx
《编译实验词法分析.docx》由会员分享,可在线阅读,更多相关《编译实验词法分析.docx(15页珍藏版)》请在冰豆网上搜索。
编译实验词法分析
词法分析器实验报告
院系:
专业:
小组成员:
学号:
日期:
一、实验的目的与任务
词法分析的目的是将输入的源程序进行划分,给出基本符号(token)的序列,并掠过注解和空格等分隔符号。
基本符号是与输入的语言定义的词法所规定的终结符。
本实验要求学生编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续进行)。
二、实验所要识别的单词分类
1.关键字。
*key[53]={"auto","bool","break","case","catch","char","class","const","continue","default","delete","do","double","else","enum","extern","false","float","for","friend","goto","if","inline","int","long","namespace","new","operator","private","protected","public","register","return","short","signed","sizeof","static","struct","switch","template","this","throw","true","try","typedef","typename","union","unsigned","using","virtual","void","volatile","while"};
2.标识符。
符合文法标识符,由字符和数字组成,首字符必须为下划线或字母。
(hjw,wyp2319,_zhg…..)
3.数字。
整型,浮点型,科学计数。
4.运算符。
*arithmetic[6]={"+","-","*","/","++","--"};
5.关系运算符。
*relation[7]={"<","<=","=",">",">=","==","!
="};
6.分界符。
*border[7]={",",";","{","}","(",")","//"};
三、输出格式
1)若为关键字,则输出格式为;例:
关键字float,输出为
2)若为一般标识符,则输出格式为;例:
标识符fzu,输出为
3)若为数字,则输出格式为;例:
数字2325,输出为<2325,数字>
4)若为算术运算符,则输出格式为<符号,算术运算符>;例:
+,输出为<+,算术运算符>
5)若为关系运算符,则输出格式为<符号,关系运算符>;例:
!
=,输出为
=,关系运算符>
6)若出错,则输出格式为;例:
错误输入为26.,则输出为<26.,ERROR>
四、正则表达式:
标识符id->letter_(letter_|digit)*
无符号数number->digitoptitionalfractionoptionalexponent
空白符ws->(blank|tab|newline)+
关系运算符relop-><|>|<=|>=|=|!
=
运算符operator->+|-|*|/|++|--
五、DFA状态转换图
六、流程图
七、实验结果
实验环境:
MicrosoftWindows7下的MicrosoftVisualStudio2010
输入
输出
输入
输出
输入
输出
八、结果分析
用格式为.txt的文件输入,一个个字符去识别,根据DFA的状态图实现跳转,把未进入接受状态的单元存放进一个数组,到达接受状态,将识别出来的词和属性一起输出。
其中识别得到的id与keyword转换过程相同,故最后得到的结果还要再判断是标识符还是关键字。
由于关键词有限,可以建个表存放关键字,通过查表实现判断关键字。
运算符和分隔符是有限的,所以把它们罗列去判断,只要是符合条件就接收。
九、实验总结
实验是理论的实践,但是通过实验加深了我们对理论课知识的理解和运用,词法分析器更是如此。
对输入的程序进行分析,将关键字,保留字与系统标识符分开,并对属性进行说明。
更通俗的来说,也就是编写一个程序,可以实现这个功能。
通过这个实验,现在我们知道了,如何用正则表达式去识别我们想要识别的单词。
但如何用程序去实现整个识别过程,又该如何去一步步执行识别呢?
最简单的方法,一个字符一个字符的读入,每读入一个字符,识别过程进入一个特定的状态,按照一定的次序在一系列状态间转换后,字符全部读入,状态也走入了终态。
那么好了,一个单词识别完毕,这就给我们启示,从一个状态转换图可以较容易的实现程序化的识别工作。
这样我们就知道如何从一个状态图去写程序了。
十、实验代码
#include"stdafx.h"
#include
#include
#include
#include
#include
usingnamespacestd;
ifstreamfp("in.txt",ios:
:
in);
charcbuffer;
char*key[53]={"auto","bool","break","case","catch","char","class","const","continue","default","delete","do","double","else","enum","extern","false","float","for","friend","goto","if","inline","int","long","namespace","new","operator","private","protected","public","register","return","short","signed","sizeof","static","struct","switch","template","this","throw","true","try","typedef","typename","union","unsigned","using","virtual","void","volatile","while"};//关键字
char*border[7]={",",";","{","}","(",")","//"};//分界符
char*arithmetic[6]={"+","-","*","/","++","--"};//算术运算符
char*relation[7]={"<","<=","=",">",">=","==","!
="};//关系运算符
intsearch(charsearchchar[],intwordtype)//search函数查表匹配
{
inti=0,t=0;
switch(wordtype)
{
case1:
{for(i=0;i<=52;i++)//关键字
{
if(strcmp(key[i],searchchar)==0)
return(i+1);
}
return(0);}
case2:
{
for(i=0;i<=6;i++)//分界符
{
if(strcmp(border[i],searchchar)==0)
return(i+1);
}
return(0);
}
case3:
{
for(i=0;i<=5;i++)//运算符
{
if(strcmp(arithmetic[i],searchchar)==0)
return(i+1);
}
return(0);
}
case4:
{
for(i=0;i<=6;i++)//关系运算符
{
if(strcmp(relation[i],searchchar)==0)
return(i+1);
}
return(0);
}
}
}
charalphaprocess(charbuffer)//字符处理过程
{
inti=-1;
charalphatp[20];
while(buffer=='_'||(isalpha(buffer))||(isdigit(buffer)))
//这两个函数分别是判字符和判数字函数位于ctype.h中
{
alphatp[++i]=buffer;
buffer=fp.get();
}
alphatp[i+1]='\0';//在末尾添加字符串结束标志
if(search(alphatp,1))
cout<<"<"<"<else
{
cout<<"<"<"<}
return(buffer);
}
chardigitprocess(charbuffer)//数字处理过程
{
inti=-1;
chardigittp[20];
while((isdigit(buffer)))
{
digittp[++i]=buffer;
buffer=fp.get();
}
if(buffer=='.')
{
digittp[++i]=buffer;
buffer=fp.get();
if(!
isdigit(buffer))
{
digittp[i+1]='\0';
cout<<"<"<"<return(buffer);
}
else
{
digittp[++i]=buffer;
buffer=fp.get();
while(isdigit(buffer))
{
digittp[++i]=buffer;
buffer=fp.get();
}
}
}
elseif(buffer=='E')
{
digittp[++i]=buffer;
buffer=fp.get();
if(buffer=='+'||buffer=='-')
{
digittp[++i]=buffer;
buffer=fp.get();
}
if(isdigit(buffer))
{
digittp[++i]=buffer;
buffer=fp.get();
}
else{
digittp[i+1]='\0';
cout<<"<"<"<return(buffer);}
}
digittp[i+1]='\0';
cout<<"<"<"<return(buffer);
}
charotherprocess(charbuffer)//分界符、运算符等
{
inti=-1;
charothertp[20];
othertp[0]=buffer;
othertp[1]='\0';
if(search(othertp,3))//运算符
{
buffer=fp.get();
othertp[1]=buffer;
othertp[2]='\0';
if(search(othertp,3))//判断该运算符是否是
//由连续的两个字符组成的
{
cout<<"<"<"<buffer=fp.get();
gotoout;
}
else//单字符逻辑运算符
{
othertp[1]='\0';
cout<<"<"<"<gotoout;
}
}
if(search(othertp,4))//关系运算符
{
buffer=fp.get();
othertp[1]=buffer;
othertp[2]='\0';
if(search(othertp,4))//判断该关系运算符是否是
//由连续的两个字符组成的
{
cout<<"<"<"<buffer=fp.get();
gotoout;
}
else//单字符逻辑运算符
{
othertp[1]='\0';
cout<<"<"<"<gotoout;
}
}
if(buffer=='!
')//"=="的判断
{
buffer=fp.get();
if(buffer=='=')
{
othertp[1]=buffer;
othertp[2]='\0';
cout<<"<"<"<buffer=fp.get();}
else{cout<<"<"<"<的处理输出
buffer=fp.get();}
gotoout;
}
else
{
if(search(othertp,2))//分界符
{
cout<<"<"<"<buffer=fp.get();
gotoout;
}
}
if((buffer!
='\n')&&(buffer!
=''))
cout<<"<"<"<buffer=fp.get();
out:
return(buffer);
}
voidmain()
{
if(!
fp)
cout<<"文件打开错误!
!
"<else
{
fp.get(cbuffer);
while(!
fp.eof())
{
if(isalpha(cbuffer)||cbuffer=='_')//isalpha函数判断输入是否为字母
{
cbuffer=alphaprocess(cbuffer);//字符处理(判断标示符和关键字)
}
elseif(isdigit(cbuffer))//isdigit函数判断输入是否为数字
{
cbuffer=digitprocess(cbuffer);//数字处理
}
else
cbuffer=otherprocess(cbuffer);//其他符号处理(各种运算符)
}
}
cout<<"完成\n";
}