2016-05-09 4 views
1

私はおもちゃコンパイラを開始しています。私は想像できる最も簡単なことをしていますが、うまくいきません。LexとYaccはコンパイラを作る?

Lexがコンパイルされ、Yaccがコンパイルされ、それらはリンクされますが、出力されたプログラムは期待したことをしません。

レックス:

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

%% 


a      { 
          yylval = atoi(yytext); 
          return AAA; 
         } 
.      yyerror("invalid character"); 

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

のYacc:a

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

%token AAA 

%% 
daaaa: 
AAA    {printf("%d\n", $1);} 

%% 

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

int main(void) { 
yyparse(); 
return 0; 
} 

私はこのコンパイラでコンパイルしようとしていたプログラムが含まれているファイルです。それでおしまい。

私は何が起こったのか分かりません!

明確化:コンパイルされたコンパイラは、ファイルを受け入れてファイルを処理し、そのファイルのコンパイル済みバージョンを吐き出すことを期待していました。

+0

あなたの期待を明らかにし、プログラムによってどのように満たされていないのかを知ることができれば助かります。 – rici

+1

文字「a」を「atoi」で整数に変換しようとする目的を説明できますか? –

+0

@ BrianTompsett-湯莱恩yylvalは、デフォルトでintを返し、 "a"でvarを減算することで、入力には以前の入力を覚えていないで26種類のyylval値を得る確実な方法が与えられます。 – Stegosaurus

答えて

2

私が知る限り、私が質問する限り、それはあなたと同じように働くべきではないので、あなたは答えたかもしれません。いう。

私はあなたのコードをそのまま使用して、ファイルgrammar.ylexer.lを作成しました。私はコードをコンパイルしました。私はMac OS X 10.11.4、GCC 6.1.0、Bison 2.3(yaccと偽装)、Flex 2.5.35(lexと偽装)を使って作業しています。

$ yacc -d grammar.y 
$ lex lexer.l 
$ gcc -o gl y.tab.c lex.yy.c 
$ ./gl <<< 'a' 
0 

$ 

続いて2つの変更を行いました。 grammar.yでは、私はにmain()を変更:

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

lexer.lに、私はにデフォルトの文字ルールを変更:

aで後
\n|.     yyerror("invalid character"); 

.は改行と一致していないので、改行入力は元の出力にデフォルトでエコーされました。同様のコンパイルを)

、出力は次のようになる。あまりに-DYYDEBUGを指定コンパイルを

$ ./gl <<< 'a' 
0 
invalid character 
$ 

$ gcc -DYYDEBUG -o gl lex.yy.c y.tab.c 
$ 

出力は、有用なデバッグ情報を含む:

$ ./gl <<< 'a' 
Starting parse 
Entering state 0 
Reading a token: Next token is token AAA() 
Shifting token AAA() 
Entering state 1 
Reducing stack by rule 1 (line 12): 
    $1 = token AAA() 
0 
-> $$ = nterm daaaa() 
Stack now 0 
Entering state 2 
Reading a token: invalid character 
Now at end of input. 
Stack now 0 2 
Cleanup: popping nterm daaaa() 
$ ./gl <<< 'aa' 
Starting parse 
Entering state 0 
Reading a token: Next token is token AAA() 
Shifting token AAA() 
Entering state 1 
Reducing stack by rule 1 (line 12): 
    $1 = token AAA() 
0 
-> $$ = nterm daaaa() 
Stack now 0 
Entering state 2 
Reading a token: Next token is token AAA() 
syntax error 
Error: popping nterm daaaa() 
Stack now 0 
Cleanup: discarding lookahead token AAA() 
Stack now 0 
$ 

入力に正しく2番目のa tr構文エラーを引き起こします(文法では許可されていません)。他の文字は許可され、「無効な文字」メッセージが生成され、それ以外の場合は無視されます(./gl <<< 'abc'bの文字メッセージ、cの文字メッセージ、改行文字のメッセージです)。

lexer.l

yylvalへ割り当てを変更:

yylval = 'a'; // atoi(yytext); 

はASCIIで'a'の文字コード、ISO 8859-1、ユニコードである97に0から印刷番号、等を変更

私はhere stringをデータソースとして使用しています。入力としてファイルを使用しているにも同様に実現可能になります:

$ echo a > program 
$ cat program 
a 
$ ./gl < a 
Starting parse 
Entering state 0 
Reading a token: Next token is token AAA() 
Shifting token AAA() 
Entering state 1 
Reducing stack by rule 1 (line 12): 
    $1 = token AAA() 
97 
-> $$ = nterm daaaa() 
Stack now 0 
Entering state 2 
Reading a token: invalid character 
Now at end of input. 
Stack now 0 2 
Cleanup: popping nterm daaaa() 
$ 

コマンドラインで名前によって指定されたファイルを読みたい場合は、あなたがそれらのファイルを処理するためにmain()でより多くのコードを記述する必要があります。

1

プログラムは、指示されなかったためファイルを受け入れません。

Yaccプログラムではの定義セクションに extern FILE *yyin;を追加する必要があります。

私はそれを信じています。

+0

正直言って、なぜ私はそれが期待していた不合理な、そして書かれていない魔法をコンパイラが期待するのか分かりません! – Stegosaurus

+0

私は 'extern FILE * yyin; 'を追加する提案は特に関連しないと思います。それを参照する目に見えるものは何もありません。私がテストするとき、それはそれなしで私のために働く。 –

+0

@JonathanLefflerは、私が言うことができる限り、質問をテストした限り、あなたが言うように動作してはならないので、あなたが答えた、多分あなたがしたこと、 – Stegosaurus

関連する問題