词法分析器flex的简单用法

安装flex

在Ubuntu下安装flex非常简单,只需要在终端中输入

sudo apt-get install flex

即可;

如果说找不到flex,可能你需要更新系统的源,百度一下“Ubuntu更新源”,应该可以解决;

flex

什么是flex?
flex是指 fast lexical analyzer generator,快速词法分析器生成器,也就是说,flex用于产生词法分析器;

flex的输入是文件或输入设备,这些输入中的信息以正则表达式和C代码的形式组成,这些形式被称为规则(rule);
flex的默认输出是C语言的源码文件:lex.yy.c,也可以重命名;该文件通过编译生成可执行的文件;
当可执行文件被执行时,其分析输入中可能存在的符合规则的内容,当找到任何一个正则表达式相匹配内容时,相应的C代码将被执行;

flex的输入文件由3段组成,用一行中只有%%来分隔;

定义:definition
%%
规则:rules
%%
用户代码:code

定义部分

其中定义有变量声明,正则表达式声明;
变量声明有两种:
例1:

%{
int a;
int b;
%}

例2:

    int a;
    int b;

需要有tab键缩进;

正则表达式声明方式:
表达式名称 表达式

在使用时需要将表达式名称用{}括起来;

规则部分

一个规则一行,每行有两部分构成:
正则表达式 {动作函数}
动作函数可以调用在用户代码中定义的函数;

例子1

编码过程

编写一个名为t1.lex的文件:

/*t1.lex*/
%option main /*生成main函数*/
%{
int fun();
%}

%%
/*第一个%%之后是规则部分*/
apple {fun();}

%%
int fun(){
    printf("banana");
    return 0;
}

这个文件的规则为如果遇到“apple”,执行代码“printf(“banana”)”,及将输入中的apple替换为banana;
通过:flex t1.lex生成lex.yy.c文件;
通过编译该c语言文件:gcc lex.yy.c
生成一个可执行文件a.out

实验过程

在终端输入:echo 123apple123 | a.out
输出为:123banana123
这里写图片描述

例子2

编写一个简单的对c语言能够解析的lex文件,代码t2.lex如下所示:

/*t2.lex*/
%option main
%{
    int line=1;
%}
DIGIT [0-9]
OINTEGER [1-9]{DIGIT}*
INTEGER ("+"|"-")?{OINTEGER}
DECIMAL {INTEGER}(.{OINTEGER})?
LETTER [a-zA-Z]
ID ({LETTER}|_)({LETTER}|_|{DIGIT})*
OPT ("+="|"-="|"*="|"/="|"+"|"-"|"*"|"/"|"<="|">="|"=="|"=")
%%
\n {++line;}
(int|float|double|short) {printf("line%d:(type,%s)\n",line,yytext);}
for {printf("line%d:(for,)\n",line);}
{INTEGER} {printf("line%d:(integer,%s)\n",line,yytext);}
{DECIMAL} {printf("line%d:(decimal,%s)\n",line,yytext);}
{ID} {printf("line%d:(identify,%s)\n",line,yytext);}
("("|")"|"{"|"}"|"["|"]") {printf("line%d:(bracket,\"%s\")\n",line,yytext);}
"\"" {printf("line%d:(QUOTE,)\n",line);}
{OPT} {printf("line%d:(OPT,%s)\n",line,yytext);}

. {}
%%
/*辅助过程部分*/

代码说明:
3~5行:全局变量的说明,需要用“%{”和“%}”括起来;
6行:类似于C语言中的宏定义,翻译规则中的{DIGIT}将被“[0-9]”所替换;”[0-9]”是一个正则表达式,表示字符’0’、’1’、…、’8’、’9’中的任意一个;
8行:+号需要用引号括起来,因为正则表达式也有+号;同理,-号也需要括起来;
21行:引号需要有反斜杠进行转义;

实验过程

创建一个test文件:

int main(){
    int a = 10;
    double b = -20.9;
    if(a<=b)
        a+=b;
    return a;
}

在终端中分别输入:
flex -o t2.c t2.lex
gcc t2.c -o ./a.out
./a.out < test
实验结果如下:
这里写图片描述
输出格式为:
元素所在行:{ID号,属性}

注意点:

  • 正规定义中[xy]等价于(x|y)
  • 定义部分一些在翻译规则中使用的变量的声明,需要由%{和%}包围起来,这部分声明将被直接抄写在lex.yy.c中,不作为正规定义和翻译规则的一部分;
  • 如果变量的声明不在%{和%}之间,那么需要在声明部分进行缩进(使用tab缩进);
  • 辅助过程是一些函数,能够被抄入到生成的c文件中,在规则后面的动作中可以调用;
  • 规则后面的动作可以通过return返回词法单元的记号;在动作、辅助过程中可以使用变量yylval、yytext、yyleng,这些变量为全局变量,通过yylval传送记号属性给语法分析器,yytext为解析出的词法单元字符串的指针,yyleng为词法单元字符串长度;
  • 若两个表达式同时匹配一个词法单元,如表达式if和[a-z]+同时匹配if\s,(注意\s表示空格),那么按照两个表达式在翻译规则中的顺序选择动作;而表达式<和<=匹配<=\s时,<可以匹配1个单词,<=可以匹配两个单词,那么选择匹配元素多的<=;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值