7

YACC (実際には Bison) で文法を書いていますが、シフト/リデュースの問題があります。これは、後置インクリメント演算子とデクリメント演算子を含めることによって生じます。以下は、文法の縮小版です。

%token NUMBER ID INC DEC

%left      '+' '-'
%left      '*' '/'
%right     PREINC
%left      POSTINC

%%

expr: NUMBER
|     ID
|     expr '+' expr
|     expr '-' expr
|     expr '*' expr
|     expr '/' expr
|     INC expr %prec PREINC
|     DEC expr %prec PREINC
|     expr INC %prec POSTINC
|     expr DEC %prec POSTINC
|     '(' expr ')'
;

%%

Bison は、12 個のシフト/リデュースの競合があることを教えてくれましたが、接尾辞のインクリメントとデクリメントの行をコメントアウトすると、問題なく動作します。この競合を修正する方法を知っている人はいますか? この時点で、LL(k) パーサー ジェネレーターに移行することを検討しています。これにより、はるかに簡単になりますが、LALR 文法は常に、より自然に記述できるように見えました。GLR も検討していますが、優れた C/C++ GLR パーサー ジェネレーターを知りません。

4

5 に答える 5

3

%glr-parserオプションセクションで指定すると、Bison/Yacc は GLR パーサーを生成できます。

于 2009-06-06T11:33:04.750 に答える
2

これを試して:

%token NUMBER ID INC DEC

%left       '+' '-'
%left       '*' '/'
%nonassoc   '++' '--'
%left       '('
%%

expr: NUMBER
|     ID
|     expr '+' expr
|     expr '-' expr
|     expr '*' expr
|     expr '/' expr
|     '++' expr 
|     '--' expr 
|     expr '++'
|     expr '--'
|     '(' expr ')'
;

%%

重要なのは、後置演算子を非結合として宣言することです。そうでなければ、あなたはできるでしょう

++var++--

shift/reduce 警告を最小限に抑えるために、括弧にも優先順位を付ける必要があります。

于 2010-01-21T12:16:33.347 に答える
0

より多くの項目を定義するのが好きです。%left、%right、%prec などは必要ありません。

simple_expr: NUMBER
 | INC simple_expr
 | DEC simple_expr
 | '(' expr ')'
;

term: simple_expr
 | term '*' simple_expr
 | term '/' simple_expr
;

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

このアプローチで遊んでください。

于 2009-05-21T15:45:22.057 に答える
0

この基本的な問題は、INCandトークンの優先順位がないため、 orDECの先読みを含むあいまいさを解決する方法がわからないことです。追加するとINCDEC

%right INC DEC

優先順位リストの最後 (unary の優先順位を高くし、postfix を prefix よりも高くしたい場合)、それは修正され、関係がないため、すべてのPREINC/を取り除くこともできますPOSTINC

于 2013-09-08T18:23:16.460 に答える