- Lexical Analysis With Flex, for Flex 2.6.2
 - Why doesn’t flex have non-greedy operators like perl does?
 
flexの正規表現
flexである文字列のセミコロン「;」開始から改行までの文字列をコメントとして読み飛ばしたかったので以下のような正規表現を書いた。
";"[^\n]*?\\n /* skip */ ;
想定通りに動けば、セミコロン〜最初の改行までが読み飛ばされるはずだが現実にはそうはならず最大マッチ(貪欲マッチ)的な動きをしている。
想定の読み飛ばし
Hello, World ; this is comment \n   this is another line \n
             ^^^^^^^^^^^^^^^^^^^^ <-- 読み飛ばし
実際の読み飛ばし
Hello, World ; this is comment \n   this is another line \n
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ???
そこで上記のflexの仕様に気づいた。上記のリンクの翻訳が以下
なぜflexにはperlのような貪欲でない演算子がないのですか?
DFAは、それ以上のマッチングが不可能であると判断するまで入力を消費するのではなく、最初に受け入れ状態に入るときに停止することで、貪欲でないマッチングを行うことができます(「ジャム」状態)。これは、実際には、最も長い左端の一致(flexが行う)よりも実装が簡単です。
しかし、それはまた、最も長い左端の一致よりもはるかに有用ではありません。一般に、貪欲でないマッチングを希望している場合、**それは通常、スキャナーに解析を行わせようとしていることを示しています。**それはまともな仕事をする力を欠いているので、それは一般的に間違ったアプローチです。個別のパーサーを導入するか、(排他的な)開始条件を使用してスキャナーを複数のスキャナーに分割することをお勧めします。
例えば‘BEGIN’という文字列を見つけたらstateを開始し、そのstateの中で‘END’を見つけたらマッチするような正規表現をもつことで、もしくは‘(.|\n)’のように単一の文字をチャンクに読み出すようにすることで…
このアプローチには、はるかに優れたエラー報告プロパティもあります。
ほう
That’s generally the wrong approach, since it lacks the power to do a decent job.
字句解析で構文解析をするなと言いたいらしい。うっせぇうっせぇうっせぇわ、あなたが思うより適当です。
じゃあどうする?
lexerの中で状態(state)を定義しとく
%s COMMENT
もしくは
%START COMMENT
上記は「%s(=start)」と「%x」でやることが異なる1、1行コメントについては10 Start Conditionsのお手本に従った。
上記状態(state)を遷移するようなプログラムを書く
- INITIAL : コメントの開始
 - -> COMMENT : コメント内部
 - -> INITIAL : 改行を見つけた
 
<INITIAL>";"        	 BEGIN COMMENT;
<COMMENT>.               /* skip */;
<COMMENT>\\n             BEGIN INITIAL;
上記のstateをもったコメント文解析は以下のページに解説がある
10 Start Conditions
stateなのかconditionなのかどっちだよ
- 
前者は包括的開始条件を宣言し、後者は排他的開始条件を宣言します。 ↩