LEX/FLEX词法分析器

CONTENTS:

[TOC]

这篇文章的内容包括:

lex语法格式

linux下flex的安装和使用

flex实例

flex源代码的编译和使用

Lex/Flex词法分析器

Lex是LEXical compiler的缩写,是Unix环境下非常著名的工具,主要功能是生成一个词法分析器(scanner)的C源码,描述规则采用正则表达式(regular expression)。描述词法分析器的文件*.l,经过lex编译后,生成一个lex.yy.c 的文件,然后由C编译器编译生成一个词法分析器。词法分析器,简单来说,其任务就是将输入的各种符号,转化成相应的标识符(token),转化后的标识符 很容易被后续阶段处理。 —— [ 百度百科 ]

Flex的安装和使用

在使用apt软件包管理器linux系统上我们可以非常方便地安装并使用flex。在终端中输入以下代码安装flex:

$> sudo apt-get install flex

flex代码的源文件往往是以.l为后缀名的。

.l文件通过以下命令编译(以文件名为scanner.l为例):

$> flex scanner.l

编译后在源代码相同目录下会生成一个lex.yy.c,这就是生成的能够执行上述scanner.l功能的c语言代码。使用gcc编译即可生成词法分析程序

void yywrap() { return 1; }

$> gcc lex.yy.c -o scanner

然后将需要分析的文件(以input.txt为例)作为参数传递给scanner执行分析:

$> ./scanner input.txt

Lex语法格式

flex的语法被分为三个部分:

{definitions}

%%

{rules}

%%

{user subroutines}

definitions:

LABEL REGULAR_EXPRESSION

LABEL是这里类字符串的名称,REGULAR_EXPRESSION则是匹配这种字符串的正则表达式。正则表达式的语法主要包括:

符号

含义

\

[]

括号中的字符取其一

\-

a-z表示ascii码中介于a-z包括a.z的字符

\\

转义(flex不能识别除字母外的字符)

*

0或多个字符

?

0或1个字符

+

1或多个字符

^

除此之外的其余字符

.

除\n外的所有字符,等价于^\n

示例:

1. INT [1-9][0-9]*|[0] /*整数类型,0或不以0开头的由0-9组成的字符串*/

2. FLOAT [0-9]*[.][0-9]+([eE][+-]?[0-9]*|[0])?f? /*浮点数格式*/

