lex的使用与正则表达式

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

学过编译原理的朋友肯定都接触过LEX这个小型的词法扫描工具. 但是却很少有人真正把LEX用在自己的程序里. 在构造专业的编译器的时候,常常需要使用到lexyacc. 正是因为这两个工具,使得我们编写编译器,解释器等工具的时候工作变得非常简单.不过话说回来,会使用lexyacc的人也确实不简单. Lexyacc里面牵涉到一系列的编译原理的理论知识,不是简单地看看书就能搞懂的. 本文只是简单地介绍一下lexyacc的使用方法.相关编译理请查看本科教材.

 

国内大学教材里面对于lexyacc的介绍很少,有些根本就没有,不过在国外的编译原理教材介绍了很多. 按照学科的分类,国内大学本科里面开的<<编译原理>>教程只是讲解编译的原理,并不讲解实践. 而对于实践方面则是另外一门学科<<编译技术>>. 关于编译技术的书籍在国内是少之又少. 前不久, 听说上海交大的计科内部出版过编译技术的教材.可惜我们这些人就无法得见了. 还好,机械工业出版社引进了美国 Kenneth C.Louden所著的经典著作<<编译原理及实践>>,比较详细地介绍lexyacc的使用.

 

Lex属于GNU内部的工具,它通常都是gcc的附带工具. 如果你使用的Linux操作系统,那么肯定系统本身就有lexyacc,不过yacc的名字变成了bison. 如果你使用的Windows操作系统,那么可以到cygwin或者GNUPro里面找得到. 网上也有windows版本lexyacc,大家可以自己去找一找.

 

本文一共有两篇,一篇是介绍lex,另一篇是介绍yacc.  Lexyacc搭配使用, 我们构造自己的编译器或者解释器就如同儿戏. 所以我把本文的名字叫做黄金组合.

 

本文以flex( Fase Lex)为例,两讲解如何构造扫描程序.

Flex可以通过一个输入文件,然后生成扫描器的C源代码.

 

其实扫描程序并不只用于编译器 .比如编写游戏的脚本引擎的时候,我看到很多开发者都是自己写的扫描器,其算法相当落后(完全没有DFA的概念化), 甚至很多脚本引擎开发者的词法扫描器都没有编写,而是在运行过程中寻找token(单词). 在现代的计算机速度确实可以上小型的脚本引擎在运行中进行词法扫描, 但是作为一个合格的程序员, 或者说一个合格的计算机本科毕业生而来说, 能够运用编译原理与技术实践,应该是个基本要求.

 

如果要说到词法分析的扫描器源代码编写, 其实也很简单, C语言的人都会写. 可是Kenneth Louden<<编译原理及技术>里面,花了50多页,原因就是从理论角度,介绍标准的,可扩展的,高效的词法扫描器的编写. 里面从正则表达式介绍到DFA(有穷自动机),再到NFA(非确定性有穷自动机),最后才到代码的编写. 以自动机原理编译扫描器的方法基本上就是现在词法扫描器的标准方法, 也就是Lex使用的方法. Lex,我们甚至不需要自己构造词法的DFA, 我们只需要把相应的正则表达式输入, 然后lex能够为我们自己生成DFA,然后生成源代码,可谓方便之极.

 

本文不讲DFA, lex的输入是正则表达式, 我们直接先看看正则表达式方面知识就可以了.

 

1.正则表达式(regular expression):

 

对于学过编译原理的朋友来说,这一节完全可以不看.不过有些东西还是得注意一下,因为在flex中的正则表达式的使用有些具体的问题是在我们的课本上没有说明的.

先看看例子:

1.1

name      Tangl_99

这就是定义了name这个正则表达式,它就等于字符串Tangl_99.所以,如果你的源程序中出现了Tangl_99这个字符传,那么它就等于出现一次name正则表达式.

 

1.2

digit        0|1|2|3|4|5|6|7|8|9

这个表达式就是说,正则表达式digit就是0,1,2,…,9中的某一个字母.所以无论是0,2,或者是9…都是属于digit这个正则表达式的.

“|”符号表示或者的意思.

那么定义正则表达式 name   Tangl_99|Running,同样的,如果你的源程序中出现了Tangl_99或者Running,那么就等于出现了一次name正则表达式.

 

1.3

one       1*

“*”符号表示零到无限次重复

那么one所表示的字符串就可以是空串(什么字符都没有), 1, 11, 111, 11111, 11111111111, 11111111…等等.总之,one就是由0个或者N1所组成(N可以为任意自然数).

”*”相同的有个”+”符号.请看下面的例子1.4

 

1.4

realone    1+

“+”符号表示”1到无限次重复

那么realoneone不同的唯一一点就是,realone不包含空串,因为”+”表示至少一次重复,那么realone至少有一个1.所以realone所表达的字符串就是1,11,111, 1111, 11111…,等等.

 

