我继承了一个ANTLR语法,现在用Python Lex Yacc实现它而不做任何改动。我的问题是,ANTLR通常使用非常高级别的EBNF来定义语法,而Yacc使用简单的上下文无关语法。
我对二进制表达式的AST定义感到困惑。根据ANTLR,他们看起来像
disjunction
: conjunction ('||' conjunction)*
此定义存在优先原因,不要怀疑名称。
在我的CFG中,它看起来像
def p_sum(self, p):
""" sum : product product_list """
???
def p_product_list(self, p):
""" product_list : PLUS product product_list
| MINUS product product_list
| epsilon
"""
???
其他一些表达式看起来像
def p_disjunction_1(self, p):
""" disjunction : conjunction """
p[0] = p[1]
def p_disjunction_2(self, p):
""" disjunction : conjunction OR disjunction """
p[0] = BinaryOp(p[2], p[1], p[3], p[1].coord)
我想要的是我的AST仅由BinaryExpression节点组成,如第二个例子中所示:
BinaryExpression('+',lhs,rhs)
但是这个语法给了我一系列因素。有什么方法可以按我的方式写出来吗? ???是我需要的地方,但是建立我的AST的表达,但我想不出一个很好的方法来做到这一点。我看到的是定义一个带有一元表达式列表的节点,但这对我来说很难看。或者还有另一种写语法的方法吗?我不敢触摸它,因为我担心我会以解析不同东西的方式改变它。
答案 0 :(得分:1)
disjunction
产生的“原始”形式(在它左移之前被删除以使其适合LL解析)是
disjunction: conjunction
| disjunction '|' conjunction
;
那将是左联合离解;如果你想要权利关联 - 例如对于赋值运算符 - 使用右递归:
assignment: expression
| expression '=' assignment
;
(这可能不是你想要的赋值运算符的左侧,但它显示了右关联规则的一般模式。)
类似地:
sum: product
| sum '+' product
| sum '-' product
;
对应于合理解析树的语法重建应该是相当机械的,但是您可能应该编写足够的测试用例,用两种语法解析它们,以确保自己正确解析它。