ある単語が現れた時に、 それを別の単語に置き換える必要の生じることがよくあります。 例えば、 ある名前が現れるたびに、 それをある1つの環境変数の値で置き換えてくれるユーティリティを作りたいとしましょう。 そして、 以下のようなことができるように、 そのユーティリティがフィルタとして動作するようにさせたいとします。
nick% myname < infile | more
nick% myname < infile > outfile
以下に、 こうしたことを実現する方法を示すFlexファイルの簡単な例を挙げます。
/*
* myname.lex : トークンの置き換えを行うFlexプログラム
* のサンプル
*/
%%
%NAME { printf("%s",getenv("LOGNAME")); }
%HOST { printf("%s",getenv("HOST")); }
%HOSTTYPE { printf("%s",getenv("HOSTTYPE"));}
%HOME { printf("%s",getenv("HOME")); }
%%
このソース・ファイルはexamplesサブディレクトリにあり、 その名前はmyname.lexです。 これをビルドするには、 examplesサブディレクトリに移動して`make myname'を実行するか、 以下を実行します。
flex myname.lex
cc lex.yy.c -o myname -lfl
ここで`-lfl'は、
リンカに対してFlexライブラリをリンクするよう通知します。
現在のところ、
Flexライブラリにはデフォルトのmain()関数だけが含まれています。
将来のバージョンのFlexでは、
他の関数も含まれるようになるでしょう。
Flexライブラリがインストールされていない場合は、
この部分は`-ll'でなければなりません。
いずれの場合でも、 最終的にはmynameという名前の実行ファイルが生成されるはずです。 これは、 以下のような変換処理を実行するフィルタです。
%NAME%HOST%HOSTTYPE%HOMEしたがって、 以下のような内容を持つファイルmyname.txtを作成して、
Hello, my name is %NAME. Actually
"%NAME" isn't my real name, it is the
alias I use when I'm on %HOST, which
is the %HOSTTYPE I use. My HOME
directory is %HOME.
以下を実行すると、
myname < myname.txt
以下のテキストに似たものがstdoutへ書き込まれます。
Hello, my name is foobar. Actually
"foobar" isn't my real name, it is the
alias I use when I'm on baz, which
is the cray I use. My HOME
directory is /home/foo/foobar.
このプログラムがうまく動作するのは、
yyinとyyoutがデフォルトではstdin、stdoutにそれぞれ割り当てられ、
かつ、
デフォルトのアクションがyyinの内容をyyoutにコピーするからです。
また、
個々のルールに対応する唯一のアクションが単一行で記述されているため、
`{ }'は必要ではないことに注意してください。
このような場合には、
アクションを`{ }'で囲むか否かは、
個人的な好みの問題になります。
これが、 引用符で囲まれた部分にあるものも含めて、 指定された名前が現れるところすべてにマッチしたことに気がつきましたか? Flexにおいては、 引用符で囲まれた部分にあるものにマッチさせたくない場合には、 それに対応するルールを作成することにより、 そうしないよう明示的にFlexに通知しなければなりません。 以下に例を示します。
/*
* myname2.lex : トークンの置き換えを行うFlexプログラムの例
*/
%{
#include <stdio.h>
%}
%x STRING
%%
\" ECHO; BEGIN(STRING);
<STRING>[^\"\n]* ECHO;
<STRING>\" ECHO; BEGIN(INITIAL);
%NAME { printf("%s",getenv("LOGNAME")); }
%HOST { printf("%s",getenv("HOST")); }
%HOSTTYPE { printf("%s",getenv("HOSTTYPE"));}
%HOME { printf("%s",getenv("HOME")); }
この例では、 排他的スタート状態を使って、 文字列中のテキストが変更されることのないようにしています。 この例もexamplesサブディレクトリにあるもので、 その名前はmyname2.lexです。