1

a以下の非常に単純な例では、単一の言語で読み取り、残りの文字が後に続かないことを保証したいと考えています。

ファイル: example.y

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

%token A
%token END
%token JUNK

%% /* Grammar Rules */
accept: A END { printf("language accepted!\n"); }
;
%%

ファイル: example.in

%{
#include "ex.tab.h"
#define YY_NO_INPUT
%}
%option nounput
%%
a printf("A found\n"); return A;
<<EOF>> { printf("EOF found\n"); return END; }
. { printf("JUNK found\n"); return JUNK; }
%%

次のテスト入力ファイルを使用してこのプログラムをコンパイルおよび実行した結果:

a

次の出力が生成されます。

A found

EOF found
language accepted!
EOF found
Error: syntax error

EOF が 2 回読み取られるため、プログラムが入力言語を受け入れないのはそのためだと思います。私の質問は、EOF が 2 回読み取られるのはなぜですか?どうすれば停止できますか?

また、EOF ルールなしで上記を実行すると、次のような入力が発生します。

abbbb

「受け入れ」メッセージを出力しますが、過剰な入力のためにすぐに失敗します。私が望むのは合格か不合格のどちらかだけです。そのため、EOF を使用して 1 つの結果が得られることを確認しようとしています。

4

3 に答える 3

1

bison (およびレモンを除いて私が知っているすべての yacc 派生物) は、その後に EOF トークンが続かない限り、開始生産を減らしません。実際には、文法を次のように変更します。

$accept: accept $end;
accept: A END {...}

ENDトークンは組み込みトークンと同じではありません$end。したがって、bison は喜んでacceptルールを減らします (したがって、printf をトリガーします。出力とは異なるメッセージがコードにあるように見えます。これは、コードの異なるバージョンからのものであることを示唆しています)。しかし、それ自体の$acceptルールは減らしません。その結果、構文エラーが報告されます。

確かに、複数回flex一致する準備ができている場合です。<<EOF>>あなたがより多くのトークンを要求する限り、それは続くと思いますが、私は間違っている可能性があります。確かに、それは 2 回一致します。しかし、それはあなたの問題ではありません。あなたの問題は、それを不可能にしたことを除いて、バイソンにとにかく行うことを強制しようとしているということです。

要するに、flex がやりたいことである EOF に対して 0 を返し、bison が EOF で終了する入力のみを受け入れるようにします。これにより、コードがはるかに簡単になります。

(トリッキーな部分は、実際には、入力の最後に行かない文を認識することです。たとえば、ある言語を別の言語の中に埋め込んでいる場合、たとえば HTML の中に JavaScript や CSS を埋め込んでいます。その場合、いくつかのゲームをプレイするためであり、レモンが通常の拡張開始ルールを挿入しないのはそのためだと思います。)

于 2013-09-12T04:37:19.867 に答える
0

答えは3倍

1) ほとんどの場合、bison パーサーが EOF を処理できるようにする必要があります。それはおそらく最も簡単な方法です。しかし、これは常に可能であるとは限りません。

2)<<EOF>>組み込みのフレックス ルールの処理には、いくつかの特別な要件があります(マニュアルへの必須のリンク)。

3) ポイント 1 に関する注記. なんらかの種類のファイル トークンの終了を必要とするように見える文法があることを最初に発見した場合 (c の一部のバリアントではこれが必要です)、それは悪い形式と見なされます (いくつかのエディターには、競合を引き起こす可能性のあるファイルの最後に改行を追加する設定があります)。

于 2013-10-22T06:08:29.550 に答える