質問の例はどちらも文脈自由ではないため、厳密に言えば、文脈自由文法で解析することはできません。しかし実際には、どちらも非常に簡単に解析できます。
Python アルゴリズムについては、Pythonリファレンス マニュアルで詳しく説明されています(ただし、文脈を理解して読む必要があります)。そこで説明されているのは、行頭の空白を体系的にトークンに置き換える前処理ステップINDENT
ですDEDENT
。
明確にするために:これは実際には前処理ステップではなく、暗黙的および明示的な行結合の後に発生することを観察することが重要です。(リファレンス マニュアルには、これらの手順を説明する前のセクションがあります。) 特に、行は括弧、中括弧、および大括弧内で暗黙的に結合されるため、プロセスは解析と絡み合っています。
実際には、行結合アルゴリズムとインデント アルゴリズムの両方をプログラムで実行できます。通常、これらは、括弧のスタックとインデント レベルの両方を維持するカスタム スキャナー (トークナイザー) 内で行われます。その後、トークン ストリームは通常のコンテキスト フリー アルゴリズムで解析できますが、トークナイザーは(正規表現を使用する場合もありますが) コンテキスト依存のロジック (スペースのカウントなど) を必要とします。【注1】
同様に、明示的なサイズを含む形式 (PNG ファイル、Google protobuf、および HTTP チャンク エンコーディングを含むほとんどのシリアル化形式など) はコンテキストフリーではありませんが、トークナイザーは単に長さを読み取ってから読み取る必要があるため、明らかに簡単にトークン化できます。その多くのバイト。
さまざまな文脈依存の形式主義があり、これらには間違いなく用途がありますが、実際の解析では、最も一般的な戦略は、チューリングと同等の形式主義 (プログラミング言語などflex
)を使用することです。トークナイザーとパーサーの文脈自由形式。【注2】
ノート:
Python のインデントが文脈自由でないことはすぐにはわからないかもしれません。文脈自由文法はいくつかのカテゴリーの一致を受け入れることができるからです。たとえば、(すべての偶数回文の言語) は のように文脈自由です。{ωω-1 | ω∈Σ*}
{anbn}
ただし、これらの例を拡張することはできません。これは、文脈に依存しない言語で可能な唯一のカウントの合意がブラケットであるためです。したがって、回文はコンテキストフリーですが (単一のスタックでチェックを実装できます)、明らかに非常に似ているものはそうではなく、どちらもそうではありません。{ωω | ω∈Σ*}
{anbncn}
そのような形式主義の 1 つは、「正規」表現での後方参照です。これは、一部の PEG 実装で使用できる可能性があります。後方参照は、さまざまな文脈依存言語の表現を許可しますが、すべての文脈自由言語の表現を許可するわけではありません。残念ながら、文字列が後方参照のある正規表現と一致するかどうかを判断する問題は NP 完全であるため、後方参照のある正規表現は実際にはうまくいきません。この質問は、姉妹 SE サイトで興味深いものになるかもしれません。(また、そのサイトhttp://cs.stackexchange.comで質問できるように質問を再構成することもできます。)