如何在 PLY yacc 中存储错误

How to store errors in PLY yacc

我正在使用 ply.yacc 来构建解析器,并且我对将所有语法错误存储在一个列表中很感兴趣。我想要这样的东西:

parser = yacc.yacc()
parser.errors = []
parser.parse(program)
print(parser.errors) # do something with parser.errors

问题是当我定义处理错误的规则时

def p_error(p):
    ...

我不知道如何访问解析器实例,所以我可以将错误附加到我的列表中。对于词法分析器,我使用了 ply.lex 并解决了这个问题,因为在规则定义中作为参数传递的标记 t 有一个对词法分析器的引用。

def t_error(t):
  t.lexer.error.append(LexicographicError(t.lineno, t.value[0]))

有什么方法可以用 yacc 解析器做类似的事情吗???

p_error 的参数通常是一个记号(因此原型最好写成 def p_error(t):),因此您可以将错误添加到您在词法分析器中使用的相同列表中。但这并不理想;首先,因为这是一个保留错误(词法和句法)的奇怪地方,其次因为有时 p_error 的参数是 None (当错误发生在输入末尾时)。

更好的解决方案是使解析器成为 class 而不是全局的,这在 Ply 文档中有相当简要的解释(主要参考关于使词法分析器成为 class 的部分).通常,您会在 Parser class 的 __init__ 方法中构建解析器,并将其保存为 self.parser。然后所有 p_* 成员函数都采用 self 参数,与任何 class 函数一样,您可以将错误列表存储为成员属性。 (您可以使用 self.parser 获取 parser,但我认为将错误列表保留在对象实例本身中比将其添加到解析器实例中更清晰。)