【发布时间】:2018-01-28 07:48:56
【问题描述】:
我正在尝试使用基于 PEG 的 Python 解析器生成器 tatsu 编写一个简单的 int 表达式解析器。这是我的代码:
import tatsu
grammar = r'''
start = expression $ ;
expression = add | sub | term ;
add = expression '+' term ;
sub = expression '-' term ;
term = mul | div | number ;
mul = term '*' number ;
div = term '/' number ;
number = [ '-' ] /\d+/ ;
'''
parser = tatsu.compile(grammar)
print(parser.parse('2-1'))
这个程序的输出是['-', '1'],而不是预期的['2', '-', '1']。
如果我满足以下条件,我会得到正确的输出:
- 删除对一元减号的支持,即将最后一条规则更改为
number = /\d+/ ; - 去掉term、mul和div规则,只支持加减法
- 将第二条规则替换为
expresssion = add | sub | mul | div | number ;
最后一个选项实际上可以在不遗漏任何功能的情况下工作,但我不明白为什么它会起作用。到底是怎么回事?
编辑:如果我只是翻转 add/sub/mul/div 规则以摆脱左递归,它也可以工作。但是随后评估表达式成为一个问题,因为解析树被翻转了。 (3-2-1 变为 3-(2-1))
【问题讨论】:
-
我见过的大多数编程语言语法实际上并没有将负号作为数字的一部分 - 它只是被解析为应用于正数文字的一元减号运算符。
-
您是否尝试过从语法中消除左递归? tatsu 文档说左递归支持是实验性的。
-
看起来它可以在没有左递归的情况下工作,但后来我失去了左关联性。所以这只是 Tatsu 的一个错误?
-
我也有同样的问题。我很想知道为什么第一部分 (2) 从 AST 中消失了。