词法分析 编译原理论文.docx
《词法分析 编译原理论文.docx》由会员分享,可在线阅读,更多相关《词法分析 编译原理论文.docx(18页珍藏版)》请在冰点文库上搜索。
词法分析编译原理论文
词法分析
***
摘要:
词法分析(lexicalanalysis)是计算机科学中将字符序列转换为单词(Token)序列的过程。
进行词法分析的程序或者函数叫作词法分析器(Lexicalanalyzer,简称Lexer),也叫扫描器(Scanner)。
词法分析器一般以函数的形式存在,供语法分析器调用。
关键词:
词法分析 标识符
计算机系统与人信息交换界面多数是应用高级语言来实现。
一个高级语言程序的实现,必须依赖于相应的编译系统。
所谓编译程序就是指能够把某一种语言程序转换成另一种与之等价的语言程序。
它通常包括五个阶段:
词法分析,语法分析,语义分析与中间代码的产生、优化,目标代码的生成。
完成计算机翻译过程的关键阶段,它为后面的语法分析、语义分析做好准备,打好基础,以便快速地、高质量地生成目标语言程序。
因此词法分析是编译的基础。
词法分析器所处理的对象即词法分析程序的输入数据,实际上是源程序经过编译预处理,去掉多余的符号后而形成的代码,这样给词法分析带来方便。
词法分析的过程是线性的从头至尾扫描一遍,复杂度较低,易实现。
一、实验目的
设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求
2.1待分析的简单词法
(1).关键字:
begin if then while do end lishumanlishuman2015041886
所有的关键字都是小写。
(2).运算符和界符 :
=+-*/()[]{},:
;><>=<===!
(3).其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:
ID = letter (letter | digit)*
NUM = digit digit*
(4).空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2各种单词符号对应的种别码
表2-2种别码
单词符号
种别码
单词符号
种别码
begin
1
(
26
if
2
)
27
then
3
[
28
while
4
]
29
do
5
{
30
end
6
}
31
lishuman
7
32
lishuman2015041886
8
:
33
letter (letter | digit)*
10
;
34
digit digit*
11
>
35
=
21
<
36
+
22
>=
37
-
23
<=
38
*
24
==
39
/
25
!
40
2.3词法分析程序的功能
输入:
所给文法的源程序字符串。
输出:
二元组(syn,token或sum)构成的序列。
其中:
syn为单词种别码;
token为存放的单词自身字符串;
sum为整型常数。
例如:
对源程序begin x:
=9:
if x>9 then x:
=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:
(1,begin)(10,x)(18,:
=)(11,9)(26,;)(2,if)……
2.4识别语言单词的状态转换图
识别语言单词的状态转换图如下图2-4所示:
状态0为初态,凡带双圈者为终态。
图2-4识别语言单词的状态转换图
三、词法分析程序的算法思想
算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想
是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1主程序示意图:
图3-1主程序示意图
其中初始包括以下两个方面:
(1). 关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程
序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标
识符。
关键字表为一个字符串数组,其描述如下:
Char *nrwtab[6]= {“begin”,“if',"then”,"while”,“do","end",};
(2).程序中需要用到的主要变量为syn,token和sum
3.2 扫描子程序的算法思想:
首先设置3个变量:
①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
图3-2扫描子程序主要部分流程图
四、运行结果
4.1.安装Linux虚拟机(已经配置好虚拟机的可以跳过此步骤)
1.安装VMware-player
2.解压Ubuntu16.04_64-bit.rar
3.在VMware-player中设置虚拟机:
点击“打开已经存在的虚拟机”,然后选择“Ubuntu16.04_64-bit.vmx”。
4.启动虚拟机,查看是否安装成功。
4.2.创建工作目录
在用户家目录下建立lishuman文件夹,建立scaner.c文件编写代码,建立testin.txt输入程序。
4.3.词法分析
1.打开命令行。
cdlishuman/回车,进入lishuman目录
2.编译程序。
编译scaner.c文件。
图4-3编译scaner.c文件
4.4.编译运行程序
testin.txt是词法分析器的输入程序(即输入的源程序,此程序由学生给出)。
运行后,自动在
lishuman目录下生成result.txt文件。
(testin.txt和result.txt文件都可由记事本查看内容)
图4-4.1testin.txt文件内容
图4-4.2result.txt文件内容
如果testin.txt中输入有误
图4-4.3testin.txt错误文件内容
则运行时显示:
图4-4.4result.txt错误文件内容
五、源程序
#include
#include
#include
#define_KEY_WORD_END"waitingforyourexpanding"
typedefstruct
{
inttypenum;
char*word;
}WORD;
charinput[255];//输入缓冲区
chartoken[255]="";//单词缓冲区
intp_input;//输入缓冲区指针
intp_token;//单词缓冲区指针
charch;//当前读入字符
char*KEY_WORDS[]={"begin","if","then","while","do","end","lishuman","lishuman2015041886",_KEY_WORD_END};
//关键字数组
WORD*scaner(WORD*word);//词法扫描函数
intmain(intargc,char*argv[])
{
intover=1;
WORD*oneword=calloc(1,sizeof(WORD*));
//printf("EnterYourwords(endwith$):
");
//scanf("%[^$]s",input);
FILE*fin;
charbuffer[1000];
if((fin=fopen("testin.txt","r"))==NULL)
{
printf("Cannotopenthefile!
\n");
exit(-1);
}
while(fgets(buffer,100,fin)!
=NULL)
{
strcat(input,buffer);
}
fclose(fin);
FILE*fout;
if((fout=fopen("result.txt","w"))==NULL)
{
printf("Cannotopenthefile!
\n");
exit(-1);
}
p_input=0;
printf("Yourwords:
\n%s\n",input);
while(over<1000&&over!
=-1){//对源程序进行分析
oneword=scaner(oneword);//获得一个新单词
if(oneword->typenum<1000)
fprintf(fout,"(%d,%s)",oneword->typenum,oneword->word);
//打印种别码和单词自身的值
over=oneword->typenum;
}
fclose(fout);
printf("\npressdone.");
}
//从缓冲区读取一个字符到ch中
charm_getch(){
ch=input[p_input];
p_input=p_input+1;
return(ch);
}
//去掉空白符号
voidgetbc(){
while(ch==''||ch==10){
ch=input[p_input];
p_input=p_input+1;
}
}
//拼接单词
voidconcat(){
token[p_token]=ch;
p_token=p_token+1;
token[p_token]='\0';
}
//判断是否字母
intletter(){
if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')return1;
elsereturn0;
}
//判断是否数字
intdigit(){
if(ch>='0'&&ch<='9')return1;
elsereturn0;
}
//检索关键字表格
intreserve(){
inti=0;
while(strcmp(KEY_WORDS[i],_KEY_WORD_END)!
=0){
if(!
strcmp(KEY_WORDS[i],token)){
returni+1;
}
i=i+1;
}
return10;
}
//回退一个字符
voidretract(){
p_input=p_input-1;
}
//数字转换成二进制
char*dtb(){
returnNULL;
}
//词法扫描程序:
WORD*scaner(WORD*word){
WORD*myword=word;
myword->typenum=10;
myword->word="";
p_token=0;
m_getch();
getbc();
if(letter()){
while(letter()||digit()){
concat();
m_getch();
}
retract();
myword->typenum=reserve();
myword->word=token;
return(myword);
}
elseif(digit()){
while(digit()){
concat();
m_getch();
}
//retract();
if(letter())
{
myword->typenum=-1;
myword->word="ERROR";
printf("In%s(),line=%d,invalidvariable,error!
\n",__func__,__LINE__);
exit(0);
}else
{
retract();
myword->typenum=20;
myword->word=token;
}
}
elseswitch(ch){
case'=':
m_getch();
if(ch=='='){
myword->typenum=39;
myword->word="==";
return(myword);
}
retract();
myword->typenum=21;
myword->word="=";
return(myword);
break;
case'+':
myword->typenum=22;
myword->word="+";
return(myword);
break;
case'-':
myword->typenum=23;
myword->word="-";
return(myword);
break;
case'*':
myword->typenum=24;
myword->word="*";
return(myword);
break;
case'/':
myword->typenum=25;
myword->word="/";
return(myword);
break;
case'(':
myword->typenum=26;
myword->word="(";
return(myword);
break;
case')':
myword->typenum=27;
myword->word=")";
return(myword);
break;
case'[':
myword->typenum=28;
myword->word="[";
return(myword);
break;
case']':
myword->typenum=29;
myword->word="]";
return(myword);
break;
case'{':
myword->typenum=30;
myword->word="{";
return(myword);
break;
case'}':
myword->typenum=31;
myword->word="}";
return(myword);
break;
case',':
myword->typenum=32;
myword->word=",";
return(myword);
break;
case':
':
myword->typenum=33;
myword->word=":
";
return(myword);
break;
case';':
myword->typenum=34;
myword->word=";";
return(myword);
break;
case'>':
m_getch();
if(ch=='='){
myword->typenum=37;
myword->word=">=";
return(myword);
}
retract();
myword->typenum=35;
myword->word=">";
return(myword);
break;
case'<':
m_getch();
if(ch=='='){
myword->typenum=38;
myword->word="<=";
return(myword);
}
retract();
myword->typenum=36;
myword->word="<";
return(myword);
break;
case'!
':
m_getch();
if(ch=='='){
myword->typenum=40;
myword->word="!
=";
return(myword);
}
retract();
myword->typenum=-1;
myword->word="ERROR";
return(myword);
break;
case'\0':
myword->typenum=1000;
myword->word="OVER";
return(myword);
break;
default:
myword->typenum=-1;
myword->word="ERROR";
return(myword);
}
}
六、实验总结
通过这次实验,我对词法分析器有了一定的了解,进一步的巩固了这部分的知识。
既通过这次用C语言对词法分析程序的编制,回顾了C语言的编程方法;又加深了对词法分析原理的理解和词法分析的实现过程,掌握了编译程序的实现方法和技术,懂得了词法分析器的工作原理。
在编程过程中,遇到了不少的问题,在同学的帮助下,问题一步一步的得到了解决。
先从实现最简单的扫描和输出开始,后继实现了扫描范围的扩大和输出结果的更加具体。