【编译原理】flex实现词法分析器

flex自动实现词法分析器

FLEX 与 BISON 的使用

FLEX介绍

Flex是一个生成词法分析器的工具,它可以利用正则表达式来生成匹配相应字符串的C语言代码,其语法格式基本同Lex相同。

单词的描述称为模式(Lexical Pattern),模式一般用正规表达式进行精确描述。FLEX通过读取一个有规定格式的文本文件,输出一个C语言源程序。

FLEX的输入文件称为LEX源文件,它内含正规表达式和对相应模式处理的C语言代码。LEX源文件的扩展名习惯上用.l表示。FLEX通过对源文件的扫描自动生成相应的词法分析函数int yylex(),并将之输出到名规定为lex.yy.c的文件中。实用时,可将其改名为lexyy.c。- - - 百度百科

fex的输入是文件或输入设备,这些输入中的信息以正则表达式和C代码的形式组成,这些形式被称为规则(rule);
当可执行文件被执行时,其分析输入中可能存在的符合规则的内容,当找到任何一个正则表达式相匹配内容时,相应的C代码将被执行。
fex的输入文件由3段组成,用一行中只有%%来分隔;

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

定义部分
其中定义有变量声明,正则表达式声明;

%{
	int a;
	int b;
%}
  • 正则表达式声明方式:

表达式名称 表达式

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

  • 规则部分

一个规则一行
正则表达式{动作函数}
动作函数可以调用在用户代码中定义的
下面有小例子

下载安装

下载地址:https://sourceforge.net/projects/winflexbison/
下载好后,解压到任意目录下都可以的。解压后:
在这里插入图片描述

操作例子

1、在减压的目录下创建一个以.l结尾的文件我这里创建的是lex.l,使用记事本打开文件(当然也可以使用别的了),编辑。在这里,就使用简单例子简洁说明一下:

%{
	#include<stdio.h>
	#include<stdlib.h>
	int line=1;
%}

DIGIT [0-9]
OINTEGER [1-9]{DIGIT}*

%%
\n {++line;}
{DIGIT} {printf("line%d:(integer, %s)\n",line,yytext);} 
{OINTEGER} {printf("line%d:(integer, %s)\n",line,yytext);} 
. {}
[ \t]+ {}

%%
int main(){
	yyin=fopen("F:/data.txt","r");
	yylex();
	return 0;
}
int yywrap(){
	return 1;
}

2、在绝对路径下创建data文件,这里是F盘下(fopen("F:/data.txt","r")),编辑文件:

扫描二维码关注公众号,回复: 10068980 查看本文章
13 14 520

3、在项目目录下,DOS 命令提示符下(cmd)。执行win_flex ‐‐nounistd lex.l(lex.l为你的项目名),执行成功会生成一个lex.yy.c文件。
在这里插入图片描述
对C程序进行编译运行:
在这里插入图片描述

词法分析器

首先写正则表达式
例如:

单位整数:DIGIT [0-9]
整数:OINTEGER [1-9]{DIGIT}*

因此,需要根据各词的特征将正则表达式写出来。

  • lex.l
%{
	#include<stdio.h>
	#include<stdlib.h>
	#include<string.h>
	int line=1;
%}
LETTER [a-zA-Z]
ID ({LETTER}|_)({LETTER}|_|{DIGIT})* 
OPT ("+"|"-"|"*"|"/"|"+="|"-="|"*="|"/="|">="|"<="|"=="|">"|"<"|"="|"++"|"--") 
BRACKET ("("|")"|"["|"]"|"{"|"}"|";"|","|"\'"|"\""|"#") 
DIGIT [0-9]
OINTEGER [1-9]{DIGIT}*
INTEGER ("+"|"-")?{OINTEGER}
DECIMAL {INTEGER}(.{OINTEGER})
FLOAT ([0-9])*+[.]([0-9])*+[Ee]([+-]?[0-9]([0-9])*|[0])
ERROEFLOAT ([0-9])*+[.](0-9)*+("E"|"e")
TYPE void|int|double|char
KEYWORD if|else|do|while|for|scanf|printf|sqrt|abs|main|return|float
TYPEIDENTIFY %d|%c|%s|%f|&{ID}
SGPS \/\/.*
DBPS \/\*(.|\n)*\*\/ 

%%
\n {++line;}
{TYPE} {printf("line%d:(type, %s)\n",line,yytext);}
{KEYWORD} {printf("line%d:(keyword, %s)\n",line,yytext);}
{DIGIT} {printf("line%d:(integer, %s)\n",line,yytext);} 
{OINTEGER} {printf("line%d:(integer, %s)\n",line,yytext);} 
{ID} {printf("line%d:(identify, %s)\n",line,yytext);} 
{BRACKET} {printf("line%d:(bracket, %s)\n",line,yytext);} 
{OPT} {printf("line%d:(OPT, %s)\n",line,yytext);}
{INTEGER} {printf("line%d:(integer, %s)\n",line,yytext);}
{DECIMAL} {printf("line%d:(decimal, %s)\n",line,yytext);}
{FLOAT} {printf("line%d:(float, %s)\n",line,yytext);}
{TYPEIDENTIFY} {printf("line%d:(typeidentify, %s)\n",line,yytext);}
{ERROEFLOAT} {printf("ERROEFLOAT\n");}
({SGPS}|{DBPS}) {}
. {}
[ \t]+ {}

%%
int main(){
	yyin=fopen("F:/data.txt","r");
	yylex();
	return 0;
}
int yywrap(){
	return 1;
}

  • 第一个测试样例:data.txt
int main(){

    int a = 10;

    double b = -20.9;

    if(a<=b)        

    a+=b;

    return a;
}

在这里插入图片描述

  • 第二个测试样例:data.txt
int main(){
    int a = 10;
    double b = -20.9;
    float c=1.2E-3;
    if(a<=b)        
    	a+=b;
    return a;
}

在这里插入图片描述

  • 第三个测试样例:data.txt
int main(){
    int a = 10;
    double b = -20.9;
    float c=1.2E3;
    printf("%d",&a);
    return a;
}

在这里插入图片描述
特别提醒:如果需要处理错误情况(如:浮点数错误,符号错误),依然是写出错误情况的正则表达式,进行匹配。需要像报错那样,只输出错误情况,而且在错误之前的语句也不输出,需要把输出存储起来,然后判断是否有错误,有错,则输出错误,否则按照正常输出。

参考文献

编译原理(龙书)

发布了55 篇原创文章 · 获赞 30 · 访问量 9832

猜你喜欢

转载自blog.csdn.net/chaifang0620/article/details/103124090