4

私は個人的な娯楽のためにCのような文法に取り組んできました。しかし、私はシフト/削減の競合に遭遇しており、それらは解決できると確信しています。

今のところ、私のexpressions見た目は、簡略化された形式で、アクションが取り除かれています。

%left '+' '-'

%%
expr
 : NUMBER
 | IDENTIFIER
 | expr '+' expr
 | expr '-' expr
 /* other operators like '*', '/', etc. */
 | expr '(' expr ')' /* function call */
%%

ただし、これにより、shift / reduceの競合が発生します。パーサーは、括弧の処理方法について確信が持てません。私の言うことから-v、のような表現が括弧にexpr '+' expr '('還元expr '+' exprされるべきか、exprそれともシフトされるべきかは不明です。

もちろん、かっこをずらして欲しいです。foo % bar(4)で終わるべきではありません(foo % bar)(4)。しかし、私は%precその意味のディレクティブを使用して成功していません。ルールを追加%left FUNCALLしたり%prec FUNCALL、ルールを追加したりしても、変更はありません。

シフト/リデュースに遭遇したときにBisonのLALRパーサーが進むデフォルトのパスはシフトであり、問​​題%expectを回避するために使用できることを私は知っています。ただし、式ごとに1つの競合が生成され、そのリストを変更する必要がある場合は、宣言も変更する必要があります。これは、私にはかなり醜い解決策のように見えます。その上、あなたの賢い子供たちの一人がその問題の解決策を持っていると確信しています。%expect

私の目標は、上記のルールと同様のルールを作成することです。Bisonは'('、関数呼び出しルールからfromに遭遇するたびに、shift / reduceの競合なしに、括弧をシフトしていることを認識します。ちなみに、ディレクティブの使用法は%prec次のとおりです。間違っている場合は、修正できます。シフト/削減の競合があります。

%left '+' '-'
%left FUNCALL

%%

expr
    : NUMBER
    | IDENTIFIER
    | expr '+' expr
    | expr '-' expr
    /* other operators like '*', '/', etc. */
    | expr '(' expr ')' %prec FUNCALL /* function call */

%%
4

1 に答える 1

4

%left '('優先順位ルールに追加する必要があります (または%nonassoc '('、より良いかもしれません)。

優先順位が yacc/bison の shift/reduce 競合を解決する方法は、削減されるルールの優先順位とシフトされるトークンの優先順位を比較することです。あなたの例では、競合は a の削減expr: expr '+' exprとシフトの間'('であるため、それを解決するには、優先順位が必要です'('(そして、から来るルールよりも高くしたい'+')

この%precディレクティブは、rhs の最初のトークンに由来するデフォルトの優先順位をオーバーライドして、ルールの優先順位を設定するだけです。ルールに表示されるトークンの優先順位にはまったく影響しません。

于 2010-01-15T00:44:52.513 に答える