2016-05-20 4 views
0

私はLexとYaccで書かれた2つの非常に小さなファイルを持っています。私のLexとYaccプログラムは一度正常に動作し、2回目の試行でクラッシュしますか?

レックス:

%{ 
    #include <stdlib.h> 
    #include "y.tab.h" 
    void yyerror(char *); 
%} 

%% 

[a] { 
    yylval = *yytext; 
    return VAR; 
    } 

[ \t\n] ; 

. yyerror("invalid character"); 

%% 

int yywrap(void) { 
return 1; 
} 

のYacc:

%token VAR 

%{ 
    void yyerror(char *); 
    int yylex(void); 
    #include <stdio.h> 
%} 

%% 

butts: 
    VAR { printf("%d\n", $1); } 

%% 

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


int main(void) { 
    #if YYDEBUG 
    yydebug = 1; 
    #endif 
    yyparse(); 
    return 0; 
} 

と私は全部(-DYYDEBUG付き)オプションをコンパイルするとき、私は出力を得る:

Starting parse 
Entering state 0 
Reading a token: a 
Next token is token VAR() 
Shifting token VAR() 
Entering state 1 
Reducing stack by rule 1 (line 12): 
    $1 = token VAR() 
97 
-> $$ = nterm butts() 
Stack now 0 
Entering state 2 
Reading a token: a 
Next token is token VAR() 
syntax error 
Error: popping nterm butts() 
Stack now 0 
Cleanup: discarding lookahead token VAR() 
Stack now 0 

"a"を2回入力する。私が最初に "a"を押すと、Reading a token:プログラムは正常に動作しているように見えますが、2回目には嘔吐します。

私はこれがなぜそうであるかについて迷っています。

+2

FWIWでは、「クラッシュ」は通常セグメンテーションなどを意味し、「嘔吐」は「莫大な量の役に立たない出力」を意味すると解釈します。ブライアンの答えが正しい場合、実際の問題の症状は「2回目は構文エラーを報告する」となります。正確な問題の説明は、問題の発見をより簡単にします。少しの非公式やユーモアには何も問題はありませんが、問題を報告するときは、何が起こったのかを明確に述べることが常に良いです。 (2)あなたは何が起こると予想したのですか。 (3)これらがどのように異なるか。 – rici

答えて

3

文法ファイルに「a」は1つしか指定できないと記載されているためです。これ以上エラーが発生すると、エラーが発生します。あなたの文法ルールは、次のように書かれています:

butts: VAR 

これ以上何も、

したがって、あなたの文法が一致したときのみ有効なプログラムは次のとおりです。

a 

のような他の入力、:

aa 

か:

a 
a 

構文エラーが発生します。あなたのルールは非常に明示的にと書かれています VAR ; VARSのシーケンスではありません。少数のヴァースではありません。ただ1つのVAR。

入力に2つ以上一致させる場合は、にはと表示されます。したがって、文法は許可されたシーケンスを記述しなければなりません:

butts: VAR | butts VAR 

これでシーケンスが許可されます。

これは明確ですか?

+0

要するに、バットは両方のバット(再帰的ツリーを開始する)であり、varはブランチの終わり(単一の解決策)であることが許されるべきですか? – Stegosaurus

関連する問題