web-dev-qa-db-ja.com

「文脈自由文法」という用語の「文脈自由」とはどういう意味ですか?

文脈自由文法(CFG)とは何かを説明しようとする資料の量を考えると、そのような文法が「文脈-自由"。そして、私の考えでは、そうすることに成功した人はいません。

私の質問は、なぜ文脈自由文法が文脈自由と呼ばれるのですか? 「コンテキスト」とは何ですか?コンテキストは、現在分析されている構成を取り巻く他の言語構成である可能性があると直感しましたが、そうではないようです。誰かが正確な説明を提供できますか?

56
rick

これは、そのすべての プロダクションルール が左側に単一の 非ターミナル を持っていることを意味します。

たとえば、一致する括弧( "()"、 "()()"、 "(())()"、...)の文字列を認識する this grammar はコンテキストフリーです。

S → SS
S → (S)
S → ()

すべてのルールの左側は、単一の非終端記号で構成されます(この場合は常にSですが、それ以外の場合もあります)。

ここで this other grammar を検討してください。これは{a ^ n b ^ n c ^ n:n> = 1}の形式の文字列を認識します(例: "abc"、 "aabbcc"、 "aaabbbccc"):

S  → abc
S  → aSBc
cB → WB
WB → WX
WX → BX
BX → Bc
bB → bb

非終端記号Bの前に終端記号/リテラル​​文字cがある場合は、その用語をWBに書き換えますが、先頭にbがある場合は、代わりにbbに展開します。これはおそらく、文脈依存文法の文脈依存性が示唆していることです。

コンテキストフリー言語は プッシュダウンオートマトン と認識できます。有限状態マシンは補助記憶装置を使用しません。つまり、その決定は現在の状態と入力のみに基づいていますが、プッシュダウンオートマトンも自由にスタックを持ち、スタックの一番上を覗いて決定を下すことができます。

実際の動作を確認するには、左括弧を右に移動して左括弧をスタックにプッシュし、右括弧が出現するたびにポップすることで、ネストされた括弧を解析できます。空のスタックからポップしようとすることがなく、文字列の最後でスタックが空の場合、文字列は有効です。

状況依存言語の場合、a PDAでは不十分です。 linear-bounded automaton が必要です。これは、テープが付いていないTuring Machineのようなものです無制限(ただし、利用可能なテープの量は入力に比例します)。これはコンピューターをかなりよく説明していることに注意してください-それらはチューリングマシンと考えるのが好きですが、現実の世界ではこれ以上勝手に取得することはできませんRAMプログラムの途中です。LBAがPDAよりも強力であることが明らかでない場合、LBAはテープの一部をスタックとして使用してPDAをエミュレートできますが、他の方法でテープを使用することもできます。

(あなたが有限状態機械が何を認識できるか疑問に思っているなら、答えは正規表現です。しかし、プログラム言語で見られるキャプチャグループと先読み/先読みを伴うステロイドの正規表現ではありません;あなたが構築できるものを意味します[abc]|*+?などの演算子を使用します。abbbzが正規表現ab*zと一致するのは、文字列と正規表現の現在の位置を維持するだけで、スタックは不要です。)

60
Doval

他の答えは、たとえ正確で正しいとしても、かなり長くなります。これは短いバージョンです。

文字列(端末と非端末)があり、その文字列の非端末を置き換える場合、コンテキストフリーの文法を使用すると、非端末を囲む文字に関係なくそれを実行できます。

次のルールを考慮してください(小文字は端末、大文字は非端末です)。

A -> a
AB -> a

最初のルールでは、Aその周りに何が表示されているかに関係なく(コンテキスト)を置き換えることができます。 2番目のルールでは、Aが後に続かない限り、Bを置き換えることはできません。その場合、両方の非端末が置き換えられますが、重要な点は、Aを囲む非端末が重要であることです。 BAaに、またはBaに置き換えることはできません。Aの後にBが続くだけです。非端末のcontextの順序が重要です。これは、2番目のルールでは非終端記号のコンテキストが重要であり、最初のルールはコンテキストフリーであるのに対し、状況依存にすることを意味します。

20
user22815

区別と用語をよりよく理解するには、文脈自由言語とは対照的に、nbn のような状況依存のnbncn。 (表記:a、b、cはここではリテラルであり、指数nはリテラルn回、n> 0、たとえば。)たとえば、aabbcまたはaabbbccは後者の言語ではありませんが、aabbccはそうです。

文脈自由言語のアクセプターanbn 周囲の状況に関係なく(つまり、abが出現するコンテキストに関係なく)abのペアを縮小でき、正しく機能し、言語の文字列のみを受け入れ、その他は拒否します。つまり、文法はS -> aSb | abプロダクションの左側に端子がないことに注意してください。 (2つのプロダクションルールがありますが、簡潔に記述しているだけです。)アクセプターは基本的に、コンテキストに依存しないローカルな決定を行うことができます。

対照的に、状況依存型言語では、そのようなことはできません。nbncn後者のために、あなたは何らかの形であなたがいた文脈、すなわち、それらをbcの収縮と一致させるためにabの収縮をいくつ行うかを覚えておかなければならないからです。後者の言語の文法は

S -> abc | aBSc
Ba -> aB
Bb -> bb

最後の2つのルールでは、左側にターミナルと非ターミナルの両方があることに注意してください。左側の端子は、非端子を展開できるコンテキストです。


