我正在寫作業控制外殼。我使用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()
建議:不要在解析器中執行命令;如果沒有解析器錯誤,則建立一棵樹並在單獨的通道中評估它。您可以處理錯誤,而無需擔心與解析器狀態的交互方式。 – Kaz