如何停止解析并重置yacc?
我正在写作业控制外壳。我使用Yacc和Lex进行分析。我的语法中的最高规则是pipeline_list
,这是一个用逗号分隔的管道列表。因此,是pipelinelists的实例如下:如何停止解析并重置yacc?
cmd1 | cmd2; cmd3; cmd4 | cmd5 <newline>
cmd1 <newline>
<nothing> <newline>
我表示与pipeline
规则管道(下面显示)。在该规则中,我执行以下操作:
1.调用execute_pipeline()
来执行管道。 execute_pipeline()
返回-1
如果执行管道时出错了。在主要功能(如下图所示)再次调用时
2.检查的execute_pipeline()
的返回值,如果它是-1
,然后停止解析输入的其余部分,并确保YACC开始新鲜。这样做的基本原理是这样的: 例如,以下管道列表:cd ..; ls -al
。我的意图是将一个目录向上移动,然后列出其内容。然而,如果流水线列表中的第一个流水线(即"cd .."
)的执行失败,则继续执行第二流水线(即" ls -al"
)将列出当前目录(不是父节点)的内容,这是错误的!因此,在解析长度为n
的流水线列表时,如果执行某个流水线k > n
失败,那么我想丢弃其余的流水线列表(即流水线k+1..n
),并确保下一次调用yyparse()开始全新(即从readline()
接收新输入 - 请参阅下面的代码)。 如果尝试以下,但它不工作:
pipeline:
simple_command_list redirection_list background pipeline_terminator // ignore these
{
if (execute_pipeline() == -1)
{
// do some stuff
// then call YYABORT, YYACCEPT, or YYERROR, but none of them works
}
}
int main()
{
while(1)
{
char *buffer = readline("> ");
if (buffer)
{
struct yy_buffer_state *bp;
bp = yy_scan_string(buffer);
yy_switch_to_buffer(bp);
yyparse()
yy_delete_buffer(bp);
free(buffer);
} // end if
} // end while
return 0;
} // end main()
可以使用YYABORT;
在动作中止当前的解析,并从yyparse以失败立即返回。您可以使用YYACCEPT;
立即从yyparse返回成功。
这两个宏只能在语法中的一个动作中直接使用 - 它们不能在动作调用的其他函数中使用。
我尝试使用YYABORT(如上面的代码部分所示),但它不起作用。 – joenatech7
上面的代码部分在语法上不正确,并且提供了来自野牛的错误。正确使用,YYABORT正常工作。尝试创建[mvce](https://stackoverflow.com/help/mcve)以显示您遇到的问题。 –
建议:不要在解析器中执行命令;如果没有解析器错误,则建立一棵树并在单独的通道中评估它。您可以处理错误,而无需担心与解析器状态的交互方式。 – Kaz