如何在 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(当错误发生在输入的末尾)。>

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