如何最好地处理野牛中同一规则的不同动作?

How to best handle varying actions for the same rule in bison?

我有以下语法(SSCCE):

%token  WORD
%%
program     : word  word
            ;

word        : WORD  // have to translate only for first word
            ;

规则 word : WORD 应该具有以下作用,即 WORD 的标记语义值适合于 "translated" 左侧的语义值,前提是规则 program: word word 中的第一个 word

在野牛中执行此操作的最佳做​​法是什么?

我不知道如何用动作来做到这一点。我必须扩展语法本身,为此:

%token  WORD
%%
program     : word_translated   word_not_translated
            ;

word_translated     : WORD  { // translate }
            ;

word_not_translated  : WORD { // do not translate }
            ;

好的,但我不喜欢这个。因为,文法中有两个符号word_translatedword_not_translated完全一样,就文法而言,文法太复杂,应该简化成一个word .增加复杂性的唯一原因是操作可以不同。

这是唯一的方法吗?这是 bison 处理这种情况的最佳做法吗?

语义操作最好从任何编译器或解释器中的解析树执行。如果您尝试从野牛规则操作中执行语言语义操作方向,您将总是陷入您所描述的那种混乱。

只需在 bison 动作中构建一个解析树,然后在知道完整的树后采取适当的语义动作遍历树。大多数标准编译器文本都有工作示例。

我非常不同意 Brian 的断言,即 bison 动作应该只用于构建解析树,然后在解析之后,应该遍历树,在此期间,应该采取真正的动作。或者,一个 "always gets into the kind of mess"。

如果是这样,经典的 O'Reilly yacc 文本就不会说:“通常操作代码会构建一个对应于 输入,以便后面的代码可以处理整个语句甚至整个 一次编程”。而不是 "often" 它会说 "always"。

但是,Brian 的回答非常有用,因为在试图理解它的同时,我不得不阅读。然后我发现恕我直言,我的问题的正确答案是 posted。我会 post 为了未来浏览器的利益而回答。

恕我直言,正确的方法是使用 [=11=]。使用我 post 中的原始语法,该操作的伪代码将是:

if ([=10=] is meaningful)
    $$ = 
else
    $$ = translate()