8

私は現在、Flex+Bison を使用して小さなコンパイラを作成しようとしていますが、エラー処理をどうするか、特にすべてを適合させる方法について、ちょっと迷っています。議論の動機付けとして、私が文字列リテラルに使用している次のレクサー フラグメントを検討してください。

["]          { BEGIN(STRING_LITERAL); init_string_buffer(); }
<STRING_LITERAL>{
    \\\\    { add_char_to_buffer('\\'); }
    \\\"    { add_char_to_buffer('\"'); }
    \\.     { /*Invalid escape. How do I treat this error?*/ }
    ["]     { BEGIN(INITIAL); yylval = get_string_buffer(); return TK_STRING; }
}

無効なエスケープがある状況をどのように処理しますか? 現在、エラーメッセージを出力して呼び出しているだけですexitが、可能であれば、続行してファイルごとに複数のエラーを検出できるようにしたいと考えています。

私の質問:

  • エラー メッセージを出力するには、どの関数を使用しますか? 後で bison が予想するのと同じ yyerror ですか? lexer と parser 用に別々のファイルがある場合、yyerror の定義はどこに置くのですか?
  • アクションからどのトークン コードを返す必要がありますか? 「ファイルの終わり」の0?特別な TK_INVALID_STRING トークンですか?
  • 字句エラー (無効なリテラル、不要な句読点など) の後、パーサーが解析を続行できるようにするにはどうすればよいですか?
4

3 に答える 3

3

C++ 出力で Bison を使用している場合、別のオプションとして例外をスローします。

.   throw yy::parser::syntax_error("invalid character: " + std::string(yytext, yyleng);

Bison 3.6 以降 (C を含むすべてのターゲット言語) を使用している場合は、YYerror 特別な tokenを返すこともできます。これは rici の提案return TK_INVALID_STRINGに似ていますが、パーサーはこの不明について不平を言いTK_INVALID_STRINGます (したがって、2 つのエラー メッセージ: yyerror への呼び出しからのエラー メッセージと、未知の TK_INVALID_STRING に関する yyparse からのエラー メッセージ)。にはそのようなことはありYYerrorませんが、エラー回復を適切に入力します。

言い換えれば、Cで提案します(yyerror可変引数をサポートしている場合):

yyerror (yylloc, _("syntax error: invalid character: %c"), c);
return YYerror;

/usr/local/share/doc/bison/examplesこれは、Bison のディストリビューション (一般的なディストリビューション、またはSavannahGitHubで利用可能) の「bistromathic」の例の抜粋です。

于 2013-09-19T07:35:13.350 に答える
2

最も簡単なことは、最終的なルールを持つことです

. return yytext[0];

これは、すべての単一の特殊文字とすべての不正な文字もカバーしています。「:」、「;」などの特殊文字を文法で直接使用します。その後、不正な文字を取得すると、パーサーのエラー処理が呼び出され、回復の可能性がいくらか与えられます。それらをレクサーで処理する場合、できることはエラーを出力して無視することだけです。

また、lex ファイルのサイズも削減されます。

于 2013-09-16T23:49:52.613 に答える