C ++は状況依存ですか、状況依存ですか?


405

C ++は状況依存言語であるという主張をよく耳にします。次の例を見てください。

a b(c);

これは変数定義ですか、関数宣言ですか?それは記号の意味に依存しcます。場合cである変数は、その後、a b(c);名前の変数を定義bタイプのをa。で直接初期化されcます。しかし、cタイプの場合、を取り、を返すa b(c);という名前の関数を宣言します。bca

文脈自由言語の定義を調べると、基本的に、すべての文法規則の左側には、1つの非終端記号だけが含まれている必要があることがわかります。一方、状況依存の文法では、左側に終端記号と非終端記号の任意の文字列を使用できます。

「C ++プログラミング言語」の付録Aを閲覧したところ、左側に単一の非終端記号以外に何もない単一の文法規則が見つかりませんでした。これは、C ++がコンテキストフリーであることを意味します。(もちろん、すべての文脈自由言語は、文脈自由言語が文脈依存言語のサブセットを形成するという意味で文脈依存でもありますが、それが目的ではありません。)

では、C ++はコンテキストフリーですか、それともコンテキスト依存ですか?


12
@CarlNorum左側に単一の非終端記号で構成されていないC ++の単一の文法規則を見せてください。すぐに信じられます。
fredoverflow 2013年

9
IIUCそれはあなたが文脈依存性のためにどこに線を引くかに少し依存します。静的型付きプログラミング言語のほとんどすべてがコンテキスト依存であり、CFG解析ツールで実用的なコンパイラを構築できないためではなく、無効なプログラムを解析してそのような実装を「だまし取る」ため、型チェック中に後でのみ拒否します。そのため、不適切な型のプログラムが言語(CSの意味では文字列のセット)ではないと見なす場合、パーサーは受け入れる必要があります。C++よりも多くの言語が状況依存です。

6
@DeadMG:いいえ、あなたは間違っています。形式的な言語理論には「解析」も「セマンティクス」もまったくなく、文字列のセットである「言語」だけです。
jpalecek 2013年

27
これまでのところ、「文脈自由文法」の定義に実際に対処した回答はありません。私の考えでは、この質問に対する正しい答えは、付録Aであなたの定義に適合しない作品を引用するか、またはあなたの定義が正しくないか不十分であることを示しています。あなたの立場を主張をする!
オービットのライトネスレース2013年

8
参照されD'sの文法本当に文脈自由?。実際、私はここの誰もがその質問とその答えを読むべきだと思います!
オービットのライトネスレース

回答:


341

以下は、C ++の解析が(おそらく)Turing-completeである理由の私の(現在の)お気に入りのデモです。これは、与えられた整数が素数である場合にのみ、構文的に正しいプログラムを示しているためです。

だから私はC ++は文脈自由でも文脈依存でもないと主張します

プロダクションの両側で任意のシンボルシーケンスを許可すると、チョムスキー階層にタイプ0文法(「無制限」)が生成されます。これは、状況依存文法よりも強力です。無制限の文法はチューリング完全です。文脈依存(タイプ1)文法では、プロダクションの左側にコンテキストの複数の記号を使用できますが、同じコンテキストをプロダクションの右側に表示する必要があります(そのため、「コンテキスト依存」という名前です)。[1]文脈依存文法は、線形境界のチューリングマシンと同等です。

サンプルプログラムでは、プライム計算は線形境界のチューリングマシンで実行できるため、チューリングの同等性を完全に証明することはできませんが、構文解析を実行するためにパーサーが計算を実行する必要があることが重要です。これは、テンプレートのインスタンス化として表現できる任意の計算である可能性があり、C ++テンプレートのインスタンス化がチューリング完全であると信じる理由はすべてあります。たとえば、Todd L. Veldhuizenの2003年の論文を参照してください。

とにかく、C ++はコンピューターで解析できるため、チューリングマシンで確実に解析できます。その結果、無制限の文法がそれを認識できます。実際にそのような文法を書くことは実際的ではありません。それが標準がそうすることを試みない理由です。(下記参照。)

特定の表現の「あいまいさ」の問題は、ほとんどがニシンです。まず、あいまいさは特定の文法の特徴であり、言語ではありません。言語に明確な文法がないことが証明できたとしても、文脈自由文法で認識できれば、文脈自由です。同様に、文脈自由文法では認識できないが、文脈依存文法では認識できる場合は、文脈依存です。あいまいさは関係ありません。

しかし、どのような場合でも、auto b = foo<IsPrime<234799>>::typen<1>();以下のプログラムの21行目(つまり)のように、式があいまいではありません。それらは単にコンテキストに応じて異なる方法で解析されます。問題の最も単純な表現では、特定の識別子の構文カテゴリは、それらがどのように宣言されているか(タイプや関数など)に依存しています。つまり、形式言語は、2つの任意の長さの文字列が同じプログラムは同一です(宣言と使用)。これは、同じ単語の2つの連続した正確なコピーを認識する文法である「コピー」文法によってモデル化できます。ポンピング補題で証明するのは簡単ですこの言語は文脈自由ではないことです。この言語の状況依存文法が可能であり、この質問への回答にタイプ0文法が提供されています。/math/163830/context-sensitive-grammar-for-the-copy-language

C ++を解析するために状況依存の(または無制限の)文法を記述しようとすると、宇宙が落書きでいっぱいになる可能性があります。C ++を解析するTuringマシンを作成することも、同様に不可能な作業です。C ++プログラムを書くことさえ困難であり、私の知る限り、どれも正しいことが証明されていません。これが、標準が完全な正式な文法を提供することを試みない理由であり、技術的な英語で解析規則の一部を記述することを選択する理由です。

C ++標準の正式な文法のように見えるものは、C ++言語の構文の完全な正式な定義ではありません。これは、前処理後の言語の完全な正式な定義でさえないため、正式化が容易になる場合があります。(ただし、これは言語ではありません。標準で定義されているC ++言語にはプリプロセッサが含まれています。プリプロセッサの操作は、文法的な形式で記述するのが非常に難しいため、アルゴリズムで記述されています。そのセクションにあります。字句分解が記述されている標準の、2回以上適用する必要があるルールを含む)

さまざまな文法(字句解析のための2つの重複する文法、前処理の前に実行される文法と、必要に応じてその後に実行される文法、および「構文」文法)は、この重要な注記(強調が追加されています)とともに付録Aに収集されています。

このC ++構文の要約は、理解を助けるためのものです。言語の正確な説明ではありません。特に、ここで説明する文法は、有効なC ++構成体のスーパーセットを受け入れます。式と宣言を区別するには、曖昧性除去ルール(6.8、7.1、10.2)を適用する必要があります。さらに、構文的には有効であるが意味のない構成を除外するために、アクセス制御、あいまいさ、および型ルールを使用する必要があります。

最後に、これが約束されたプログラムです。21行目は、N in IsPrime<N>が素数の場合にのみ構文的に正しいです。それ以外の場合typenは、テンプレートでtypen<1>()はなく整数であり、構文的に有効な式ではない(typen<1)>()ため()、構文的に正しくないものとして解析されます。

template<bool V> struct answer { answer(int) {} bool operator()(){return V;}};

template<bool no, bool yes, int f, int p> struct IsPrimeHelper
  : IsPrimeHelper<p % f == 0, f * f >= p, f + 2, p> {};
template<bool yes, int f, int p> struct IsPrimeHelper<true, yes, f, p> { using type = answer<false>; };
template<int f, int p> struct IsPrimeHelper<false, true, f, p> { using type = answer<true>; };

template<int I> using IsPrime = typename IsPrimeHelper<!(I&1), false, 3, I>::type;
template<int I>
struct X { static const int i = I; int a[i]; }; 

