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

如何在编译器项目中优雅放置大常量矩阵以提升可读性?

优化编译器预计算表可读性的几种方案

针对你遇到的13×13算符分析表可读性差的问题,这里有几个实用的优化方向:

方案一:用枚举+指定初始化器(C99及以上)

先把所有行/列对应的符号定义成枚举,然后用指定初始化器明确每个元素对应的列,不用靠注释和位置对应,代码逻辑一目了然:

// 定义所有Token类型,对应矩阵的行和列索引
typedef enum {
    TOKEN_PLUS,    // +
    TOKEN_MINUS,   // -
    TOKEN_MUL,     // *
    TOKEN_DIV,     // /
    TOKEN_EQ,      // ==
    TOKEN_REL,     // <,>,<=,...
    TOKEN_LOGIC,   // and/or
    TOKEN_NOT,     // !
    TOKEN_LPAREN,  // (
    TOKEN_RPAREN,  // )
    TOKEN_INT,     // i(整数)
    TOKEN_BOOL,    // b(布尔)
    TOKEN_EOF,     // $(结束符)
    TOKEN_COUNT    // 用于校验矩阵大小,避免越界
} TokenType;

// 预计算值的常量定义(根据你的实际需求替换)
#define PREC_LT 0  // 左移/优先级低
#define PREC_EQ 1  // 相等/同级
#define PREC_GT 2  // 右移/优先级高

// 用枚举索引定义表,每个元素明确对应列
const Table_contents_T precedence_table[TOKEN_COUNT][TOKEN_COUNT] = {
    // 行:+
    {
        [TOKEN_PLUS] = PREC_EQ,
        [TOKEN_MINUS] = PREC_EQ,
        [TOKEN_MUL] = PREC_LT,
        [TOKEN_DIV] = PREC_LT,
        [TOKEN_EQ] = PREC_LT,
        [TOKEN_REL] = PREC_LT,
        [TOKEN_LOGIC] = PREC_LT,
        [TOKEN_NOT] = PREC_LT,
        [TOKEN_LPAREN] = PREC_LT,
        [TOKEN_RPAREN] = PREC_GT,
        [TOKEN_INT] = PREC_GT,
        [TOKEN_BOOL] = PREC_GT,
        [TOKEN_EOF] = PREC_GT
    },
    // 行:-
    {
        [TOKEN_PLUS] = PREC_EQ,
        [TOKEN_MINUS] = PREC_EQ,
        [TOKEN_MUL] = PREC_LT,
        [TOKEN_DIV] = PREC_LT,
        [TOKEN_EQ] = PREC_LT,
        [TOKEN_REL] = PREC_LT,
        [TOKEN_LOGIC] = PREC_LT,
        [TOKEN_NOT] = PREC_LT,
        [TOKEN_LPAREN] = PREC_LT,
        [TOKEN_RPAREN] = PREC_GT,
        [TOKEN_INT] = PREC_GT,
        [TOKEN_BOOL] = PREC_GT,
        [TOKEN_EOF] = PREC_GT
    },
    // 剩余行按照同样格式补充即可
};

这种方式的好处是:不用数元素位置,修改某个元素时直接找对应的枚举名,注释也可以大幅简化,同时枚举定义能统一所有符号的索引,避免手动计数出错。

方案二:统一排版对齐(兼容旧C标准)

如果不能用C99的指定初始化器,就把每个元素单独占一行,对齐注释,让每行的对应关系清晰可见:

// 预计算值常量定义
#define PREC_LT 0
#define PREC_EQ 1
#define PREC_GT 2

