词法分析
词法分析程序又称词法分析器或扫描器,是编译程序的基本子过程之一。
3.1 词法分析程序的功能及实现方案
词法分析程序的功能是:扫描源程序字符,按语言的词法规则识别出各类单词符号(Token),并将有关字符组合成为单词并输出,同时进行词法检查。语言的保留字、标示符,常数和运算符等等都是单词的例子。词法分析程序的主要任务是进行词法分析,同时完成相关单词转化和处理。
归纳如下:
(1),词法分析:从源程序第一个字符开始,顺序的读字符,一个个读入并确定单词同时进行词法检查,若发现单词组成有错误时输出有关错误信息。
(2),对数字常数完成数字字符串到二进制数值的转换,并将其值输出。
(3),删去空格、换行、制表字符和注释。
词法分析程序可以单独作为一遍来实现,此时将它的输出放在一个单独文件中,语法分析器可以从该文件中取得输入。也可以将其存放到内存中,提高效率。通过这一遍的加工,就可以将字符串表示的源程序表示为以单词表示的源程序了。
3.2 单词的种类及词法分析程序的输出形式
1,单词的种类:
(1),保留字:程序语言预定义的字符串,如begin,end,for,if,then,do等
(2),标识符:用户定义的标示各种名字的字符串,如变量名,数组名和函数名等。
(3),常数。
(4),分界符或操作符。
2,词法分析程序的输出形式:
为了便于编译程序进一步加工,单词的输出形式一般采用二元式,如图:
单词类别 |
单词值 |
整型 保留字 |
58
for |
其实,一个单词符号如何分类、怎么样编码是一个技术性的问题,主要取决于处理上的方便。
3.3 正则文法和状态图
由形式语言和自动子理论可以知道,对于正则文法所描述的语言,可以用一种有穷自动机来识别。我们直接介绍这种自动机的非形式表示,即状态图。
3.3.1 状态图
状态图也称状态转换图,是一个有向图。
略
3.4 词法分析程序的设计与实现
首先确定词法分析程序的具体输出形式,然后编写程序。
1,输出形式:
仍采用二元式,下表表示了词法分析程序的输出形式
单词名称 |
类别编码 |
记忆符 |
单词值 |
BEGIN END IF THEN ELSE 标示符 整常数 + - * / ( ) , ; : := = |
1 2 3 4 5
20
21 22 23 24 25 26 27 28 29 30 31 32 |
BEGINSY ENDSY IFSY THENSY ELSESY
IDSY
INTSY PLUSSY MINUSSY STARSY DIVISY LPARSY RPARSY COMMASY SEMISY COLONSY ASSIGNSY EQUSY |
- - - - -
内部字符串表示
二进制数值表示 - - - - - - - - - |
2,全局变量和过程:
词法分析程序所用的全局变量和要调用的过程和函数如下:
char:字符全局变量,存放当前读入的字符。
token:字符数组,存放单词的字符串
symbol:枚举型全局变量,保存当前所识别的单词类型。
getchar():读字符过程,每调用一次镀金一个字符放在char中,并把读字符指针指向下一个字符.
clearToken():清空token字符数组
isSpace(),isNewline(),isTab():判断char中字符是否为空格、换行、Tab
isLetter(),isDigit():判断char中字符是否为数字、字母
isClono(),isComma(),isSemi():判断char中字符是否为冒号,逗号,分号
isEqu(),isPlus(),isMinus(),isDivi():判断char中字符是否为等号,加号,减号,除号
isStar():判断char中字符是否为*号
isLpar(),isRpar():判断char中字符是否为左右括号
catToken():每次调用把当前char中字符与token数组中的字符串联接。
retract():将读字符指针后退一个字符。
reserver():查找保留字,如果返回值为0,则表示token中字符串是一个标示符,否则为保留字编码,返回当前保留字的类编码。
transNum():将token中的字符串转换成整型数值,返回这个值
error():错误处理过程。
对应的词法分析程序算法如下:
/*词法分析程序*/ int getsym() { clearToken(); while(isSpace()||isNewline()||isTab()) getchar();/*读取字符,跳过空格换行和tab*/ if(isLetter())/*判断当前字符是否是一个字母*/ { while(isLetter()||isDigit())/*将字符拼接成字符串*/ { catToken(); getchar(); } retract();/*指针后退一个字符*/ int resultValue = reserver();/*resultValue是查找保留字的返回值*/ if(resultValue==0) symbol=IDSY;/*resultValue=0,token中的字符串为标识符*/ else symbol=resultValue;/*否则token中的字符串为保留字*/ } else(isDigit())/*判断当前字符是否是一个数字*/ { while(isDigit())/*将字符拼接成整数*/ { catToken(); getchar(); } retract(); num = transNum();/*将token中的字符串转换成整数*/ symbol=INTSY;/*此时识别的单词是整数*/ } else(isColon())/*判断当前字符是否是冒号*/ { getchar(); if(isEqu()) symbol=ASSIGNSY;/*判断是否是赋值符号*/ else retract(); symbol=COLONSY; } else if(isPlus()) /*判断是否是加号*/ symbol=PLUSSY; else if(isMinus()) /*判断是否是减号*/ symbol=MINUSSY; else if(isStar())/*判断是否时星号*/ symbol=STARSY; else if(isLpar())/*判断是否是左括号*/ symbol=LPARSY; else if(isRpar())/*判断是否是右括号*/ symbol=RPARSY; else if(isComma())/*判断是否是逗号*/ symbol=COMMASY; else if(isSemi())/*判断是否是分号*/ symbol=SEMISY; else if(isDivi())/*判断是否是斜竖*/ { getchar(); if(isStar())/*处理注释*/ { do{ do{ getchar();} while(!isStar()); do{ getchar(); if(isDivi()) return 0;/*注释处理完毕*/ }while(isStar()); }while(!isStar()); } else{ retract(); symbol=DIVISY;/*如果不是注释则为除号*/ } } else error(); return 0; }