收藏 分享(赏)

lex一个词法分析器的生成器 翻译版.docx

上传人:hwpkd79526 文档编号:8098784 上传时间:2019-06-08 格式:DOCX 页数:22 大小:49.71KB
下载 相关 举报
lex一个词法分析器的生成器 翻译版.docx_第1页
第1页 / 共22页
lex一个词法分析器的生成器 翻译版.docx_第2页
第2页 / 共22页
lex一个词法分析器的生成器 翻译版.docx_第3页
第3页 / 共22页
lex一个词法分析器的生成器 翻译版.docx_第4页
第4页 / 共22页
lex一个词法分析器的生成器 翻译版.docx_第5页
第5页 / 共22页
点击查看更多>>
资源描述

1、Lex-词法分析器生成器(M.E.Lesk,E.Schmidt 著,中文翻译)Lex - 词法分析器生成器 M. E. Lesk 与 E. SchmidtBell LaboratoriesMurray Hill, New Jersey 07974 翻译:寒蝉退士译者声明:译者对译文不做任何担保,译者对译文不拥有任何权利并且不负担 任何责任和义务。原文:http:/cm.bell- Lex 帮助书写其控制流由在输入流中的正则表达式的实例来导向的程序。它适合于编辑器脚本类型的变换,和为解析例程做准备工作而分解输入。Lex 源码是正则表达式和相应的程序片段的表格。Lex 把这个表格变换成读取输入流、

2、复制它到输出流、并把输入划分到匹配给定表达式的字符串中的一个程序。随着每个这种字符串被识别出来,相应的程序片段就被执 行。表达式通过用 Lex 生成的确定有限自动机来识别。用户书写的程序片段按照对应的正则表达式在输入流中出现的次序来执行。 用 Lex 写成的词法分析程序接受有歧义的规定,并在每个输入点上选择最长的匹配可能。如果需要,在输入上进行实质的超前查看(lookahead),但输入流会被 回退(backup)到当前划分的结束处,所以用户有操纵它的普遍自由。 Lex 可以生成用 C 语言或 Ratfor 语言写的分析器,Ratfor 可以自动的转换成可移植的 Fortran。它可以在 PD

3、P-11 UNIX、 Honeywell GCOS 和 IBM OS 系统上得到。本手册只讨论在 UNIX 系统上的生成 C 语言的分析器,这是在 UNIX 第 7 版中唯一支持的 Lex 形式。设计 Lex 时简化了与编译器的编译系统 Yacc 的交接。 July 21, 1975 目录 1. 介 绍 2. Lex 源码 3. Lex 正则表达式 4. Lex 动作 5. 歧 义源规则 6. Lex 源定义 7. 用 法 8. Lex 与 Yacc 9. 例 子 10. 左 上下文敏感 11. 字符集 12. 源格式总结 13. 告诫和缺陷 14. 致 谢 15. 引 用1. 介绍 Lex

4、是设计用于字符输入流的词法处理的一个程序生成器。它接受高级的、面向问题的对字符串匹配的规定,并生成识别正则表达式的通用语言写的一个程序。正则表达式在用户给 Lex 的源规定中指定。Lex 写出的代码识别在输入流中的这些表达式,并把输入流划分到匹配这些表达式的字符串中。在字符串间的分界上执行用户提供的程序片段。Lex 源文件对正则表达式关联上程序片段。随着每个表达式出现在给 Lex 写出的程序的输入中,相应的程序片段就被执行。用户提供超出表达式所需要的额外代码来完成他的任务,可能包括用其他生成器写出的代码。生成的识别表达式的程序采用用户的程序片段所采用的通用编程语言。因此,提供了高级表达式语言来

5、写要被匹配的字符串表达式,而用户写动作的自由不受侵犯。这避 免了强制希望使用字符串操纵语言做输入分析的用户、去使用同样的并且经常不适合字符串处理的语言来书写处理程序。 Lex不是完整的语言,而是体现了可增加到叫做“宿主语言”的不同编程语言中的新语言特征的一个生成器。正如同通用语言可以生成在不同计算机硬件上运行的代 码,Lex 可以写出不同宿主语言的代码。宿主语言被用于 Lex生成的输出代码和用户增加的程序片段。还为不同的宿主语言提供兼容的运行时间库。这使 Lex 适应不同的环境和不同的用户。每个应用都可以被定向到适合这个任务的硬件和宿主语言、用户背景和本地实现性质的各种组合上。目前唯一支持的宿

