[链接] 可以在Python里用的parsing library

有室友的毕业设计是做程序切片相关的,需要对代码做解析;指导老师建议他们用Python为实现语言,所以看来是需要找点适合Python使用的parsing library。解析源码这种事情正好是我熟悉的领域,就自告奋勇说看看能不能帮上啥忙。不过听说要解析的源语言或许是C++我就冒冷汗……||||||

手写parser真是太痛苦了,虽然我已经做了很多次但我还是不想建议室友也重复我的痛苦。特别是像C++那么复杂的语言 =v=
总之调查一下有些什么可选项,先记在这边再说。

有点想推荐用[url=http://antlr.org/]ANTLR[/url]来生成lexer和parser,因为[url=http://www.antlr.org/works]ANTLRWorks[/url]用于编写词法和语法规则相当方便。[url=http://www.jython.org/]Jython[/url]的解析器就是用ANTLR来生成的,ANTLR官网首页上甚至有Python之父Guido van Rossum的赞词:
[quote="Guido van Rossum"]I'm actually really liking ANTLR! I have a pretty darn good velocity with...[/quote]
我手写RD系解析器的时候一般也会用ANTLRWorks来写个语法来确认一下构思中的语法有没有错,然后再手工转换成具体实现。不过问题是ANTLR的库普遍都比较“大”,里面东西也挺多挺复杂的,或许上手要花点时间?
说到大,刚看了一下[url=http://antlr.org/download/Python]ANTLR的Python target[/url],看来没我原本想像的那么大。[url=http://antlr.org/download/Python/antlr_python_runtime-3.1.2-py2.5.egg]antlr_python_runtime-3.1.2-py2.5.egg[/url]才145KB。还行。
要是室友用ANTLR,那我能跟他分享的经验就会多一些,例如说ANTLRWorks的使用之类。在ANTLR官网的[url=http://antlr.org/grammar/list]Grammars[/url]一栏里有些现成的C/C++语法文件,包括Sun在NetBeans中使用C/C++预处理器和解析器的语法文件。可惜Sun的那两个文件是对应ANTLR v2.7的,而且有很重的NetBeans自身的痕迹,不能直接拿来用。
要开始用ANTLR与Python的组合很简单:
1、先到[url=http://antlr.org/download.html]ANTLR官网的下载页面[/url]下载一个[url=http://www.antlr.org/download/antlrworks-1.2.3.jar]ANTLRWorks+ANTLR[/url]的包,用于进行语法编辑和调试;
2、到[url=http://antlr.org/download/Python]ANTLR的Python target页面[/url]下载[url=http://antlr.org/download/Python/antlr_python_runtime-3.1.2-py2.5.egg]对应Python 2.5的运行时库[/url];
3、阅读[url=http://www.antlr.org/wiki/display/ANTLR3/Antlr3PythonTarget]ANTLR 3 Python Target[/url]的文档来了解使用Python target的注意点;
4、阅读[url=http://www.antlr.org/wiki/display/ANTLR3/Example]Example: Book Examples Modified for Python[/url]来了解一个简单的lexer/parser的写法,找到感觉;
5、自己继续探索吧…… =w=

ANTLR之外,[url=http://www.dabeaz.com/ply/]PLY[/url]看来也是个不错的选择。它可以看做是lex/yacc的纯Python实现,最大的优势就是它完全继承了lex/yacc系工具的特征,把符合lex/yacc的规则写在doc string里就行,这样就能最大限度的利用到处都能找到的lex/yacc相关的教学资料,包括我手上的几本书,以及许多现成的C/C++的lex/yacc例子;作者当初是为了教授编译器课程而编写这个库的,有较强的教学背景,适合学生使用;另外,作为纯Python实现的解析器库,它的速度在可接受范围内(作者提供的例子称它比ANTLR快)。
在Google Code上有个[url=http://code.google.com/p/pycparser/]pycparser[/url]项目使用PLY来实现了C的解析和代码生成;SourceForge上也有个[url=http://sourceforge.net/projects/cppheaderparser/]CppHeaderParser.py[/url]用PLY来解析C++头文件以获取类的结构信息。应该说还是有些实际应用的。
[url=http://www.dabeaz.com/ply/ply-3.1.tar.gz]PLY-3.1的整个tarball[/url]才143KB,相当小。里面包括了一些例子,例如一个完整的Dartmouth BASIC解释器的Python实现。有lex/yacc基础的话这个库上手应该很快。不过用它来解析C++或许会比较吃力……

室友说最近的任务就是周末前用Python写一个C++的词法分析器,貌似是要输出关键字出现的行号还是怎样,具体要求还没问清楚。这个的话用ANTLR、PLY或者手写倒都不困难就是了。C++词法分析里最麻烦的或许是字符串的分析吧?里面的各种转义序列都得考虑到,规则写起来冗长。其它都还好,前提是代码已经经过了预处理……自己做预处理的话又是件超麻烦的事情。在当前C++规范下嵌套的泛型声明的尖括号间还是得有空白字符,所以这个现在还不是问题。

[url=http://nedbatchelder.com/]Ned Batchelder[/url]做了份颇有用的[url=http://nedbatchelder.com/text/python-parsers.html]Python parsing tools[/url]列表,如果要找其它可选项的话可以从这个列表里发掘一下。
突然想起的事情:貌似不少库都对空白字符有自己的主张,喜欢自动忽略它们;很多时候这带来了方便,但如果要解析Python或者F#这些用缩进表示块结构的语言就麻烦了。到底是该让用户显式指定忽略规则,还是默认带有忽略空白字符的规则好呢?

有人推荐[url=http://pyparsing.wikispaces.com/]pyparsing[/url],不过我稍微看了些例子,第一感觉是我不太喜欢它处理语法规则的方式:它主要通过运算符重载和一些工厂函数来实现fluent API式的internal DSL来表达语法规则,但我觉得这样的代码在Python里看起来挺怪的。
从官网上引用段例子过来:
[quote="pyparsing"]
from pyparsing import Word, alphas
greet = Word( alphas ) + "," + Word( alphas ) + "!" # <-- grammar defined here
hello = "Hello, World!"
print hello, "->", greet.parseString( hello )
#=> Hello, World! -> ['Hello', ',', 'World', '!']
[/quote]
Python用来做internal DSL总觉得有点硬(语法层面上)然而又不够硬(类型层面上)。说语法硬主要是Python库能对语法做的定制余地不大,而且Python社区也比较喜欢统一的做事方式;说类型不够硬是指静态类型语言能够通过精巧的类层次/API设计来在编译时对fluent API做“语法检查”,而Python的变量没有类型所以fluent API要是写错了也得到运行时才能发现。嘛,静态/动态方面的观点总是有争议的,我这里纯粹是自己的感觉,没有想说服别人的意思。[url=http://boo.codehaus.org/]Boo[/url]用于internal DSL就比Python来得方便,多得语法宏。
呵呵,事实上我自己在写的一个库也是用fluent API来表达语法规则的;跟pyparsing一样,我也是重载了+来表示顺序结构、|来表示选择结构,等;但那样的代码出现在C#里我就没觉得很奇怪。呃诶……

可视化工具里除了ANTLRWorks之外我也很喜欢新的Oslo的Intellipad,不过Oslo的运行时依赖于.NET Framework,算了,不用来推荐给室友。据说Oslo team的人用MGrammar写过VB和C#的语法?呵呵,it's got all the potentials, let's just wait and see what comes out of it.
还有些别的语法编辑器不过貌似要收费……呜,收费的暂时无视。

今天先记这么多。要是有时间的话手写个简单的词法分析器作为例子也可以……不过现在我想睡觉了
P.S. Python自己的编译器是如何实现的呢?可以关注一下[url=http://www.python.org/dev/peps/pep-0339/]PEP-339[/url]的描述。是一个典型的LL(1)解析器解析出AST之后,生成CFG然后生成bytecode。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值