var a = X<Y
このトピックでは、ドキュメントの解析中に発生しうる曖昧さおよびその取扱方法について説明します。
このトピックを理解するためには、以下のトピックを理解しておく必要があります。
Syntax Parsing Engine は、ボトムアップ式のパーサーであり、構文ツリーが構文解析中に作成される方向を参照します。左から右へ処理するときにレクサーからトークンに対するノードを作成して開始します。次に、ツリーの各種ブランチをグループ化し、非終端記号を表す親ノードを渡します。この操作は、文章校正の開始記号を表す親ノードをブランチのグループが渡されるまで継続します。各「ブランチのグループ化」には、本文内で定義される順序で生産の本文から記号を表すすべてのノードを発見し、生産からヘッドの非終端記号に関連づけられる親ノードを渡すことが含まれます。この操作は リダクション と呼ばれます。パーサーは生産の本体をヘッド記号に軽減するためです。このプロセスは、パーサーが次のトークンを読み取るかリダクションを実行するために 1 つの作業のみを行う限り非常に高速です。しかしパーサーが実施できる作業が複数あると、あいまいさが起こります。
Syntax Parsing Engine は、あいまいさを処理できますが、それらを渡すとパフォーマンスが影響を受けます。文章校正の定義であいまいさを最小限に維持すると、構文アナライザーはできる限り高速になります。
以下の 2 タイプのあいまいさがあります:
ローカルのあいまいさは、十分なテキストを読み取り後に結果としてパーサーが十分に回復するものです。
たとえば、パーサーが C# ドキュメントを読み取っており、以下で始まるステートメントになると、
C# の場合:
var a = X<Y
パーサーは、以下であるかどうか把握しません。
「X」はジェネリック型の名前であり、「Y」はジェネリック型の名前のパラメータである、たとえば、
C# の場合:
var a = X<Y>.CreateNew();
または「X」および「Y」は変数またはプロパティであり、より小記号 (<) と比較される、たとえば
C# の場合:
var a = X<Y;
しかし、どのような場合でも、パーサーは「Y」を超えて読み取り続けると見当をつけます。このため、あいまいさは一時的なものでありパーサーは結果としてそこから回復します。
グローバルなあいまいさにおいて、1 つのテキストがいくつかの異なる方法に解釈できます。一部の言語では、解釈は使用しなければならないと文章校正ライターがパーサーに伝える限り有効です。
あいまいな C# ステートメントの例
C# の場合:
A(B<C,D>(E+F));
「A」という名前のメソッドが起動されることは明白ですが、メソッドに何が渡されるかはあいまいです。2 つのブール値引数 (“B<C” and “D>(E+F)”) またはジェネリック メソッド呼び出し (“B<C,D>(E+F)”) の戻り値である 1 つの引数のどちらかです。
この問題を解決するには、 NonTerminalSymbol.HasPriority プロパティを使用できます。コンテンツのいずれかの解釈のためのサブツリーにこのプロパティセットを持つ記号がある場合、その解釈はその他に対して選択されます。どちらのサブツリーにも優先順位がある場合、サブツリー内で非終端記号ノードの優先順位が高い方が優先順位を得ます。上記の例では、文章校正ライターはジェネリック型メソッド呼び出しとして解釈されると、ジェネリック型メソッド呼び出しとして解釈しなければならないと指定します。ジェネリック型引数を表す記号上で HasPriority
プロパティを True
に設定すると、あいまいさが取り除かれます。
以下の 2 つの図は、パーサーがこのステートメントのフルコンテンツを読み取ったときに2 つのサブツリーがどのように見えるかについて示しています。
2 つの引数の解釈:
サブツリー内の優先ノードを持つ 1 つの引数解釈
注:
グローバルなあいまいさを解決するもう 1 つの方法は、 LanguageBase 派生クラス上で OnGlobalAmbiguityDetected を上書きすること、または CustomLanguage クラス上で GlobalAmbiguityDetected イベントを取り扱うことです。これらは、ドキュメントの同じコンテンツを表すことができ、開発者がどちらを使用すべきかを選択できる 2 つのサブツリー候補と共に起動されます。解釈の可能性が 2 通り以上ある場合は、これらのメンバーは 1 つのサブツリーのみになるまで複数回起動されます。
グローバルなあいまいさが解決されない場合、つまりグローバルあいまいさメソッド/イベントが処理されない、またはコンテキストオブジェクトの PreferredSubTreeRoot 値が設定されない場合、パーサーはいずれかのサブツリーを任意に選択して使用します。
このトピックの追加情報については、以下のトピックも合わせてご参照ください。