プログラミングユーティリティ

定義

lex の定義セクションには、複数のクラスの項目を入れることができます。最も重要なのは、外部定義、#include などの前処理文、および略語です。正式な lex ソースではこのセクションは省略可能ですが、ほとんどの場合において、これらの項目のいくつかは必要になります。前処理文と C ソースコードは、%{%} の行の間に記述します。

この区切り記号の間の行 (空白で始まる行も含む) は、すべて yylex() の定義の直前に lex.yy.c にコピーされます。(区切り記号で囲まれていない定義セクション内の行は、同じ場所にコピーされ、その先頭には空白が入れられます。)

定義セクションは通常、規則セクション内のアクションまたは外部にリンクされたルーチンによってアクセスされるオブジェクトの C 定義を配置する場所です。

たとえば、字句アナライザを呼び出すパーサーを生成する yacc と共に lex を使用するときには、ファイル y.tab.h をインクルードします。このファイル中で、#define を使用してトークン名を定義することができます。

%{ 
#include "y.tab.h"
extern int tokval; 
int lineno;
%} 

#include 文と宣言の終わりを示す %} の後には、規則セクション内の正規表現の略語を置いてください。行の左側には略語、行の右側にはその定義または変換後の正規表現を記述して、両者を 1 つ以上の空白文字で区切ります。

規則の中で略語を使用するときには、その略語を中括弧で必ず囲んでください。略語を使用することにより、仕様を繰り返し記述する手間が省け、見た目にも読みやすくなります。

たとえば、lex の高度な機能」で取り上げた lex ソースについて再検討します。定義を使用することによって、数字、文字、空白文字が後で見た時にわかりやすくなります。

これは、同じ仕様が何度も現われる場合に特に効果的です。

D                 [0-9]
L                 [a-zA-Z]
B                 [ ¥t]+
%%
-{D}+             printf("negative integer");
¥+?{D}+           printf("positive integer");
-0.{D}+           printf("negative fraction"); 
G{L}*             printf("may have a G word
                          here"); 
rail{B}road       printf("railroad is one word");
crook             printf("criminal"); 
 ...
 ...