「契約」対「拡張」の用語などに関するブートノート:正式な文法は[正式には、ハハ]生成的ですが、パーサーで実際に実装される方法は実際には還元主義です。つまり、基本的にすべてを非ターミナルに連絡しますルールを「逆に」適用するため、上記の最初の文法でもプログラムでは実用的ではありません(適用するルールを決定できないため、有名なShift-Reduce競合が発生します)が、上記の2つ文法は、文脈自由と文脈依存の違いを説明するのに十分です。文脈自由文法のあいまいさの問題はかなり複雑であり、実際にはこの質問のトピックではないので、ここではこれ以上は触れません。特に、ウィキペディアには それについてのまともな記事がある 。対照的に、文脈自由の記事、特に文脈依存言語の記事は!@#$ @!#$で、特にトピックに不慣れな場合は...私のTODOリストのほうが多いと思います。

7
Fizz

上記の答えはそれが何であるかについてかなり良い定義を与えます。説明を20ではなく23にするために、自分の言葉で説明できるかどうかを見てみましょう。文法の目的は、特定の文が特定の言語の文であるかどうかを理解することです。ただし、文法と構文解析を実際に使用するのは、文の意味を理解することです。これは、学校で英語のクラスに戻った場合と行っていない場合がある古い文章の図のようなものです。文は主語部分と述語部分で構成され、主語部分には名詞と形容詞があり、述語部分には動詞と目的語名詞があり、さらに形容詞がいくつかあります。

英語の文法があった場合(そして、コンピューターサイエンスの意味ではそうではないと私は考えていません)、プロダクションと呼ばれる次の形式のルールがあります。

Sentence -> SubjectPart PredicatePart
SubjectPart -> Adjective Noun

等...

次に、プログラムを記述して任意の文を渡します。プログラムは文法を使用して、各Wordが文のどの部分であり、それらが互いにどのような関係にあるかを理解できます。

すべてのプロダクションで左側にあるものが1つしかない場合は、文の右側が表示されるたびに、左側で代用することが許可されます。たとえば、形容詞の名詞を見たときはいつでも、その語句以外のことには何も注意を払わずに「That's a SubjectPart」と言うことができます。

ただし、英語(上記で説明した英語の簡単な説明でさえ)は状況依存です。 「形容詞名詞」は常にSubjectPartであるとは限らず、PredicatePartのNounPhraseの場合もあります。状況によります。疑似英語の文法を少し拡張してみましょう。

Sentence -> SubjectPart PredicatePart
SubjectPart -> Adjective Noun
PredicatePart -> VerbPhrase ObjectNounPhrase
VerbPhrase ObjectNounPhrase -> VerbPhrase Adjective Noun

「形容詞名詞」は、VerbPhraseの直後に来る場合にのみObjectNounPhraseにすることができます。

基本的に、プロダクションがあり、いつでもそれを適用できる場合は、それを囲むものに関係なく、コンテキストフリーです。

文法が文脈自由であるかどうかはいつでも簡単にわかります。矢印の左側に複数の記号があるかどうかを確認してください。

どの言語も複数の文法で記述される場合があります。言語の文法が文脈自由である場合、その言語は文脈自由です。一部の言語では、文脈に依存しない文法がないことを証明できます。上記で説明している簡略化された疑似英語サブセットには、文脈自由文法があるかもしれません。

なぜそれが重要なのかについては、文脈自由文法を解析するためのより単純な種類のプログラムが必要です。他の回答で述べたように、文脈自由文法を解析するためにチューリングマシンの全機能を必要としません。特定の文脈自由文法のための先読みLR(1)パーサー(一種のプッシュダウンマシン)は、文の長さに線形の時間および空間でその文法の任意の文を解析できます。文が言語である場合、パーサーは文の各記号が何を意味するか(または少なくとも構造内でどの部分を再生するか)を識別する構造ツリーを生成します。文が文法にない場合、パーサーは最初の記号に気づき、停止します。これは、文法および先行する記号(最初の「エラー」)と一致させることは不可能です。

さらに良いのは、文法の説明と、各部分の処理方法のリスト(各プロダクションに「意味」を付けること)のリストを提供できるプログラムがあり、プログラムがパーサーを作成することです。あなたのために。プログラムは文を解析し、構造を見つけ、構造の各部分で命令を実行します。この種のプログラムは、パーサージェネレーターまたはコンパイラーコンパイラーと呼ばれます。

この種の言語分析は自然言語(英語など)の自動分析のために考案されましたが、これはコンピュータ言語の分析に最も役立つことがわかりました。言語設計者は、新しい言語を取り込む文法を記述し、それをパーサージェネレーターで実行して、自分の言語を解析し、必要に応じて翻訳、解釈、コンパイル、実行などを行うプログラムを取得できます。

実際、ほとんどの場合、これを実際に行うことはできません。たとえば、対応する括弧は文脈自由言語ですが、使用する前にすべての変数を宣言する必要がある言語は文脈依存です。パーサーはコンパイラーの一部ですが、これらの他の要件を適用するには追加のロジックが必要です。次に、可能な限り多くの言語をキャプチャする文法を記述し、それをパーサージェネレーターで実行してから、残りの要件(シンボルテーブルハンドラーなど)を適用するコードを記述します。

状況依存の文法は、サポートがはるかに不十分であるため、通常は使用しません。状況依存言語のLR(k)パーサージェネレーターに相当するものがあるかどうかはわかりません。はい、Turingマシン(または線形バインドマシン)は1つを解析できますが、LR(1 )ジェネレーターは、プッシュダウンマシンの解析テーブルを作成します。私の推測では、パーサーの下にあるテーブルは指数関数的に大きくなるでしょう。いずれにせよ、CSの学生(私と同じように)は、通常、文脈自由文法とYACCなどのLR(1)パーサージェネレーターを教えられます。

5
kwan3217