1.5

digit      [0-9]

letter     [a-zA-Z]

这里的digit等于例1.2中的digit,也就是说,a|b|c就相当于[a-c].

同理,letter也就是相当于 a|b|c|d|e|f|…|y|z|A|B|C|D…|Z 不过注意的一点就是,你不能把letter写成[A-z],而必须大写和小写都应该各自写出来.

 

1.6

notA        [^A]

“^”表示非,也就是除了这个字符以外的所有字符

所以notA表示的就是除了A以外的所有字符.

下面让我们来看看一些一般高级程序语言中常用的综合例子.

digit        [0-9]

number     {digit}+

letter       [a-zA-Z_]

digit前面多次提起过,就是0-9的阿拉伯数字.number就是所有的数字组合,也就是整数.

Letter前面也提起过,唯一不同的就是多了一个下划线.因为一般我们的C语言中容许有下划线来表示定义的变量名,所以我也把下划线当成英语字母来处理了.

这里number中使用上面定义的digit正则表达式.lex,{digit}就是表示正则表达式digit.

 

newline      [/n]

whitespace   [ /t]+

newline就是提行的意思.这里我们使用的是/n这个符号,它和C语言中表示提行号一致.问题是大家可能要问到为什么要使用[]符号.因为在lex,如果你使用[],那么里面表示的肯定就是单个字符号,而不会被理解成”/””n”两个字符.

Whitespace就是空格符号的意思.一般的高级程序语言中有两种,一种就是简单的空格,还有一种就是/t制表符.使用了”+”符号,就表示了这些空白符号的无限组合.

 

 

Lex实战:如何用正则表达式自动生成词法分析器?从规则编写到DFA优化 本文详细解析了如何使用Lex工具通过正则表达式自动生成高效的词法分析器,涵盖从规则编写到DFA优化的全流程。文章深入探讨了正则表达式到NFA、DFA的转换原理,并提供了工程实践中的优化技巧和性能对比数据,帮助开发者提升编译原理中的词法分析效率。 阅读详情

相关推荐

正则表达式到词法分析器:NFA和DFA转换在Lex/Yacc实战中的应用指南

本文深入探讨了从正则表达式到词法分析器的实现过程,重点介绍了NFA和DFA转换在Lex/Yacc实战中的应用。通过详细解析子集构造法和Hopcroft算法,帮助开发者理解自动机转换原理,并展示如何优化DFA性能。文章还提供了集成Lex/Flex工具链的实用技巧和简易DSL词法分析器的实战案例。

weixin_42525551的博客 236

linux下lex程序例子,一个Lex/Yacc完整的示例(可使用C++)

作者: 胡彦 2013-4-28本例子虽小却演示了lex/yacc程序最重要和常用的特征:* lex/yacc程序组成结构、文件格式。* 如何在lex/yacc使用C++和STL库,用extern "C"声明那些lex/yacc生成的、要链接的C函数,如yylex(), yywrap(), yyerror()。* 重定义YYSTYPE/yylval为复杂类型。* lex里多状态的定义和使用,用B...

weixin_29534143的博客 969

Lex识别C风格字符串和注释

LexYacc是Unix下错的词法分析器和语法分析器,在linux下,这两个工具被成为flex和bison,也是C++经常用来构建字符分析程序的工具。我们这里讨论一些其有趣的用法和注意的事项

西风世界 1万+

yacc&lex-调用C++代码

要点用lex&yacc命令缺省生成的是C文件,但事实上,仅是文件扩展名表示为C文件。可以用g++或者直接改名为C++就可以在lex&yacc中用C++功能。

A Flying Bird 1331

编写自己的Shell解释器

==================================================START======================================================== 编写自己的Shell解释器 摘要:本期的目的是向大家介绍shell的概念和基本原理,并且在此基础上动手做一个简单shell解释器。同时,还将就用到的...

weixin_30487201的博客 413

Yacc Lex

C语言的lexyacc工具说明 http://www.chinaunix.net 作者:xzh2002  发表于:2004-11-06 21:48:09 Lex工具 -------    Lex工具是一种词法分析程序生成器,它可以根据词法规则说明书的要求来生成单词识别程序,由该程序识别出输入文本中的各个单词。 1、lex程序的结构 -定

ZFIVE5 2067

lex&yacc说到编译器(1.正则表达式)

lex&yacc说到编译器(1.正则表达式)作者:tangl_99QQ:8664220msn:tangl_99@hotmail.comemail:tangl_99@sohu.com 学过编译原理的朋友肯定都接触过LEX这个小型的词法扫描工具. 但是却很少有人真正把LEX用在自己的程序里. 在构造专业的编译器的时候,常常需要使用lexyacc. 正是因为这两个工具,使得

Liang Tang's 专栏 6558

