1

このコードが機能すると仮定します。

left '*'
left '+'

expr: expr '+' expr
    | expr '*' expr
    ;

次のような他の優先順位マーカーを定義したい:

left MULTIPLY
left PLUS

expr: expr '+' expr %prec PLUS
    | expr '*' expr %prec MULTIPLY
    ;

しかし、これは実際には効果的ではありません。

これら 2 つの形式は同等であるはずですが、そうではありません。

実用上の問題ではありません。この現象の理由と原理を知りたいだけです。

ありがとう。

4

3 に答える 3

3

あなたは、特定の実際的な問題を解決しようとしているのではないと言います。そして、あなたの質問から、優先順位マーカーをどのように使用しようとしているのかについて少し混乱しています。

優先順位マーカーを頻繁に使用する必要がないことがわかると思います。優先順位が明示的に考慮されるように文法を書き直す方が、通常はより単純で、読者にとってより明確です。乗算と除算を足し算と引き算よりも優先するには、次のようにします (John Levine、lex & yacc 2/e、1992 からの例)。

%token NAME NUMBER

%%

stmt : NAME '=' expr
     | expr
     ;

expr : expr '+' term
     | expr '-' term
     | term
     ;

term : term '*' factor
     | term '/' factor
     | factor
     ;

factor : '(' expr ')'
       | '-' factor
       | NUMBER
       ;

あなたの例では、実際のトークンではありませんPLUS。および とMULTIPLY同じ意味で使用することはできません。Levine はそれらを疑似トークンと呼んでいます。それらは、プロダクションを、および宣言で定義した優先順位のリストにリンクするためにあります。彼は、「-」トークンの優先順位が低い場合でも、単項マイナスの優先順位を高くするために使用する方法の例を示しています。'+''*'%left%nonassoc%prec

%token NAME NUMBER
%left '-' '+'
%left '*' '/'
%nonassoc UMINUS

%%

stmt : NAME '=' expr
     | expr
     ;

expr : expr '+' expr
     | expr '-' expr
     | expr '*' expr
     | expr '/' expr
     | '-' expr %prec UMINUS
     | '(' expr ')'
     | NUMBER
     ;

要約すると、2 番目のコード例ではなく、最初のコード例のパターンに従うことをお勧めします。文法を明確にする。

于 2012-06-11T23:29:18.333 に答える
0

Shift-reduce 競合は、プロダクションを削減しようとすることと、トークンをシフトしてネスト状態に移行することとの間の競合です。Bison が競合を解決するとき、2 つのルールを比較してそのうちの 1 つを選択するのではなく、削減したい 1 つのルールと、他のルールでシフトしたいトークンを比較します。シフトするルールが 2 つある場合、これはより明確になる可能性があります。

expr: expr '+' expr
    | expr '*' expr
    | expr '*' '*' expr

これがすべて紛らわしい理由は、Bison が「reduce」ルールに優先順位を与える方法は、それをトークン (デフォルトではルールの最後の端末または prec 宣言のトークン) に関連付けてから、優先順位を使用することです。テーブルを使用して、そのトークンをシフトしようとしているトークンと比較します。基本的に、プレ宣言は競合の「削減」部分に対してのみ意味があり、シフト部分にはカウントされません。

これを確認する 1 つの方法は、次の文法を使用することです。

command: IF '(' expr ')' command               %prec NOELSE
       : IF '(' expr ')' command ELSE command

この文法では、最初のルールを減らすか、ELSE トークンをシフトするかを選択する必要があります。これを行うには、')' トークンと ELSE トークンを優先するか、または prec 宣言を使用して ')' の代わりに NOELSE を優先します。秒に prec 宣言を与えようとすると、それは無視され、Bison は優先順位テーブルで ELSE トークンの優先順位を探し続けます。

于 2013-09-21T14:13:50.173 に答える