首先了解一下lex:
一、lex的书写规则
<definitions>
%%
<rules>
%%
<user_code>
1)Definition部分
(1)Definition部分用来引入一些头文件或一些词法分析过程中用到的函数。他们将直接的拷贝到输出文件中。这部分内容放到%{和%}之间。
(2)Definition还可以用来定义一些词法分析器用到的宏。这部分内容要放到%{ 。。。。%}的下面。
2)规则部分
"if" {return IF;}
"=" {returnASSIGN;}
";" {returnEND_STMT;}
{IDENT} {Identifier(); returnID;}
{STR} {StringConstant(); returnSTRING;}
"//" {EatComment();} /*comment: skip */
\n {lineno++;} /*newline: countlines */
{WSPACE}{} /*whitespace: (donothing) */
. {returnERROR_TOKEN;} /*other char: error,illegal token */
3)用户代码部分
这部分内容将原封不动的拷贝到LEx的输出文件当中。一般是词法分析过程中用到的一些函数1)yytext 可能是一个数组或一个指针。指向被识别的记号。
2)yylex() 是lex解析器的主函数,通过调用yylex()来实现对字符流的解析。通常作为一个词法扫描器的自动实现函数,他的返回值是一个整数,且通常是从258开始(防止和通常的acsii码冲突)。但有一个例外,那就是返回值0(0代表着到了文件结尾),通常我们匹配完一个模式后就要让yylex返回。例如:
[a-zA-Z]+ {return 258; }
这个模式就是匹配一个单词的动作,匹配完成立即返回。也就是说。外部的程序每次调用yylex()函数,只要匹配到这个WORD模式,就会立即返回。
但是我们也可以让它不返回(继续留在yelex()的调用里面),例如:
[a-zA-Z]+ {printf(“WORD\n”; }
[0-9}+ {printf(“NUM\n”);}
我们只是让它匹配完模式后在屏幕打印一些字符而已。注意:此时并未退出yylex()函数。而且yylex会继续从模式匹配的开头开始匹配,即会继续匹配下一个token。
有关这一点的差别困扰了很多初学者。。
用《flex && bison》书上的原话就是:Ifaction code returns , scanning resumes on the next call toyylex(); if it doesn’t return , scanning resumes immediately.
3)yyleng,所匹配的yytext所指向的字符串的长度。
4)yyin,是一个文件指针,指向待进行词法分析的字符流文件。
5)yywrap(),当yylex()到达输入文件的尾端时,它调用yywrap(),该函数返回数值0或1.如果值为1,那么程序完成而且没有输入。换句话说,如果值为0,那么词法分析程序假设yywrap()已经打开了他要读取的另外一个文件,而且继续读取yyin。默认yywrap()总是返回1.用户可以自己编写yywrap();
6)input()获取下一个而字符,但是如果目标语言是c++,则用yyinput(),避免与c++本身的input()函数冲突。