我正在编写一个作业控件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()
答案 0 :(得分:0)
您可以在操作中使用YYABORT;
来中止当前解析并立即从yyparse返回失败。您可以使用YYACCEPT;
立即从yyparse返回成功。
这两个宏只能直接用于语法中的动作 - 它们不能用于动作调用的其他函数。