如何在 yacc 中进行条件编译。类似于在 C 中使用 ifdef 完成的。
我想根据条件创建规则。yacc中可以吗?例子。基于条件规则A定义如下:
ruleA : A | B, /* For condition 1 */
ruleA : C /* If condition 1 is not satisfied */
如何在 yacc 中进行条件编译。类似于在 C 中使用 ifdef 完成的。
我想根据条件创建规则。yacc中可以吗?例子。基于条件规则A定义如下:
ruleA : A | B, /* For condition 1 */
ruleA : C /* If condition 1 is not satisfied */
btyacc具有基于定义标志的条件编译,类似于 C 预处理器。你可以说:
%ifdef VERSION_A
ruleA: A | B ;
%endif
%ifdef VERSION_B
ruleA: C ;
%endif
然后使用-DVERSION_A
or-DVERSION_B
命令行参数来获取一个或另一个版本。它非常原始(每个 只能测试一个标志%ifdef
,不能嵌套%ifdef
s 并且没有%else
),但对于简单的事情来说已经足够了。
如果您无法使用适当的预处理器预处理您的 Yacc 语法,那么您可以使用基于操作的解决方案:
ruleA : A { if (condition1) { process OK; } else YYERROR; }
| B { if (condition1) { process OK; } else YYERROR; }
| C { if (!condition1) { process OK; } else YYERROR; }
;
YYERROR 动作触发 Yacc 的正常错误处理机制。这意味着就 Yacc 而言,您的语法必须与运行中的两组规则一起“工作”。如果这由于移位/减少(甚至减少/减少)冲突而导致复杂性,那么预处理就是要走的路。结果语法将更小,更集中。
我的建议是您将条件标志公开为终端符号,我们可以将其称为模式终端。(因此,从技术上讲,它是运行时而非编译时条件。)
您需要在每一个对解析产生影响的地方都返回模式终端。您的语法在收到额外的语法时可以忽略它。它只能在“条件 1”的情况下返回模式终端,只能在“非条件 1”的情况下返回,或者您可以在两种情况下都返回不同的终端。所以假设你有两个令牌 C1 和 C2,每个模式一个。
如果您正在解析现有的语法,这可能效果不佳,但如果您将语法和解析器一起设计,所有问题都是可以解决的。
然后你最终得到:
ruleA : C1 A | C1 B | C2 C ;