源于编译的实验作业……
参考链接:blog.csdn.net/dl88250/article/details/1714626
Lex工具是一种词法分析程序生成器,它可以根据词法规则说明书的要求来生成单词识别程序,由该程序识别出输入文本中的各个单词。
一、结构:定义部分、规则部分、用户子程序部分
1、定义部分
定义部分起始于"%{"符号,终止于"%}"符号,其间可以是包括include语句、声明语句在内的C语句。
%{
#include "stdio.h"
#include "y.tab.h"
extern int lineno;
%}
第二部分是一组正规定义和状态定义。正规定义是为了简化后面的词法规则而给部分正规式定义了名字。每条正规定义也都要顶着行首写。例如下面这组正规定义分别定义了letter,digit和id所表示的正规式:
letter [A-Za-z]
digit [0-9]
id {letter}({letter}|{digit})*
注意:上面正规定义中出现的小括号表示分组,而不是被匹配的字符。而大括号括起的部分表示正规定义名。
2、规则部分
规则部分起始于"%%"符号,终止于"%%"符号,其间则是词法规则。
词法规则由模式和动作两部分组成。模式部分可以由任意的正则表达式组成,动作部分是 由C语言语句组成,这些语句用来对所匹配的模式进行相应处理。需要注意的是,lex将识别出来的单词存放在yytext[]字符数据中,因此该数组的内容 就代表了所识别出来的单词的内容。
%%
[/t] {;}
[0-9]+/.?|[0-9]*/.[0-9]+
{ sscanf(yytext,"%1f", &yylval.val);
return NUMBER; }
/n { lineno++;return '/n'; }
. { return yytex+[0]; }
%%
3、用户子程序部分
用户子程序部分可以包含用C语言编写的子程序,而这些子程序可以用在前面的动作中,这样就可以达到简化编程的目的。下面是带有用户子程序的lex程序片段。
"/*" skipcmnts();
. /* rest of rules */
%%
skipcmnts()
{
for ( ; ; )
{
while (input()!='*');
if(input()!='/')
unput(yytext[yylen-1]);
else return;
}
二、Lex常规表达式
参考链接:blog.csdn.net/hguisu/article/details/7490027
举例:
标记声明举例:
三、 Lex源程序中常用到的变量及函数:
yyin和yyout:这是Lex中本身已定义的输入和输出文件指针。这两个变量指明了lex生成的词法分析器从哪里获得输入和输出到哪里。默认:键盘输入,屏幕输出。
yytext和yyleng:这也是lex中已定义的变量,直接用就可以了。
yytext:指向当前识别的词法单元(词文)的指针
yyleng:当前词法单元的长度。
ECHO:Lex中预定义的宏,可以出现在动作中,相当于fprintf(yyout, “%s”,yytext),即输出当前匹配的词法单元。
yylex():词法分析器驱动程序,用Lex翻译器生成的lex.yy.c内必然含有这个函数。
yywrap():词法分析器遇到文件结尾时会调用yywrap()来决定下一步怎么做:
若yywrap()返回0,则继续扫描
若返回1,则返回报告文件结尾的0标记。
由于词法分析器总会调用yywrap,因此辅助函数中最好提供yywrap,如果不提供,则在用C编译器编译lex.yy.c时,需要链接相应的库,库中会给出标准的yywrap函数(标准函数返回1)。