次: Activating States, 前: Start States, 上: Start States
スタート状態は、
あるルールがアクティブになるのはいつであるかを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ではサポートしていません。