1

如何在 yacc 中进行条件编译。类似于在 C 中使用 ifdef 完成的。
我想根据条件创建规则。yacc中可以吗?例子。基于条件规则A定义如下:

ruleA : A | B, /* For condition 1 */  
ruleA : C      /* If condition 1 is not satisfied */  
4

3 回答 3

2

btyacc具有基于定义标志的条件编译,类似于 C 预处理器。你可以说:

%ifdef VERSION_A
ruleA: A | B ;
%endif
%ifdef VERSION_B
ruleA: C ;
%endif

然后使用-DVERSION_Aor-DVERSION_B命令行参数来获取一个或另一个版本。它非常原始(每个 只能测试一个标志%ifdef,不能嵌套%ifdefs 并且没有%else),但对于简单的事情来说已经足够了。

于 2012-11-01T21:26:43.020 回答
0

如果您无法使用适当的预处理器预处理您的 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 而言,您的语法必须与运行中的两组规则一起“工作”。如果这由于移位/减少(甚至减少/减少)冲突而导致复杂性,那么预处理就是要走的路。结果语法将更小,更集中。

于 2012-11-01T05:21:28.177 回答
0

我的建议是您将条件标志公开为终端符号,我们可以将其称为模式终端。(因此,从技术上讲,它是运行时而非编译时条件。)

您需要在每一个对解析产生影响的地方都返回模式终端。您的语法在收到额外的语法时可以忽略它。它只能在“条件 1”的情况下返回模式终端,只能在“非条件 1”的情况下返回,或者您可以在两种情况下都返回不同的终端。所以假设你有两个令牌 C1 和 C2,每个模式一个。

如果您正在解析现有的语法,这可能效果不佳,但如果您将语法和解析器一起设计,所有问题都是可以解决的。

然后你最终得到:

ruleA : C1 A | C1 B | C2 C ;
于 2012-11-01T20:09:09.260 回答