2012-02-01 7 views
3

GLRメソッドでshift \ reduceの競合を解決するにはどうすればよいですか?
右シフト演算子とそれ自身のテンプレート引数の2つの閉じ角括弧の間の競合をパーサが解決するようにしたいとします。レクサーは2つの連続した ">"記号を別々のトークンとして1つの ">>"トークンにマージせずに渡します。次に、私は文法にこれらのルールを入れます:Bison、C++ GLR解析:シフトを強制する方法競合を減らすには?

operator_name: 
    "operator" ">" 
    | "operator" ">" ">" 
; 

私はこれをshift \ reduce conflictにしたいと思います。左の結合性を持つ ">"のトークン宣言があれば、これは矛盾しません。だから私はトークン優先順位\連想性の宣言を削除する必要がありますが、これは、競合する各ルールのコンテキスト優先順位を指定して手動で解決したくない他の多くの競合を引き起こします。だから、トークンを宣言している間にshift \ reduce conflictを強制する方法はありますか?

+0

">"は、シフト演算子またはテンプレート終了タグトークンとは別のトークンとして扱われます。同じことが " - "、負の符号または減算演算子の場合に発生します – umlcat

+0

はい、C#とJavaではこの手法を使用していましたが、ANTLRベースのパーサーであり、単純なものでした。 – slavasav

答えて

2

operator_nameのルールでcontext-dependent precedenceを使用すると効果があります。

更新された標準で指定されているC++文法は、実際に>>トークンを2つの開いているテンプレート宣言を閉じるものとして受け入れるように文法を変更します。私は標準的な動作を得るためにそれをフォローすることをお勧めします。たとえば、 "x >> y"が "x >> y"として解析されないように注意する必要があります。また、 "foo < bar < 2 >> 1 >>"は無効です。 "foo <バー<(2 >> 1)>>が有効です。

+0

bisonは、コンテキスト依存の優先順位を指定すると、競合が解決されたとみなします。つまり、最初のルールの優先順位を2番目のルールの優先順位と同じにすることを明示的に指定して、シフトを減らすように指定すると、bisonはglrによって解決される競合を残す代わりにシフトすることを選択しますランタイム。 – slavasav

0

私は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 ">" 
; 

乾杯。

+0

私は、事例を明らかにするために演算子の例を使用しました。 「私たちの心はコンパイラのように動作する」ことを考慮すると、私は同意し、無限の先読みを使って構文解析に影響を与える方法があります。しかし、この場合、bisonは、何らかの競合を解決するために解析スタックを分割するたびにすべてのセマンティックアクションを延期し、決定的な状態に戻るときにこれらのアクションを実行するため、その時点で構文解析に影響を与えるのは遅すぎます。 – slavasav

関連する問題