言語がプログラム可能であるためには、文脈自由文法に基づいていることが必須ですか?


23

実際には、最終的にシステムレベルの命令にコンパイル/変換できる言語の場合、コンテキストのない文法である必要がありますか?

例:すべてのプログラミング/スクリプト言語は文脈自由文法ですか?JavaはCFGに基づいていますが、実際にはすべてのプログラミング言語がCFGに基づいているのですか?

必須ではないようですが、私の理解にはギャップがあります。

質問の背景:文法規則も提供するJava言語仕様を見ていました。これは私にこの質問について考えさせました。


1
一般に、コンパイルの問題を計算可能にしたいだけで、CFGの解析は素晴らしく簡単だと思います。たとえば、有効なperlプログラムを認識することは実際には計算不可能な問題であるという主張を聞いたことがありますが。
ジャンヌH.コルホネン

2
実際に必要なのは、チューリング決定可能な構文(すべてのCFGがそうです)だけです。また、構文がチューリングで決定できないプログラミング言語を作成することもできますが、入力ミスを行うと、コンパイラが有効な構文であるかどうかを判断しようとしている間、コンパイラが停止しないことがあります。これは本当に便利ではありません
ラチェットフリーク

@ratchet、構文は再帰的に列挙可能でなければならないと仮定していますか?
デビッドハリス

4
@JanneKorhonen:具体的には、Perlを静的に解析することはできません。つまり、実行もせずに解析することはできません。上記の実行は終了しない可能性があるため、Perlを静的に解析すると、ホールティング問題を解決することになります。
ジョンパーディ

@janneつまり、後処理は、計算可能または不可能な問題を伴う可能性がありますが、一般的に、プログラムの検証対象となる最終文法はコンテキストに依存しません。より具体的には、前処理後、トークンのシーケンスに適合するルールを識別するために、シーケンスを囲む他のトークンを調べる必要があります。理にかなっているかどうかはわかりませんが、ごめんなさい。私は実際に少し混乱しています。
sandeepkunkunuru

回答:


20

二回

まず、ほとんどのHPLにはコンテキストがありません。通常、CFGに基づいた構文がありますが、静的セマンティクスと呼ばれるものもあります(多くの場合、構文という用語にも含まれています)。これには、正しいプログラムをチェックアウトする必要がある名前とタイプを含めることができます。例えば、

class A {
  String a = "a";
  int b = a + d;
}

は構文的に正しいJavaプログラムですが、d定義されてaおらず、フィッティングタイプがないためコンパイルされません。

第二に、コンテキストに依存しない言語を解析できます(コンパイラの存在によって明らかに証明されているように)。一般的に、CSGが効率的に解析できないのに対して、CFGは効率的に解析できるだけです。ただし、効率を維持しながら、特定の非コンテキストフリー機能を追加できます。

コンパイラは、多くの場合、フェーズで実行されます。最初のトークン化(通常)、次にコンテキストのない解析、名前と型の分析(コンテキスト依存、場合によってはさらに難しい)。表示されるエラーメッセージの種類によって、その動作を観察できます。


3
忘れないでくださいpublic class Program { public static void main(String[] args) { ... } }... Javaを使用すると、それほど簡単になりません。:-)
ロイティンカー

技術的にclass A { ... }は、javac実際に実行できないものをコンパイルするのに完全に十分です(エントリポイントがないため)。しかし、はい。
ラファエル

20

6
これはPerlジョークのパンチラインになるはずだと思う:)
Suresh Venkat

5
Suresh:SIGBOVIK 2011(sigbovik.org/2011/proceedings.pdf-ページ79-)の「Unlexable Programming Languages」という論文で、このジョークはすでに作成しましたが、あまり良いジョークではありませんでした。82)。
ロブシモンズ

1
注:Perlインタープリターはまだ決定的ではありませんが、それが誰にとっても快適であれば:)
ロイティンカー

15

Pythonの文法が文脈自由であるとは思わない。同じコードブロックの行に同じ量のインデントを設定するという要件は、文脈自由文法がうまく処理するようなものではありません。

より正確には、次の形式のPythonブロックの言語から準同型があるようです。

条件の場合:
     ライン1
     2行目
     line3
その他:
     line4

0n10n10n


4
厳密にあなたは正しいですが、プログラミング言語のコンテキストでは、tokenizationと呼ばれる前処理ステップの結果として生じるコンテキストフリーな言語を作成しようとします。その前にインデントがチェックされると思います。
ディエゴデエストラダ

7
ええ、Python lexer(トークン化機能)には、インデントの深さのスタックがあります。トークンストリームには、各ブロックの先頭にINDENTシンボルがあり、末尾にDEDENTシンボルがあります。これらは、コンテキストフリーの方法で解析できます(INDENTおよびDEDENTは、Cの中括弧のように機能します)。Cには、「宣言または式がわからない」問題がfoo * bar;あります。宣言は、時間fooへのポインターbarまたは乗算としてですか?foobar
マックス

8
確かに、しかし、あなたは、レキサーをしばしば有限状態のトランスデューサーにするのではなく、レクサーに同じ複雑さを隠しているだけです。
デビッドエップスタイン

1
@DavidEppstein:公平を期すため、複雑さは決して素晴らしいものではないと述べました。
ジョンパーディ

1
字句解析器でのINDENT / DEDENTの処理とは別に、Pythonには非常に単純なLL(1)文法があります。
rmmh

