5

私はコンパイラ構築のコースを受講しており、現在の課題は、実装している言語のレクサーを作成することです。レクサーが連結されたトークンを認識しなければならないという要件を満たす方法がわかりません。つまり、空白で区切られていないトークンです。例: 文字列は数字とキーワード39ifとして認識されるはずです。同時に、レクサーは無効な入力に遭遇したときにも実行する必要があります。39ifexit(1)

私が持っているコードの簡略版:

%{
#include <stdio.h>
%}

%option main warn debug

%%

if      |
then    |
else    printf("keyword: %s\n", yytext);

[[:digit:]]+    printf("number: %s\n", yytext);

[[:alpha:]][[:alnum:]]*     printf("identifier: %s\n", yytext);

[[:space:]]+    // skip whitespace
[[:^space:]]+   { printf("ERROR: %s\n", yytext); exit(1); }

%%

これ (または私の完全なバージョン) を実行して input を渡すと39if、エラー ルールが一致し、出力はERROR: 39if次のようになります。

number: 39
keyword: if

(つまり、入力として入力した場合と同じ39 ifです。)

マニュアルによると、エラー ルールが数字やキーワード ルールよりも長い可能な入力に一致し、flex がそれを優先することが原因であるという予感があります。とは言っても、この状況を解決する方法がわかりません。エラー以外のすべての入力を拒否する明示的な正規表現を作成することは実行不可能に思えます。また、字句解析エラーを処理するために「キャッチオール」ルールを作成する方法が他にわかりません。

更新:キャッチオールルールを作成することもできると思います. { exit(1); }が、「1行目で混乱しました」よりも優れたデバッグ出力を取得したいと思います。

4

1 に答える 1

4

フォールバックとして単一の「任意の」文字に一致する必要があることは、まったく正しいことです。解析が行のどこにあるかに関する情報を取得する「標準的な」方法は、--bison-bridgeオプションを使用することですが、特に を使用していない場合は、少し面倒な場合がありますbison。他にもたくさんの方法があります-たとえば、独自のi/o関数を指定する方法についてはマニュアルを参照してください-しかし、最も簡単なIMHOは開始条件を使用することです:

%x LEXING_ERROR
%%
// all your rules; the following *must* be at the end
.                 { BEGIN(LEXING_ERROR); yyless(1); }
<LEXING_ERROR>.+  { fprintf(stderr,
                            "Invalid character '%c' found at line %d,"
                            " just before '%s'\n",
                            *yytext, yylineno, yytext+1);
                    exit(1);
                  }

注: ルールで空白を無視していることを確認してください。このパターン.+は、少なくとも 1 つの改行以外の文字、つまり現在の行の末尾までを除く任意の数字に一致します (これにより、flex はそこまで読み取らなければならなくなりますが、これは問題にはなりません)。yyless(n)読み取りポインターを文字単位でバックアップするnため、ルールが一致した後、.その文字を再スキャンして (うまくいけば) ある程度妥当なエラー メッセージを生成します。(入力がマルチバイトであったり、変な制御文字が含まれていたりすると、実際には合理的ではないので、より慎重なコードを書くことができます。あなた次第です。また、エラーが行末にある場合も合理的ではない可能性があります。より多くのコンテキストを取得する、より慎重な正規表現を作成したい場合もあり、読み取る前方文字数を制限することもできます.ここには多くのオプションがあります.)

との詳細については、フレックスマニュアルで開始条件を調べてください。%xBEGIN

于 2013-04-16T03:22:06.683 に答える