t_error() 函数用于处理检测到非法字符时发生的词法错误。我的问题是:如何使用此功能获取有关错误的更具体信息?像错误类型,错误出现在哪个规则或部分等。
3 回答
一般来说,t_error() 函数可用的信息非常有限。作为输入,它接收一个标记对象,其中值已设置为剩余的输入文本。对该文本的分析完全取决于您。您可以使用 t.lexer.skip(n) 函数让词法分析器向前跳过一定数量的字符,仅此而已。
除了存在与任何已知标记的正则表达式不匹配的输入字符这一事实之外,没有“错误类型”的概念。由于词法分析器与解析器分离,因此无法直接获取有关解析引擎状态的任何信息或找出正在解析的语法规则。即使你能得到状态(这只是 LALR 状态机的底层状态编号),解释它可能会非常困难,因为解析器可能处于匹配几十个可能的语法规则的中间阶段,以寻找 reduce行动。
我的建议如下:如果您需要 t_error() 函数中的其他信息,您应该设置某种在代码的词法分析器和解析器组件之间共享的对象。您应该明确地使编译器的不同部分根据需要更新该对象(例如,它可以在特定的语法规则中更新)。
顺便说一句,通常很少有针对不良令牌的行动方案。本质上,您得到的输入文本不属于语言字母表的任何已知部分(例如,没有已知符号)。因此,您甚至无法为解析器提供任何类型的令牌值。通常,唯一的做法是报告错误输入,将其丢弃,然后继续。
作为 Raymond 回答的后续行动,我也不建议在 t_error() 中修改词法分析器对象的任何属性。
Ply 在名为cpp.py的文件中包含一个示例 ANSI-C 样式词法分析器。它有一个如何从 t_error() 中提取一些信息的示例:
def t_error(t):
t.type = t.value[0]
t.value = t.value[0]
t.lexer.skip(1)
return t
在该函数中,您还可以访问词法分析器的公共属性:
- lineno - 当前行号
- lexpos - 输入字符串中的当前位置
还有一些其他属性未列为公共属性,但可能会提供一些有用的诊断:
- lexstate - 当前的词法分析器状态
- lexstatestack - 词法分析器状态堆栈
- lexstateinfo - 状态信息
- lexerrorf - 错误规则(如果有)
在 PLY 中确实有一种管理错误的方法,看看这个非常有趣的怨恨:
http://www.slideshare.net/dabeaz/writing-parsers-and-compilers-with-ply
在第 6.8.1 章