词法分析器
词法分析器功能:处理m语言源程序,过滤掉无用符号,判断源程序中单词的合法性,分解出正确的单词,输出二元组。
一、样本m语言的定义(实质:C语言子集)
<程序>->{<声明语句><语句>}
<声明语句>-><声明语句>(const|static|ε)double ID([NUM]|ε);
|<声明语句>(const|static|ε) float ID([NUM]|ε);
|<声明语句>(const|static|ε)int ID([NUM]|ε);
|<声明语句>(const|static|ε)char ID([NUM]|ε);
|double (const|static|ε)ID([NUM]|ε);
|float (const|static|ε)ID([NUM]|ε);
|int (const|static|ε)ID([NUM]|ε);
|char (const|static|ε)ID([NUM]|ε);
<语句>->if(<布尔表达式>) <语句> else <语句>
|if (<布尔表达式>) <语句>
|while (<布尔表达式>) <语句>
|do<语句> while (<布尔表达式>)
|for<语句> <语句>
|switch<语句> case <语句>
|ID=<算术表达式>
|continue
|break
|default
|return(NUM|ε)
|{<复合语句> }
<复合语句>-><语句>;<复合语句> | <语句>
<布尔表达式>->| ID relop ID |ID
<算术表达式>-><算术表达式> op <算术表达式>
|(<算术表达式>)| ID | NUM
ID -><Letter> {<Letter> | <Digit>}*
NUM -><Digit>|(<digit>)*
relop-> ==|!=|<|<=|>|>=
op->+|-|*|/
Letter ->a|b|…|y|z
Digit->0|1|…|8|9
二、根据样本m语言的定义,一个合法的程序如下:
void cXydata()
{
int i=10,j=30,k=0;
if(i>=j)
k=i;
else k=j;
}
三、样本m语言的单词类别及内部表示
1、五类单词:
第一类:关键字(21个)break、case、char、const、continue、default、do、double、else、float、for、if、int、return、sizeof、
static、struct、switch、typedef、void、while
第二类:标识符 Letter(Letter|Digit)*
第三类:常数 Digit(Digit)*
第四类:算术运算符 +、-、*、/、<、>、<=、>=、!=、==、=
第五类:分隔符 {、}、[、]、(、)、,、;
2、自定义编码:(方便判断对应字符类型)
<$,0> <break,1> <case,2><char,3> <const,4> <continue,5> <default,6><do,7> <double,8> <else,9> <float,10>
<for,11><if,12> <int,13> <return,14> <sizeof,15><static,16> <struct,17> <switch,18> <typedef,19><void,20> <while,21>
<+,22> <-,23> <*,24></,25> <<,26> <>,27> <<=,28> <>=,29><!=,30> <==,31> <=,32> <{,33> <},34> <[,35><],36> <(,37>
<),38> <,,39> <;,40> <NUM,41><ID,42>
注意:规定$为源程序末尾标志,即词法分析器分析结束标志。
3、输出形式(二元组形式):
<break,-> <case,-><char,-> <const,-> <continue,-> <default,-><do,-> <double,-> <else,-> <float,->
<for,-> <if,-> <int,-><return,-> <sizeof,-> <static,-> <struct,-><switch,-> <typedef,-> <void,-> <while,->
<relop,+><relop,-> <relop,*> <relop,/> <relop,<><relop,>> <relop,<=> <relop,>=> <relop,!=><relop,==>
<relop,=> <{,--> <},--> <[,--><],--> <(,--> <),--> <,,--> <;,--> <NUM,数值> <ID,标识符名>
四、样本m语言的单词识别的状态转换图
每个单词的识别都是从初始状态开始,如果把状态转换图看成一个函数,则每次调用只能识别出一个单词。
状态转换图如下:
五、程序分析
1、几个重要变量
charresourceProject[1000];//源程序存放处。
chartoken[20]={0};//存储每次扫描的结果。
intsys=-1;//syn即为编码,约定$的种别码为0,为整个源程序的结束符号。
intp= 0;//源程序指针,始终指向当前源程序待扫描位置。
2、几个重要函数
searchReserve(charKeyword[ ][20], char s[]):查找保留字,成功查找,返回对应编码,否则返回42,代表查找不成功,即为 标识符。
IsLetter(chara):判断是否为字母。
IsDigit(chara):判断是否为数字。
filterResource(chara[],int b):取出无用的字符和注释。
Scanner(chara[],char b[],int p):核心程序。
3、执行步骤
(1)打开源文件,读取文件内容,直至遇上$字符,读取结束。
(2)对读取的文件进行预处理,从头到尾进行扫描,去除//和/* */的内容,以及无用字符。
(3)从头开始扫描,略去空格,逐步进行判断,单词都会保存在token[ ]中,返回编码序号。
(4)主程序负责对每次识别的编码sys进行判断,对于不同的单词种别做出 不同的反应,直到遇见sys=0为止。
注意: (1)源程序必须存在$作为读取结束标志。
(2)简单起见只可以读取整数。
(3)需要自己编写源程序进行词法分析。
源码: