Flex と Bison を同時に使う

Flex と Bison を併用するとき、Flex から生成される関数 (yylex) は、トークン (終端記号) の情報を戻り値とし、それを Bison が利用します。 トークンが 1 文字の場合は、通常、戻り値は文字リテラルそのものです。トークンが 2 文字以上の場合は、Bison で %token により宣言されたマクロ を使用します。

ここでは 2文字以上の演算子の例として、「*+」という演算子を x *+ yx * 256 + y を表し、「+」「-」と同じ優先順位を持つ、 左結合の演算子として導入します。仮に FOO 演算子と呼ぶことにします.

Flex のソースファイル(mylexer.l)には、C 定義部に次のような #include 文を入れておきます。インクルードされるファイル (myparser.h) は Bison が生成するファイルで、bison を実行するときに与えるオプションで指定した C ソースファイルの名前の .c を .h に変えたものです。ここに %token に より宣言されたマクロの定義が書かれています。

ファイル mylexer.l

動作の中に return 文を入れておくと、 その式の値が Flex の生成する yylex 関数の戻り値になります。 yylex 関数は呼び出されるたびに、次のトークンを返します。

トークンは、1文字からなるトークンの場合は通常、 文字コードそのまま、2文字以上からなるトークンの場合は %token で宣言されたマクロです。

トークンの “種類”(NUMBER など)を yylex 関数の値として返し、値(“属性”)を yylval という大域変数に代入していることに注意します。 これが通常の yylex 関数の書き方です。

この例では [0-9]+(\.[0-9]+)?(E[+\-]?[0-9]+)? という正規表現にマッチする文字列 があれば、NUMBER というトークンを yylex の戻り値として返します。 そのときの属性値は yylval という大域変数に代入されています。

一般に正規表現にマッチした文字は、 yytext という配列に保持されています。また yyleng という変数にマッチした文字の数が保持されています。 だからマッチした文字は一般に yytext[0]yytext[yyleng - 1] ということになります。(通常の C 言語の文字列とは異なり、 最後 (yytext[yyleng]) にナル文字 '\0' は入っていないので注意が必要です。)

この例では、+, -, *, /, (, ), =, \n のいずれかの文字が現れたときは、その文字コードを返します。

例えば、入力が “(12*+34)*56\n” という文字列の場合、 yylex() の戻り値とそのときの yylval の値は次のようになります。

1回目2回目3回目4回目5回目6回目7回目8回目
yylex()'('NUMBERFOO NUMBER')''*'NUMBER'\n'
yylval 12.0  34.0  56.0 

Bison のソースファイル (myparser.y)の方は、 単独で使う場合とあまり変わりませんが、 yylex 関数は Flex の方で用意するので C 宣言部でプロトタイプ宣言だけしておきます。 (この例では Bison のソースファイルに yylex の定義を書いてはいけません。)

ファイル myparser.y

生成規則の中で、トークン(終端記号)として文字リテラル('+', '-' など)と %token で宣言したマクロ(FOO) を用いることができます。

C ソースファイルはそれぞれ次のコマンドで生成します。

bison -omyparser.c -d myparser.y
flex -omylexer.c -I mylexer.l

必ず -d オプションをつけて Bison を実行します。 このとき -o オプションで、 C ファイル名 (この場合 myparser.c) を指定しておきます。 すると、拡張子を除いて同じ名前のヘッダーファイル (この場合 myparser.h) も生成されます。 (-o オプションをつけないと、 myparser.tab.cmyparser.tab.h という名前のファイルが生成されます。)

あとはこの 2 つの C ソースファイルをまとめてコンパイルします。

Microsoft Visual Studio の場合は、

cl /Fecalc mylexer.c myparser.c

/Fe は実行ファイルの名前を指定するオプションです。

これで calc.exe という名前の実行可能ファイルが生成されます。 次のコマンドで実行できます.

calc

PowerShell の場合は、次のコマンドになる。

.\calc
コンパイラのホームページ
Koji Kagawa