2010-07-19 44 views
4

我使用柠檬作为解析器生成器,其错误处理与yacc和野牛的相同,如果您不知道柠檬。在解析(柠檬)中恢复错误标记

柠檬有一个选项可以在一组规则中定义错误标记以捕获分析错误。生成的解析器的默认行为是销毁导致错误的令牌;有什么方法可以重写这种行为,以便我可以保持令牌?

下面就来展示一下发生的事情为例:基本上我追加令牌每个规则一起改革输入字符串,这里是一个例子语法:

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

使用yacc/bison时,如果可能,解析错误会将工具降至错误恢复模式。它将尝试放弃令牌进入“干净”状态。

我无法找到柠檬的参考,所以我不能显示一些柠檬代码来解决这个问题,但与yacc /野牛,人们会使用规则here

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

作为一个例子,如果定义为MyOther MyOther语法看见MyTok MyOther:

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

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

为了实现这一点,考虑使用yybackup。我无法找到一种替代方法,但yybackup皱起了眉头。

+0

如果有人感兴趣,我最终转换到RE2C [[link](http://re2c.org/)]。用RE2C宏获取行为要容易得多。我编写了宏,以便任何不匹配的子字符串都是简单的输出,而任何匹配的子字符串都是由RE2C修改的。 – 2015-05-05 17:29:15

2

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

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

+1

有回复旧问题和选票的徽章(死灵法师和复兴),所以有充足的理由回答老问题没有答案(或没有一个很好的答案)。 – 2011-05-28 00:07:15

+0

词法分析器可能处理标记之间的空间等。这是标准的分工 - 词法分析器处理注释和空白和字符串;语法处理由词法分析器发现的不被它吃的令牌。 – 2011-05-28 00:09:11

+0

@Jonathan Leffler,我不能根据这个问题做出这个假设。令牌序列NUMBER NAME预计会捕获1234Joseph,但通常情况并非如此(1234Joseph不会是合法令牌)。我希望你看到我的意思是空间。 – 2011-05-28 18:49:22