template<typename A> struct foo;
template<>struct foo<answer<true>>{
  template<int I> using typen = X<I>;
};
template<> struct foo<answer<false>>{
  static const int typen = 0;
};

int main() {
  auto b = foo<IsPrime<234799>>::typen<1>(); // Syntax error if not prime
  return 0;
}

[1]より技術的に言えば、状況依存文法のすべてのプロダクションは次の形式でなければなりません。

αAβ → αγβ

ここで、Aは非終端記号であり、は空の文法記号シーケンスでありαβは空でγはないシーケンスです。(文法記号は、終端または非終端のいずれかです)。

これはA → γ、文脈でのみ読むことができます[α, β]。コンテキストフリー(タイプ2)文法で、空αβなければなりません。

すべてのプロダクションが次の形式でなければならない「単調な」制限で文法を制限することもできることがわかります。

α → βここで|α| ≥ |β| > 0  (|α|は「長さ」を意味しますα

単調文法で認識される言語のセットが状況依存文法で認識される言語のセットとまったく同じであることを証明することは可能であり、単調文法に基づいて証明を行う方が簡単な場合がよくあります。したがって、「状況依存」が「単調」を意味するかのように使用されるのはよくあることです。


27
そのため、コンテキスト依存であるだけでなく、テンプレートで表現できる、チューリング完全なコンテキストに依存するようにすることができます。
Puppy

7
@mehrdadのOPは、文脈依存の文法ではなく、「文脈依存の言語」と言っています。あいまいさは言語ではなく文法の機能です。この言語は確かに文脈依存ですが、特定の文法があいまいだからではありません。
リシ

2
私の例があいまいではないことに注意してください。これは、有効なプログラムを明確に表現したものです。21行目の値を変更すると、形式が正しくなくなる可能性があります。しかし、どちらの場合もあいまいではありません。
リチ

5
ひとつ疑問があります。あなたが示すように、テンプレート評価の結果は、整形式のプログラムと整形式のプログラムを区別することができます。テンプレートの評価が完了しました。文字列が言語(C ++)であるかどうかを正しく判断するには、チューリング完全性が必要ですか?あなたが言うように、文脈依存言語は「単なる」「線形境界オートマトン」であり、チューリング完全なAFAIKではありません。それとも、C ++標準がテンプレートの評価の深さなどのいくつかに課している制限を利用して、あなたの議論はありますか?

4
@AntonGolov:その例の私のオリジナルバージョンはそれを実行しました(単純なものの場合、の0内部に配置することでそれを実現できます())が、次のように認識するためにもテンプレートのインスタンス化が必要であることを示しているため、この方法はより興味深いと思います文字列は構文的に正しいC ++プログラムです。両方のブランチがコンパイルされる場合、違いが「セマンティック」であるという主張に異議を唱えるために私は一生懸命努力する必要があります。奇妙なことに、私はしばしば「構文」を定義するように挑戦されますが、「構文ではないと思うもの」以外に「意味論」の定義を誰も提供したことがありません:)
rici

115

まず、C ++標準の最後の文法には文脈依存ルールがないため、文法文脈自由です。

ただし、その文法はC ++言語を正確に記述していません。これは、次のような非C ++プログラムを生成するためです。

int m() { m++; }

または

typedef static int int;

「整形式のC ++プログラムのセット」として定義されているC ++言語はコンテキストフリーではありません(宣言する必要のある変数だけがそうすることを示すことは可能です)。理論的には、テンプレートでチューリング完全なプログラムを記述し、その結果に基づいてプログラムを不適切な形式にすることができれば、状況に依存することすらありません。

現在、(無知)の人々(通常は言語理論家ではなく、パーサーの設計者)は、通常、次のような意味で「コンテキストフリーではない」を使用しています。

  • 曖昧
  • バイソンでは解析できません
  • LL(k)、LR(k)、LALR(k)、または選択したパーサー定義の言語クラスではない

標準の後ろにある文法はこれらのカテゴリを満たしていません(つまり、あいまいであり、LL(k)...ではありません)。そのため、C ++文法は「文脈自由」ではありません。そして、ある意味で、それらは正しいです。動作するC ++パーサーを作成するのは非常に難しいのです。

ここで使用されるプロパティは、文脈自由言語に弱く関連しているだけであることに注意してください-あいまいさは文脈依存性とは何の関係もありません(実際、文脈依存規則は通常、プロダクションの曖昧性解消に役立ちます)、他の2つは単にコンテキストのサブセットです-無料の言語。また、文脈自由言語の解析は線形プロセスではありません(ただし、決定論的言語の解析は線形プロセスです)。


7
ambiguity doesn't have anything to do with context-sensitivityこれも私の直感だったので、誰かが(a)同意し、(b)説明できないところを説明してくれてうれしいです。私はそれがに基づくすべての議論を失格にし、a b(c);文脈が曖昧さによるものであるという「よく聞かれる」主張が最初の質問を部分的に満たしていると信じています...特に、文法の場合、実際にさえ曖昧性がない場合MVP。
オービットのライトネスレース2013年

6
@KonradRudolph:標準では、「再帰的なインスタンス化の合計深度に制限を指定する実装定義の数量があり、これには複数のテンプレートが含まれる場合があります。インスタンス化における無限再帰の結果は定義されていません。」(14.7.1p15)実装がすべての有効なc ++プログラムを理解する必要がないことを意味すると解釈します。再帰の深さが大きすぎるプログラムは無効ではありません。無効とマークされているのは、再帰の深さが無限であるものだけです。
リチ

3
@KonradRudolph:私はそれが「一般的な参照」であることに異議を唱えます。私がそのかなり複雑な記事を読んで、この小さな事実を明らかにするのに十分に理解していないという事実は、それを実証するのに十分なはずです。「コンピューターは一般的に電気を使用している」、「ビットは正しいか間違っているか」のように言ったわけではありません。
オービットのライトネスレース2013年

3
この事実が本当に広く知られているとすれば、それが提供されるべきかどうかについて詳細に議論するよりも、その参照を見つける方がはるかに簡単だと思います。建設的なことは言うまでもありません。
Samuel Edwin Ward

5
私が知る限り、@ Konradは、「状況依存はチューリング完了と同等」と言ったときに誤解されました。(少なくとも、「Turing complete」で「Recursively enumerable」を示していたなら、彼はそうでした)そして、それ以来この間違いを認識することができませんでした。ここでは、ここで関係する適切な集合の包含関係の基準とは、次のとおりです。en.wikipedia.org/wiki/Chomsky_hierarchy
pnkfelix

61

はい。次の式は、型解決されたコンテキストに応じて、操作の順序が異なります

編集:実際の操作の順序が変わると、装飾する前に装飾されていないASTに解析する「通常の」コンパイラーを使用することが非常に難しくなります(型情報の伝播)。言及されている他の状況依存の事柄は、これに比べて「かなり簡単」です(テンプレートの評価はまったく簡単ではありません)。

#if FIRST_MEANING
   template<bool B>
   class foo
   { };
#else
   static const int foo = 0;
   static const int bar = 15;
#endif

に続く:

static int foobar( foo < 2 ? 1 < 1 : 0 > & bar );

スコープ内にある型定義を覚えておくことで、Cのように問題を解決できないのはなぜですか。
Blaisorblade、2012年

1
@Blaisorblade:コンパイラを「クリーン」にする1つの方法は、入力から解析ツリーを作成し、その後に型分析を行うステップを作成するなど、タスクをチェーン内の独立したステップに分離することです。C ++では、1)これらの手順を1つにマージするか、2)可能な両方またはすべての解釈に従ってドキュメントを解析し、型解決ステージで正しい解釈に絞り込むことができます。
Sam Harwell 2012年

