From 8bf0cdc546d30c34f21fd1733a825c3ca0d4faa6 Mon Sep 17 00:00:00 2001 From: Lizongdi <1210855344@qq.com> Date: Wed, 23 Sep 2026 15:08:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=91=E7=8A=B6=E5=9B=BE=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E5=B0=8F=E5=B7=A5=E5=85=B7=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/gen_html_tree.py | 292 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 tools/gen_html_tree.py diff --git a/tools/gen_html_tree.py b/tools/gen_html_tree.py new file mode 100644 index 0000000..77d0898 --- /dev/null +++ b/tools/gen_html_tree.py @@ -0,0 +1,292 @@ +#!/usr/bin/env python3 +""" +解析 C 文件中的 TKeyForest 初始化表,生成全局共享模式的 HTML 交互树状图。 + +用法: + python gen_shared_html_tree.py [table_name] +""" + +import re +import sys +import os +from collections import defaultdict + +def parse_table(c_file, table_name): + """从 .c 文件中提取并解析 TKeyForest 初始化表""" + with open(c_file, "r", encoding="utf-8") as f: + content = f.read() + + # 1. 定位初始化块 + pat = re.compile( + r'(?:const\s+)?TKeyForest\s+' + re.escape(table_name) + + r'\s*=\s*\{(.*)\}\s*;', + re.DOTALL + ) + m = pat.search(content) + if not m: + print(f"错误:未找到 {table_name} 的初始化块", file=sys.stderr) + sys.exit(1) + + body = m.group(1) + key_blocks = [] + pos = 0 + + # 2. 拆分各个 Key + while pos < len(body): + km = re.search(r'\.(\w+)\s*=\s*\{', body[pos:]) + if not km: + break + field_name = km.group(1) + start = pos + km.end() + + depth = 1 + i = start + while i < len(body) and depth > 0: + if body[i] == '{': depth += 1 + elif body[i] == '}': depth -= 1 + i += 1 + + block_content = body[start:i - 1] + key_blocks.append((field_name, block_content)) + pos = i + + # 3. 解析三元组 {Mode, SubMode, Func} + # 使用集合去重,确保相同的 Mode->Func 关系只被记录一次 + edges = set() + all_keys = set() + + for field_name, block in key_blocks: + all_keys.add(field_name) + block_clean = re.sub(r'//.*', '', block) # 去除注释 + for em in re.finditer(r'\{([^}]+)\}', block_clean): + parts = [p.strip().strip(',') for p in em.group(1).split(',')] + if len(parts) >= 3: + mode, sub_mode, func = parts[0], parts[1], parts[2] + if func != "NULL": + # 记录边关系:Key -> Mode -> Func + edges.add((field_name, mode, func)) + + return list(all_keys), edges + +def build_html(keys, edges): + """构建包含 CSS 和 JS 的完整 HTML 字符串""" + + # 预处理数据,计算每个节点的入度和出度 + node_stats = defaultdict(lambda: {'in': 0, 'out': 0}) + + # 用于生成唯一 ID,避免特殊字符 + def get_id(name): + return name.replace('-', '_').replace('(', '').replace(')', '') + + for key, mode, func in edges: + k_id = get_id(key) + m_id = get_id(mode) + f_id = get_id(func) + + node_stats[k_id]['out'] += 1 + node_stats[m_id]['in'] += 1 + node_stats[m_id]['out'] += 1 + node_stats[f_id]['in'] += 1 + + # 构建 HTML 结构 + html_parts = [] + html_parts.append(""" + + + + +KeyForest 全局共享树状图 + + + +

TKeyForest 全局共享交互图 (单击节点高亮路径)

+
+ +
+""") + + # 渲染 Keys + for key in sorted(keys): + k_id = get_id(key) + stats = node_stats[k_id] + html_parts.append(f'
{key}
') + + html_parts.append(""" +
+
+ + +
+""") + + # 收集所有唯一的 Modes + all_modes = sorted(set(mode for _, mode, _ in edges)) + for mode in all_modes: + m_id = get_id(mode) + stats = node_stats[m_id] + html_parts.append(f'
{mode}
') + + html_parts.append(""" +
+
+ + +
+""") + + # 收集所有唯一的 Funcs + all_funcs = sorted(set(func for _, _, func in edges)) + for func in all_funcs: + f_id = get_id(func) + stats = node_stats[f_id] + html_parts.append(f'
{func}()
') + + html_parts.append(""" +
+
+
+ + + + +""") + + return "".join(html_parts) + +def main(): + if len(sys.argv) < 2: + print("用法: python gen_shared_html_tree.py [table_name]", file=sys.stderr) + sys.exit(1) + + c_file = sys.argv[1] + table_name = sys.argv[2] if len(sys.argv) > 2 else "g_ActionTable" + + if not os.path.isfile(c_file): + print(f"错误:文件不存在: {c_file}", file=sys.stderr) + sys.exit(1) + + keys, edges = parse_table(c_file, table_name) + html_content = build_html(keys, edges) + + out_file = os.path.splitext(c_file)[0] + "_shared_tree.html" + with open(out_file, "w", encoding="utf-8") as f: + f.write(html_content) + + print(f"成功生成全局共享 HTML 树状图: {out_file}") + +if __name__ == "__main__": + main() \ No newline at end of file