野牛解析器:我什么时候需要'返回',什么时候不需要?

时间:2013-11-16 17:55:03

标签: c++ c bison flex-lexer

现在我正在写Bison解析器中的第一份作品,一个计算器。

我注意到了以下规则:

expr_double: expr_double '+' expr_double          { $$ = $1 + $3; }
        | expr_double '-' expr_double           { $$ = $1 - $3; }
        .
        .
        .
        etc...

我不需要使用'return 0'指定解析的结束,并且解析器知道何时停止并完成作业。 这适用于输入,例如print double_expr:5,10 + 10等......

但是,对于以下规则,我最后需要写'return 0',否则它不会起作用:

print_expr: PRINT expr_int      { cout<<$2<<endl; return 0; }
        | PRINT expr_double     { printf("%.3f\n", $2); return 0; }
        .
        .
        .
        etc...

我没有提供任何进一步的代码,因为我认为它不相关。如果需要,我会发布更多的代码,但我认为这里显示的是差异。

为什么我需要在后面的规则中“返回”,但在第一个中不需要?

编辑: 添加了我的程序的第一条和第二条规则......

program: command '\n'
        ;

command: print_expr
        | define_var
        | assign_var
        ;

2 个答案:

答案 0 :(得分:4)

在野牛的正常使用中,你根本不会返回。相反,“开始”规则会减少,然后yyparse()会正常返回。

我怀疑你在任何行动中都需要return

那就是说,我已经看到过使用这种回归方式。它只会导致yyparse()过早返回。 “开始”规则尚未减少,因此此时您的输入与整个语法不匹配。

将这条规则视为短语你的语法。 一旦操作中返回的规则减少,yyparse()将立即返回并在此时停止解析。 可能你想要什么。

换句话说,只要解析器看到一个print语句,它就会停止解析。


更新:你可能想要的是一个接一个地解析许多命令。这个语法看起来像这样:

program: commands '\n'
        ;
commands : command
         | commands command
         ;
command: print_expr
        | define_var
        | assign_var
        ;

答案 1 :(得分:2)

不要直接从解析器尝试return,您可能会泄漏,因为您将跳过清理堆栈的所有代码。如果您想要成功退出,请使用YYACCEPT,否则使用YYABORT