2017-08-31 136 views
0

我正在寫作業控制外殼。我使用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

回答

0

可以使用YYABORT;在動作中止當前的解析,並從yyparse以失敗立即返回。您可以使用YYACCEPT;立即從yyparse返回成功。

這兩個宏只能在語法中的一個動作中直接使用 - 它們不能在動作調用的其他函數中使用。

+0

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

+0

上面的代碼部分在語法上不正確,並且提供了來自野牛的錯誤。正確使用,YYABORT正常工作。嘗試創建[mvce](https://stackoverflow.com/help/mcve)以顯示您遇到的問題。 –