私はYacc(Bisonと同様)で同様のシナリオで作業しました。
標準的な文法は、時には「構文に基づく構文解析」と呼ばれます。
このケースは時には「セマンティクスに基づく構文解析」のようなものです。
例:
...
// shift operator example
if ((x >> 2) == 0)
...
// consecutive template closing tag example
List<String, List<String>> MyList =
...
は、私たちの心は、コンパイラのように動作し、覚えています。人間の心はこれをコンパイルできますが、以前の文法ではできません。 Mhhh。人間の心がどのようにこのコードをコンパイルするかを見てみましょう。
あなたがすでに知っているように、連続する ">"と ">"トークンの前にある "x"は、式または左辺値を示します。心は、 "expireionの後の2つの連続する大なり記号は、単一のシフト演算子トークンになるべきだ"と考えます。
"文字列"トークンの場合: "2つの連続する大なり記号は、型識別子の後に2つの連続するテンプレート終了タグトークンになるはずです"。
このケースは、通常の演算子の優先順位、シフトまたはリダクション、または文法だけでは処理できませんが、パーサー自体が提供するいくつかの関数を使用して(「ハッキングする」)ことはできないと思います。
例の文法ルールではエラーは表示されません。 「演算子」記号は、あなたが言及した2つのケースを混乱させないようにします。シフト演算子が使用されていた文法や連続したテンプレートの終了タグが使用されている部分には注意が必要です。
operator_expr_example:
lvalue "<<" lvalue |
lvalue ">>" lvalue |
lvalue "&&" lvalue |
;
template_params:
identifier |
template_declaration_example |
array_declaration |
other_type_declaration
;
template_declaration_example:
identifier "<" template_params ">"
;
乾杯。
">"は、シフト演算子またはテンプレート終了タグトークンとは別のトークンとして扱われます。同じことが " - "、負の符号または減算演算子の場合に発生します – umlcat
はい、C#とJavaではこの手法を使用していましたが、ANTLRベースのパーサーであり、単純なものでした。 – slavasav