@ 280Z28:同意したが、Cもそうだ。私はC ++がここにリンクされ博士論文がするC.よりも悪いですなぜこの質問に良い答えが表示されるはずだと思う:stackoverflow.com/a/243447/53974
Blaisorblade

26

質問に答えるには、2つの異なる質問を区別する必要があります。

  1. ほとんどすべてのプログラミング言語の単なる構文はコンテキストフリーです。通常、これは拡張バッカスナウア形式または文脈自由文法として与えられます。

  2. ただし、プログラムがプログラミング言語で定義されている文脈自由文法に準拠していても、必ずしも有効なプログラムであるとは限りません。有効なプログラムになるためにプログラムが満たさなければならない、文脈に依存しない多くのpopertiesがあります。たとえば、最も単純なそのようなプロパティは変数のスコープです。

結論として、C ++がコンテキストフリーであるかどうかは、質問する内容によって異なります。


5
プログラミング言語用のCFGを取得するために、「単なる構文」レベルを予想よりも低く設定する必要がある場合があることに注意してください。たとえば、Cを取り上げます。あなたは、Cでの単純な変数宣言のための文法規則があることだろうと思うかもしれないVARDECL : TYPENAME IDENTIFIERが、あなたはできませんあなたがCFレベルで他の識別子から型の名前を区別できないので、それを持っています。別の例:CFレベルではa*b、変数宣言(へbのポインタタイプa)として解析するか、乗算として解析するかを決定できません。
LaC、2013年

2
@LaC:はい、これを指摘してくれてありがとう!ちなみに、単なる構文には、より一般的に使用されている専門用語があると思います。誰か正しい言葉はありますか?
Dan

4
@ダン:あなたが話しているのは、文脈自由文法によって与えられた言語の近似です。もちろん、そのような近似は、定義上、テキストを含まない。これは、プログラミング言語を議論するときに「構文」がよく使用される感覚です。
reinierpost 2013年

13

あなたはを見てみたいことがありますC ++ザデザイン&進化ビャーネ・ストロヴストルップにより、。その中で彼は、yacc(または同様のもの)を使用してC ++の初期バージョンを解析しようとしている問題と、代わりに再帰的降下を使用したいと述べています。


うわー...ありがとう。CFGよりも強力なものを使用して人工言語を解析することを考えるのは本当に理にかなっているのでしょうか。
ダービンサンク

C ++の理由を理解するための素晴らしい本。C ++がどのように機能するかを理解するために、これとLippman's Inside the C ++ Object Modelをお勧めします。どちらも少し古いですが、それらはまだ良い読み物です。
マット価格

「Meta-S」は、Quinn Tyler Jacksonによる状況依存解析エンジンです。私は使ったことはありませんが、彼は印象的な物語を語っています。彼のコメントをcomp.compilersで確認し、rnaparse.com / MetaS%20defined.htm
Ira Baxter

@IraBaxter:今日のx-refはMIAであり、ソフトウェアへの確かな参照はとらえどころのないようです(Google検索では、「site:rnaparse.com meta-s」または「quinn jackson meta- s ';ビットと断片がありますが、meta-s.comは情報のないWebサイトにリンクします(たとえば)。
ジョナサンレフラー

@ジョナサン:しばらくして、あなたの不満に気づきました。どうしてリンクが悪いのか、書いて良かったなぁと思いました。Quinnは以前comp.compilersでかなりアクティブでした。グーグルは不安定になっているようです、これは私が見つけることができるすべてです: groups.google.com/group/comp.compilers/browse_thread/thread/…IIRC、彼はマーケティングするためにハワイのいくつかの衣装にMetaSへの権利に署名しました。これがどれほど奇妙に奇妙だったかを考えると、私見はこれがその死亡令状に署名している。とても賢い計画のように聞こえました。
Ira Baxter、

12

うん、C ++は状況依存で、非常に状況依存です。コンテキストフリーパーサーを使用してファイルを解析するだけでは構文ツリーを構築できません。場合によっては、決定するために以前の知識からシンボルを知る必要があります(解析中にシンボルテーブルを構築するなど)。

最初の例:

A*B;

これは掛け算式ですか?

または

これはB、型のポインタである変数の宣言Aですか?

Aが変数の場合、それは式です。Aがタイプの場合、それはポインター宣言です。

2番目の例:

A B(bar);

これはbar型の引数を取る関数プロトタイプですか?

または

これは変数を宣言していますか Bは型のをし、初期化子として定数を使用してAAのコンストラクターを呼び出しbarますか?

bar変数であるか、シンボルテーブルの型であるかを再度知る必要があります。

3番目の例:

class Foo
{
public:
    void fn(){x*y;}
    int x, y;
};

これは、xとyの宣言が関数定義の後に来るため、解析中にシンボルテーブルを作成しても効果がない場合です。したがって、最初にクラス定義をスキャンし、2番目のパスでメソッド定義を調べて、x * yが式であり、ポインター宣言などではないことを確認する必要があります。


1
A B();関数定義でも関数宣言です。最も厄介な解析を探してください
AProgrammer

「ファイルを単に解析するだけでは構文ツリーを構築できません」FALSE。私の答えを見てください。
Ira Baxter

10

C ++はGLRパーサーで解析されます。つまり、ソースコードの解析中に、パーサーあいまいさを見つける可能性がありますが、続行して、後で使用する文法規則を決定する必要があります。

また見て、

C ++がLR(1)パーサーで解析できないのはなぜですか?


文脈自由文法は、プログラミング言語構文のすべての規則を記述できるわけではないことに注意してください。たとえば、属性文法は、式タイプの有効性をチェックするために使用されます。

int x;
x = 9 + 1.0;

あなたはできません文脈自由文法では、次のルールを説明します。 割り当ての右側には、左側の同じタイプである必要があります。


4
ほとんどのC ++パーサーはGLR解析テクノロジーを使用しません。GCCはサポートしていません。一部はします。機能するものについては、semanticdesigns.com / Products / FrontEnds / CppFrontEnd.htmlを参照してください。
Ira Baxter、

10

「文脈依存」の正式な定義と「文脈依存」の非公式な使用との間には、いくつかの混乱があるように感じます。前者には明確な意味があります。後者は、「入力を解析するにはコンテキストが必要です」と言うために使用されます。

これもここで尋ねられます: 文脈依存性vsあいまいさ

これが文脈自由文法です:

<a> ::= <b> | <c>
<b> ::= "x"
<c> ::= "x"

これはあいまいなので、入力 "x"を解析するには、何らかのコンテキストが必要です(またはあいまいさを伴うか、または "警告:E8271-入力が行115であいまいです"が発生します)。しかし、それは確かに文脈依存の文法ではありません。


プロダクションの左側に複数のシンボルを配置すると、この問題をどのように解決できますか?この答えが質問に答えているとは思いません。
user541686 2013年

1
私の答えは、最初の文に対する応答です。「C ++は状況依存言語であるという主張をよく耳にします。」これらの主張が非公式に「文脈依存」という表現を使用する場合、問題はありません。C ++が正式に文脈依存であるとは思わない。
Omri Barel

C ++ 形式的にコンテキスト依存であると思いますが、私が抱えている問題は、CFGの場合よりもコンテキスト依存の文法の方がC ++の解析でどのように成功するのか理解できないことです。
user541686 2013年

6

Algolに似た言語には、文脈に依存しないものはありません。これは、識別子とその型に基づいて表示される式とステートメントを制約するルールがあり、宣言と使用の間に発生する可能性のあるステートメントの数に制限がないためです。

通常の解決策は、実際に有効なプログラムのスーパーセットを受け入れ、状況依存部分をアドホックに配置するコンテキストフリーパーサーを作成することです。ルールに添付された「セマンティック」コードに。

C ++は、チューリング完全なテンプレートシステムのおかげで、これをはるかに超えています。Stack Overflow Question 794015を参照してください。




5

a b(c);2つの有効なparses宣言と変数があるため、状況依存です。「If cis a type」と言うと、それがコンテキストであり、C ++がそれに対してどのように敏感であるかを正確に説明しました。「何cですか」というコンテキストがなかった場合 これを明確に解析することはできません。

ここでは、コンテキストはトークンの選択で表現されます。パーサーがタイプに名前を付ける場合、パーサーは識別子をtypenameトークンとして読み取ります。これは最も簡単な解決策であり、状況依存である(この場合)の複雑さの多くを回避します。

編集:もちろん、状況依存の問題はもっとあります。私は、あなたが示したものに単に焦点を合わせました。テンプレートはこれに対して特に厄介です。


1
またa<b<c>>d、そうですか?(あなたの例は、実際にはCからの古典であり、それはコンテキストフリーであることへの唯一の障害です。)
Kerrek SB

それはもっと厄介な問題だと思います。しかし、確かに同じカテゴリーです。
パピー

2
質問者は、それはだか聞いていない以上だけで、それは文脈依存であることを示すために、コンテキスト依存Cより。
パピー

では、C ++ Cよりも状況依存ですか?
Kerrek SB、2013

2
@DeadMG私はあなたが質問に答えているとは思わない(私もそうだったとは思わない)。プロダクションの左側にターミナルを配置すると、この問題をどのように解決できますか?
user541686 2013年

5

C ++標準のプロダクションはコンテキストフリーで記述されていますが、誰もが知っているように、言語を正確に定義しているわけではありません。ほとんどの人が現在の言語で曖昧であると見なしているものの一部は、状況依存の文法で(はっきりと)解決できるでしょう。

最も明白な例として、Most Vexing Parse:を考えてみましょうint f(X);。場合は、X値は、この定義であるfと初期化される変数としてXXがタイプの場合、それはfタイプの単一パラメーターを取る関数として定義されますX

これを文法的な観点から見ると、次のように見ることができます。

A variable_decl ::= <type> <identifier> '(' initializer ')' ';'

B function_decl ::= <type> <identifier> '(' param_decl ')' ';'

A ::= [declaration of X as value]
B ::= [declaration of X as type]

もちろん、完全に正しくするためには、他の型の宣言が介在する可能性を考慮して、いくつかの追加の「もの」を追加する必要があります(つまり、AとBは両方とも、実際に「Xの宣言を含む宣言...」でなければなりません。 、またはその順序で何か)。

ただし、これは典型的なCSG(または少なくとも私が覚えているもの)とはかなり異なります。これは、構築されているシンボルテーブルに依存します。X、タイプまたは値としてれる、これに先行するあるタイプのステートメントだけでなく、正しいシンボル/識別子の正しいタイプのステートメントです。

そのため、確認するために何らかの調査を行う必要がありますが、少なくとも通常はこの用語が使用されているため、これは実際にはCSGとしては適格ではないと推測します。


(コンテキストフリー)プロダクションは、最も厄介な解析を十分に定義しているため、コンテキストフリー解析エンジンで解析できます。これにより、解析が完了するまで有効な複数の解釈を決定する問題が遅延しますが、従来のC ++パーサーのように複雑ではなくモジュール化されているため、パーサーと名前リゾルバーのエンジニアリングが簡単になります。:最も厄介なの解析のためのASTを参照してくださいstackoverflow.com/questions/17388771/...
アイラバクスター

5

文脈自由でない文法の最も単純なケースは、テンプレートを含む式の解析を含みます。

a<b<c>()

これはどちらかとして解析できます

template
   |
   a < expr > ()
        |
        <
      /   \
     b     c

または

 expr
   |
   <
 /   \
a   template
     |
     b < expr > ()
          |
          c

2つのASTは、「a」の宣言を調べることによってのみ明確になります。「a」がテンプレートの場合は前者のAST、そうでない場合は後者です。


C ++ 11では後者の解釈が義務付けられていると思います。前者にオプトインするには括弧を追加する必要があります。
Joseph Garvin 2013年

1
@JosephGarvin、いいえ。C ++では<、可能であればブラケットである必要があります(たとえば、テンプレートを指定する識別子の後に続く)。C ++ 11 は、その使用がもっともらしい場合>、の最初の文字を>>閉じ角かっことして解釈するという要件を追加しました。これは、テンプレートがであるa<b>c>場所の解析に影響しますが、にaは影響しませんa<b<c>
rici 2013年

@aaron:それはa();expr.callまたはexpr.type.conv)よりも簡単ですか?
rici 2013年