6、主语言是 C,尽管过去曾经支持过 Fortran(Ratfor 2形式)。Lex 自身存在于 UNIX、GCOS 和 OS/370;但 Lex 生成的代码可以采用于存在适当的编译器的任何地方。 Lex 把用户的表达式和动作(在本文中叫做源码)转换成宿主通用语言;生成的程序叫做 yylex。yylex 程序将识别在流(在本文中叫做输入)中的表达式,并在检测到的时候执行给每个表达式的动作。参见图 1。 +-+源码 - | Lex | - yylex+-+-+输入 - | yylex | - 输出+-+Lex 概述图 1作为一个平凡的例子,考虑从输入中删除所有行结束处的空白或 tab 的程序。 %

7、t+$ ;就是所需要的。这个程序包含标记规则开始的一个 % 分界符和一个规则。这个规则包含匹配在行结束处之前的空白或 tab(按照 C 语言约定写为 t)字符的一个或多个实例的一个正则表达式。方括号指示由空白和 tab 构成的字符类;同于 QED,+ 指示“一或多个”;而 $ 指示“行结束”。没有指定动作,所以 Lex 生成的程序(yylex)将忽略这些字符。所有其他东西都被复制。要把任何余下的空白或 tab 的字符串改变为一个单一的空白,可增加另一个规则: % t+$ ; t+ printf(“ “);为这个源码生成的有限自动机将立刻扫描这两个规则,在空白或 tab 的字符串的终止处观察是否

8、有一个换行字符,并执行想要的规则动作。第一个规则匹配在行结束处的所有空白或 tab 的字符串,而第二个规则匹配所有余下的空白或 tab 的字符串。Lex 可以单独的用做简单变换,或在词法层次上聚集(gather)出的分析和统计。Lex 还可以与解析器一起使用而进行词法分析阶段;交接 Lex 与 Yacc 3 是特别容易的。Lex 程序只识别正则表达式;Yacc 写出接受一大类上下文无关文法的解析器,但是需要底层的分析器来识别输入记号(token)。所以,Lex 和 Yacc 的组合经常是适当的。在用做后面的解析器生成器的预处理器的时候,Lex 用来划分输入流,而解析器生成器指派文法结构到结果的

9、词法块(piece)。这种情况下的(编译器的前半部分)控制流在图 2 中展示。其他生成器或手工写的额外的程序可以轻易的增加到 Lex 写出的程序。 词法规则 文法规则| |v v+-+ +-+| Lex | | Yacc |+-+ +-+| |v v+-+ +-+输入 - | yylex | - | yyparse | - 解析后的输入+-+ +-+Lex 与 Yacc 一起图 2Yacc 用户会发现 yylex 的名字就是 Yacc 期望词法分析器叫的名字,所以 Lex 采用这个名字简化了交接。Lex 从源码中的正则表达式生成一个确定有限自动机4。为了节省空间,这个自动机是解释的而不是编译的

10、。结果仍是一个快速的分析器。特别是,Lex 程序识别和划分输入流所花费的时间正比于输入的长度。Lex 规则的数目或规则的复杂性在决定速度上都不重要,除了包含前向(forward)上下文的规则需要大量的重新扫描之外。与规则的数目和复杂性一起增加的是 自动机的大小,因此也是 Lex 生成的程序的大小。 在 Lex 写出的程序中,用户的片段(表示在找到每个正则表达式时要进行的动作)被收集一起成为 switch 语句中各个 case。自动机的解释器导向控制流。提供给用户在包含动作的例程中插入声明或增加语句,或者在这些动作例程之外增加例程的机会。 Lex 不受限制于可在提前查看一个字符基础上得到解释的源

