開始条件を使用すると、単独の ^ 演算子よりも細かく前方コンテキストを取り扱うことができます。たとえば、行の終わりまたはファイルの始まりよりも複雑な前方コンテキストに従って、異なる規則を式に適用する場合があります。
その場合には、規則の適用条件となるコンテキスト内の変化を示すフラグを設定して、そのフラグをテストするコードを作成できます。あるいは、各規則の適用条件となるさまざまな「開始条件」を lex 用に定義することもできます。
以下の問題について考えます。
入力を出力にコピーする。ただし、文字 a で始まる行にあるワード magic をすべて first に変更する。
b で始まる行にある magic をすべて second に変更する。
c で始まる行にある magic をすべて third に変更する。フラグを使用してこの問題を扱った場合のコード例を以下に示します。
すでに説明したように、ECHO は printf ("%s", yytext) と同義の lex マクロです。
int flag %% ^a {flag = 'a'; ECHO;} ^b {flag = 'b'; ECHO;} ^c {flag = 'c'; ECHO;} ¥n {flag = 0; ECHO;} magic { switch (flag) { case 'a': printf("first"); break; case 'b': printf("second"); break; case 'c': printf("third"); break; default: ECHO; break; } }
開始条件を使用してこれと同じ問題を扱うには、以下のような行を lex の定義セクションに記述する必要があります。定義セクションには、任意の順序で条件を記述することができます。
%Start name1 name2 ...
ワード Start は、S または s と短縮できます。この条件を参照する場合は、規則の先頭で角括弧 <> を使用します。たとえば、スキャナの開始条件が name1 のときにだけ認識される規則は、以下のようになります。
<name1>式
開始条件に入るには、以下のアクションの文を実行します。
BEGIN name1;
上記の文は、開始条件を name1 に変更します。通常の状態に戻す場合は、以下の文を使用します。
BEGIN 0;
この文は、スキャナの初期条件をリセットします。
規則は、複数の開始条件によってアクティブにすることができます。たとえば、以下のような開始条件にすることもできます。
<name1,name2,name3>
前置演算子 <> で開始されていない規則は、すべてアクティブです。
開始条件を使用した場合には、前述の例は以下のように記述できます。
%Start AA BB CC %% ^a {ECHO; BEGIN AA;} ^b {ECHO; BEGIN BB;} ^c {ECHO; BEGIN CC;} ¥n {ECHO; BEGIN 0;} <AA>magic printf("first"); <BB>magic printf("second"); <CC>magic printf("third");