lex 词法分析 linux,Lex词法分析器
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词法分析器相关推荐
- lex 词法分析 linux,lex语言词法分析
1.添加行号 %{ #include #include int line=1; %} %% [^\n] {yymore();} [\n] {printf("%2d %s",line ...
- 【编译原理】 实验一:词法分析器的自动实现(Lex词法分析)
一.实验内容 1.借助词法分析工具Flex或Lex完成(参考网络资源) 2.输入:高级语言源代码(如helloworld.c) 3.输出:以二元组表示的单词符号序列. 二.实验目的 通过设计.编制.调 ...
- 《编译与反编译技术实战》——1.2 词法分析生成器LEX
本节书摘来自华章计算机<编译与反编译技术实战>一书中的第1章,第1.2节,作者 刘晓楠 陶红伟 岳峰 戴超,更多章节内容可以访问云栖社区"华章计算机"公众号查看. 1. ...
- linux终端lex程序运行,lex的简单使用
Lex & Flex 简介 Lex是lexical compiler的缩写,是Unix环境下非常著名的工具, Lex (最早是埃里克·施密特和 Mike Lesk 制作)是许多 UNIX 系统 ...
- 基于Flex (词法分析生成器) 构造词法分析器
备忘录1 - 阿林的词法分析器答辩内容 前言: 我们知道,通过一些词法分析生成器工具可以完成一个编译器的词法分析过程,比如说flex,我们可以通过它完成词法分析过程,但是它完成了这个过程并不会将整个词 ...
- Lex/Yacc 初识Lex
因工作需要接触了一下Lex和Yacc,个人感觉挺有趣的,所以就写下来了. Lex是Lexical的缩写,大概就可以理解为词汇提取. Yacc是Yet another compiler compiler ...
- 词法分析程序 LEX和VC6整合使用的一个简单例子
词法分析的理论知识不少,包括了正规式.正规文法.它们之间的转换以及确定的有穷自动机和不确定的有穷自动机等等... 要自己写一个词法分析器也不会很难,只要给出了最简的有穷自动机,就能很方便实现了,用if ...
- 实验一 词法分析java,java词法分析器实验报告
java词法分析器实验报告 Java 词法分析器实验报告 --07111101 --奥特曼 一.词法分析器功能概述: 1. 使用DFA实现词法分析器的设计: 2. 实现对Java 源程序中注释和空格( ...
- java实现词法分析_Java 实现词法分析器
最后一次更新于 2019/12/19 效果演示图 项目介绍 词法分析器是编译器的重要组成部分用于生成某种形式的中间语言,该中间语言可用于将一种计算机编程语言转换为机器语言. 因此,本仓库引入了一种新的 ...
- Yacc 与 Lex 快速入门(词法分析和语法分析)
Lex 代表 Lexical Analyzar.Yacc 代表 Yet Another Compiler Compiler. 让我们从 Lex 开始吧. Lex Lex 是一种生成扫描器的工具.扫描器 ...
最新文章
- 写代码时发现......还得是 SpringBoot !一篇拿下
- 先写API文档还是先写代码?你需要这款神器Apifox!
- 集成开发环境IDE的概述
- 张高兴的 .NET Core IoT 入门指南:(二)GPIO 的使用
- java 抽样_Java编程实现二项分布的采样或抽样实例代码
- Jenkins(Pipeline)
- 陈小琼,你真不好等!
- mysql的临时表空间_Mysql临时表空间详解
- 用Html5制作 汤姆猫 小游戏
- fiddler抓包如何只抓手机端的包 不抓电脑的包
- C语言——获取键盘方向键效果
- 服务器运维用macos,MacOS和Linux区别_网站服务器运行维护,linux,macos
- 用Jsp开发wap应用
- linux查看某个文件大小
- linux怎么远程调整屏幕亮度,linux怎么调节屏幕亮度
- 两个向量组的秩相等说明什么_若两个向量组等价,它们的秩是否相等?
- arm 各种 gcc 编译器区别
- Java反射机制的学习
- python爬虫(以简书为例)
- 解密四参七参工程坐标系,并使用图新地球完成四参七参计算,实现不同投影坐标参数数据融合