解析时恢复错误令牌(柠檬)

时间:2010-07-19 21:29:45

标签: c parsing token yacc lemon

我使用Lemon作为解析器生成器,如果你不认识Lemon,它的错误处理与yacc和bison相同。

Lemon可以选择在一组规则中定义错误标记,以便捕获解析错误。生成的解析器的默认行为是销毁导致错误的令牌;有没有办法覆盖这种行为,以便我可以保留令牌?

这是一个显示正在发生的事情的示例:基本上我将每个规则的标记附加在一起以改变输入字符串,这是一个示例语法:

input ::= string(A) { printf("%s", A); } // Print the result
string(A) ::= string(B) part(C). { A = append(B, C); }
string(A) ::= part(B). { A = B; }
part(A) ::= NUMBER(B) NAME(C). { A = append(C, B); } // Rearrange the number and name
part(A) ::= error(B). { A = B; } // On error keep the token anyways

输入时:

"Username 1234Joseph"

我得到输出:

"Joseph1234"

因为文本“用户名”在部分(A):: =错误(B)规则中被解析器废弃,但我真的想要:

"Username Joseph1234"

作为输出。

如果您可以在野牛或其他解析器生成器中解决此问题,我会接受这样的答案:)

2 个答案:

答案 0 :(得分:2)

这是一个旧的,但为什么不......

语法必须包含空格。目前,语法只允许一系列NUMBER NAME标记(令牌之间没有任何空格)。

答案 1 :(得分:2)

使用yacc / bison时,如果可能,解析错误会将工具放入错误恢复模式。它将尝试在去往“干净”状态的途中丢弃令牌。

我无法找到柠檬的参考,所以我无法显示一些柠檬代码来解决这个问题,但是使用yacc / bison,可以使用规则here

即,您需要调整错误规则以声明解析器可以使用yyerrok以防止它丢弃令牌。接下来,它将尝试重新读取“错误”令牌,因此您需要使用yyclearin清除它。最后,由于附加到错误代码的规则包含令牌的内容,因此您需要设置一个调整输入堆栈的函数,方法是获取当前令牌内容并创建具有相同内容的新(正确)令牌。

例如,如果定义为MyOther MyOther的语法看到了MyTok MyOther:

stack
MyTok: "the text"
MyOther: "new text"

stack
MyOther: "the text"
MyOther: "new text"

要完成此操作,请查看使用yybackup。我无法找到替代方法,但yybackup不赞成。