3. LP \( /*一个左圆括号*/

注:用%{ %}括起来的语句将被完全写入编译后的c语言文件中。

例如

`%{

#include

int num_id = 0;

%}`

rules:

规则部分的语法如下:

{LABEL1} |

{LABLE2} |

...

{

/*TODO*/

}

TODO部分是告诉编译器在匹配到字符串之后程序需要做些什么。

例如在匹配到整数后打印这个整数:

{INT} {

printf("Pick up an integer, value is %d", atoi(yytext));

printf("Pick up an integer, value is %s", yytext);

}

其中atoi()函数将字符串转换为整数。

user subroutines

此处主要是放置用户需要执行的c语言代码。他们会被原封不动地加入到lex.yy.c文件的末尾。

这里一般用来存放main函数,详细会在后面说明。

FLEX实例

下面通过一个实例来具体展示flex的使用方式,主要功能是扫描并匹配文件中的字符串,并回显其类型和内容,代码如下:

/************************

* scanner.l

* @author mist

* 2015-9-21 23:08

************************/

%{

#include "stdio.h"

#include "stdlib.h"

%}

INT_DEX [1-9][0-9]*|[0]

INT_HEX [0][Xx]([1-9][0-9]*|[0])

INT_OCT [0][0-7]

FLOAT [0-9]*[.][0-9]+([eE][+-]?[0-9]*|[0])?f?

SEMI [;]

COMMA [,]

ASSIGNOP [=]

RELOP [>]|[][=]|[

PLUS [+]

MINUS [-]

STAR [*]

DIV [/]

AND [&][&]

OR [|][|]

DOT [.]

NOT [!]

TYPE int|float

LP \(

RP \)

LB \[

RB \]

LC \{

RC \}

STRUCT struct

RETURN return

IF if

ELSE else

WHILE while

SPACE [ \n\t]

ID [a-zA-Z_][a-zA-Z_0-9]*

/*end of definition*/

%%

{SEMI} {

printf("get semmi : %s\n", yytext);

}

{COMMA} {

printf("get comma : %s\n", yytext);

}

{ASSIGNOP} {

printf("get assignop : %s\n", yytext);

}

{INT_DEX} |

{INT_HEX} |

{INT_OCT} {

printf("get an integer: %s\n", yytext);

}

{FLOAT} {

printf("get a float: %s\n", yytext);

}

{PLUS} |

{MINUS} |

{DIV} |

{STAR} {

printf("get an operator: %s\n", yytext);

}

{RELOP} {

printf("get a relop: %s\n", yytext);

}

{AND} |

{OR} |

{NOT} {

printf("get a logic operator: %s\n", yytext);

}

{DOT} {

printf("get a dot: %s\n", yytext);

}

{STRUCT} |

{RETURN} |

{IF} |

{ELSE} |

{WHILE} {

printf("get keyword: %s\n", yytext);

}

{TYPE} {

printf("get type: %s\n", yytext);

}

{LP} |

{RP} |

{LB} |

{RB} |

{LC} |

{RC} {

printf("get brackets : %s\n", yytext);

}

{SPACE} |

. {

/*ABANDON THESE CHARACTORS*/

}

{ID} {

printf("get an ID: %s\n", yytext);

}

%%

int yywrap() {

return 1;

}

int main(int argc, char** argv) {

if (argc > 1) {

if (!(yyin = fopen(argv[1], "r"))) {

perror(argv[1]);

return 1;

}

}

while (yylex());

return 0;

我们需要为生成的分析程序编写main函数。首先需要通过yyin来获取指向被分析文件的文件FILE指针,一般文件的路径通过控制台的第二个参数获得。分析部分的实体在函数yylex()中。

yywrap()用于判断是否已经扫描完了所有的文件。如果它在最后一个文件的末尾被调用,则返回值为1。此时程序将停止分析,可以用来扫描多个文件。

输入文本:

`int float {}()[] 0

0x0 0x123

123.5

.3e-10f

= >= || && ! ; ,

this_is_an_id

id123

if then else

`

输出:

get type: int

get type: float

get brackets : {

get brackets : }

get brackets : (

get brackets : )

get brackets : [

get brackets : ]

get an integer: 0

get an integer: 0x0

get an integer: 0x123

get a float: 123.5

get a float: .3e-10f

get assignop : =

get a relop: >=

get a logic operator: ||

get a logic operator: &&

get a logic operator: !

get semmi : ;

get comma : ,

get an ID: this_is_an_id

get an ID: id123

get keyword: if

get an ID: then

get keyword: else

另外附上词法要求:

INT  /A sequence of digits without spaces1/

FLOAT  /* A real number consisting of digits and one decimal point. The deci-

mal point must be surrounded by at least one digit2 */

ID  /* A character string consisting of 52 upper- or lower-case alphabetic, 10

numeric and one underscore characters. Besides, an identifier must not start

with a digit3 */

SEMI  ;

COMMA  ,

ASSIGNOP  =

RELOP  > | < | >= | <= | == | !=

PLUS  +

MINUS  -

STAR  *

DIV  /

AND  &&

OR  ||

DOT  .

NOT  !

TYPE  int | float

LP  (

RP  )

LB  [

RB  ]

LC  {

RC  }

STRUCT  struct

RETURN  return

IF  if

ELSE  else

WHILE  while

1) 词法单元INT表示的是所有(无符号)整型常数。一个十进制整数由0~9十个数字组

成,数字与数字中间没有如空格之类的分隔符。除“0”之外,十进制整数的首位数字

不为0。例如,下面几个串都表示十进制整数:0、234、10000。为方便起见,你可以

假设(或者只接受)输入的整数都在32bits位之内。

2) 整型常数还可以以八进制或十六进制的形式出现。八进制整数由0~7八个数字组成并以

数字0开头,十六进制整数由0~9、A~F(或a~f)十六个数字组成并以0x或者0X开头。

例如,0237(表示十进制的159)、0xFF32(表示十进制的65330)。

3) 词法单元FLOAT表示的是所有(无符号)浮点型常数。一个浮点数由一串数字与一个

小数点组成,小数点的前后必须有数字出现。例如,下面几个串都是浮点数:0.7、

12.43、9.00。为方便起见,你可以假设(或者只接受)输入的浮点数都符合IEEE754单

精度标准(即都可以转换成C语言中的float类型)。

4) 浮点型常数还可以以指数形式(即科学记数法)表示。指数形式的浮点数必须包括基

数、指数符号和指数三个部分,且三部分依次出现。基数部分由一串数字(0~9)和一

个小数点组成,小数点可以出现在数字串的任何位置;指数符号为“E”或“e”;指

数部分由可带“+”或“”(也可不带)的一串数字(0~9)组成,“+”或“”(如

果有)必须出现在数字串之前。例如01.23E12(表示1.23  1012)、43.e-4(表示43.0 

10-4)、.5E03(表示0.5  103)。

5) 词法单元ID表示的是除去保留字以外的所有标识符。标识符可以由大小写字母、数字

以及下划线组成,但必须以字母或者下划线开头。为方便起见,你可以假设(或者只

接受)标识符的长度小于32个字符。

6) 除了INT、FLOAT和ID这三个词法单元以外,其它产生式中箭头右边都表示具体的字

符串。例如,产生式TYPE  int | float表示:输入文件中的字符串“int”和“float”都

将被识别为词法单元TYPE。

2.2

High-level Definitions

生成词法分析程序 可能会发生yywrap未定义的错误。yywrap必须由用户亲自编写,一般按如下形式即可: ↩

