如何停止解析并重置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() 
+0

建议:不要在解析器中执行命令;如果没有解析器错误,则建立一棵树并在单独的通道中评估它。您可以处理错误,而无需担心与解析器状态的交互方式。 – Kaz

可以使用YYABORT;在动作中止当前的解析,并从yyparse以失败立即返回。您可以使用YYACCEPT;立即从yyparse返回成功。

这两个宏只能在语法中的一个动作中直接使用 - 它们不能在动作调用的其他函数中使用。

+0

我尝试使用YYABORT(如上面的代码部分所示),但它不起作用。 – joenatech7

+0

上面的代码部分在语法上不正确,并且提供了来自野牛的错误。正确使用,YYABORT正常工作。尝试创建[mvce](https://stackoverflow.com/help/mcve)以显示您遇到的问题。 –