C 对bison中规则的所有组件执行操作

C 对bison中规则的所有组件执行操作,c,bison,flex-lexer,C,Bison,Flex Lexer,我的野牛档案中有以下规则: affectation: VAR '=' expr ';' | VAR PLUSEQ expr ';' | VAR MINUSEQ expr ';' ; 我希望解析器在每次做作时都显示变量名及其内容。为此,我使用动作{printf(“%s:%s\n”,$1,$3);}。然而,由于矫揉造作有3种形式,有没有一种方法可以在不写的情况下将此动作应用于所有组件: affectation: VAR '=' expr ';' {printf(

我的野牛档案中有以下规则:

affectation: VAR '=' expr ';'
    | VAR PLUSEQ expr ';'
    | VAR MINUSEQ expr ';'
    ;
我希望解析器在每次做作时都显示变量名及其内容。为此,我使用动作
{printf(“%s:%s\n”,$1,$3);}
。然而,由于矫揉造作有3种形式,有没有一种方法可以在不写的情况下将此动作应用于所有组件:

affectation: VAR '=' expr ';'
      {printf("%s:%s\n",$1, $3);} 
    | VAR PLUSEQ expr ';'
      {printf("%s:%s\n",$1, $3);}
    | VAR MINUSEQ expr ';'
      {printf("%s:%s\n",$1, $3);}
    ;

基本上,答案是否定的。在大多数用例中,这三个产品将具有不同的语义,因此它们有三个不同的操作是正常的,尽管它们可能共享代码。(一如既往,重构共享代码可以减少重复的需要。)

如果这三个规则在语义上完全相同,则可以将不同的运算符收集到前缀规则中:

aff_pfx: VAR '=' | VAR PLUSEQ | VAR MINUSEQ
affectation: aff_pfx expr ';' { handle($1, $2); }
这依赖于在
aff_pfx
的所有产品中复制
$$=$1
的默认操作,因此它不是完全通用的。此外,它完全抹去了这三种语法之间的任何区别,这似乎不太可能是正确的


如果您只是尝试生成解析的跟踪,请查看bison的内置调试功能。

基本上,答案是否定的。在大多数用例中,这三个产品将具有不同的语义,因此它们的三个不同操作是正常的,尽管它们可能共享代码。(一如既往,重构共享代码可以减少重复的需要。)

如果这三个规则在语义上完全相同,则可以将不同的运算符收集到前缀规则中:

aff_pfx: VAR '=' | VAR PLUSEQ | VAR MINUSEQ
affectation: aff_pfx expr ';' { handle($1, $2); }
这依赖于在
aff_pfx
的所有产品中复制
$$=$1
的默认操作,因此它不是完全通用的。此外,它完全抹去了这三种语法之间的任何区别,这似乎不太可能是正确的


如果您只是试图生成一个解析跟踪,请查看bison的内置调试功能。

您还可以使用
affectation:VAR eqop expr';'
,带有
eqop:'='| PLUSEQ | MINUSEQ
,这可能更容易理解。这两种转换格式的问题是,如果您想在运算符上使用优先级来解决歧义,它将不再起作用--您需要复制规则才能使优先级起作用。@chrisdd:我不确定该语法如何在这些特定运算符上需要优先级,但是稍微打开语法以允许级联赋值和更有趣的左值似乎仍然适用于
aff_pfx
和优先级声明。它不适用于
eqop
公式,这就是为什么我没有首先使用它的原因。你也可以使用
矫揉造作:VAR eqop expr';'
,带有
eqop:'='| PLUSEQ | MINUSEQ
,这可能更容易理解。这两种转换格式的问题是,如果您想在运算符上使用优先级来解决歧义,它将不再起作用--您需要复制规则才能使优先级起作用。@chrisdd:我不确定该语法如何在这些特定运算符上需要优先级,但是稍微打开语法以允许级联赋值和更有趣的左值似乎仍然适用于
aff_pfx
和优先级声明。它不适用于
eqop
公式,这就是为什么我一开始没有使用它的原因。