const Table_contents_T precedence_table[13][13] = {
    // + 行:对应列 → +  -  *  /  == <>=... and/or !  (  )  i  b  $
    {
        PREC_EQ,   // + vs +
        PREC_EQ,   // + vs -
        PREC_LT,   // + vs *
        PREC_LT,   // + vs /
        PREC_LT,   // + vs ==
        PREC_LT,   // + vs <>=...
        PREC_LT,   // + vs and/or
        PREC_LT,   // + vs !
        PREC_LT,   // + vs (
        PREC_GT,   // + vs )
        PREC_GT,   // + vs i
        PREC_GT,   // + vs b
        PREC_GT    // + vs $
    },
    // - 行
    {
        PREC_EQ,   // - vs +
        PREC_EQ,   // - vs -
        PREC_LT,   // - vs *
        PREC_LT,   // - vs /
        PREC_LT,   // - vs ==
        PREC_LT,   // - vs <>=...
        PREC_LT,   // - vs and/or
        PREC_LT,   // - vs !
        PREC_LT,   // - vs (
        PREC_GT,   // - vs )
        PREC_GT,   // - vs i
        PREC_GT,   // - vs b
        PREC_GT    // - vs $
    },
    // 剩余行按同样格式补充
};

这种方式通过统一的换行和注释对齐,解决了原代码中换行混乱、注释错位的问题,查看和修改时能快速定位到对应位置。

方案三:脚本生成代码(适合大型/频繁修改的表)

如果这个表需要频繁调整,或者后续可能扩展,建议用脚本生成C代码:

  1. 把表格数据整理成CSV格式(天然的表格结构,可读性极强):
,+,-,*,/,==,<>=...,and/or,!,(,),i,b,$
+,EQ,EQ,LT,LT,LT,LT,LT,LT,LT,GT,GT,GT,GT
-,EQ,EQ,LT,LT,LT,LT,LT,LT,LT,GT,GT,GT,GT
*,GT,GT,EQ,EQ,LT,LT,LT,LT,LT,GT,GT,GT,GT
/,GT,GT,EQ,EQ,LT,LT,LT,LT,LT,GT,GT,GT,GT
==,GT,GT,GT,GT,EQ,EQ,LT,LT,LT,GT,GT,GT,GT
<>=...,GT,GT,GT,GT,EQ,EQ,LT,LT,LT,GT,GT,GT,GT
and/or,GT,GT,GT,GT,GT,GT,EQ,LT,LT,GT,GT,GT,GT
!,LT,LT,LT,LT,LT,LT,LT,EQ,LT,GT,GT,GT,GT
(,LT,LT,LT,LT,LT,LT,LT,LT,LT,EQ,LT,LT,LT
),GT,GT,GT,GT,GT,GT,GT,GT,XX,GT,GT,GT,GT
i,GT,GT,GT,GT,GT,GT,GT,GT,XX,GT,XX,XX,GT
b,GT,GT,GT,GT,GT,GT,GT,GT,XX,GT,XX,XX,GT
$,LT,LT,LT,LT,LT,LT,LT,LT,LT,LT,LT,LT,XX
  1. 写一个简单的Python脚本读取CSV,生成对应的C代码:
import csv

# 预计算值映射
PREC_MAP = {
    "LT": "PREC_LT",
    "EQ": "PREC_EQ",
    "GT": "PREC_GT",
    "XX": "0"  # 占位符,根据实际情况替换
}

with open("precedence_table.csv", "r") as f:
    reader = csv.reader(f)
    headers = next(reader)
    rows = list(reader)

# 生成C代码
print("// 自动生成的算符优先级表,请勿手动修改")
print("const Table_contents_T precedence_table[13][13] = {")
for row in rows:
    token = row[0]
    print(f"    // {token} 行")
    print("    {")
    for col_idx, val in enumerate(row[1:]):
        col_token = headers[col_idx+1]
        print(f"        {PREC_MAP[val]},   // {token} vs {col_token}")
    print("    },")
print("};")

运行脚本就能得到格式规范的C代码,后续修改表格只需要调整CSV文件,完全避免手动修改代码时的错误。

内容的提问来源于stack exchange,提问作者Matyáš Ott

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 14:39:49