あいまいさがないとわかっている文法の shift/reduce 競合を理解するのに問題があります。ケースはif elseタイプの1つですが、コードブロックを区切る必須のEND句があるため、「ぶら下がっているelse」の問題ではありません。
gppg の文法は次のとおりです (これは Bison のようなコンパイラ コンパイラです ... エコーではありません)。
%output=program.cs
%start program
%token FOR
%token END
%token THINGS
%token WHILE
%token SET
%token IF
%token ELSEIF
%token ELSE
%%
program : statements
;
statements : /*empty */
| statements stmt
;
stmt : flow
| THINGS
;
flow : '#' IF '(' ')' statements else
;
else : '#' END
| '#' ELSE statements '#' END
| elseifs
;
elseifs : elseifs '#' ELSEIF statements else
| '#' ELSEIF statements else
;
競合の出力は次のとおりです。
// Parser Conflict Information for grammar file "program.y"
Shift/Reduce conflict on symbol "'#'", parser will shift
Reduce 10: else -> elseifs
Shift "'#'": State-22 -> State-23
Items for From-state State 22
10 else: elseifs .
-lookahead: '#', THINGS, EOF
11 elseifs: elseifs . '#' ELSEIF statements else
Items for Next-state State 23
11 elseifs: elseifs '#' . ELSEIF statements else
// End conflict information for parser
私はすでにすべてを切り替えており、それを解決する方法を知っていますが、その解決策には、右再帰のために「elseif」で左再帰を放棄することが含まれます。
この問題に関してインターネットで見つけたすべての希少なドキュメントを調べましたが (最後にいくつかのリンクを投稿します)、まだエレガントな解決策を見つけていません。ANTLR については知っていますが、今は検討したくありません。ソリューションを Yacc/Bison パーサーに制限してください。
/* empty */ ルールを削除し、空のリストを必要とするすべてのものを複製することでなんとかそれを実現できましたが、私が取り組んでいるより大きな文法では、「スパルゲッティ文法症候群」のようになってしまいます。
ここにいくつかのリンクがあります:
http://nitsan.org/~maratb/cs164/bison.html