词法分析器的生成器——lex/flex


1.词法分析器和语法分析器

词法分析器:将文本分解成token

语法分析器:判断token是否符合规定的语法规则

  • 可以自己实现词法/语法分析器,分离文本,编写语法规则。但是为了方便和规范的词法语法分析,我们使用flex和bison;
  • flex是词法分析器的生成工具,bison是语法分析器的生成工具;
  • 使用此工具就让我们脱离了繁琐的代码编写上,只需要关注我们需要什么符号,使用什么规则。

2.flex

1.使用

1.编写好词法规则文件,一般以.l为文件格式(flex对文件格式没要求,不是.l也没关系)

2.flex xxx.l 生成lex.yy.c

3.gcc lex.yy.c -lfl (-lfl带不带都没关系) 可以修改lex.yy.c名字

例子:

/*flex-wc.l*/
%option noyywrap	//option、noyywrap是flex的关键字,语法部分介绍
%{
int chars = 0;		//声明
int words = 0;
int lines = 0;
%}
%%
[a-zA-z]+ { words++; chars += strlen(yytext); }	//规则
\n 		  { lines++; chars++; }
. 		  { chars++; }
%%					//以下部分会在lex.yy.c上原地展开
int main() {
    yylex();		//根据以上规则生成的词法分析函数		
    printf("%8d %8d %8d\n", lines, words, chars);
    return 0;
}

2.文件格式

%{
C语言声明,一般声明全局变量和函数,会复制进lex.yy.c中
%}
定义正则表达式的名字,可以在规则段中使用
%%
规则段,每一行都是一条规则,每一条规则由匹配模式和事件组成。每当一个模式被匹配到,后面的事件被执行!
%%
用户自定义过程,直接复制到lex.yy.c末尾

flex提供的全局变量:

  • yytext:刚刚匹配到的字符串
  • yyleng:刚刚匹配到的字符串的长度
  • yyin:FILE*类型
  • yyout:指向输出的文件,缺省情况下指向标准输入输出
  • yylineno:当前行数信息
  • yylval:可由yytext取出数字atoi(yytext)

flex提供的函数:

  • yylex():词法分析器驱动程序,用Lex翻译器生成的lex.yy.c内必然含有这个函数;YY_DECL
  • yywrap():词法分析器遇到文件结尾时会调用yywrap()来决定下一步怎么做:这是一个约束函数。若yywrap()返回0,则继续扫描; 当它返回1时,代表扫描结束,此时结束程序;

以下部分作为了解:

  • yyless(int n):用来送回除了前n个字符外的所有读出标记
  • yymore():告诉lexer将下一个标记符加到当前标记后
  • yymore():将当前识别的词形保留在yytext中,分析器下次扫描时的词形将加追加在yytext中。例模式定义如下
   hello {printf(“%s!”,yytext);yymore();}
   world {printf(“%s!”,yytext);}
12

​ 当输入串为”helloworld”时,将输出”hello!helloworld!”

  • REJECT:放弃当前匹配的字符串和当前的模式,让分析器重新扫描当前的字符串,并选择另一个最佳的模式再次进行匹配。
  • yyless(int n):回退当前识别的词形中n个字符到输入中
  • unput(char c):回退字符c到输入,它将作为下一次扫描的开始字符
  • input():让分析器从输入缓冲区中读取当前字符,并将yyin指向下一字符
  • yyterminate():中断对当前文件的分析,将yyin指向EOF。
  • yyrestart(FILE * file):重新设置分析器的扫描文件为file
  • ECHO: #define ECHO fwrite(yytext, yyleng, 1, yyout)将当前识别的字符串拷贝到yyout
  • BEGIN:激活开始条件对应的模式

规则部分的语法:

遵循正则表达式,如一些比较有用的规则:

[ \t]       { /*ignore white space*/ }	//{}中什么都不做,就是将空格删除
.           { printf("unexpected token: (%s)\n", yytext); 
              return -1; }		//其他情况,一般放在最后,表示意外情况,返回错误

3.条件模式(了解)

LEX提供控制模式在一定状态下使用的功能,称为条件模式。LEX首先在定义部份通过%start来定义条件句。在规则部份可通过宏
BEGIN 条件名 来激活条件。BEGIN INITIAL或BEGIN 0将休眠所有的条件模式,使分析器回到开始状态。
例:将输入文件中的单词”magic” 作如下处理:识别”magic”时,如”magic”所在行行首为字符’a’,则输出”first”;若为’b’,则输出”second”;否则,输出”magic”。如不用条件模式,LEX源文件可这样写:

%{int flag;}%
%%
^a {flag=’a’;ECHO;}
^b {flag=’b’;ECHO;}
/n {flag=0;ECHO;}
magic {
switch(flag)
{
case ‘a’:printf(“first”);break;
case ‘b’:printf(“second”);break;
default :ECHO;break;
}
}
%%

如使用条件模式,则上述源文件可简化为

%start AA BB CC
%%
^a {ECHO;BEGIN AA;}
^b {ECHO;BEGIN BB;}
/n {ECHO;BEGIN 0;}
<AA>magic {printf(“first”);}
<BB>magic {printf(“second”);}
%%
##

参考文章:
https://blog.csdn.net/damontive/article/details/115289890
https://www.cnblogs.com/wanghetao/archive/2011/11/07/2240193.html
https://blog.csdn.net/liwei_cmg/article/details/1530492

  • 5
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值