0

我继承了一个 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,但我想不出一个好的方法来做到这一点。我看到的是用一元表达式列表定义一个节点,但这对我来说很难看。还是有另一种写语法的方法?我不敢碰它,因为我担心我会改变它以解析不同的东西。

4

1 回答 1

1

产生式的“原始”形式disjunction(在消除左递归以使其适合 LL 解析之前)是

disjunction: conjunction
           | disjunction '|' conjunction
           ;

那将是左关联析取;如果你想要右关联——例如赋值运算符——使用右递归:

assignment: expression
          | expression '=' assignment
          ;

(这可能不是您想要的赋值运算符左侧的内容,但它显示了右关联规则的一般模式。)

相似地:

sum: product
   | sum '+' product
   | sum '-' product
   ;

对应于合理解析树的语法重构应该是相当机械的,但是您可能应该编写足够的测试用例,用两种语法解析它们,以确保您得到它是正确的。

于 2013-10-22T14:25:18.893 回答