输入文件为tiny.l,内容如下
%{
#include "globals.h"
#include "util.h"
#include "scan.h"
char tokenString[MAXTOKENLEN+1];
extern int lineno;
%}
digit [0-9]
number {digit}+
letter [a-zA-Z]
identifier {letter}+
newline \n
whitespace [ \t]+
%%
"if" {return IF;}
"then" {return THEN;}
"else" {return ELSE;}
"end" {return END;}
"repeat" {return REPEAT;}
"until" {return UNTIL;}
"read" {return READ;}
"write" {return WRITE;}
":=" {return ASSIGN;}
"=" {return EQ;}
"<" {return LT;}
"+" {return PLUS;}
"-" {return MINUS;}
"*" {return TIMES;}
"/" {return OVER;}
"(" {return LPAREN;}
")" {return RPAREN;}
";" {return SEMI;}
{number} {return NUM;}
{identifier} {return ID;}
{newline} {lineno++;}
{whitespace} {}
"{" {
.
%%
{
}
需要说明一下,虽然注释也可以用正则表达式"{"[^\}]*"}"来处理,但是为了处理lineno,还是要进行特殊处理。tiny.l通过lex产生tiny.c和tiny.h,直接和其它源文件一起编译就可以了,也就是说只需要用tiny.c代替原来的scan.c即可,别的就不需要改变了,另外利用VC进行调试时,要链接上yld.lib,以及定义宏YYDEBUG。词法分析器输出的结果如下:
int action;
#endif
{
#line 15 ".\\tiny.l"
return IF;
#line 153 "tiny.c"
...
}//end of switch
}
实际上yylex()就是根据yyreturnflg 是否为True来决定是否继续分析的,在本例中每匹配一个正则表达式就会返回,执行不到yyreturnflg = YYFALSE;所以yylex直接返回当前Token就可以了。可以做一个小实验,将上面代码开头处的yyreturnflg = YYTRUE;换成yyreturnflg = YYFALSE;则输出如下结果:
14: EOF
以上结果说明了我的分析是正确的,另外上面在处理换行的时候并不需要考虑各种平台下换行的表示方法,比如Windows平台下换行标志为0D0A,这是因为我们采用的C库函数,C运行库已经帮我们做了这些转换工作。