@rici:おっと、非対称であることに気づかなかった。
ジョセフガービン

5
あいまいさ、または文脈依存性を説明していますか?
corazza 14年

4

C ++テンプレートはチューリングパワフルであることが示されています。正式なリファレンスではありませんが、ここでその点を確認してください。

http://cpptruths.blogspot.com/2005/11/c-templates-are-turing-complete.html

私は推測(70年代のALGOLはCFGで表すことができなかったことを示す民俗的で簡潔なCACM証明と同じくらい古い)に挑戦し、C ++はCFGだけで正しく解析できないと言います。CFGと、ツリーパスまたは削減イベント中のさまざまなTPメカニズムとの組み合わせ-これは別の話です。一般的な意味では、停止問題のために、正しいか正しくないかを示すことはできませんが、それでも正しいか正しくないいくつかのC ++プログラムが存在します。

{PS- Meta-Sの作者として(上記で数人の人が述べました)-私は、Thothicが機能しておらず、無料で利用できるソフトウェアでもないと私は確信できます。おそらく、私がこのバージョンの応答を削除したり、-3に投票したりしないように言いました。}


3

C ++はコンテキストフリーではありません。コンパイラの講義で少し前にそれを学びました。簡単な検索でこのリンクが得られました。「構文またはセマンティクス」セクションでは、CおよびC ++がコンテキストフリーではない理由を説明しています。

ウィキペディアトーク:文脈自由文法

よろしく、
Ovanes


2

明らかに、質問を逐語的に行う場合、識別子を持つほとんどすべての言語は状況依存です。

識別子の使用の一部を正しく行うには、識別子が型名(クラス名、typedefによって導入された名前、typenameテンプレートパラメータ)、テンプレート名、またはその他の名前であるかどうかを知る必要があります。例えば:

x = (name)(expression);

name型名であり、型名であり、関数呼び出しはname関数名のは。もう1つのケースは、いわゆる「最も厄介な解析」で、変数の定義と関数の宣言を区別することができません(関数の宣言であるというルールがあります)。

その困難によりtypenametemplate依存名の必要性が生じました。C ++の残りの部分は、私が知る限り、コンテキスト依存ではありません(つまり、C ++のコンテキストフリー文法を書くことは可能です)。


2

Meta-S "は、Quinn Tyler Jacksonによる状況依存解析エンジンです。私は使っていませんが、彼は印象的な物語を語っています。comp.compilersで彼のコメントを確認し、rnaparse.com / MetaS%20defined.htmを参照してください– Ira Baxter 7月25日10:42

正しいリンクは謎を解析しています

Meta-Sは、Thothicと呼ばれる消滅した会社の所有物でした。Meta-Sの無料のコピーを興味のある人なら誰にでも送ることができ、私はそれをrna解析研究で使用しました。サンプルフォルダーに含まれている「疑似結び目文法」は、バイオインフォマティクスではない、成熟したプログラマーによって書かれたものであり、基本的に機能しないことに注意してください。私の文法は異なるアプローチを取り、非常にうまく機能しています。


これは実際には興味深い発見です。
ダービンサンク