13

Bodo MantheyとMartinBöhmeは、すべてのC ++コンパイラが必然的にチューリング完全であることを示しています。つまり、コンパイル時に部分的な再帰関数を計算できます。そのため、コンテキスト依存よりもはるかに悪いです。

http://wwwhome.math.utwente.nl/~mantheyb/journals/BotEATCS_BoehmeManthey_CompilingCPP.pdf


はい。ただし、コンパイラは決してコンテキストフリーの文法ではありません。コンパイラーではなく、文法そのものについて議論する必要があります。
ジェフバードズ

@Jeff:私の答えの「コンパイル時間」は、「特定のC +ソースコードが正しいかどうかを確認する」ことを意味します。論文の構成をわずかに変更することにより、決定可能なすべての言語をすべての正しいC ++プログラムのセットに減らすことができます。
マルクスブレイザー

7

変数を使用する前の宣言と、OOP言語の関数多型は、コンテキストフリーの文法では処理できないプログラミング言語仕様の他の例だと思います。

int myfun(int a) { ... }
int myfun(int a, int b) { ... }
int myfun(int a, int b, int c, ...) { ... }
...
int I_m_I_cfg = myfun(1,2);
...

私は少しGoogle検索を作って、私はこの記事が見つかりました:単純なBoolean言語用のブール文法を A.Okhotin(2004)によって; 彼によると、本当の問題は、正式な文法で完全に記述されたプログラミング言語を見つけることです。

おもちゃの手続き型プログラミング言語が定義され、 この言語の整形式プログラムのセットのブール文法が構築されます。これは明らかに正式な文法によるプログラミング言語の最初の仕様です。

この記事の「はじめに」セクションは短いですが、非常に明確です。


6

Cの文法は、パーサーがDuffのデバイスをサポートするために常にコンテキストに依存しないテクニックを使用するという点で、技術的にのみコンテキストに依存すると信じています

インデントベースの言語は、デイビッドが言ったように自然にコンテキストフリーではありませんが、パラメータ化されたインデントトークンに比べてコンテキストフリーになります。

Haskellでは、infixとinfixlを使用して演算子の優先順位を変更できます。Perlの厳密なプラグマモジュールは、語彙設定$ ^ Hおよび%^ Hを使用して実装されます。これにより、コンテキストフリーではなく、おそらく他の設定も可能になります。

TeXのようなマクロエキスパンダー言語には、実行しないとafaik解析が意味をなさないものがあります。

交差点は文脈自由ではないが、チューリング機械について記述している文脈自由文法もおそらく2つあります。

Javaとアセンブラーは、おそらくどちらも自然にコンテキストフリーです。


2
(a)-bCの文脈依存性の曖昧さはありませんか?(a変数またはtypedefの可能性があります-他の一部の言語では、この理由で単項マイナス式をキャストできません)
ランダム832

コメントが非常に遅れたことをおizeびしますが、Duffのデバイスには構文上の逸脱はありません。ブレースのバランスは正しく調整されています。Cがコンテキストフリーであるかどうかについての議論では、C機能はほとんどの場合無視されます。私は、たとえ非公式ではあるが、「コンテキストフリー」の解釈があり、それを使用してマクロプロセッサで言語を記述することを許可していますが、行儀の良いものであっても懐疑的です。また、Cプリプロセッサは、正常な動作ではありません。
リチ

4

いいえ、実用的な言語の多くはコンテキストに依存しません。たとえば、C ++の文法はそうではありません。コンテキストによっては、文法の解決がコンテキストに依存しない情報の入力に依存するためです。


4

まず、プログラミング言語の構文と言語自体を区別します。

多くの言語の構文は(少なくとも基づく)Context Free Grammar(CFG)です。これらはよく研究されており、CFGを効率的に解析できるアルゴリズムがあり、CFGで解決できないエッジケースを特別に処理できるためです。

ただし、実際には多くの言語はコンテキストフリーではありません(java、C(++)、Dなどで使用前宣言シンボルが使用されている場合)。

おもしろい事実:Dにはチューリング完全なコンパイル時関数の評価とテンプレートの拡張があり、言語自体をチューリングが決定できないようにしています。しかし、言語の作成者は、構文をCFGにするためにかなりの時間を費やしました。


名前とタイプの分析は、通常、本質的に非コンテキストのないタスクを実行します。
ラファエル

C ++のテンプレートメタプログラミングはチューリング完了です。
ジェフバージス

3

「すべてのプログラミング/スクリプト言語は文脈自由文法ですか?」一部が関係している、答えは明確なNoです

Re:「最終的にシステムレベルの命令にコンパイル/変換できる言語の場合」という主な質問ですが、なぜCFGである必要があるのか​​はわかりません。ただし、より良い説明が出てくる可能性があります。


1
クリス、非文脈自由文法ベースのプログラミング言語の例をいくつか教えてください。つまり、計算可能な場合とそうでない場合がある問題を伴う前処理の後処理、つまりプログラムが検証される最終文法。
sandeepkunkunuru

3

プログラミング言語は、ある種の文法形式に基づいている必要がありますが、CFGはその一例です。CFGが最も一般的です(とuniviersitiesでコンパイラのコースで教えられていつもの事です)が、そのようなあなたはもっとについて読むことができるの解析表現文法、などの他の形式主義があり、ここ(PDF)またはWikipediaでより多くの一口サイズの読み取りのためには。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.