4

我使用 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"

因为文本“用户名”被解析器在 part(A) ::= error(B) 规则中丢弃,但我真的想要:

"Username Joseph1234"

作为输出。

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

4

2 回答 2

2

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

语法必须包含空格。目前,该语法仅允许 NUMBER NAME 记号序列(记号之间没有任何空格)。

于 2011-05-27T20:25:05.253 回答
2

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

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

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

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

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

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

为此,请考虑使用yybackup。我无法找到替代方法,但yybackup不赞成。

于 2012-06-06T17:57:09.857 回答