如何在Linux Bison(Yacc)中复用语法规则内的重复代码?
Yacc重复动作代码的复用方法
以下是几种可行的复用方案,直接解决你代码重复的问题:
抽成独立C函数
把重复的逻辑封装成单独的C函数,在Yacc的声明块(%{ ... %})里定义或声明,之后在两个产生式的动作中直接调用即可。示例:%{ // 定义共用处理函数 void handle_statement(int expr_val) { // 原code1、code2的逻辑 printf("处理结果:%d\n", expr_val); } %} // 词法规则等省略... statement: expression { handle_statement($1); } | ROUND_BRACKET_L expression ROUND_BRACKET_R { handle_statement($2); // 注意这里取括号内表达式的语义值$2 } ;用中间非终结符合并规则
将两个分支抽象为一个中间非终结符,统一处理语义值传递,然后在顶层statement产生式里只写一次动作代码。示例:// 中间非终结符,处理带/不带括号的表达式 expr_with_opt_paren: expression { $$ = $1; } // 传递表达式语义值 | ROUND_BRACKET_L expression ROUND_BRACKET_R { $$ = $2; } // 传递括号内表达式语义值 ; // 顶层产生式仅需一次动作 statement: expr_with_opt_paren { // 原code1、code2的共用逻辑,用$1访问表达式语义值 printf("处理结果:%d\n", $1); } ;用C宏定义复用代码
如果逻辑代码较短,可使用C宏封装,在声明块里定义宏后,在动作中调用。示例:%{ // 用do-while包裹宏,避免语法歧义 #define HANDLE_STMT(val) do { \ printf("处理结果:%d\n", val); \ // 其他共用逻辑... \ } while(0) %} statement: expression { HANDLE_STMT($1); } | ROUND_BRACKET_L expression ROUND_BRACKET_R { HANDLE_STMT($2); } ;
内容的提问来源于stack exchange,提问作者czg
相关产品推荐
相关产品推荐

