我目前正在尝试使用 Python SLY 模块为命题逻辑构建解析器。SLY 是 lex 和 yacc 的 Python 实现。
https://sly.readthedocs.io/en/latest/sly.html#introduction
文档说,“SLY 没有提供用于构造抽象语法树的特殊函数。但是,这种构造很容易自己完成。” 这就是我想要做的。在他们的示例代码中,他们建议通过为树节点定义自己的数据结构并在语法规则中使用它来执行此操作。
class BinOp(Expr):
def __init__(self, op, left, right)
self.op = op
self.left = left
self.right = right
class Number(Expr):
def __init__(self, value):
self.value = value
@_('expr PLUS expr',
'expr MINUS expr',
'expr TIMES expr',
'expr DIVIDE expr')
def expr(self, p):
return BinOp(p[1], p.expr0, p.expr1)
@_('LPAREN expr RPAREN')
def expr(self, p):
return p.expr
我的问题是,对于我解析命题逻辑的应用程序,虽然这种解析方式可以正确检查语法并表示解析的逻辑表达式的含义,但解析器会将 AST 构造为二叉树。因此,如果我让它解析以下两个表达式:
- pvqvr
- pv(qvr)
生成的 AST 看起来是一样的(具有正确的关联性)。
对于我项目的不同部分,将合取和析取运算视为 n 元而不是二进制对我来说很重要。以上面的第一个表达式为例,析取运算同时应用于三个操作数 p、q 和 r。我需要能够通过查看 AST 本身来区分上面的两个示例表达式。下图显示了我要追求的差异
v v
/ | \ / \
p q r p v
/ \
q r
从理论上讲,LR 解析是否可以创建具有两个以上子节点的 AST?如果是这样,SLY 框架是否足够强大,让我能够做到这一点,还是我需要创建自己的解析器?如果 LR 解析无法创建这样的树,我应该考虑其他算法吗?创建树后我没有做任何进一步的编译,我只需要形成表示命题逻辑表达式的树,如上所示。
如果这是一个愚蠢的问题,请提前道歉,我刚刚在 2020 年春季学期学习了编程语言和翻译,并且随着世界上正在发生的一切,学习体验相当混乱。我将不胜感激任何建议。非常感谢!