1. ホーム
  2. bison

[解決済み] ファイル全体をパースした後、Flexが "input in flex scanner failed "と投げる?

2022-02-05 01:09:11

質問

C++でFlexとBisonを使ってパーサーを作ろうとしています。オンラインでは、解析のために悪いファイルを提供する投稿でのみ、"input in flex scanner failed"を見かけました。しかし、私のファイル全体が正しくパースされた後、このエラーが表示されます。フレックスがEOFを正しく検出できないバグがあるのでしょうか?以下は関連する定義です。

バイソン

%union {
    char node;
    char gate;
    int index;
}

%token END;
%token <node> NODE;
%token <gate> GATE;
%token <index> INDEX;

%%

atpg:
    body END { cout << "Reading last line." << endl; };
body:
    assignments;
assignments:
    assignments assignment { cout << "Token: assignments - rec." << endl; }
    | assignment         { cout << "Token: assignments - first." << endl; };
assignment:
    outnode gatedec '(' nodelist ')'  {
        cout << "Token: assignment" << endl;
        g_gatelist[last_gate].setOutput(&g_nodelist[out_node]);
        for(int i : t_nodelist)
            g_gatelist[last_gate].addInput(&g_nodelist[i]);
        t_nodelist.clear();
        };
outnode:
    nodedec '='  {
        cout << "Token: outnode" << endl;
        out_node = last_node;
        };
nodedec:
    NODE INDEX  {
        num_nodes ++;
        if ($1 == 'i') input_nodes ++;
        if ($1 == 'o') output_nodes ++;

        new(&g_nodelist[$2]) Node($1, $2);
        last_node = $2;

        cout << g_nodelist[$2] << endl;
        };
gatedec:
    GATE INDEX  {
        num_gates ++;

        createGateFromName(&g_gatelist[$2], $1, $2);
        last_gate = $2;

        cout << "Gate: " << $1 << "-" << $2 << endl; 
        };
nodelist:
    nodedec nodelist { 
        cout << "Token: nodelist - rec" << endl;
        t_nodelist.push_back(last_node);
        }
    | nodedec {
        cout << "Token: nodelist - first" << endl;
        t_nodelist.push_back(last_node);
        };

フレックス

%{
#include "gatelist.tab.h"
#define YY_DECL extern "C" int yylex()
%}

INDEX    [0-9]+
GATE     and|or|not
NODE     n|i|o

%%

{GATE}      { yylval.gate = yytext[0]; return GATE; }

{NODE}      { yylval.node = yytext[0]; return NODE; }

{INDEX}     { yylval.index = atoi(yytext); return INDEX; }

[\(\)=]     { return yytext[0]; }

end         { return END; }

.|\n ;/* ignore */
%%
;

入力

n3 = and1 ( i0 i1 i2 )
n4 = or2 ( i1 i2 )
n5 = not3 ( n4 )
n6 = and4 ( n5 n4 )
end

出力

Node(n-3 = 0)
Token: outnode
Gate: a-1
Node(i-0 = 0)
Node(i-1 = 0)
Node(i-2 = 0)
Token: nodelist - first
Token: nodelist - rec
Token: nodelist - rec
Token: assignment
Token: assignments - first.
Node(n-4 = 0)
Token: outnode
Gate: o-2
Node(i-1 = 0)
Node(i-2 = 0)
Token: nodelist - first
Token: nodelist - rec
Token: assignment
Token: assignments - rec.
Node(n-5 = 0)
Token: outnode
Gate: n-3
Node(n-4 = 0)
Token: nodelist - first
Token: assignment
Token: assignments - rec.
Node(n-6 = 0)
Token: outnode
Gate: a-4
Node(n-5 = 0)
Node(n-4 = 0)
Token: nodelist - first
Token: nodelist - rec
Token: assignment
Token: assignments - rec.
Reading last line.
input in flex scanner failed

解決方法は?

Bisonは常に、入力が完全なファイルにマッチするように、提供された開始ルールにマッチするゴールルールの後にファイル終了インジケータ(トークン番号0)を追加することによって、提供された文法を補強します。独自の終了マーカーを使用し、認識された時点で解析を終了させたい場合は YYACCEPT アクションを使用すると、それ以上トークンを読み込まずにパースを終了させることができます。

フレックススキャナがデータを読み込もうとしたときに、読み取りエラーが発生した場合に表示されるエラーです。ファイルの終端は ではない というエラーがあり、I/Oエラーはかなり珍しいです。通常、このエラーは、ファイルの終わりが報告された後、入力を読み続けようとしたことを示し yyin を閉じた(あるいは無効な値を設定した)。一般に、ファイル終了が報告された後にトークンを読み込むことは避けるべきである。これはしばしば機能するが、完全にサポートされているわけではなく、ある種のスキャナ・オプションでは予期せぬ結果をもたらす。


副次的な問題として、通常、bisonの組み込みの トレース機能 コード中にprintfをばらまくよりも。printfを追加したり削除したりするのは面倒ですし、bisonのトレースのように何が起こっているのかを完全に把握することはできません。