【问题标题】:Recovering error tokens in parsing (Lemon)在解析中恢复错误标记(柠檬)
【发布时间】:2011-03-18 03:33:44
【问题描述】:

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

作为输出。

如果你可以在 bison 或其他解析器生成器中解决这个问题,我会接受它作为答案:)

【问题讨论】:

    标签: c parsing token yacc lemon


    【解决方案1】:

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

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

    【讨论】:

    • 有徽章(死灵法师和复兴)用于回答旧问题和获得投票,因此完全有理由在没有答案(或没有好的答案)的情况下回答旧问题。
    • 词法分析器大概处理token之间的空格等。这是标准的分工——词法分析器处理cmets和空格和字符串;语法处理词法分析器发现但未被它吃掉的标记。
    • @Jonathan Leffler,我无法根据这个问题做出这个假设。记号序列 NUMBER NAME 预计会捕获 1234Joseph,但通常情况并非如此(1234Joseph 不是合法记号)。我希望你明白我关于空间的意思。
    • 很公平 - 在不知道词法分析器如何分析内容的情况下,很难确定发生了什么。
    【解决方案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 不受欢迎。

    【讨论】:

    • 如果有人感兴趣,我最终切换到 RE2C [link]。使用 RE2C 宏更容易获得行为。我编写了宏,以便简单地输出任何不匹配的子字符串,而任何匹配的子字符串都由 RE2C 修改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多