You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 06:30:12