0

ここでの大きな問題は、「文脈自由」と「文脈依存」という用語は、コンピュータサイエンスでは少し直感的でないということです。C ++の場合、文脈依存性はあいまいさのように見えますが、一般的なケースでは必ずしもそうではありません。

C / ++では、ifステートメントは関数本体内でのみ許可されます。それは状況に依存するように見えるでしょう?うーん、ダメ。コンテキストフリーの文法は、実際には、コード行を取り出してそれが有効かどうかを判断できるプロパティを必要としません。これは実際にはコンテキストフリーの意味ではありません。それは実際には、それがどのように聞こえるかに関連するある種の何かを漠然と暗示する単なるラベルです。

ここで、関数本体内のステートメントが、直接の文法上の祖先の外で定義されたもの(たとえば、識別子が型または変数を表すかどうか)に応じて異なる方法で解析されるa * b;場合、実際には、状況依存です。ここには実際のあいまいさはありません。a型の場合はポインタの宣言として解析され、それ以外の場合は乗算として解析されます。

状況依存であることは、必ずしも「解析が難しい」という意味ではありません。悪名高いa * b;「あいまいさ」は、typedef以前に遭遇したを含むシンボルテーブルで解決できるため、Cは実際にはそれほど難しくありません。C ++が時々行うようなケースを解決するために、任意のテンプレートのインスタンス化(チューリング完全であることが証明されている)を必要としません。C ++と同じコンテキスト依存性があっても、有限時間でコンパイルされないCプログラムを作成することは実際には不可能です。

Python(およびその他の空白を区別する言語)もインデントトークンとデデントトークンを生成するためにレクサーの状態を必要とするため、コンテキストに依存しますが、通常のLL-1文法よりも解析が難しくなることはありません。実際には、パーサージェネレーターを使用しています。これは、Pythonにこのような情報のない構文エラーメッセージがある理由の一部です。ここではa * b;、Python の問題のような「あいまいさ」がないことにも注意してください。最初の段落で述べたように、「あいまいな」文法のない状況依存言語の良い具体例を示します。


-4

この回答は、C ++はコンテキストフリーではないことを示しています...解析できないという意味(回答者によるものではない)があり、その回答は、特定の定数がaでない場合に無効なC ++プログラムを生成する難しいコード例を提供します素数。

他の人が観察したように、言語が文脈依存/自由かどうかについての質問は、特定の文法についての同じ質問とは異なります。

解析可能性に関する問題を解決するために、C ++にはコンテキストフリーの文法があるという実証的な証拠を提供します。これを使用して、実際に既存のGLRで構文解析することにより、ソーステキストのコンテキストフリーの構文解析用のASTを生成できます。 -parserベースのツールで、明示的な文法によって駆動されます。

はい、それは「受け入れすぎる」ことで成功します。受け入れるすべてが有効なC ++プログラムであるとは限らないため、追加のチェック(型チェック)が行われます。そして、はい、型チェッカーは計算可能性の問題に遭遇するかもしれません。実際には、ツールにはこの問題はありません。人々がそのようなプログラムを書いた場合、それらはどれもコンパイルされません。(私は標準がテンプレートを展開することができる計算の量に実際に制限を課すと思うので、実際には計算は実際には有限ですがおそらくかなり大きいです)。

つまり、ソースプログラムが有効なC ++ソースプログラムのセットのメンバーであるかどうかを判断します。問題がかなり難しいことに同意します。しかし、問題は解析ではありません。

このツールは、解析されたプログラムの型チェックから解析を分離することにより、この問題を解決します。(コンテキストがない場合に複数の解釈がある場合は、解析ツリーに曖昧なノードが記録れ、いくつかの可能な解析が行われます。型チェックにより、どちらが正しいかが判断され、無効なサブツリーが削除されます)。以下の例では、(部分的な)解析ツリーを見ることができます。ツリー全体が大きすぎてSOの答えに収まりません。値234797または234799が使用されているかどうかにかかわらず、解析ツリーが表示されることに注意してください。

元の値234799でASTを介してツールの名前/タイプリゾルバーを実行すると、成功します。値が234797の場合、名前リゾルバーは(予想どおり)失敗し、「typenはタイプではありません」というエラーメッセージが表示されます。したがって、そのバージョンは有効なC ++プログラムではありません。

