次: , 前: Start States, 上: Start States


3.8.1 スタート状態の説明

スタート状態は、 あるルールがアクティブになるのはいつであるかをFlexに通知するブール値のようなものです。 スタート状態は、 定義セクションにおいて (排他的スタート状態の場合)%x 、 または(包含的スタート状態の場合)%sを使って宣言されます。

     %x start_state_name
     %s start_state_name

start_state_nameは一意な名前でなければならない点に注意してください。 つまり、 他のスタート状態や定義が同じ名前を持ってはならないということです。 スタート状態は、 1つの状態の名前、 または、 カンマで区切られた複数の状態の名前をかぎ括弧< >で囲むことによって、 ルール・セクションで参照されます。 スタート状態の参照はルールの先頭になければならず、 1つのルール中には1対のかぎ括弧< >のみ許されます。 このことは、

     %x state1
     %s state2
     %x state3 state4
     %%
     <state1>"foo"
     <state2,state3,state4>"bar"

が正当であり、

     integer [-+]?[0-9]*
     %x integer
     %s state1,state2,state3
     %%
     <integer>"foo"
     "bar"<state1>
     <state1>"bar"<state2,state3>

はすべて不当であることを意味しています。 integerについては同じ名前を持つ定義が存在し、 それ以外のものについてはスタート状態の参照の位置が正しくないか、 複数の参照が存在するからです。

これまでのところでは、 Flexが異なる2種類のスタート状態をサポートしている事実から目をそらしてきました。 2つのスタート状態とは、 包含的スタート状態%s)と排他的スタート状態%x)のことです。 これら2つの相違点は、 排他的スタート状態が活性化された場合は、 その状態に属するルールだけが活性化されるのに対して、 包含的スタート状態の場合は、 その状態に属するルールとスタート状態への参照を持たないルールの両方が活性化されるという点にあります。 この違いを示す例を挙げると、 以下のようになります。

     %s state1
     %%
     <state1>"one" printf("two");
     "three"       printf("four");

この場合、 state1状態が活性化されている場合は`one'を`two'に置き換え、 state1状態が活性化されているか否かにかかわらず`three'を`four'に置き換えます。 デフォルトのルールにより、 その他のテキストはstdoutに出力されます。 これに対して、

     %x state1
     %%
     <state1>"one" printf("two");
     "three"       printf("four");

は、 state1状態が活性化されている時は`one'を`two'に置き換え、 state1状態が活性化されていない時のみ`three'を`four'に置き換えます。 デフォルトのルールにより、 その他のテキストはstdoutに出力されます。

このことは、 排他的スタート状態が使われる場合には、 マッチしないテキストがstdoutに出力されてはならないのであれば、 すべての可能な入力にマッチするルールを、 個々の排他的スタート状態が持たなければならないことを意味しています。 包含的スタート状態の場合は、 あらゆる状態において有効な、 スタート状態への参照を持たないルールを1つ持つ必要があります。

注: 排他的スタート状態はPOSIXの一部であるにもかかわらず、 Lexではサポートしていません。