如何停止解析和重置yacc?

时间:2017-08-31 21:42:53

标签: parsing bison flex-lexer yacc lex

我正在编写一个作业控件shell。我使用Yacc和Lex进行解析。我的语法中的最高规则是pipeline_list,它是由逗号分隔的管道列表。因此,管道列表的示例如下:

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),AND确保下一次调用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()

1 个答案:

答案 0 :(得分:0)

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

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