どのようにポストインクリメント演算子からの競合を減らす/ YACCシフトを修正するには?
-
23-08-2019 - |
質問
私はYACC(実際バイソン)で文法を書いている、と私はシフト/問題を軽減を抱えています。これは、後置インクリメントを含むことに起因します。ここでは文法のトリムダウンバージョンは次のとおりです。
%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 ')'
;
%%
バイソンが12シフト/競合を減らすがありますが、私は後置インクリメントとデクリメントの行をコメントアウトした場合、それは正常に動作します私に語りました。誰もがこの競合を解決する方法を知っていますか?この時点で、私はそれがはるかに容易になりLL(k)はパーサジェネレータに移動検討しているが、LALR文法は常にはるかに自然書くように見えてきました。私はまた、GLRを検討しているが、私は何か良いC / C ++ GLRパーサジェネレータを知りません。
解決
%glr-parser
を指定した場合、バイソン/ yaccはGLRパーサを生成することができます。
他のヒント
これを試してください:
%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++--
括弧はまた、警告を/シフトを最小限に低減するために優先順位を与えられる必要がある
私はより多くの項目を定義したいです。あなたは%の左、右%の、%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
;
このアプローチで遊んでみてください。
この基本的な問題は、あなたがINC
とDEC
トークンの優先順位を持っていないということですので、INC
またはDEC
の先読みを伴うあいまいさを解決する方法を知りません。あなたが追加した場合、
%right INC DEC
優先順位リストの最後に(あなたはunariesが接頭辞よりも優先順位が高いとpostfixの高いようにしたい)、それはそれを修正し、それは無関係だとして、あなたも、すべてのPREINC
/ POSTINC
のものを取り除くことができます。
は、前置インクリメントとポストインクリメント演算子はnonassocを有するように優先セクションおよびルールでは、
%prec
を用いてこれらの演算子の優先順位を高くするように定義します