11、码。例如,如果有两个规则一个查找 ab 而另一个查找 abcdefg,则在输入流是 abcdefh 的时候,Lex 将识别 ab 并留下输入指针正好在 cd 之前。这种回退比起简单语言的处理要更加高代价。 2. Lex 源码 Lex 源码的一般格式为: 定义%规则%用户子例程这里的定义和用户子例程部分经常被省略。第二个 % 是可选的,但是需要第一个来标记规则的开始。绝对极小的 Lex 程序是 %(没有定义,没有规则)它被变换成无改变的复制输入到输出的一个程序。 在上述 Lex 程序的轮廓中,规则代表用户的控制决定;它们是个表格,在其中左列包含正则表达式(参见章节 3)而右列包含动作,在识别了表

12、达式的时候要执行的程序片段。所以如下一个单独规则 integer printf(“found keyword INT“);在输入流中查找 integer 字符串并在它出现的时候打印消息“found keyword INT”。在这个例子中宿主过程语言是 C 并使用 C 库函数 printf 打印这个字符串。表达式的结束通过第一个空白或 tab 字符来指示。如果动作只是一个单一的 C 语言表达式,它可以给出在这行的右侧;如果它是复合的或多余一行,则应当包围在花括号中。作为稍微有用一些的例子,假设想要把一些美式拼写改为英式拼写。 Lex 规则如下 colour printf(“color“);mec

13、hanise printf(“mechanize“);petrol printf(“gas“);将是一个好的开始。这些规则非常不够,因为单词 petroleum 将变成 gaseum;后面会讨论处理它的方式。 3. Lex 正则表达式 正则表达式的定义非常类似于 QED5 中的定义。正则表达式指定要被匹配的一组字符串。它包含文本字符(它匹配被比较的字符串中的相应的字符)和操作符字符(它指定重复、选择和其他特征)。字母表字母和数字总是文本字符;所以正则表达式 integer匹配字符串 integer 只要它出现,而表达式 a57D查找字符串 a57D。 操作符操作符字符有 “ - ? . * +

14、 | ( ) $ / % 如果它们被用做文本字符,应当使用转义(escape)。引号操作符(“)指示在一对引号之间包含的任何东西都被当作文本字符。所以 xyz“+“匹配字符串 xyz+,在它出现的时候。注意可以引用字符串的一部分。引用普通字符是无害和没有必要的;表达式 “xyz+“同于上面的表达式。所以通过引用用做文本字符的所有非字母数字字符,用户可以避免记住上面的操作字符列表,并在 Lex 进一步扩展这个列表的时候是安全。 还可以通过前导一个 来把一个操作符字符转义为一个文本字符,比如 xyz+是上述表达式的另一个更少可读性的等价者。引用机制的另一个用处是把空白介入到表达式中;如上所述正常情

15、况下空白或 tab 结束一个规则。不包含在 (见后)内的任何空白字符必须被引用。还识别使用 的一些常见的 C 转义: n 是换行、t 是 tab 而 b 是退格(backspace)。要录入 自身需使用 。因为换行在一个表达式中是非法的,必须使用 n;不需要转义 tab 和退格。除了空白、tab、换行和上述列表中字符之外的所有字符总是文本字符。 字符类字符类可以使用运算符对 来指定。构造 abc 匹配一个单一字符,可以是 a、b 或 c。在方括号内,忽略多数字符的意义。只有三个字符特殊: 它们是 - 和 。- 字符指示范围。例如 a-z0-9 引用: 表达式只在 Lex 处在开始条件“名字 1

16、”的时候被识别。要进入一个开始条件,执行动作语句 BEGIN 名字 1;它把开始条件改为“名字 1”。要恢复正常状态, BEGIN 0;重置 Lex 自动机解释器的初始状态。一个规则可以活跃在多个开始条件下: 是一个合法前缀。任何不开始于 前缀操作符的规则总是活跃的。上述例子可以写为: %START AA BB CC%a ECHO; BEGIN AA;b ECHO; BEGIN BB;c ECHO; BEGIN CC;n ECHO; BEGIN 0;magic printf(“first“);magic printf(“second“);magic printf(“third“);这里的逻辑完

