フレックスマニュアルでは、「トレーリングコンテキスト」パターン(r/s
)について言及しています。これは、が後に続く場合に限り、を意味しr
ますs
。ただし、次のコードはコンパイルされません(代わりに、「認識されないルール」のエラーが発生します。なぜですか?
LITERAL a/b
%%
{LITERAL} { }
フレックスマニュアルでは、「トレーリングコンテキスト」パターン(r/s
)について言及しています。これは、が後に続く場合に限り、を意味しr
ますs
。ただし、次のコードはコンパイルされません(代わりに、「認識されないルール」のエラーが発生します。なぜですか?
LITERAL a/b
%%
{LITERAL} { }
簡単な答えは、推奨されていない-l
オプションを使用しない限り、名前の定義に末尾のコンテキストを入れることはできないということです。それはフレックスのためです:
括弧内の末尾のコンテキストは許可されません。と
いくつかの状況を除いて、定義の展開を括弧で自動的に囲みます(以下を参照)。
フレックスが拡張を括弧で囲む理由は、そうでなければ奇妙なことが起こるからです。例えば:
prefix milli|centi
%%
{prefix}pede return BUG;
自動括弧がないと、パターンは次のように展開されます。
milli|centipede
これは一致しませんmillipede
。(さまざまな接尾辞演算子にも同様の問題があります。{prefix}?pede
たとえば、考えてみてください。)
Flexでは、このような式の多くはコンパイルが難しいため、括弧内の末尾のコンテキストは許可されていません。実際には、2つの正規表現の共通部分であるパターンを記述してしまう可能性があります。(たとえば、({base}/{a}){b}
一致の後に接頭辞またはの射影であるaが{base}
続く。)これらはまだ正規表現ですが、正規表現を有限状態マシンに変換するためのトムソンアルゴリズムでは考慮されていません。必要になったとしても、それを実装する試みはほとんど行われませんでした。{b}
{a}
残念ながら、括弧内の末尾のコンテキストを禁止すると、末尾のコンテキストを含むパターンの前後の冗長な括弧も禁止されます。これには、定義が冗長な括弧で拡張されるため、定義の拡張も含まれます。
元のAT&T lexは括弧を追加しませんでした。そのため、lexとの互換性を強制すると-l
、flexファイルをコンパイルできます。ただし、上記のように他の問題が発生する可能性があるため、お勧めしません。
また、ここでの「トレーリングコンテキスト」とは、フォームr/s
またはフォームの完全なパターンのいずれかを意味しますr$
。r/s
(明示的または暗黙的に)括弧内に入れるとエラーメッセージが生成されますが、括弧r$
内に入れると、行の終わりでパターンを強制的に一致させるのではなく$
、文字に一致させるだけです。$
この場合、エラーや警告は表示されません。
そのため、名前定義内で$
(または)を使用できなくなります。^
ただし、バージョン2.3.53より前のある時点で、定義が。で始まる^
か、で終わる場合に括弧を抑制するハックが挿入されました$
。また、私が完全には理解していない理由により、末尾のコンテキストの最後で展開が発生した場合は、括弧も抑制されます。これはバグである可能性があり、実際にそれに関連するバグレポートがあります。
info
次のページのFAQで、問題の答えを見つけましたflex
。「問題は、スキャナーの定義の一部で「/」の末尾のコンテキスト演算子が使用されており、()で囲まれていることです。Flexでは許可されていません。この演算子は()で囲む必要があります。これは、などの未定義の正規表現を許可するため"(a/b)+"
です。したがって、解決策は括弧を削除することです。AT&T lex互換性のオプションを使用してスキャナーを構築する必要があることに注意してください-l
。このオプションがない場合、 flexは定義を括弧で自動的に囲みます。」(バーンパクソンからの引用)。FAQの末尾のコンテキストも参照してください
可能な場合は、末尾のコンテキストの使用は避けた方がよいでしょう。上で説明したように、ネストされた式では許可されていません。あなたの例は-l
オプションで機能します。