在yacc工具中制作自定义错误消息

时间:2018-10-29 14:50:15

标签: syntax message bison yacc

嗨,我刚刚开始研究lex和yacc工具。

我意识到yyerror仅从yacc接收字符串“语法错误”。 我想知道是否可以自定义此字符串。

哦,我还能区分不同类型的错误吗? (试图将丢失的令牌和其他令牌作为不同的错误。) 如果是这样,我应该如何..

非常感谢。

1 个答案:

答案 0 :(得分:2)

您可以在yyerror中随意打印任何想要的消息(甚至根本不打印任何消息),因此可以根据需要自定义消息。常见的自定义方法是添加触发错误的令牌的行号(可能还有列号)。当然,您可以根据需要更改文本,但是如果您只想将其更改为其他语言,则可能应该使用gettext机制。您可以在源分发的.po子目录中找到runtime-po个文件。如果启用了此功能,则bison会在将字符串传递给yyerror之前安排要翻译的字符串,但是当然,如​​果这样更方便,您可以自己在yyerror中进行翻译。< / p>

我怀疑您真正想要的是让野牛产生更多信息的错误消息。野牛只有一种可选的错误消息格式,其中包括“期望的”令牌列表。您可以通过添加

,要求Bison产生此类错误消息。
%define parse.error verbose

在您的序言中。与the manual indicates一样,野牛解析算法有时可能会产生不正确的预期标记列表(因为它不是为特定目的而设计的);您还可以通过以下方式启用lookahead correction,以获得更精确的列表:

%define parse.lac full

这确实有轻微的性能损失。有关详细信息,请参见链接的手册部分。

此功能生成的令牌列表使用野牛文件中提供的令牌名称。这些名称通常不是很友好,因此您可能会发现自己生成错误消息,例如臭名昭​​著的PHP错误

syntax error, unexpected T_CONSTANT_ENCAPSED_STRING

(注意:最新的PHP版本会产生不同但同样神秘的消息。)

为避免这种情况,请为令牌定义双引号别名。这也可以使您的语法更具可读性:

%type <string> TOK_ID "identifier"
%token TOK_IF "if" TOK_ELSE "else" TOK_WHILE "while"
%token TOK_LSH "<<"
/* Etc. */

%%

stmt: expr ';' 
    | while 
    | if
    | /* ... */
while: "while" '(' expr ')' stmt
expr: "identifier"
    | expr "<<" expr
/* ... */

引用的名称将不会通过gettext传递。这适合作为关键字的名称,但是可能需要翻译描述性令牌别名。 this answer中概述了这样做的过程。