あなたがそうcheck_types_match
が呼ばれた瞬間に、yylineno
は、あなたがエラーを生成したい場合2.
行目にポイントする必要があり、2行目にあるセミコロンを、到達するまで、文はそのように認識されていませんメッセージに異なる行番号がある場合は、印刷する行を決定する必要があります。エラーはトークンint
とトークンtrue
の間にあるため、少なくとも2つの可能性があります。この場合、それらの両方は、1行目にありますが、どのようなプログラムテキストがあった場合:
int x =
true;
これらのトークンのいずれかがエラーの原因としてフラグ付けされるべきであると合理的なようなので問題は把握に減少しトークンがどの行に現れたかを調べる。そのトークンは、減少が起こるまでの古代の歴史なので、これを行う唯一の方法は、依然としてパーサースタックに残っているすべてのトークンである、まだ必要なすべてのトークンの場所を覚えておくことです。
幸いにも、bison
には簡単な方法があります。必要に応じて、パーザスタックと並行して位置スタックを維持し、次に@1
を参照するだけでトークン1のロケーションオブジェクトにアクセスできます。さらに簡単に、あなたのバイソンファイルのどこかにあるロケーションオブジェクトへの参照を使うだけで、バイソンにこの情報を維持するように説得するのに十分です。だから、あなたがあなたの行動を変えることができる:(。あなたはExp
にエラーを帰することがより適切と思われる場合、または@4
)
Statement : Type ID ASSIGN Exp {check_types_match($1.type, $4.type, @1)} SC
もちろん
を、それは非常に単純なことはありません。 bison
には、すべての着信トークンの場所を知るために、また、新しく作成された非終端記号の場所を作成する方法を理解する必要があります(上記の例ではExp
など)。)
ロケーションオブジェクトは、(非終端記号の場合のように)トークンのシーケンスの場所を参照することがあります。これは、複数の行にまたがって表示されることがあります。終点。さらに、正確なエラーメッセージを生成するために、行番号と列オフセットの両方を使用することが一般的です。このため、デフォルトの場所のオブジェクトは、次のタイプがあります。
typedef struct YYLTYPE {
int first_line;
int first_column;
int last_line;
int last_column;
} YYLTYPE;
、デフォルトでは、あなたが
N
がある
@$.first_line = @1.first_line;
@$.first_column = @1.first_column;
@$.last_line = @N.last_line;
@$.last_column = @N.last_column;
のようなものを書いていたかのように、非端末の位置オブジェクトが計算され、右側の最後の文法記号のインデックス。 (bison
は "文法記号の数"の表記法を持たず、$N
構造の変数も許可していないので、実際には書き込むことはできません)。
あなたが望むものをかなりよく、バイソンの側からは問題はありません。しかし、あなたはまた、最初にflex
から情報を取得する必要があります。
グローバル変数に依存しflex
とbison
間の単純なインタフェースを使用する場合は、現在のトークンに対応する位置のオブジェクトの名前(yylval
に類似)yylloc
あります。 flex
はyylineno
を自動的に作成できますが、自動的にはyylloc
に格納されませんし、列番号を追跡するためのメカニズムも組み込まれていません。返されたトークンが2行以上に渡っている場合も処理できます文字列定数など)。
インフラストラクチャをすべて正しく設定することは、回線番号情報のみを要求するため、この質問の対象外です。あなただけの行番号を追跡する必要があり、複数行のトークンを持っていない、すべてのフレックスルールに以下を追加するのに十分である場合:あなたは、あなたが複数行のトークンを持っている場合は
yylloc.first_line = yylloc.last_line = yylineno;
すべてのトークンのアクション、何も(コメントと空白文字)を行わないものも含めに追加しなければならないであろう
yylloc.first_line = yylloc.last_line;
yylloc.last_line = yylineno;
:代わりに以下を使用することができます。幸運なことに、flex
には、すべてのアクションの冒頭に追加されるマクロがあります。したがって、フレックスファイル全体を複雑にする必要はありません。あなたはまた、yylloc.last_line
が1
に初期化されていることを確認する必要があります(あなたが列番号を追跡してしまう場合は、あまりにも、あなたはそれを修正する必要があります)
#define YY_USER_ACTION do { \
yylloc.first_line = yylloc.last_line; \
yylloc.last_line = yylineno; \
} while(0)
;:それはのような何かを追加するのに十分ですそれ以外の場合、最初のトークンは0行目から開始します。詳細については
、取扱説明書をお読みください:
あなたが再入/純粋スキャナとパーサを使用している場合は、マニュアルを参照してくださいする必要があります場所オブジェクトがグローバルなしでどのように渡されるかについて。 %bison-locations
宣言は、必ずしもあなたが望むものではないことに注意してください(リエントラント/純粋なスキャナとパーサを使用していない場合は、あなたが望むものではありません)。
詳細な返信をありがとうございます!それは私を助けました:)乾杯! – Loay