2017-08-15 98 views
-1

我正在爲使用yacc/lex編寫一個簡單的shell語法。我希望我的語法能夠識別具有以下形式的管線: command1 | command2 | ... | commandn。我可以將單個命令重新規範化,其中the simple_command規則作爲下面代碼中的起始非終端。但是,當我添加其他規則(simple_command_listpipeline)來解析管道時,事情不起作用。爲了測試語法,我使yacc從以下字符串讀取輸入: char *input = "command1 | command2 | command3 | command4\n\0",在主函數中定義。當問及解析這個字符串,YACC只解析第一個命令,打印 「語法錯誤」,並停止,就像這樣:yacc無法解析simpe shell語法

command "command1" 
simple command 
1B 
parse error 

LEX CODE:

%{ 

#include <string.h> 
#include "y.tab.h" 

%} 

%% 


\n  { 
       return NEWLINE; 

     } 

[ \t] { 
       /* Discard spaces and tabs */ 
     } 

">"  { 
       return GREAT; 
     } 

"<"  { 
       return LESS; 
     } 



「|」 { 
       return PIPE; 
     } 

「&」 { 
       return AMPERSAND; 
     } 


[a-zA-Z][a-zA-Z0-9]* { 
       /* Assume that file names have only alpha chars */ 
       yylval.str = strdup(yytext); 
       return WORD; 
     } 



.  { 
       /* Invalid character in input */ 
       return BAD_TOKEN; 
     } 

%% 
int yywrap(void) { 
return 1; 
} 

YACC CODE:

%{ 
#include <string.h> 
#include <stdio.h> 
int yylex(void); 

void yyerror(char *); 


%} 

%union 
{ 

    char *str; 
    int i; 

} 

%token <i> AMPERSAND GREAT LESS PIPE NEWLINE BAD_TOKEN 
%token <str> WORD 
%start pipeline 
%expect 1 


%% 

cmd: 
    WORD 
    { 
     printf("command \"%s\"\n", $1); 

    } 
; 

arg: 
    WORD 
    { 

     printf("argument \"%s\"\n", $1); 
    } 

; 

arg_list: 
    arg_list arg 
    { 

     //printf(" argument list: \n"); 
    } 
    | // empty 


; 

simple_command: 
    cmd arg_list 
    { 

     printf("simple command \n"); 
    } 

; 

simple_command_list: 
     simple_command_list PIPE simple_command 
     { 
      printf("1A\n"); 
     } 
     | simple_command 
     { 
      printf("1B\n"); 
     } 
; 

pipeline: 
    simple_command_list NEWLINE 
    { 

    printf("p-A\n"); 
    } 
    | NEWLINE 
    { 
     printf("p-B\n"); 
    } 
    ; 


%% 


void yyerror(char *s) { 
    fprintf(stderr, "%s\n", s); 
} 


int main(void) { 
    // read input from a string 
    //YY_BUFFER_STATE *bp; 
    struct yy_buffer_state *bp; 

    char *input = "command1 | command2 | command3 | command4\n\0"; 

    // connect input buffer to specified string 
    bp = yy_scan_string(input); 

    // read from the buffer 
    yy_switch_to_buffer(bp); 


    // parse 
    yyparse(); 

    // delete the buffer 
    yy_delete_buffer(bp); 

    // delete the string (or not) 


    return 0; 
} 
+0

Yacc完美地分析了你的語法,並生成了C代碼。 *你的語法*是不起作用的。停止重新發布。 – EJP

回答

0

您的lex源文件包含如(U-201C左側雙引號)和(U-201D右側雙引號)的Unicode字符,該lex不會識別作爲引號,查找包含該7字節utf-8序列的輸入序列,而不是單個字節|

將這些替換爲Ascii "個字符,它應該可以工作。

如果您啓用了對bison的--debug選項進行調試,您應該看到它獲取的令牌以及它正在轉移和減少的規則。在你的情況下,獲得|BAD_TOKEN ...

+0

謝謝!我的殼現在可以工作。在github上檢查一下:https://github.com/joenatech7/Ash – joenatech7