现在我正在写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
;
答案 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
。