ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

codegraph 的 COBOL 语法改造:用 tree-sitter-cobol 补丁解析真实主机与 GnuCOBOL 代码

codegraph 的 COBOL 语法改造:用 tree-sitter-cobol 补丁解析真实主机与 GnuCOBOL 代码 codegraph 的 COBOL 语法改造用 tree-sitter-cobol 补丁解析真实主机与 GnuCOBOL 代码【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraph本文以 codegraph 仓库内docs/grammars/tree-sitter-cobol.md为核心完整讲解 vendored 的 COBOL tree-sitter 语法是如何在上游基础上打补丁的10 项补丁各自修复了哪些真实生产代码中的语法盲区补丁前后的实测解析健康度数据以及如何一步步重建出tree-sitter-cobol.wasm。读完本文你可以理解 codegraph 为什么必须改造上游 COBOL 语法才能索引 CICS/DB2/GnuCOBOL 代码并能按文档中的步骤在本地复现并重建这个 wasm 二进制。补丁的来源与动机codegraph 仓库中使用的 COBOL 语法文件 tree-sitter-cobol.wasm 是从上游 yutaro-sakamoto/tree-sitter-cobol 这份补丁改动集中在grammar.js与src/scanner.c两个文件其余产物全部由tree-sitter generate重新生成。上游语法的目标是 COBOL85派生自 opensource-cobol 项目并通过过 NIST 测试集因此它解析教科书式的批处理 COBOL 没有问题。但文档指出它恰恰卡死在真实 mainframe 和 GnuCOBOL 代码中占主导地位的构造上——补丁正是为了解决这些盲区。补丁新增/修复的 10 类语法以下 10 项完整对应原文档 What the patch adds 一节并补充补丁文件中的具体实现位置。1.EXEC ... END-EXEC块CICS / SQL / DLI上游完全没有 EXEC 支持——EXEC SQL、EXEC CICS内部的 token 会被前面的语句持续吸收直到某个 token 把句法打断级联效应是把数百行代码坍缩成一个大 ERROR。补丁在外部扫描器中新增了一个EXEC_BLOCKtoken扫描器一旦匹配到单词EXEC大小写不敏感后跟空白就用一个 8 字节滑窗向后消费直到END-EXEC把整个块作为一个不透明的单节点发出。补丁后的语法把它暴露为exec_statement既可作为过程语句procedure statement也可作为数据分区的条目用于EXEC SQL INCLUDE/DECLARE场景。这一点在补丁的src/scanner.c部分中可见EXEC_BLOCK加入TokenType枚举tree_sitter_COBOL_external_scanner_scan中新增了按字符滚动匹配end-exec的滑窗逻辑。2. 不带空格的NOTIBM COBOL 接受NOT这种写法。上游的_NOT_EQUALtoken 只匹配!或NOT [空格] (EQUAL|)补丁把正则改为(!)|([nN][oO]tT)使NOT无需空格也能被识别。3.FD name.后直接跟COPY真实代码里文件描述条目常常只有FD MYFILE.一行记录布局由后面的COPY提供。上游要求每个 FD 之后必须有字面的记录描述record description导致解析失败。补丁把file_description和linkage_section中的record_description_list从必选改为optional(...)同时允许record_description_list内部穿插exec_statement。4. 多对替换的COPY ... REPLACING pseudo-text BY pseudo-text上游的replacing_clause存在两个问题从不消费REPLACING关键字本身且只允许一对 WORD/字符串替换。补丁重写为replacing_clause: $ seq($._REPLACING, repeat1($.replacing_pair))并新增pseudo_texttoken正则/([^\n]|[^\n])*/支持占位符形式的伪文本替换对数量不再受限。5. 单引号字符串的续行固定格式 COBOL 用第 7 列的连字符表示续行。上游扫描器只对双引号字符串实现了续行补丁把引号字符泛化为扫描时实际遇到的引号或并额外处理了双写引号转义DONT中相邻两个是转义而非闭合。补丁同时把字符串消费时的右边界从硬编码的 72 列改为可变宽度见第 8 项 wide mode。6.FUNCTION intrinsic(refmod)上游的泛型 FUNCTION 回退规则能接受参数但不接受引用修饰后缀reference modification例如FUNCTION CURRENT-DATE(1:4)会解析失败——那些专用内建函数 token如CURRENT-DATE-FUNC只匹配 opensource-cobol 预处理后的名称。补丁把泛型回退规则改为seq($.WORD, optional($.func_args), optional($.func_refmod))补上了func_refmod这一段。7. 独立 copybook 入口点.cpy文件copybook没有IDENTIFICATION DIVISION上游的start规则只接受program_definition所以独立 copybook 无法解析。补丁把start改为optional(choice(repeat1($.program_definition), $.copybook_fragment))并新增copybook_fragment规则其内容是record_description_list或过程分区内容的二选一——一个文件要么是完整程序要么是一个 fragment从而保持程序后缀的无歧义。8. 自由格式源码的 wide mode这是补丁中最巧妙的一项也是 codegraph 提取器与扫描器协同设计的核心提取器侧codegraph 的 COBOL 提取器在解析前preParse把自由格式 COBOL 转成固定格式——每行左侧补 7 个空格并在第一行的序列区第 1–6 列写入CGWIDE哨兵扫描器侧外部扫描器在消费第 1 行序列区时逐字节比对CGWIDE六个字符匹配成功就把扫描器状态置 1随后把固定格式的右边界第 72 列放宽到 4096 列CG_FIXED_WIDTH 72/CG_WIDE_WIDTH 4096——自由格式的行经常超过 72 列不放宽会截断字符串和语句状态持久化这个 1 字节的标志位通过外部扫描器的serialize/deserialize接口携带保证 tree-sitter 的增量解析不会丢失 wide mode 状态兼容性固定格式文件不写哨兵行为与上游完全一致不受影响。在 codegraph 源码中可以看到这段预处理的具体实现src/extraction/languages/cobol.ts 的preParse钩子先探测自由格式division 头、PROGRAM-ID或 level number 行出现在第 8 列之前命中后逐行左移 7 列并在首行插入CGWIDE行号保持不变列号漂移 7 列对行导向的消费者可以接受。9. COBOL-2002 / GnuCOBOL 表面语法补丁一次性补齐了一批现代 COBOL 写法构造补丁中的体现BINARY-LONG-LONG、FLOAT-LONG、FLOAT-SHORT用法新增_BINARY_LONG_LONG/_FLOAT_LONG/_FLOAT_SHORT大小写不敏感正则及对应 exposed token并加入usage规则的 choicePROGRAM-ID. X IS RECURSIVE.新增is_recursive规则并入program_name尾部选项关系型WHEN对象WHEN 0_evaluate_object新增prec.right(seq(choice(, , , , , $._NOT_EQUAL), $.expr))缩略组合关系WHEN X 0 OR Yexpr规则新增seq($.expr, choice($.AND, $.OR), $._comparator, $._expr_calc)——第二比较的主体被隐含。补丁注释说明语法里原有的AND_LT/OR_GT组合 token 永远打不过关键字词法分析所以必须显式建模位运算符B-AND/B-OR/B-XOR/B-NOT/B-SHIFT-L(-LC)/B-SHIFT-R(-RC)新增B_AND等 6 个 token 正则进入_expr_calc_binary/_expr_calc_unaryFREE语句新增free_statement规则加入_statementchoiceVALUE constant-namevalue_item的开头从$._literal改为choice($._literal, $.qualified_word)PIC X(CONSTANT-NAME)picture_x正则从(\([0-9]\))?扩展为(\(([0-9]|[a-zA-Z][a-zA-Z0-9-]*)\))?编译指令作为注释新增directive: $ /[^\n]*/并放入extrasGnuCOBOL 的SOURCE、IF、DEFINE等ENTRY literal USING ...IMS 批处理替代入口点新增entry_statement规则_statement中加入空DATE-COMPILED./DATE-WRITTEN./SECURITY.头三个 section 规则的comment_entry从repeat1改为repeat允许零个注释条目10.CALL ... GIVING上游本意是支持GIVING的但一个嵌套位置写错的field()调用把RETURNING和GIVING两个选项整体吞掉了它们在源码里被包进了同一个optional(choice(...))内部导致语法生成时该分支失效。补丁把结构修正为optional(choice(field(returning, ...), field(giving, ...)))。实测解析健康度vendoring 时测量原文档给出了补丁落地时的实测数据这是评估为什么要打补丁的最直接证据语料库干净解析数AWS CardDemo 全部程序含 DB2/IMS/MQ 变体44 个.cbl43/44——上游在同一基础集上仅 9/31。唯一残余项是段落之间一条无句点的EXEC SQL INCLUDE由提取器的preParse修复见下文AWS CardDemo copybook29 个.cpy28/29——上游为 0/29失败原因是COPY REPLACING模板内含(TESTVAR1)占位符替换前本来就不是合法 COBOLNIST COBOL85 套件382 个程序373/382——与上游持平无回归CobolCraft17 个自由格式 GnuCOBOL 程序经 wide mode 处理17/17——上游完全无法解析自由格式上游自身的语料库测试保留 1 个既有失败comment无新增失败其中 AWS CardDemo 的残余项43/44 中的 1 个在 codegraph 中有专门的工程化处理DB2 惯例把EXEC SQL INCLUDE member END-EXEC写成不带句点、夹在两个段落之间的形式这会绊倒语法的句子机制。提取器的 terminateSqlIncludes 在preParse阶段给这种单行形式的END-EXEC后补一个句点写入其后本为空格的那个字符位或在行尾追加且对其它所有字符保持偏移不变不影响行号映射。codegraph 如何消费这套补丁后的语法补丁让解析能过codegraph 的提取层则让解析结果有用。以下实现细节来自仓库源码用于佐证文档中各项补丁的实际用途文件类型映射src/extraction/grammars.ts 把.cbl、.cob、.cobol、.cpy四种扩展名统一映射到cobol语言加载tree-sitter-cobol.wasmCOBOL 属于 vendored wasm 语言集合与 Rust kernel 侧的 grammar parity 校验一起维护版本对齐。EXEC 块的二次挖掘补丁让EXEC ... END-EXEC成为单个不透明节点后提取器在 handleExec 中对这个不透明节点做文本级挖掘只提取可静态解析的形状EXEC CICS LINK/XCTL PROGRAM(X)产生跨程序calls边EXEC CICS RETURN/START TRANSID发出带cics-transid:前缀的引用供框架解析器消费EXEC SQL INCLUDE产生import节点加imports引用DB2 版的 COPY。CICS 事务跳转的框架级解析cics-transid:XXXX引用由 src/resolution/frameworks/cics.ts 解析——CICS 的 CSD 配置从不出现在代码仓库中但按近乎普遍的惯例每个程序会把自有的事务 id 声明为工作存储常量05 WS-TRANID PIC X(04) VALUE CB00.。解析器扫描所有名字含TRAN的数据项的VALUE字面量把事务 id 映射回声明它的程序模块无匹配则保持未解析而不是猜测。copybook fragment 的消费cobol.ts 的visitNode对copybook_fragment分两条路含record_description_list时走数据条目遍历产出variable/field/constant节点否则按程序段落走过程遍历产出function节点——对应补丁第 7 项数据 copybook 给出记录结构过程 copybook 给出段落。保守的动态分发策略文档式的补丁只负责让语法解析通过提取层对无法静态确定的目标如CALL>git clone https://github.com/yutaro-sakamoto/tree-sitter-cobol cd tree-sitter-cobol git checkout e99dbdc3d800d5fa2796476efd60af91f6b43d93 git apply path/to/tree-sitter-cobol.patch # tree-sitter 0.24.x 需要 tree-sitter.json语法名必须保持 COBOL # C 符号是 tree_sitter_COBOL* cat tree-sitter.json JSON { grammars: [ { name: COBOL, camelcase: COBOL, scope: source.cobol, path: ., file-types: [cbl, cob, cpy] } ], metadata: { version: 0.1.1, license: MIT, description: COBOL grammar for tree-sitter, links: { repository: https://github.com/yutaro-sakamoto/tree-sitter-cobol } } } JSON npm install tree-sitter-cli0.24.5 npx tree-sitter generate npx tree-sitter build --wasm -o tree-sitter-cobol.wasm # 需要 emscripten 或 Docker两个关键约束值得注意必须固定在 commite99dbdc3上打补丁——补丁是针对该提交的grammar.js/scanner.c编写的上游若合并补丁前随意切换 commitgit apply可能失败语法名必须保持COBOL——生成的 C 符号是tree_sitter_COBOL*wasm 的导出符号名由此确定改名会导致加载失败。npx tree-sitter generate之后src/parser.c等产物全部再生成补丁本身只手写两处grammar.js的语法规则和src/scanner.c的外部扫描器逻辑EXEC_BLOCKtoken、CGWIDE 哨兵检测、引号泛化的多行字符串。上游化Upstreaming与可移植性设计文档明确说明补丁按可直接上游的方式编写——每一项都相互独立且各自附带了导致失败的构造文档便于单独评审。这些改动已经作为 PR上游仓库的 pull request #41分支real-world-cobol-sources提交给 yutaro-sakamoto/tree-sitter-cobol。PR 描述中列出的实测结论与上文健康度表格一致AWS CardDemo 从 9/31 提升到 43/44CobolCraft 从 0 到 17/17NIST COBOL85 持平于 373/382上游语料库测试维持唯一一个既有失败comment。如果上游合并该 PRcodegraph vendored 的 wasm 就可以改为跟随上游版本发布不再依赖这份补丁在那之前在上游 commite99dbdc3上执行git apply tree-sitter-cobol.patch可以逐字节复现当前 fork。这也解释了文档为何把补丁文件tree-sitter-cobol.patch与说明文档并置在docs/grammars/下补丁是事实来源wasm 是构建产物两者必须可互推。小结一个补丁如何打通解析→索引→解析引用整条链路回到 codegraph 的项目定位——为 AI 编码代理预索引代码知识图减少 token 与工具调用。对 COBOL 这种语法即布局的列导向语言仅仅能用上游语法解析教科书代码毫无意义真实仓库里占主导的 EXEC 块、COPY 替换、自由格式和 COBOL-2002 语法恰恰是上游的盲区。这份补丁的意义在于它打通了三层链路解析层scanner.c grammar.js 补丁让tree-sitter parse对生产代码产出干净 AST43/44 与 17/17 就是这一层的验收指标提取层cobol.ts把 flat 的、列导向的 AST 还原为有范围的程序/段落/字段节点把 EXEC 不透明块二次挖掘为 CICS/SQL 调用边引用解析层cics.ts用仓库内普遍存在的TRAN* VALUE XXXX惯例补上 CSD 缺失的事务映射把RETURN TRANSID解析到真正的目标程序。三层中任何一层缺失索引出的 COBOL 代码图都只是空壳——而这份文档记录的正是第一层如何被工程化地补齐以及它如何与后两层精确咬合。【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraph创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表