LexYacc学习(五)之正则表达式

正则表达式语法 lex模式是由编辑程序和实用程序使用正则表达式的扩展版本。正则表达式由常规字符(代表它们本身)和元字符(在一种模式中具有特殊含义)组成。 元字符 . . 匹配除了换行符 \n 之外的任意单个字符 [] [] 匹配括号中字符的任意一个。用“-”(短划线)指示字符的范围,例如[0-9]指10个数字中的任意一个。如果开括号之后的第一个字符是短划线或者闭括号,那么它就能被解

指尖飞舞 6616

lex入门

1.正则表达式下面列出一些模式部分的正则表达式字符含义:A-Z, 0-9, a-z 构成模式部分的字符和数字。- 指定范围。例如:a-z 指从 a 到 z 之间的所有字符。/ 转义元字符。用来覆盖字符在此表达式中定义的特殊意义,只取字符的本身。[] 表示一个字符集合

cnctloveyu的专栏 1447

lex正则表达式练习

龙书上的表格: (^在中括号内表示取补,否则表示和行的开头匹配,比如 ^ab匹配以ab开头的字符串) Write regular definitions for the following languages: Comments, consisting of a string surrounded by /* and */, without an intervening */, unless ...

AI出海日记 1426

lex 正则表达式

规则: . 匹配除换行符之外的任何单个

dinghuican的专栏 2166

Lex正则表达式

  字符   解释.          匹配除换行符("/n")以外的任何单个字符*         匹配前面表达式的零个或多个拷贝[]         匹配括号中的任意的字符类^           作为正则表达式的第一个字符匹配行的开头$         作为正则表达式的最后一个字符匹配行的结尾{}       当括号中包含一个或2个数字时,指示前面的模式被允许

深未来技术 1101

lex 命令中的扩展的正则表达式

在 lex 说明文件中指定扩展的正则表达式在 sed 或者 ed 命令中所使用的方法相似。 扩展的正则表达式指定了要匹配的字符串的集合。表达式包含文本字符和运算符字符。文本字符正在被比较的字符串中的相应字符匹配。运算符字符指定重复次数、选项和其他功能。 数字和字母表的字母被认为是文本字符。例如,扩展的正则表达式 integer 字符串 integer 匹配,表达式 a57D 搜索

Embeded system Development 1402

Lex的简单入门和正则表达式基础

编译原理上机课任务如下: flex 是- fast lexical analyzer generator 的简称,一个词法分析器生成工具。 下述文件已经保存到我的百度云 (一) 目录介绍 在本实验目录中,包括两个子目录。 1、子目录 flex  它包含flex.exe, flex.hlp, libfl.lib 三个文件,另外还有一个例子文件 example.

邂逅黛玛姑娘 5886

正则表达式到最小DFA:一张图讲清Lex词法分析器的核心优化

本文深入解析了Lex词法分析器中从正则表达式到最小DFA的优化过程,揭示了DFA最小化技术如何显著提升编译效率。通过可视化拆解和性能对比,展示了最小化DFA在减少状态数、提升缓存命中率等方面的优势,帮助开发者优化词法分析器性能。

weixin_28689507的博客 318

LexYacc应用方法(二).再识LexYacc

LexYacc应用方法(二).再识LexYacc草木瓜  20070314早在二十世记七十年代之前,编写编译器一直是一个非常费时的工作。但到了1975这一年这一切却发生了重大转变,首先Stephen C. Johnson Lesk在贝尔实验室完成了Yacc开发,为了配合yacc更好的协作, Mike Lesk和Eric Schmidt又完成了lex。从而Lexyacc成为计算机编译领

草木瓜 1万+

LexYacc使用学习笔记(一)

 概述使用LexYacc构造编译器过程如下图所示: Yacc 读入bas.y 中的语法描述而后生成一个剖析器,即y.tab.c 中的函数 yyparse。b as.y 中包含的是一系列的标记声明。Lex 读入bas.l 中的正则表达式的说明,包含文件 y.tab.h,然后生成词汇解释器,即文件lex.yy.c 中的函数yylex。最终,这个解释器和剖析器被连接到一起,而组

皮业勇的技术专栏 1780

LexYacc从入门到精通(2)--正则表达式

正则表达式在Unix/Liunx系统中起着非常重要的作用,在很大一部分的程序中都使用正则表达式,可以这么说:“在Unix/Linux系统中,如果正则表达式算会使用该系统”。本文中使用LexYacc都是基于正则表达式的应用,因此有必要用一篇文档的形式详细说明在LexYacc使用正则表达式为何物!其实正则表达式非常简单,用过DOS的人都知道通配符吧,说得简单一点,正则表达式就是

8598
下一篇: P2P 之 UDP穿透NAT的原理与实现
abookdog
博客等级 码龄22年 2粉丝 13原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值