首页 存档 技术 查看内容

70行Python代码编写一个递归下降解析器

2018-3-30 13:00 |来自: 互联网 385 0

摘要: (点击上方公号,可快速关注) 作者:Stories For Sad Robots 译者:开源中国社区 链接:http://www.oschina.net/translate/how-to-write-a-calculator-in-70-python-lines-by-writing-a-recursive-descent-parser? ...

(点击上方公号,可快速关注)


作者:Stories For Sad Robots

译者:开源中国社区

链接:http://www.oschina.net/translate/how-to-write-a-calculator-in-70-python-lines-by-writing-a-recursive-descent-parser?print

3个月前,我写了一篇文章,详细讲述了用解析库编写计算器的过程。然而,读者们普遍反应,他们对于见到一个从头开始写并且除了电池以外别无他物的计算器更感兴趣。我想,为什么不呢?

写一个计算机很简单,如果你使用针对算术表达式的hacks 的话。但是hacks的产生的后果也几乎总是一样的:解决方案不够优雅,不可扩展,并且很难直观的理解。我喜欢挑战,并且打算发一个有益的帖子,所以我决定用通用递归下降解析器来写它。本着与上次相同的精神,我打算用尽可能少的行数来干这件事,所以它充满了hacks和tricks。但它们是表面的,并且不止限于我手头的任务。

这篇文章我将一步一步详细的解释一下。如果你想直接跳到代码,你可以滚动到这篇文章的最后。我希望当你读完后你能更好的理解如何解析内部的工作,启发你用适当的解析库,以避免混乱。

要理解这篇文章,你应该很好的理解Python,建议你要了解一些它是怎么解析,它是用来干什么的。如果你不知道,我建议你阅读我的前一篇文章,在里面我详细解释的语法及怎么去使用。

第一步:标记化

处理表达式的第一步就是将其转化为包含一个个独立符号的列表。这一步很简单,且不是本文的重点,因此在此处我省略了很多。

首先,我定义了一些标记(数字不在此中,它们是默认的标记)和一个标记类型:

token_map = {' ':'ADD', '-':'ADD',

'*':'MUL', '/':'MUL',

'(':'LPAR', ')':'RPAR'}

Token = namedtuple('Token', ['name', 'value'])

下面就是我用来标记 expr 表达式的代码:

split_expr = re.findall('[\d.] |[%s]' % ''.join(token_map), expr)

tokens = [Token(token_map.get(x, 'NUM'), x) for x in split_expr]

第一行是将表达式分割为基本标记的技巧,因此

'1.2 / ( 11 3)' --

声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部