2017-08-15 4 views
-1

yacc/lexを使ってシェルのための簡単な文法を書いています。私は文法にパイプラインを認識させたいと思っています。パイプラインの形式は次のとおりです: command1 | command2 | ... | commandn。私は以下のコードでthe simple_commandルールを非終端記号の開始として使用して、単一のコマンドを再調整することができます。しかし、パイプラインを解析するために追加のルール(simple_command_list、および)を追加すると動作しません。文法をテストするには、main関数で定義されている char *input = "command1 | command2 | command3 | command4\n\0"の文字列からyaccの読み込みを行います。この文字列を解析するように求められたら、yaccはだけちょうどそうと同じように、最初のコマンド、版画 "パースエラー" を解析し、停止します。yaccがsimpeシェル文法を解析できません

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

レックスソースファイルには、(U-201C LEFT DOUBLE QUOTATION MARK)や(U-201D右ダブルクォーテーションマーク)などのユニコード文字が含まれています引用符で囲むように、1バイトの|ではなく、その7バイトのutf-8シーケンスを含む入力シーケンスを探しています。

これらをAscii "文字に置き換えるとうまくいくはずです。

--debugオプションを使用してデバッグを有効にすると、どのトークンが取得されているのか、どのルールがシフトおよび削減されているのかを確認する必要があります。あなたの場合、|BAD_TOKENを取得する...

+0

ありがとう!私のシェルは今働いている。 githubでチェックしてください:https://github.com/joenatech7/Ash – joenatech7

関連する問題