17、全同于处理这个问题的前种方法,但由 Lex 而不是用户代码做这种工作。11. 字符集 Lex 生成的程序只通过例程 input、output 和 unput 处理字符 I/O。所以在这些例程中提供的字符表示被 Lex 接受并在 yytext 的返回值中采用。对于内部使用一个字符被表示为一个小整数,如果使用了标准库,它们的值等于表示主机计算机字符的位模式(pattern)的整数值。正常 的,字母 a 用同字符常量 a 相同的形式来表示。如果通过提供转换这些字符的 I/O 例程改变了这种释义,则必须通过给出一个转换表格告知 Lex。这个表格必须在定义节中,并且必须由只包含“%T”的行包围着。这个表

18、格包含如下形式的行 整数 字符串它指示关联于每个字符的值。所以下面的例子 %T1 Aa2 Bb.26 Zz27 n28 +29 -30 031 1.39 9%T样例字符表。把小写和大写字母一起映射到整数 1 到 26,换行映射到 27,+ 和 - 映射到 28 和 29,数字映射到 30 到 39。注意转义换行。如果提供了这个表格,在规则中或任何有效输入中出现的所有字符都要包含在表格中。没有字符可以被指派数值 0,没有字符可以被关联上比硬件字符集大小更大的数值。12. 源格式总结 Lex 源文件的一般形式是: 定义%规则%用户子例程定义节包含如下定义的组合 1. 定义,形如“名字 转换”。2.

19、 包含代码,形如“ 代码”。3. 包含代码,形如%代码%4. 开始条件,形如%S 名字 1 名字 2 .5. 字符集表格,形如%T数值 字符串.%T6. 改变内部数组大小,形如%x nnn这里的 nnn 是表示数组大小的十进制整数而 x 选择如下参数: 字母 参数p 位置n 状态e 树节点a 转变k 包装(pack)起来的字符类o 输出数组大小在规则节中的行有“表达式 动作”的形式,这里的动作通过使用花括号做界定可以接续在后续的行上。Lex 中的正则表达式使用如下操作符: x 字符 “x“。“x“ “x“,即使 x 是运算符。x “x“,即使 x 是运算符。xy 字符 x 或 y。x-z 字符

20、 x、y 或 z。x 除了 x 的任何字符。. 除了换行的任何字符。x 在一行开始处的 x。x 当 Lex 处在开始条件 y 时的 x。x$ 在一行结束处的 x。x? 可选的 x。x* 0,1,2, . 个 x 的实例。x+ 1,2,3, . 个 x 的实例。x|y x 或 y。(x) x。x/y x,但只在跟随着 y 时。xx 来自定义节的 xx 的转换。xm,n x 的 m 到 n 次出现。13. 告诫和缺陷 有些病态的表达式在转换成确定自动机的时候生成指数增长的表格;幸运的是这很少见。 REJECT 不重新扫描输入;而是记住前面扫描的结果。这意味着如果找到带有尾随上下文的规则,并且执行了

21、 REJECT,用户一定不能使用 unput 来改变即将来自输入流的字符。这是对用户操纵仍未处理的输入的能力的唯一限制。 14. 致谢 从上文可明显的看出,Lex 外部是用 Yacc 模制的而内部采用了 Aho 的字符串匹配例程。所以 S. C. Johnson 和 A. V. Aho 二者很大程度上是 Lex 的实际创作者和调试者。感谢他们。当前版本的 Lex 的代码是由 Eric Schmidt 设计书写和调试的。 15. 引用 1. B. W. Kernighan and D. M. Ritchie, The C Programming Language, Prentice-Hall,

22、N. J. (1978).2. B. W. Kernighan, Ratfor: A Preprocessor for a Rational Fortran, Software Practice and Experience, 5, pp. 395-496 (1975).3. S. C. Johnson, Yacc: Yet Another Compiler Compiler, Computing Science Technical Report No. 32, 1975, Bell Laboratories, Murray Hill, NJ 07974.4. A. V. Aho and M.

23、 J. Corasick, Efficient String Matching: An Aid to Bibliographic Search, Comm. ACM 18, 333-340 (1975).5. B. W. Kernighan, D. M. Ritchie and K. L. Thompson, QED Text Editor, Computing Science Technical Report No. 5, 1972, Bell Laboratories, Murray Hill, NJ 07974.6. D. M. Ritchie, private communication. See also M. E. Lesk, The Portable C Library, Computing Science Technical Report No. 31, Bell Laboratories, Murray Hill, NJ 07974.原文地址 http:/cm.bell-

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报