簡體   English   中英

關於野牛/ YACC語法的困惑

[英]Confusion about a Bison/YACC Grammar

使用以下語法,使用這種輸入會出現語法錯誤:

ls /home > foo #Runs and works okay, but raises error token
ls /home /foo /bar /etc #works okay

我認為這可能與前瞻的工作方式有關,但這是我的第一個語法,我對為什么它不能這樣工作感到有些困惑:external_cmd GT WORD是重定向,redirect是命令,command是命令,因此輸入命令NEWLINE應該可以使用。

語法最高規則:

input:
    error NEWLINE {
        printf("Error Triggered\n");
        yyclearin;
        yyerrok; 
        prompt(); 
    } |
    input NEWLINE {
        prompt();
    } | 
    input commands NEWLINE {
        prompt (); 
    } | 
    /* empty */
    ;   

commands: 
    command |   
    command SEMI | 
    command SEMI commands
    ;   

command:
    builtin_cmd |
    redirect |
    external_cmd { 
        execute_command($1, 0, NULL);
    }
    ;

redirect:
    external_cmd GT WORD  {
        printf("Redirecting stdout of %s to %s\n", $1->cmd, $3);
        //printf("DEBUG: GT\n");
        execute_command($1, STDOUT_FILENO, $3);
    }
    external_cmd LT WORD {
        printf("Redirecting stin of %s to %s\n", $1->cmd, $3);
        //printf("DEBUG: GT\n");
        execute_command($1, STDIN_FILENO, $3);
    }
    ;

引發錯誤令牌時的調試/詳細輸入:

Next token is token WORD ()
Shifting token WORD ()
Entering state 6
Reading a token: Next token is token WORD ()
Shifting token WORD ()
Entering state 24
Reading a token: Next token is token GT ()
Reducing stack by rule 22 (line 115):
   $1 = token WORD ()
-> $$ = nterm arg_list ()
Stack now 0 2 6
Entering state 26
Reducing stack by rule 19 (line 91):
   $1 = token WORD ()
   $2 = nterm arg_list ()
-> $$ = nterm external_cmd ()
Stack now 0 2
Entering state 16
Next token is token GT ()
Shifting token GT ()
Entering state 29
Reading a token: Next token is token WORD ()
Shifting token WORD ()
Entering state 33
Reducing stack by rule 11 (line 68):
Redirecting stdout of ls to foo
DEBUG: redirect mode is 1
DEBUG: Command to run is ls
DEBUG: Adding Argument /home
admin  kbrandt  tempuser
-> $$ = nterm @1 ()
Stack now 0 2 16 29 33
Entering state 34
Reading a token: Next token is token NEWLINE ()
syntax error
Error: popping nterm @1 ()
Stack now 0 2 16 29 33
Error: popping token WORD ()
Stack now 0 2 16 29
Error: popping token GT ()
Stack now 0 2 16
Error: popping nterm external_cmd ()
Stack now 0 2
Error: popping nterm input ()
Stack now 0
Shifting token error ()
Entering state 1
Next token is token NEWLINE ()
Shifting token NEWLINE ()
Entering state 3
Reducing stack by rule 1 (line 38):
   $1 = token error ()
   $2 = token NEWLINE ()
Error Triggered
-> $$ = nterm input ()
Stack now 0
Entering state 2

更新:
external_cmd是:

external_cmd:
    WORD arg_list {
        $$ = malloc( sizeof(struct ext_cmd) );
        if ( $$ == NULL)
            printf("Memory Allocation Error\n");
        $$->cmd = $1;
        $$->args_pp = $2;
    } |
    WORD    {
        $$ = malloc( sizeof(struct ext_cmd) );
        if ( $$ == NULL)
            printf("Memory Allocation Error\n");
        $$->cmd = $<string>1;
        $$->args_pp = NULL;
    }

語法錯誤來自您對yyparse的第二次調用。 進行重定向后,語法將執行YYACCEPT,這將導致解析器立即返回而無需讀取更多內容。 在第二次調用中,讀取的第一個令牌是一個NEWLINE,它可以防止出現錯誤(您的語法不允許空行。)

沒有重定向,就沒有YYACCEPT,因此語法會繼續運行,讀取換行符並返回到輸入的末尾。

  1. 你真的真的應該使用左遞歸與LALR(1)語法分析器發電機。 正確的遞歸要求所有元素都必須轉移到解析器狀態堆棧上,甚至可以進行一次歸約。 您可以想象這對錯誤恢復有什么作用。

  2. external_cmd到底是什么? 看起來好像它在早期減少,但是很難說出來,因為您沒有包括它。

  3. 為什么重定向后會調用YYACCEPT 如果打算在每行上重新啟動解析器,則不應具有遞歸輸入收集器。 只要您有,就不要做YYACCEPT。

找到它后,在我的重定向規則中有一個缺失的管道,因此有兩個組件而不是兩個組件,其中一個具有中規則操作,這不是我想要的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM