1. 前言与要求
这篇文档提供了ply的lexing与parsing总体说明。鉴于解析的内在复杂性(Given the intrinsic complexity of parsing),我强烈推荐你在开始你ply的大型项目之前应该阅读(或至少略读)整篇文档。
Ply3.5 兼容 python2 与 python3. 如果你正在使用python2,你必须使用python2.6或更新的。
2. 介绍
PLY是一款非常受欢迎的编译器构造工具lex与yacc的纯PYTHON版本。PLY的主要目标是忠诚于(stay farily faithful)传统的lex/yacc工具的工作方式。这支持LALR(1)分析,也支持额外的输入验证、错误输出以及诊断。因此,如果你已经使用了yacc在另外的编程语言,你应该可以相对容易的使用PLY。
早期版本的PLY被开发出来支持我2001年在芝加哥大学编译原理入门课程。因为PLY最初开发作为一个构造工具,你发现它对语法与符号规范相当的挑剔(picky)。部分地,这增加了用于捕捉新手容易造成的常见的编程错误的程序。当然,高级的使用者当在用于构建真正的编程语言的复杂的语法规则时的,也会发现一部分非常有用的细节。应该注意的是PLY不提供太多花里胡哨的方法(the way of bells and whistles)(比如自动构造语法抽象树,树的遍历等)。我不认为这是一个语法分析框架,相反地,你可以发现这是一个全部用python编写的,基本但完全可以使用(bare-bones,yet fully capable)的 lex/yacc工具。
这剩余文档的部分假设(assume)你已经或多或少的了解解析理论(parsing theory),语法制导翻译(syntax directed translation) 和其他语言编写的如lex/yacc等编译器构造工具的使用。如果你不熟悉这些话题,你可以去参阅(consult)一个入门文章如 Aho, Sethi, and Ullman的 "Compilers: Principles, Techniques, and Tools",O'Reilly 与 John Levine 的"Lex and Yacc" 也是不错的(also be handy)。事实上,因为实际上相同的概念(as the concepts are virtually identical.),O'Reilly的书可以被用来当做PLY的参考书。【译者注:这里放上原书的链接 lex&yacc 】
3. PLY总览
PLY有两个模块组成(consist of):lex.py 与 yacc.py,他们都被封装在一个叫ply的包里。这lex.py模块被用于拆散(break)输入文本,使其成为由一组(a collection of)正则表达式定义的一组符号。yacc.py被用于识别以上下文无关文法形式指定的语言语法(language syntax that has been specified in the form of a context free grammar)。
这两个旨在(be mean to)一起工作。特别的,lex.py以token()函数的形式提供了一个外部接口(an external interface in the form of a token() function),该接口向输入流返回一个下一个有效的符号。yacc.py反复地调用这个来检索符号和调用(invoke)语法规则。yacc.py的输出也经常被用于构建抽象语法数(AST)。然而,这完全取决于使用者。如果愿意,yacc.py可以被当做一个简单实现编译器的工具。
像它对应(counterpart)的Unix版,yacc.py提供大多数你所期待的特性,这部分包含广泛的错误检查,语法有效性,空产生式的支持,符号错误和通过优先规则来解决歧义(ambiguity resolution via precedence rules)。实际上,每一个在传统的yacc上的事情也会被PLY所支持。
yacc.py 与 Unix yacc 的主要不同是 yacc.py 不包含一个单独的代码生成过程( a separate code-generation process.) 相反,PLY依赖于反射(内省introspection)来建立它的lexers于parsers,不像传统的lex/yacc一样需要一个专门转换为一个单独的源文件的输入文件,PLY的这个规则是符合Python项目的(the specifications given to PLY are valid Python programs.)。这意味着不需要有额外的源文件和最特殊的编译器构建步骤(比如运行yacc来为编译器生成python代码)。因此解析表的生成是相对昂贵的,PLY缓存(cache)结果并将它们保存到一个文件中。如果检测到输入源文件没有改变,这张表从缓存中读取,否则它们将生成新的。
4. LEX