1

私は次の文法を書きました:

%union{
    string *s;
    float num;
}
%token div_token mod_token sqrt_token it_token abs_token
%token <num> num_token 
%token <s> Stampa
%type <num> E


%left '+' '-'
%left '*' '/' div_token mod_token
%left UMINUS
%left abs_token sqrt_token


%%

Program: Program Line '\n'   { }
| Line  '\n' { }
;

Line: Stampa    {cout<<*$1<<endl;}
| E         {cout<<$1<<endl; broj = $1;}
| it_token      {cout<<broj<<endl;}
;

E: E '+' E {$$ = $1 + $3;}
| E '-' E {$$ = $1 - $3;}
| E '*' E {$$ = $1 * $3;}
| E '/' E {if($3!=0) 
              $$ = $1 / $3;
            else
              yyerror("Deljenje nulom");
            }
| mod_token E E {$$ = (float)((int)$2 % (int)$3);}
| div_token E E {$$ = (float)((int)($2 / $3));}
| sqrt_token E  { $$ = sqrt($2); }
| '(' E ')' {$$=$2;}
| abs_token E { $$ = abs($2);}
| '-' E %prec UMINUS {$$=-$2;}
| num_token {$$ = $1;}
;

現在、bison は 8 つの reduce/reduce 競合を発見しました。行を削除すると

| '-' E %prec UMINUS {$$=-$2;}

ありません。優先順位と連想プロパティは明確に定義されていると思います。誰かが競合を解決する方法を教えてもらえますか?

4

2 に答える 2

2

現在、bison は 8 つの reduce/reduce 競合を発見しました。行を削除すると

| '-' E %prec UMINUS {$$=-$2;}

ありません。優先順位と連想プロパティは明確に定義されていると思います。誰かが競合を解決する方法を教えてもらえますか?

これで問題が解決するはずです:

%union{
      string *s;
      float num;
}
%token div_token mod_token sqrt_token it_token abs_token
%token <num> num_token 
%token <s> Stampa
%type <num> E

%left '+' '-'
%left '*' '/' div_token mod_token
%left UMINUS
%left abs_token sqrt_token

%%

Program: Program Line '\n'   { }
| Line  '\n' { }
;

Line: Stampa    {cout<<*$1<<endl;}
| E         {cout<<$1<<endl; broj = $1;}
| it_token      {cout<<broj<<endl;}
;

E: E '+' E {$$ = $1 + $3;}
| E '-' E {$$ = $1 - $3;}
| E '*' E {$$ = $1 * $3;}
| E '/' E {if($3!=0) 
                $$ = $1 / $3;
                    else
                yyerror("Deljenje nulom");
          }
| E mod_token E {$$ = (float)((int)$1 % (int)$3);}
| E div_token E {$$ = (float)((int)($1 / $3));}
| sqrt_token E  { $$ = sqrt($2); }
| '(' E ')' {$$=$2;}
| abs_token E { $$ = abs($2);}
| '-' %prec UMINUS E {$$=-$2;}
| num_token {$$ = $1;}
;

これにより、いくつかの問題が修正されます。あなたはおそらく次のことを意味していました:

| E mod_token E {$$ = (float)((int)$1 % (int)$3);}
| E div_token E {$$ = (float)((int)($1 / $3));}

そして、次のように書くとより明確になります。

| '-' %prec UMINUS E {$$=-$2;}

-v以下を生成するbison オプションとの競合を確認できますxyz.output

state 35

    6 E: E . '+' E
    7  | E . '-' E
    7  | E '-' E .
    8  | E . '*' E
    9  | E . '/' E
   15  | '-' E 

.

    div_token   reduce using rule 7 (E)
    div_token   [reduce using rule 15 (E)]
    mod_token   reduce using rule 7 (E)
    mod_token   [reduce using rule 15 (E)]
    sqrt_token  reduce using rule 7 (E)
    sqrt_token  [reduce using rule 15 (E)]
    abs_token   reduce using rule 7 (E)
    abs_token   [reduce using rule 15 (E)]
    num_token   reduce using rule 7 (E)
    num_token   [reduce using rule 15 (E)]
    '+'         reduce using rule 7 (E)
    '+'         [reduce using rule 15 (E)]
    '-'         reduce using rule 7 (E)
    '-'         [reduce using rule 15 (E)]
    '*'         reduce using rule 15 (E)
    '/'         reduce using rule 15 (E)
    '\n'        reduce using rule 15 (E)
    '('         reduce using rule 7 (E)
    '('         [reduce using rule 15 (E)]
    ')'         reduce using rule 15 (E)
    $default    reduce using rule 7 (E)

オペレーターは を縮小しdiv_tokenmod_token疑いがあります。文法のあいまいさは、これらの演算子が 2 つの式に適用されるために発生しますE

編集

おそらく、接頭辞 div および mod 演算子を保持しようとしているでしょう。もしそうなら、文法を明確にする必要があります。考えられる解決策の1つは次のとおりです。

| mod_token F F {$$ = (float)((int)$2 % (int)$3);}
| div_token F F {$$ = (float)((int)($2 / $3));}
| F
;
F: '(' E ')' {$$=$2;}
| sqrt_token E  { $$ = sqrt($2); }
| abs_token E { $$ = abs($2);}
| '-' %prec UMINUS E {$$=-$2;}
| num_token {$$ = $1;}
;

次のタイプを追加しFます。

%type <num> E F
于 2017-07-10T16:24:42.407 に答える
1

優先関係は、シフト/削減の競合を解決するためにのみ使用されます。優先順位の比較は常にプロダクション(縮小される可能性がある) とトークン(シフトされる可能性がある) の間で行われるため、reduce/reduce の競合を解決するために使用することはできません。

それを念頭に置いて、式を解析するプロセスを検討してください。

div 7 - 3 - 2

div(それがあなたの書き方であると仮定しますdiv_token)。

それぞれ-は、中置減算演算子または前置否定演算子のいずれかです。このコンテキストでは、div正確に 2 つの式が続く必要があるため、マイナス記号の 1 つだけを中置にする必要があります。しかし、どれ?それは...ですか

div (7-3) (-2)

また

div (7) (-3-2)

もちろん、他のコンテキストも可能です。式がであるdiv 7 - 3 - 2 a場合、唯一の有効な解析は になりますがdiv ((7-3)-2) 8、式が である場合、div div 7 - 3 - 2解析は である必要がありますdiv (div 7 (-3)) (-2)

-vオプションを使用して解析レポートを作成するように bison に依頼し、.output生成されたファイルを確認することで、競合についてより多くの洞察を得ることができます。あなたの文法では、そのレポートは、reduce/reduce 競合が状態 35 にあることを示しています。これは次のとおりです。

State 35

    6 E: E . '+' E
    7  | E . '-' E
    7  | E '-' E .
    8  | E . '*' E
    9  | E . '/' E
   15  | '-' E .

    div_token   reduce using rule 7 (E)
    div_token   [reduce using rule 15 (E)]

(actions truncated for space)

.可能な削減は、末尾にa が付いた LR アイテム (E '-' E .および) に対応し'-' E .ます。ほとんどの (すべてではない) 先読みトークンでは、これらの削減のいずれかが可能です。(が先読み文字である場合*、規則よりも が優先されるE: E '-' Eため、最初の削減の可能性が排除されます。同様に.)*/

このように中置式と前置式を混在させることは、通常は良い考えではありません。まさにこのあいまいさのためです。

于 2017-07-10T17:16:50.423 に答える