967 tree nodes in tree.
15 ambiguity nodes in tree.
(translation_unit@Cpp~GCC5=2#6b11a20^0 Line 1 Column 1 File C:/temp/prime_with_templates.cpp
 (declaration_seq@Cpp~GCC5=1021#6b06640^1#6b11a20:1 {10} Line 1 Column 1 File C:/temp/prime_with_templates.cpp
  (pp_declaration_seq@Cpp~GCC5=1022#6b049a0^1#6b06640:1 Line 1 Column 1 File C:/temp/prime_with_templates.cpp
   (declaration@Cpp~GCC5=1036#6b04980^1#6b049a0:1 Line 1 Column 1 File C:/temp/prime_with_templates.cpp
   |(template_declaration@Cpp~GCC5=2079#6b04960^1#6b04980:1 Line 1 Column 1 File C:/temp/prime_with_templates.cpp
   | (template_parameter_list@Cpp~GCC5=2082#6afbde0^1#6b04960:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp
   |  (template_parameter@Cpp~GCC5=2085#6afbd80^1#6afbde0:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp
   |   (parameter_declaration@Cpp~GCC5=1611#6afbd40^1#6afbd80:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp
   |   |(basic_decl_specifier_seq@Cpp~GCC5=1070#6afb880^1#6afbd40:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp
   |   | (decl_specifier@Cpp~GCC5=1073#6afb840^1#6afb880:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp
   |   |  (trailing_type_specifier@Cpp~GCC5=1118#6afb7e0^1#6afb840:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp
   |   |   (simple_type_specifier@Cpp~GCC5=1138#6afb7a0^1#6afb7e0:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp)simple_type_specifier
   |   |  )trailing_type_specifier#6afb7e0
   |   | )decl_specifier#6afb840
   |   |)basic_decl_specifier_seq#6afb880
   |   |(ptr_declarator@Cpp~GCC5=1417#6afbc40^1#6afbd40:2 Line 1 Column 15 File C:/temp/prime_with_templates.cpp
   |   | (noptr_declarator@Cpp~GCC5=1421#6afbba0^1#6afbc40:1 Line 1 Column 15 File C:/temp/prime_with_templates.cpp
   |   |  (declarator_id@Cpp~GCC5=1487#6afbb80^1#6afbba0:1 Line 1 Column 15 File C:/temp/prime_with_templates.cpp
   |   |   (id_expression@Cpp~GCC5=317#6afbaa0^1#6afbb80:1 Line 1 Column 15 File C:/temp/prime_with_templates.cpp
   |   |   |(unqualified_id@Cpp~GCC5=319#6afb9c0^1#6afbaa0:1 Line 1 Column 15 File C:/temp/prime_with_templates.cpp
   |   |   | (IDENTIFIER@Cpp~GCC5=3368#6afb780^1#6afb9c0:1[`V'] Line 1 Column 15 File C:/temp/prime_with_templates.cpp)IDENTIFIER
   |   |   |)unqualified_id#6afb9c0
   |   |   )id_expression#6afbaa0
   |   |  )declarator_id#6afbb80
   |   | )noptr_declarator#6afbba0
   |   |)ptr_declarator#6afbc40
   |   )parameter_declaration#6afbd40
   |  )template_parameter#6afbd80
   | )template_parameter_list#6afbde0
   | (declaration@Cpp~GCC5=1033#6b04940^1#6b04960:2 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
   |  (block_declaration@Cpp~GCC5=1050#6b04920^1#6b04940:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
   |   (simple_declaration@Cpp~GCC5=1060#6b04900^1#6b04920:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
   |   |(basic_decl_specifier_seq@Cpp~GCC5=1070#6b048e0^1#6b04900:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
   |   | (decl_specifier@Cpp~GCC5=1073#6b048c0^1#6b048e0:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
   |   |  (type_specifier@Cpp~GCC5=1110#6b048a0^1#6b048c0:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
   |   |   (class_specifier@Cpp~GCC5=1761#6b04880^1#6b048a0:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
   |   |   |(class_head@Cpp~GCC5=1763#6afb980^1#6b04880:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
   |   |   | (class_key@Cpp~GCC5=1791#6afbca0^1#6afb980:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp)class_key
   |   |   | (IDENTIFIER@Cpp~GCC5=3368#6afbcc0^1#6afb980:2[`answer'] Line 1 Column 25 File C:/temp/prime_with_templates.cpp)IDENTIFIER
   |   |   | (optional_base_clause@Cpp~GCC5=1872#6afba60^1#6afb980:3 Line 1 Column 32 File C:/temp/prime_with_templates.cpp)optional_base_clause
   |   |   |)class_head#6afb980
   |   |   |(member_specification@Cpp~GCC5=1794#6b042e0^1#6b04880:2 {2} Line 1 Column 34 File C:/temp/prime_with_templates.cpp
   |   |   | (member_declaration_or_access_specifier@Cpp~GCC5=1806#6b04060^1#6b042e0:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
   |   |   |  (member_declaration@Cpp~GCC5=1822#6b04040^1#6b04060:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
   |   |   |   (function_definition@Cpp~GCC5=1632#6b04020^1#6b04040:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
   |   |   |   |(function_head@Cpp~GCC5=1673#6afbec0^1#6b04020:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
   |   |   |   | (ptr_declarator@Cpp~GCC5=1417#6afbfe0^1#6afbec0:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
   |   |   |   |  (noptr_declarator@Cpp~GCC5=1422#6afbf80^1#6afbfe0:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
   |   |   |   |   (noptr_declarator@Cpp~GCC5=1421#6afbf60^1#6afbf80:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |(declarator_id@Cpp~GCC5=1487#6afbea0^1#6afbf60:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
   |   |   |   |   | (id_expression@Cpp~GCC5=317#6afbb40^1#6afbea0:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |  (unqualified_id@Cpp~GCC5=319#6afbc80^1#6afbb40:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |   (IDENTIFIER@Cpp~GCC5=3368#6afbc20^1#6afbc80:1[`answer'] Line 1 Column 34 File C:/temp/prime_with_templates.cpp)IDENTIFIER
   |   |   |   |   |  )unqualified_id#6afbc80
   |   |   |   |   | )id_expression#6afbb40
   |   |   |   |   |)declarator_id#6afbea0
   |   |   |   |   )noptr_declarator#6afbf60
   |   |   |   |   (parameter_declaration_clause@Cpp~GCC5=1559#6afbd00^1#6afbf80:2 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |(pp_parameter_declaration_list@Cpp~GCC5=1570#6afb940^1#6afbd00:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
   |   |   |   |   | (pp_parameter_declaration_seq@Cpp~GCC5=1574#6afb800^1#6afb940:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |  (parameter_declaration@Cpp~GCC5=1610#6afb9a0^1#6afb800:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |   (basic_decl_specifier_seq@Cpp~GCC5=1070#6afbf40^1#6afb9a0:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |   |(decl_specifier@Cpp~GCC5=1073#6afbfa0^1#6afbf40:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |   | (trailing_type_specifier@Cpp~GCC5=1118#6afbfc0^1#6afbfa0:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |   |  (simple_type_specifier@Cpp~GCC5=1140#6afb860^1#6afbfc0:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp)simple_type_specifier
   |   |   |   |   |   | )trailing_type_specifier#6afbfc0
   |   |   |   |   |   |)decl_specifier#6afbfa0
   |   |   |   |   |   )basic_decl_specifier_seq#6afbf40
   |   |   |   |   |  )parameter_declaration#6afb9a0
   |   |   |   |   | )pp_parameter_declaration_seq#6afb800
   |   |   |   |   |)pp_parameter_declaration_list#6afb940
   |   |   |   |   )parameter_declaration_clause#6afbd00
   |   |   |   |   (function_qualifiers@Cpp~GCC5=1438#6afbce0^1#6afbf80:3 Line 1 Column 46 File C:/temp/prime_with_templates.cpp)function_qualifiers
   |   |   |   |  )noptr_declarator#6afbf80
   |   |   |   | )ptr_declarator#6afbfe0
   |   |   |   |)function_head#6afbec0
   |   |   |   |(function_body@Cpp~GCC5=1680#6b04000^1#6b04020:2 Line 1 Column 46 File C:/temp/prime_with_templates.cpp
   |   |   |   | (compound_statement@Cpp~GCC5=888#6afbee0^1#6b04000:1 Line 1 Column 46 File C:/temp/prime_with_templates.cpp)compound_statement
   |   |   |   |)function_body#6b04000
   |   |   |   )function_definition#6b04020
   |   |   |  )member_declaration#6b04040
   |   |   | )member_declaration_or_access_specifier#6b04060
   |   |   | (member_declaration_or_access_specifier@Cpp~GCC5=1806#6b042c0^1#6b042e0:2 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
   |   |   |  (member_declaration@Cpp~GCC5=1822#6b04820^1#6b042c0:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
   |   |   |   (function_definition@Cpp~GCC5=1632#6b04280^1#6b04820:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
   |   |   |   |(function_head@Cpp~GCC5=1674#6b04220^1#6b04280:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
   |   |   |   | (basic_decl_specifier_seq@Cpp~GCC5=1070#6b040e0^1#6b04220:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
   |   |   |   |  (decl_specifier@Cpp~GCC5=1073#6b040c0^1#6b040e0:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
   |   |   |   |   (trailing_type_specifier@Cpp~GCC5=1118#6b040a0^1#6b040c0:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |(simple_type_specifier@Cpp~GCC5=1138#6b04080^1#6b040a0:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp)simple_type_specifier
   |   |   |   |   )trailing_type_specifier#6b040a0
   |   |   |   |  )decl_specifier#6b040c0
   |   |   |   | )basic_decl_specifier_seq#6b040e0
   |   |   |   | (ptr_declarator@Cpp~GCC5=1417#6b04200^1#6b04220:2 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
   |   |   |   |  (noptr_declarator@Cpp~GCC5=1422#6b041e0^1#6b04200:1 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
   |   |   |   |   (noptr_declarator@Cpp~GCC5=1421#6b041a0^1#6b041e0:1 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |(declarator_id@Cpp~GCC5=1487#6b04180^1#6b041a0:1 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
   |   |   |   |   | (id_expression@Cpp~GCC5=317#6b04160^1#6b04180:1 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |  (unqualified_id@Cpp~GCC5=320#6b04140^1#6b04160:1 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |   (operator_function_id@Cpp~GCC5=2027#6b04120^1#6b04140:1 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |   |(operator@Cpp~GCC5=2070#6b04100^1#6b04120:1 Line 1 Column 62 File C:/temp/prime_with_templates.cpp)operator
   |   |   |   |   |   )operator_function_id#6b04120
   |   |   |   |   |  )unqualified_id#6b04140
   |   |   |   |   | )id_expression#6b04160
   |   |   |   |   |)declarator_id#6b04180
   |   |   |   |   )noptr_declarator#6b041a0
   |   |   |   |   (parameter_declaration_clause@Cpp~GCC5=1558#6afba40^1#6b041e0:2 Line 1 Column 65 File C:/temp/prime_with_templates.cpp)parameter_declaration_clause
   |   |   |   |   (function_qualifiers@Cpp~GCC5=1438#6b041c0^1#6b041e0:3 Line 1 Column 66 File C:/temp/prime_with_templates.cpp)function_qualifiers
   |   |   |   |  )noptr_declarator#6b041e0
   |   |   |   | )ptr_declarator#6b04200
   |   |   |   |)function_head#6b04220
   |   |   |   |(function_body@Cpp~GCC5=1680#6b04300^1#6b04280:2 Line 1 Column 66 File C:/temp/prime_with_templates.cpp
   |   |   |   | (compound_statement@Cpp~GCC5=889#6b04760^1#6b04300:1 Line 1 Column 66 File C:/temp/prime_with_templates.cpp
   |   |   |   |  (pp_statement_seq@Cpp~GCC5=894#6b04780^1#6b04760:1 Line 1 Column 67 File C:/temp/prime_with_templates.cpp
   |   |   |   |   (statement@Cpp~GCC5=857#6b04440^1#6b04780:1 Line 1 Column 67 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |(jump_statement@Cpp~GCC5=1011#6afba80^1#6b04440:1 Line 1 Column 67 File C:/temp/prime_with_templates.cpp
   |   |   |   |   | (pm_expression@Cpp~GCC5=551#6b04380^1#6afba80:1 Line 1 Column 74 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |  (cast_expression@Cpp~GCC5=543#6b04360^1#6b04380:1 Line 1 Column 74 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |   (unary_expression@Cpp~GCC5=465#6b04340^1#6b04360:1 Line 1 Column 74 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |   |(primary_expression@Cpp~GCC5=307#6b04320^1#6b04340:1 Line 1 Column 74 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |   | (id_expression@Cpp~GCC5=317#6b042a0^1#6b04320:1 Line 1 Column 74 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |   |  (unqualified_id@Cpp~GCC5=319#6b04260^1#6b042a0:1 Line 1 Column 74 File C:/temp/prime_with_templates.cpp
   |   |   |   |   |   |   (IDENTIFIER@Cpp~GCC5=3368#6b04240^1#6b04260:1[`V'] Line 1 Column 74 File C:/temp/prime_with_templates.cpp)IDENTIFIER
   |   |   |   |   |   |  )unqualified_id#6b04260
   |   |   |   |   |   | )id_expression#6b042a0
   |   |   |   |   |   |)primary_expression#6b04320
   |   |   |   |   |   )unary_expression#6b04340
   |   |   |   |   |  )cast_expression#6b04360
   |   |   |   |   | )pm_expression#6b04380
   |   |   |   |   |)jump_statement#6afba80
   |   |   |   |   )statement#6b04440
   |   |   |   |  )pp_statement_seq#6b04780
   |   |   |   | )compound_statement#6b04760
   |   |   |   |)function_body#6b04300
   |   |   |   )function_definition#6b04280
   |   |   |  )member_declaration#6b04820
   |   |   | )member_declaration_or_access_specifier#6b042c0
   |   |   |)member_specification#6b042e0
   |   |   )class_specifier#6b04880
   |   |  )type_specifier#6b048a0
   |   | )decl_specifier#6b048c0
   |   |)basic_decl_specifier_seq#6b048e0
   |   )simple_declaration#6b04900
   |  )block_declaration#6b04920
   | )declaration#6b04940
   |)template_declaration#6b04960
   )declaration#6b04980
  )pp_declaration_seq#6b049a0
  (pp_declaration_seq@Cpp~GCC5=1022#6b06620^1#6b06640:2 Line 3 Column 1 File C:/temp/prime_with_templates.cpp
   (declaration@Cpp~GCC5=1036#6b06600^1#6b06620:1 Line 3 Column 1 File C:/temp/prime_with_templates.cpp
   |(template_declaration@Cpp~GCC5=2079#6b065e0^1#6b06600:1 Line 3 Column 1 File C:/temp/prime_with_templates.cpp
   | (template_parameter_list@Cpp~GCC5=2083#6b05460^1#6b065e0:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
   |  (template_parameter_list@Cpp~GCC5=2083#6b05140^1#6b05460:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
   |   (template_parameter_list@Cpp~GCC5=2083#6b04ee0^1#6b05140:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
   |   |(template_parameter_list@Cpp~GCC5=2082#6b04cc0^1#6b04ee0:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
   |   | (template_parameter@Cpp~GCC5=2085#6b04ca0^1#6b04cc0:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
   |   |  (parameter_declaration@Cpp~GCC5=1611#6b04c80^1#6b04ca0:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
   |   |   (basic_decl_specifier_seq@Cpp~GCC5=1070#6b04a40^1#6b04c80:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
   |   |   |(decl_specifier@Cpp~GCC5=1073#6b04a20^1#6b04a40:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
   |   |   | (trailing_type_specifier@Cpp~GCC5=1118#6b04a00^1#6b04a20:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
   |   |   |  (simple_type_specifier@Cpp~GCC5=1138#6b049e0^1#6b04a00:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp)simple_type_specifier
   |   |   | )trailing_type_specifier#6b04a00
   |   |   |)decl_specifier#6b04a20
   |   |   )basic_decl_specifier_seq#6b04a40
   |   |   (ptr_declarator@Cpp~GCC5=1417#6b04c40^1#6b04c80:2 Line 3 Column 15 File C:/temp/prime_with_templates.cpp
   |   |   |(noptr_declarator@Cpp~GCC5=1421#6b04be0^1#6b04c40:1 Line 3 Column 15 File C:/temp/prime_with_templates.cpp
   |   |   | (declarator_id@Cpp~GCC5=1487#6b04bc0^1#6b04be0:1 Line 3 Column 15 File C:/temp/prime_with_templates.cpp
   |   |   |  (id_expression@Cpp~GCC5=317#6b04b60^1#6b04bc0:1 Line 3 Column 15 File C:/temp/prime_with_templates.cpp
   |   |   |   (unqualified_id@Cpp~GCC5=319#6b04ac0^1#6b04b60:1 Line 3 Column 15 File C:/temp/prime_with_templates.cpp
   |   |   |   |(IDENTIFIER@Cpp~GCC5=3368#6b049c0^1#6b04ac0:1[`no'] Line 3 Column 15 File C:/temp/prime_with_templates.cpp)IDENTIFIER
   |   |   |   )unqualified_id#6b04ac0
   |   |   |  )id_expression#6b04b60
   |   |   | )declarator_id#6b04bc0
   |   |   |)noptr_declarator#6b04be0
   |   |   )ptr_declarator#6b04c40
   |   |  )parameter_declaration#6b04c80
   |   | )template_parameter#6b04ca0
   |   |)template_parameter_list#6b04cc0
   |   |(template_parameter@Cpp~GCC5=2085#6b04ec0^1#6b04ee0:2 Line 3 Column 19 File C:/temp/prime_with_templates.cpp
   |   | (parameter_declaration@Cpp~GCC5=1611#6b04ea0^1#6b04ec0:1 Line 3 Column 19 File C:/temp/prime_with_templates.cpp
   |   |  (basic_decl_specifier_seq@Cpp~GCC5=1070#6b04b40^1#6b04ea0:1 Line 3 Column 19 File C:/temp/prime_with_templates.cpp
   |   |   (decl_specifier@Cpp~GCC5=1073#6b04ba0^1#6b04b40:1 Line 3 Column 19 File C:/temp/prime_with_templates.cpp
   |   |   |(trailing_type_specifier@Cpp~GCC5=1118#6b04c60^1#6b04ba0:1 Line 3 Column 19 File C:/temp/prime_with_templates.cpp
   |   |   | (simple_type_specifier@Cpp~GCC5=1138#6b04580^1#6b04c60:1 Line 3 Column 19 File C:/temp/prime_with_templates.cpp)simple_type_specifier
   |   |   |)trailing_type_specifier#6b04c60
   |   |   )decl_specifier#6b04ba0
   |   |  )basic_decl_specifier_seq#6b04b40
   |   |  (ptr_declarator@Cpp~GCC5=1417#6b04e60^1#6b04ea0:2 Line 3 Column 24 File C:/temp/prime_with_templates.cpp
   |   |   (noptr_declarator@Cpp~GCC5=1421#6b04e40^1#6b04e60:1 Line 3 Column 24 File C:/temp/prime_with_templates.cpp
   |   |   |(declarator_id@Cpp~GCC5=1487#6b04de0^1#6b04e40:1 Line 3 Column 24 File C:/temp/prime_with_templates.cpp
   |   |   | (id_expression@Cpp~GCC5=317#6b04d80^1#6b04de0:1 Line 3 Column 24 File C:/temp/prime_with_templates.cpp
   |   |   |  (unqualified_id@Cpp~GCC5=319#6b04ce0^1#6b04d80:1 Line 3 Column 24 File C:/temp/prime_with_templates.cpp
   |   |   |   (IDENTIFIER@Cpp~GCC5=3368#6b04560^1#6b04ce0:1[`yes'] Line 3 Column 24 File C:/temp/prime_with_templates.cpp)IDENTIFIER
   |   |   |  )unqualified_id#6b04ce0
   |   |   | )id_expression#6b04d80
   |   |   |)declarator_id#6b04de0
   |   |   )noptr_declarator#6b04e40
   |   |  )ptr_declarator#6b04e60
   |   | )parameter_declaration#6b04ea0
   |   |)template_parameter#6b04ec0
   |   )template_parameter_list#6b04ee0
   |   (template_parameter@Cpp~GCC5=2085#6b05120^1#6b05140:2 Line 3 Column 29 File C:/temp/prime_with_templates.cpp
   |   |(parameter_declaration@Cpp~GCC5=1611#6b05100^1#6b05120:1 Line 3 Column 29 File C:/temp/prime_with_templates.cpp
   |   | (basic_decl_specifier_seq@Cpp~GCC5=1070#6b04d20^1#6b05100:1 Line 3 Column 29 File C:/temp/prime_with_templates.cpp
   |   |  (decl_specifier@Cpp~GCC5=1073#6b04dc0^1#6b04d20:1 Line 3 Column 29 File C:/temp/prime_with_templates.cpp
   |   |   (trailing_type_specifier@Cpp~GCC5=1118#6b04e80^1#6b04dc0:1 Line 3 Column 29 File C:/temp/prime_with_templates.cpp
   |   |   |(simple_type_specifier@Cpp~GCC5=1140#6b046e0^1#6b04e80:1 Line 3 Column 29 File C:/temp/prime_with_templates.cpp)simple_type_specifier
   |   |   )trailing_type_specifier#6b04e80
   |   |  )decl_specifier#6b04dc0
   |   | )basic_decl_specifier_seq#6b04d20
   |   | (ptr_declarator@Cpp~GCC5=1417#6b05080^1#6b05100:2 Line 3 Column 33 File C:/temp/prime_with_templates.cpp
   |   |  (noptr_declarator@Cpp~GCC5=1421#6b05020^1#6b05080:1 Line 3 Column 33 File C:/temp/prime_with_templates.cpp
   |   |   (declarator_id@Cpp~GCC5=1487#6b05000^1#6b05020:1 Line 3 Column 33 File C:/temp/prime_with_templates.cpp
   |   |   |(id_expression@Cpp~GCC5=317#6b04fa0^1#6b05000:1 Line 3 Column 33 File C:/temp/prime_with_templates.cpp
   |   |   | (unqualified_id@Cpp~GCC5=319#6b04f00^1#6b04fa0:1 Line 3 Column 33 File C:/temp/prime_with_templates.cpp
   |   |   |  (IDENTIFIER@Cpp~GCC5=3368#6b046c0^1#6b04f00:1[`f'] Line 3 Column 33 File C:/temp/prime_with_templates.cpp)IDENTIFIER
   |   |   | )unqualified_id#6b04f00
   |   |   |)id_expression#6b04fa0
   |   |   )declarator_id#6b05000
   |   |  )noptr_declarator#6b05020
   |   | )ptr_declarator#6b05080
   |   |)parameter_declaration#6b05100
   |   )template_parameter#6b05120
   |  )template_parameter_list#6b05140
   |  (template_parameter@Cpp~GCC5=2085#6b05440^1#6b05460:2 Line 3 Column 36 File C:/temp/prime_with_templates.cpp
   |   (parameter_declaration@Cpp~GCC5=1611#6b05420^1#6b05440:1 Line 3 Column 36 File C:/temp/prime_with_templates.cpp
   |   |(basic_decl_specifier_seq@Cpp~GCC5=1070#6b05160^1#6b05420:1 Line 3 Column 36 File C:/temp/prime_with_templates.cpp
   |   | (decl_specifier@Cpp~GCC5=1073#6b04fe0^1#6b05160:1 Line 3 Column 36 File C:/temp/prime_with_templates.cpp
   |   |  (trailing_type_specifier@Cpp~GCC5=1118#6b050e0^1#6b04fe0:1 Line 3 Column 36 File C:/temp/prime_with_templates.cpp
   |   |   (simple_type_specifier@Cpp~GCC5=1140#6b050c0^1#6b050e0:1 Line 3 Column 36 File C:/temp/prime_with_templates.cpp)simple_type_specifier
   |   |  )trailing_type_specifier#6b050e0
   |   | )decl_specifier#6b04fe0
   |   |)basic_decl_specifier_seq#6b05160
   |   |(ptr_declarator@Cpp~GCC5=1417#6b053e0^1#6b05420:2 Line 3 Column 40 File C:/temp/prime_with_templates.cpp
   |   | (noptr_declarator@Cpp~GCC5=1421#6b053c0^1#6b053e0:1 Line 3 Column 40 File C:/temp/prime_with_templates.cpp
   |   |  (declarator_id@Cpp~GCC5=1487#6b05360^1#6b053c0:1 Line 3 Column 40 File C:/temp/prime_with_templates.cpp
   |   |   (id_expression@Cpp~GCC5=317#6b05280^1#6b05360:1 Line 3 Column 40 File C:/temp/prime_with_templates.cpp
   |   |   |(unqualified_id@Cpp~GCC5=319#6b051a0^1#6b05280:1 Line 3 Column 40 File C:/temp/prime_with_templates.cpp
   |   |   | (IDENTIFIER@Cpp~GCC5=3368#6b046a0^1#6b051a0:1[`p'] Line 3 Column 40 File C:/temp/prime_with_templates.cpp)IDENTIFIER
   |   |   |)unqualified_id#6b051a0
   |   |   )id_expression#6b05280
   |   |  )declarator_id#6b05360
   |   | )noptr_declarator#6b053c0
   |   |)ptr_declarator#6b053e0
   |   )parameter_declaration#6b05420
   |  )template_parameter#6b05440
   | )template_parameter_list#6b05460

それが変数宣言であるか乗算であるかを判別することは、型チェック機能ではありません。また、私はその自己宣伝に関するあなたの答えをスクラブする必要がありました...もう一度。
パピー

@Puppy:好きなことを言うことができますが、それがツールの機能です。ツール名を削除することは、おそらくツール名が何であるかを人々に尋ねさせることになるでしょう。
Ira Baxter、2016年

それがツールの動作方法であるかどうかは関係ありません。質問はツールの動作を要求しないためです。また、それが実際に起こるのを安全に待つことができると思います。
パピー、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.