Flexは正規表現を記述したソースファイルから、 字句解析プログラム(スキャナ)を自動生成するプログラムです。 Flexのソースファイル(通常 .lか .lexという拡張子をつける)は、次のようなものです。
(構文解析系(パーサ)から利用するための関数を生成する本来の使用法ですが、 この例では標準出力に結果を出力しています。)
%{ /* 次の 2行は決まり文句 */ #define YY_SKIP_YYWRAP int yywrap() { return 1; } %} /* この例ではここには何も書かない */ %% /* ここに動作記述を書く。*/ /* ECHOはマッチした文字列をそのまま出力するマクロ */ [hH]ello { printf("Bon Jour"); } . { ECHO; } /* その他の文字はそのまま出力 */ %% /* その他の関数の定義などをここに書く。*/ int main () { return yylex(); }
%{ /* 動作記述のなかで用いる関数の定義や宣言をここに書く。 */ void ansi(int d) { /* 出力する文字の色を変える */ printf("\033[%dm", d); } /* 次の 2行は決まり文句 */ #define YY_SKIP_YYWRAP int yywrap() { return 1; } %} /* ここは正規表現の定義(良く使う正規表現に名前をつける) */ /* 行頭に空白を入れないようにしてください。 */ delim [ \t] ws {delim}+ letter [A-Za-z] digit [0-9] ident {letter}({letter}|{digit})* number {digit}+(\.{digit}+)?(E[+\-]?{digit}+)? %% /* ここに動作記述を書く。*/ /* ECHOはマッチした文字列をそのまま出力するマクロ */ {ws} { ansi(34)/* 青 */; putchar('_'); ansi(0); ansi(5); ansi(7); /* 黒に戻す */; } {number} { ansi(31)/* 赤 */; ECHO; ansi(0); ansi(5); ansi(7); } {ident} { ansi(32)/* 緑 */; ECHO; ansi(0); ansi(5); ansi(7); } "." { ECHO; exit(1); } . { ECHO; } /* 上の動作記述では値を返していないが、動作記述の中で return文を書くと、yylexという関数の戻り値になる。(これが本来の使い方)*/ %% /* その他の関数の定義などをここに書く。*/ int main () { return yylex(); } /* この例では lexer単独で動作させるので main関数を定義し、 その中で yylex関数を呼んでいる。*/
bison(構文解析部生成系)で生成した構文解析部といっしょに動作させる例は、 ここにあります。
\ " . [ ] * + ? { } | ( ) - < > ^ % /
式 | 意味 | 例 |
c | 上記の特殊文字以外の文字はその文字そのもの | a |
\c | 文字 c そのもの | \* |
"str" | 文字列 str そのもの | "**" |
. | 改行以外の任意の文字 | a.*b |
[str] | str 中の任意の文字 | [abc] |
[c1-c2] | c1-c2の範囲の任意の文字 | [a-zA-Z] |
[^str] | str に含まれない任意の文字 | [^abc] |
r* | rの 0回以上の繰り返し | a* |
r+ | rの 1回以上の繰り返し | a+ |
r? | 0回か 1回の r | a? |
r1r2 | r1の後に r2 | ab |
r1|r2 | r1または r2 | a|b |
{name} | nameという正規表現の定義の展開 | {ident} |
この他、(と)がグループ化のために用いられます。 例えば、 (ab|cd)* abまたはcdの 0回以上の繰り返しを表わします。
このようなファイル(lexer.lとする)から Cソースファイルを生成するにはflex -I lexer.lというコマンドを実行します。 これで lexyy.cという名前の Cソースファイルができます。また、
flex -ofoo.c -I lexer.lというように-oの後にファイル名を書くと、 その名前(この場合 foo.c)の Cソースファイルができます。
この例の場合は、この Cソースファイル(foo.c)を bcc32でコンパイル(
bcc32 foo.cまたは
bcc32 -ebar foo.c)すると、実行可能ファイルができます。 (いくつか、Warning(警告)がでますが、気にしない。) (-eは、 実行可能ファイルの名前を指定するためのオプションです。 後者のように -ebarというように使うと bar.exeという実行可能ファイルができます。)
Ctrl-cまたは Ctrl-zで終了できます。
ansi関数は lexファイルの一番最初で定義しています。 文字の色を変えるための関数です。ansi(0);は MS-DOSプロンプトのデフォルトの「黒地に白」に表示を戻します。 「白地に黒」の DOSプロンプトを使っている人は、この部分を ansi(0); ansi(5); ansi(7);に変えて下さい。
ただしこの ansi関数は Windows NT/2000ではうまく動かないので注意して下さい。
exitはプログラムを終了させるための、関数です。 例2では 「.」を入力するとプログラムを終了するようになっています。
\.はピリオドそのものを表わします。 「.」(ピリオド)は flexの規則中では特別な意味を持つので、 ピリオドそのものを表わすには\でエスケープしてやります。 同様に「-」もエスケープが必要で、 [+\-]は 「+または -」の意味になります。