1、词法分析*摘 要:词法分析(lexical analysis )是计算机科学中将字符序列转换为单词(Token)序列的过程。进行词法分析的程序或者函数叫作词法分析器(Lexical analyzer,简称 Lexer),也叫扫描器(Scanner )。词法分析器一般以函数的形式存在,供语法分析器调用。关键词:词法分析 标识符计算机系统与人信息交换界面多数是应用高级语言来实现。一个高级语言程序的实现,必须依赖于相应的编译系统。所谓编译程序就是指能够把某一种语言程序转换成另一种与之等价的语言程序。它通常包括五个阶段:词法分析,语法分析,语义分析与中间代码的产生、优化,目标代码的生成。完成计算机翻译
2、过程的关键阶段,它为后面的语法分析、语义分析做好准备,打好基础,以便快速地、高质量地生成目标语言程序。因此词法分析是编译的基础。词法分析器所处理的对象即词法分析程序的输入数据,实际上是源程序经过编译预处理,去掉多余的符号后而形成的代码,这样给词法分析带来方便。词法分析的过程是线性的从头至尾扫描一遍,复杂度较低,易实现。一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。二、实验要求2.1 待分析的简单词法(1).关键字: begin if then while do end lishuman lishuman2015041886所有的关键字都是小写。(2).运算符和界符 :
3、 = + - * / ( ) , : ; = 35= 21 = 37- 23 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 主程
4、序示意图其中初始包括以下两个方面:(1). 关键字表的初值。关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。如能查到匹配的单词,则该单词为关键字,否则为一般标识符。关键字表为一个字符串数组,其描述如下:Char *nrwtab6= “begin”,“if,“then”,“while”,“do“,“end“,;(2).程序中需要用到的主要变量为 syn,token 和 sum 3.2 扫描子程序的算法思想: 首先设置 3 个变量:token 用来存放构成单词符号的字符串; sum 用来整型单词;syn用来存放单词符号的种别码。图 3-2
5、 扫描子程序主要部分流程图四、运行结果4.1.安装 Linux 虚拟机(已经配置好虚拟机的可以跳过此步骤)1.安装 VMware-player2.解压 Ubuntu16.04_64-bit.rar3.在 VMware-player 中设置虚拟机:点击“打开已经存在的虚拟机 ”,然后选择“Ubuntu16.04_64-bit.vmx”。4.启动虚拟机,查看是否安装成功。4.2.创建工作目录在用户家目录下建立 lishuman 文件夹,建立 scaner.c 文件编写代码,建立 testin.txt 输入程序。4.3.词法分析1.打开命令行。 cd lishuman/回车,进入 lishuman
6、目录2.编译程序。编译 scaner.c 文件。图 4-3 编译 scaner.c 文件4.4. 编译运行程序testin.txt 是词法分析器的输入程序(即输入的源程序,此程序由学生给出)。运行后,自动在lishuman 目录下生成 result.txt 文件。(testin.txt 和 result.txt 文件都可由记事本查看内容)图 4-4.1 testin.txt 文件内容图 4-4.2 result.txt 文件内容如果 testin.txt 中输入有误图 4-4.3 testin.txt 错误文件内容则运行时显示:图 4-4.4 result.txt 错误文件内容五、源程序#in
7、clude #include #include #define _KEY_WORD_END “waiting for your expanding“typedef struct int typenum;char * word; WORD;char input255;/输入缓冲区 char token255=“;/单词缓冲区 int p_input;/输入缓冲区指针 int p_token;/单词缓冲区指针 char ch;/当前读入字符 char* KEY_WORDS=“begin“,“if“,“then“,“while“,“do“,“end“,“lishuman“,“lishuman2015
8、041886“,_KEY_WORD_END;/关键字数组 WORD* scaner(WORD* word);/词法扫描函数 int main(int argc,char * argv)int over=1;WORD* oneword= calloc(1,sizeof(WORD*);/printf(“Enter Your words(end with $):“);/scanf(“%$s“,input);FILE *fin;char buffer1000;if(fin=fopen(“testin.txt“,“r“)=NULL)printf(“Cannot open the file!n“);exi
9、t(-1);while(fgets(buffer,100,fin)!=NULL)strcat(input,buffer);fclose(fin);FILE *fout;if(fout=fopen(“result.txt“,“w“)=NULL)printf(“Cannot open the file!n“);exit(-1);p_input=0;printf(“Your words:n%sn“,input);while(overtypenumtypenum,oneword-word);/打印种别码和单词自身的值 over=oneword-typenum;fclose(fout);printf(“
10、npress done.“);/从缓冲区读取一个字符到 ch 中 char m_getch()ch=inputp_input;p_input=p_input+1;return (ch);/去掉空白符号 void getbc()while(ch= |ch=10)ch=inputp_input;p_input=p_input+1;/拼接单词 void concat()tokenp_token=ch;p_token=p_token+1;tokenp_token=0;/判断是否字母 int letter()if(ch=amyword-word=“;p_token=0;m_getch();getbc()
11、;if(letter()while(letter()|digit()concat();m_getch();retract();myword-typenum=reserve();myword-word=token;return(myword);else if(digit()while(digit()concat();m_getch();/ retract();if(letter()myword-typenum=-1;myword-word=“ERROR“;printf(“In %s(), line=%d, invalid variable, error!n“, _func_, _LINE_);e
12、xit(0);elseretract();myword-typenum=20;myword-word=token; else switch(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=2
13、3;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 : my
14、word-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 :
15、 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 typenum=38;myword-word=“typenum=36;mywo
16、rd-word=“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 语言的编程方法;又加深了对词法分析原理的理解和词法分析的实现过程,掌握了编译程序的实现方法和技术,懂得了词法分析器的工作原理。在编程过程中,遇到了不少的问题,在同学的帮助下,问题一步一步的得到了解决。先从实现最简单的扫描和输出开始,后继实现了扫描范围的扩大和输出结果的更加具体。