(構文解析系(パーサ)から利用するための関数を生成する本来の使用法ですが、 この例では標準出力に結果を出力しています。)
%{
/* 次の 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)/* 白に戻す */; }
{number} { ansi(31)/* 赤 */; ECHO; ansi(0); }
{ident} { ansi(32)/* 緑 */; ECHO; ansi(0); }
"." { ECHO; exit(1); }
. { ECHO; }
/* 上の動作記述では値を返していないが、動作記述の中で
return文を書くと、yylexという関数の戻り値になる。(これが本来の使い方)*/
%%
/* その他の関数の定義などをここに書く。*/
int main () {
return yylex();
}
/* この例では lexer単独で動作させるので main関数を定義し、
その中で yylex関数を呼んでいる。*/
\ " . [ ] * + ? { } | ( ) - < > ^ % /
| 式 | 意味 | 例 |
| c | 上記の特殊文字以外の文字はその文字そのもの | a |
| \c | 文字 c そのもの | \* |
| "s" | 文字列 s そのもの | "**" |
| . | 改行以外の任意の文字 | a.*b |
| [s] | s 中の任意の文字 | [abc] |
| [c1-c2] | c1-c2の範囲の任意の文字 | [a-zA-Z] |
| [^s] | s に含まれない任意の文字 | [^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} |
このようなファイル(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)すると、実行可能ファイルができます。 (-eは、 実行可能ファイルの名前を指定するためのオプションです。 後者のように -ebarというように使うと bar.exeという実行可能ファイルができます。)