在编写一个("理论上的")语法时,如果规则的右侧为空,通常会使用符号 ε(或 1)来明确表示这个空值:
A → ε | a A
在 Yacc 和其他类似的语法中,这样的文法看起来会像这样
a: | 'a' a
或者更糟。a: { $$ = new_list(); }
| a 'a' { $$ = $1; $$->append($1); }
;
在“现实世界中的语法”(如 Yacc、Bison 等)中,规则的空右侧部分没有明确标记为空,这一事实让我感到困扰:很容易忽略右侧为空的事实,或者更糟糕的是忘记插入 |
并实际使用中间规则动作:
a: { $$ = new_list(); }
a 'a' { $$ = $1; $$->append($1); }
;
1)我不知道是否有任何工具提供使空rhs显式的方法。是否有这样的工具?
Bison的未来版本可能会支持专用符号,当在非空rhs中使用时产生错误,并在留下隐式空rhs时产生警告。
2)人们认为这有用吗?
3)你建议使用什么符号表示?
目前的候选符号是$empty
:
a: $empty { $$ = new_list(); }
| a 'a' { $$ = $1; $$->append($1); }
;
编辑
所选的语法是%empty
:
a: %empty { $$ = new_list(); }
| a 'a' { $$ = $1; $$->append($1); }
;
的确,$empty
看起来像一个伪符号,例如Bison为初始规则生成的$accept
或中间规则操作的$@n
伪符号,或表示文件结尾的$eof
。但它绝对不是一个符号,而是恰好没有符号。
另一方面,%
明显表示指令(某种属性/元数据),例如%pred
。
所以这只是语法上的微小差异,但与整体语法更加一致。功劳归于Joel E. Denny。
%empty
、/* empty */
还是只是空格,都没有关系。如果归约/归约冲突对你造成了问题,你需要通过重构语法来消除它,就像任何其他的归约/归约冲突一样。通常,这取决于规则在哪些上下文中被使用。 - Chris Dodda:| a'a';
将优先考虑空规则,而a:a'a'|;
将优先考虑非空规则。 - Chris Dodd