要求:在理解词法分析器原理的基础上,用C语言写一个类C的词法分析器。
1) 明确词法分析器的功能及原理
2) 定义单词符号的种类
3) 定义单词编码的规则
4) 输入预处理的功能
5) 定义词法错误及错误显示方式
6) 程序设计及调试
******************************************************************************
Z语言词法分析程序(Z Language Lexical Analysis)使用说明
******************************************************************************
一. 词法分析的功能及原理
(1)词法分析的功能是:扫描源程序字符流,按照原语言的此法规则识别出单词符号,并产生用语语法分析的符号序列,即将字符串源程序转化为符号串源程序。程序设计语言的保留字或关键字、标识符、常数、各种运算符都是单词符号的例子。
(2)词法分析工作原理是:从源程序第一个字符开始,顺序读字符,一次读一个,根据所读的字符识别各类单词,同时去掉源程序中的注释和空白。词法分析检查的错误主要是挑出源程序中的非法符号。所谓非法符号是指不是程序设计语言中允许出现的符号,就像自然语句中的错字。
二.Z语言(类C语言)简介
Z语言是为本词法分析程序专门设计的一种程序语言,它在语法上与C语言类似,但要比C语言简单的多。它的所有变量都是整数变量。它具有if、while、for等控制语句。注释用/*和*/括起来,但注释不能够嵌套。Z语言的表达式局限于布尔表达式和算术表达式。
三. Z语言词法分析程序简介
根据DFA来构造词法分析程序有两种方法:直接编程的词法分析器和表驱动的词法分析程序。本Z语言词法分析程序采用的是前一种直接编程的词法分析器。
所谓的直接编程的词法分析器,是将DFA识别过程转化为程序,即用程序来模拟DFA的行为。在这种方法里,首先将DFA用状态图表示,然后按下列步骤根据状态图画出词法分析程序的流程图:
(1) 初始状态对应程序的开始;
(2) 结束状态对应程序的结束;
(3) 状态转移对应条件语句或者多分支选择语句;
(4) 状态图的环对应程序中的循环语句;
(5) 终态返回时,应满足最长匹配原则;
其中最长匹配原则是指识别出的单词有混淆时,按长度最长来确定。例如,符号串"<="认为是一个单词,而不是"<"和"="。
这种设计方法适合手工实现,编写出的词法分析程序比较精简,分析速度快。但但要与识别语言的单词密切相关,通过程序控制流的转移来完成对输入字符的响应,程序中每一条语句都与要识别的单词符号有关,一旦语言的单词符号集(此法规则)发生变化,则要重新编写程序。
四. 定义单词符号的种类
1. 通常词法分析程序定义以下5种单词符号:
(1) 保留字。if、while、for、else、do等保留字在程序设计语言中有固定的意义,是编译程序识别各类语法的依据,用户不能用他们作为标识符。
(2) 标识符。有用户定义,用来表示各种名字,如变量名、函数名、数组名等。
(3) 无符号数。如137、0.67、34.2等为无符号数。
(4) 分界符:如+、-、*、/、;、(、)等单分界符;>=、<=、!=、==等双分界符。
(5) 注释符:/*········*/
五.定义单词编码的规则
1. 本词法分析程序采用的(类C语言)Z语言所定义的单词符号有:
(1) 标识符:字母开头、后接字母或数字。
(2) 保留字:if、else 、while、for、do、int、char、double。
(3) 无符号整数:由0~9数字组成。
(4) 分界符:如+、-、*、/、;、(、)单分界符;>=、<=、!=、==双分界符。
(5) 注释符:用/*········*/括起。
2. Z语言各类单词符号的正则文法规则如下:
<identifier>: : = a|b|···|z|<identifier>a|···|<identifier>z
|<identifier>0|···|<identifier>9
<number>: : = 0|1|···|9|< number >0|···|< number >9
<letter>: : = a|b|···|z|A|B|···|Z
<digit>: : = |1|2|···|9|0|
<singleword>: : = | + | - | * | / | = | ( | ) | { | } | : | , | : | < | > | !
<doubleword>: : = <great> |···
<greater>: : = >
<equal>: : = =
<comment_first>: : /*
<comment_last>: : */
六. 输入预处理的功能
#include<stdio.h> 输入输出功能
#include<string.h> 字符串处理功能
七. 定义词法错误及错误显示方式
(1)打开词法分析输入文件错误
//ZscanProgram.c
if((fin=fopen(Scanin,"r"))==NULL)
{
printf("\n打开词法分析输入文件出错!\n");
return(1);
}
(2)词法分析过程中出错
//ZMain.c
int es=0;
es=Zscan();
if(es>0)printf("词法分析有错,编译停止!");
(3)创建词法分析输出文件错误
//ZscanProgram.c
if((fout=fopen(Scanout,"w"))==NULL) //判断输出文件名是否正确
{
printf("\n创建词法分析输出文件出错!\n");
return(2); //输入文件出错返回代码1
}
八. Z语言词法分析程序的实现
1. 输出形式
为了使词法分析的输出含义明确,易于理解,本程序对识别出的每个单词符号输出两项内容:一是单词记号(即单词的意义,是标识符还是数字等),二是单词值。对于保留字分界符直接输出相同的字符串作为单词记号,此时,单词记号与单词值相同,为了统一输出形式两者一同输出。以下列出不同类型的单词及其对应的单词记号:
单词 单词记号 单词值
标识符 ID 实际标识符
无符号整数 NUM 数字字符串
保留字 KEYWORD 实际保留字
但分界符 SINGLEWORD 实际单分界符
双分界符 DOUBLEWORD 实际双分界符
2. Z语言词法分析程序Z Language Lexical Analysis
该词法分析程序采用C语言编制。
(1) 关于保留字处理
程序中将保留字保存在一个指针数组中,可随时增加和修改。本Z语言词法分析程序保留字不区分大小写,但标识符区分。
(2) 关于单分界符处理
分界符单分界符与双分界符之分。对于那些和双分界符或其他符号没有冲突的单分界符连接起来,作为一个字符串并保存在字符数组singleWord中,这样,通过判断读入的字符是否是singleword的中字符就可识别单分界符。
(3) 关于双分界符处理
双分界符需要单独处理,本程序处理的双分界符第二个字符都相同,所以可以将uoyou双分界符的第一个符号连接成字符串并保存在字符数组doubleword中,当判断字符时doubleword中的字符时,要再读入一个字符,如果这个字符是'=',则识别出双分界符,如果不是则输出相应的单分界符。
(4) 对于注释处理
对于注释和单分界符'/'要单独处理。当读入的字符是'/'时,要读入下一个字符,如果不是'*',则输出单分界符'/';如果是'*'号,则进行注释处理。处理方法是:增加一个新变量ch1, ch保存前一个字符,ch1为新读入的字符,如果ch是'*',而ch1是'/',则遇到注释尾,否则令ch=ch1,ch1则读下一个字符,再判断,直到遇到注释尾,这样就可以将注释去掉。
(5) 关于函数Zscan()返回值
词法分析函数Zscan返回值为整型,如返回值为0表示没有词法分析错误发生,返回值为1或2则表示输入或输出文件错误,为3表示有非法符号即未在Z语言中定义。
(6) 关于文件的输入输出与运行
本词法分析程序处理的源文件名和输出文件名保存在字符数组Scanin和Scanout中,执行词法分析程序前,首先要建立词法分析的源程序。并在运行词法分析程序时按提示输入源文件名和输出文件名。如果输入和输出文件与词法分析程序(Z Language Lexical Analysis.exe)在同一debug目录下,建议直接运行exe文件输入文件名加文件格式(文件名.格式)即可,否则应输入包含路径的文件名。另外,在VC++中调试也须输入路径。词法分析程序运行后,若成功在用户设置的相应输出文件位置会产生一个新文件(建议用txt表示),打开该文件即可查看结果。