lex 词法分析 linux,Lex词法分析器相关推荐

  1. lex 词法分析 linux,lex语言词法分析

    1.添加行号 %{ #include #include int line=1; %} %% [^\n] {yymore();} [\n] {printf("%2d %s",line ...

  2. 【编译原理】 实验一:词法分析器的自动实现(Lex词法分析)

    一.实验内容 1.借助词法分析工具Flex或Lex完成(参考网络资源) 2.输入:高级语言源代码(如helloworld.c) 3.输出:以二元组表示的单词符号序列. 二.实验目的 通过设计.编制.调 ...

  3. 《编译与反编译技术实战》——1.2 词法分析生成器LEX

    本节书摘来自华章计算机<编译与反编译技术实战>一书中的第1章,第1.2节,作者 刘晓楠 陶红伟 岳峰 戴超,更多章节内容可以访问云栖社区"华章计算机"公众号查看. 1. ...

  4. linux终端lex程序运行,lex的简单使用

    Lex & Flex 简介 Lex是lexical compiler的缩写,是Unix环境下非常著名的工具, Lex (最早是埃里克·施密特和 Mike Lesk 制作)是许多 UNIX 系统 ...

  5. 基于Flex (词法分析生成器) 构造词法分析器

    备忘录1 - 阿林的词法分析器答辩内容 前言: 我们知道,通过一些词法分析生成器工具可以完成一个编译器的词法分析过程,比如说flex,我们可以通过它完成词法分析过程,但是它完成了这个过程并不会将整个词 ...

  6. Lex/Yacc 初识Lex

    因工作需要接触了一下Lex和Yacc,个人感觉挺有趣的,所以就写下来了. Lex是Lexical的缩写,大概就可以理解为词汇提取. Yacc是Yet another compiler compiler ...

  7. 词法分析程序 LEX和VC6整合使用的一个简单例子

    词法分析的理论知识不少,包括了正规式.正规文法.它们之间的转换以及确定的有穷自动机和不确定的有穷自动机等等... 要自己写一个词法分析器也不会很难,只要给出了最简的有穷自动机,就能很方便实现了,用if ...

  8. 实验一 词法分析java,java词法分析器实验报告

    java词法分析器实验报告 Java 词法分析器实验报告 --07111101 --奥特曼 一.词法分析器功能概述: 1. 使用DFA实现词法分析器的设计: 2. 实现对Java 源程序中注释和空格( ...

  9. java实现词法分析_Java 实现词法分析器

    最后一次更新于 2019/12/19 效果演示图 项目介绍 词法分析器是编译器的重要组成部分用于生成某种形式的中间语言,该中间语言可用于将一种计算机编程语言转换为机器语言. 因此,本仓库引入了一种新的 ...

  10. Yacc 与 Lex 快速入门(词法分析和语法分析)

    Lex 代表 Lexical Analyzar.Yacc 代表 Yet Another Compiler Compiler. 让我们从 Lex 开始吧. Lex Lex 是一种生成扫描器的工具.扫描器 ...

最新文章

  1. 写代码时发现......还得是 SpringBoot !一篇拿下
  2. 先写API文档还是先写代码?你需要这款神器Apifox!
  3. 集成开发环境IDE的概述
  4. 张高兴的 .NET Core IoT 入门指南:(二)GPIO 的使用
  5. java 抽样_Java编程实现二项分布的采样或抽样实例代码
  6. Jenkins(Pipeline)
  7. 陈小琼,你真不好等!
  8. mysql的临时表空间_Mysql临时表空间详解
  9. 用Html5制作 汤姆猫 小游戏
  10. fiddler抓包如何只抓手机端的包 不抓电脑的包
  11. C语言——获取键盘方向键效果
  12. 服务器运维用macos,MacOS和Linux区别_网站服务器运行维护,linux,macos
  13. 用Jsp开发wap应用
  14. linux查看某个文件大小
  15. linux怎么远程调整屏幕亮度,linux怎么调节屏幕亮度
  16. 两个向量组的秩相等说明什么_若两个向量组等价,它们的秩是否相等?
  17. arm 各种 gcc 编译器区别
  18. Java反射机制的学习
  19. python爬虫(以简书为例)
  20. 解密四参七参工程坐标系,并使用图新地球完成四参七参计算,实现不同投影坐标参数数据融合

热门文章

  1. 松下PLC 三个单位的延时定时器指令的使用
  2. 液晶显示屏工作原理和点亮屏幕
  3. 永久免费的内网端口映射工具推荐【无公网IP】
  4. 记录 UiPath 学习中遇到的一些问题以及解决办法
  5. 多么乐alexa网站流量数据报告助手
  6. docker下beego开发环境搭建
  7. Raw Socket(原始套接字)实现Sniffer(嗅探)
  8. 深入浅出理解 Java回调机制(异步)
  9. 华为手机怎么使用读卡器_华为G7手机OTG功能详细使用教程
  10. 解决打印机问题的方法