# COBOL 语句测试基准 — 详细测试计划 v1.0 > 日期: 2026-06-21 | 对象: D:\cobol-java\cobol-java-v3 > 范围: COBOL 85/2002 语句类型全覆盖 × 解析/数据生成/分类 三维度 --- ## 1. 总览 ### 1.1 目标 建立 COBOL 语句级别的测试基准,验证平台对每种 COBOL 语句的: - **解析正确性** — `cobol_testgen` 能否正确解析该语句结构 - **路径生成** — 是否能生成覆盖该语句所有分支的测试数据 - **程序分类** — HINA pipeline 能否正确判定含该语句的程序类型 - **覆盖率统计** — 静态分析能否正确统计该语句贡献的分支数 ### 1.2 范围 覆盖 COBOL 85 标准 + 部分 COBOL 2002 扩展,按 COBOL 语句功能分类: | 分组 | 语句数 | 优先级 | 现有覆盖 | |:-----|:------:|:------:|:--------:| | 条件分支 | 3 | P0 | ✅ IF/EVALUATE | | 循环控制 | 5 | P0 | ✅ PERFORM 全系 | | 算术运算 | 5 | P0 | ✅ ADD/SUBTRACT/MULTIPLY/DIVIDE/COMPUTE | | 数据搬移 | 8 | P0 | ✅ MOVE/INITIALIZE/STRING/UNSTRING | | 文件操作 | 8 | P0 | ✅ OPEN/READ/WRITE/REWRITE/DELETE/START/CLOSE | | 程序调用 | 3 | P0 | ✅ CALL/GOBACK/STOP RUN | | 条件检测 | 6 | P0 | ✅ IF/SET/ACCEPT/INSPECT/SEARCH | | 排序合并 | 4 | P1 | ✅ SORT/MERGE/RELEASE/RETURN | | CICS 语句 | ~10 | P1 | ✅ DFHCOMMA/ATI/... | | SQL 语句 | ~5 | P1 | ✅ EXEC SQL | | 异常处理 | 4 | P2 | USE/ declaratives | | 其他语句 | ~10 | P2 | ALTER/EXIT/GO TO/CONTINUE/etc | ### 1.3 度量标准 | 维度 | 目标 | 测量方式 | |:-----|:----:|:---------| | 语句解析率 | 100% (P0) | `extract_structure()` 返回非空结构 | | 分支覆盖率(测试) | ≥95% | 测试数据覆盖所有分支路径 | | 分类确信度 | >0.80 | HINA pipeline 输出 confidence | | 样本程序数 | 60+ | test-data/cobol/statement\_\*/\*.cbl | | 测试断言数 | 200+ | parametrized 测试点 | --- ## 2. 现有覆盖分析 ### 2.1 解析器已支持的语句 (cobol_testgen/core.py _BrParser) | 语句 | 语法变体 | 支持程度 | 现有样本 | |:-----|:---------|:--------:|:---------| | IF | IF...ELSE, IF...END-IF, nested IF | ✅ 完整 | HINA005, 多个 | | EVALUATE | EVALUATE...WHEN...OTHER, ALSO | ✅ 完整 | HINA006 | | PERFORM | VARYING/UNTIL/TIMES/THRU/para | ✅ 完整 | MT01-33, 多个 | | SEARCH | SEARCH, SEARCH ALL, VARYING, AT END, WHEN | ✅ 完整 | — | | CALL | BY REFERENCE/CONTENT/VALUE, USING | ✅ 完整 | HINA025 | | MOVE | MOVE literal TO var, MOVE var TO var | ✅ 完整 | 全部 | | COMPUTE | var = expr (+, -, *, /), ROUNDED | ✅ 完整 | DV01-DV03 | | ADD | TO, TO...GIVING, 多GIVING, ROUNDED | ✅ 完整 | — | | SUBTRACT | FROM, FROM...GIVING, ROUNDED | ✅ 完整 | — | | MULTIPLY | BY, BY...GIVING, ROUNDED | ✅ 完整 | — | | DIVIDE | INTO, INTO...GIVING, BY...GIVING, REMAINDER | ✅ 完整 | DV01-DV03 | | ACCEPT | FROM DATE/TIME/DAY/YEAR, FROM USER | ✅ 完整 | — | | READ | READ...INTO, AT END, NOT AT END, END-READ | ✅ 基本 | — | | WRITE | WRITE...FROM, AFTER/BEFORE ADVANCING | ✅ 基本 | — | | REWRITE | REWRITE...FROM | ✅ 基本 | — | | INITIALIZE | INITIALIZE, REPLACING | ✅ 完整 | — | | STRING | STRING...DELIMITED BY...INTO, END-STRING | ✅ 完整 | CV01 | | UNSTRING | UNSTRING...INTO, END-UNSTRING | ✅ 基本 | — | | INSPECT | TALLYING/REPLACING/CONVERTING, BEFORE/AFTER | ✅ 完整 | CV02 | | SET | SET...TO TRUE/FALSE, 88-level | ✅ 基本 | — | | GO TO | GO TO para, GO TO para1 DEPENDING ON | ✅ 基本 | — | | EXIT | EXIT PARAGRAPH/PERFORM/SECTION | ✅ 基本 | — | | STOP RUN | STOP RUN | ✅ 基本 | 全部 | | GOBACK | GOBACK | ✅ 基本 | — | ### 2.2 样本 COBOL 程序覆盖的语句 现有 `test-data/cobol/` 下 33 个样本程序,按类别: | 类别 | 程序数 | 文件名 | 覆盖的语句 | |:-----|:------:|:-------|:-----------| | matching | 10 | MT01-33 | IF, MOVE, PERFORM, OPEN/CLOSE/READ, WRITE | | sort | 2 | ST01-02 | SORT, MERGE, OPEN, READ, WRITE | | validation | 2 | VL01-02 | OPEN, READ, IF, MOVE, PERFORM, SET | | division | 3 | DV01-03 | DIVIDE, IF, DISPLAY | | csv | 3 | CV01-03 | STRING, INSPECT, IF, PERFORM, MOVE | | cics | 1 | CI01 | CICS keyword simulation | | db | 1 | DB01 | EXEC SQL simulation | | sketch | 11 | HINA001-101 | MOVE, IF, PERFORM, CALL, EVALUATE, SEARCH | ### 2.4 解析器支持类型说明 解析器对语句的支持分三种等级: | 等级 | 含义 | 语句 | |:-----|:------|:------| | ✅ **专用解析器** | core.py 中有 `_parse_*` 方法 | IF/EVALUATE/PERFORM/SEARCH/INITIALIZE/STRING/UNSTRING/CALL/ACCEPT/READ/WRITE/REWRITE/SET/INSPECT + 全部算术赋值(MOVE/COMPUTE/ADD/SUB/MULT/DIV) | | ⚠️ **Pass-through** | 解析器无专用方法,跳过但不中断流程 | CLOSE/DELETE/DISPLAY/START/CONTINUE | | ❌ **无处理** | 解析器无法识别,可能产生意外结果 | ALTER/USE/MERGE/SORT/RELEASE/RETURN/EXECUTE/GENERATE | > **注意:** MERGE 和 SORT 在分类器 (classifier.py) 中有关键词检测,但在解析器中是 pass-through。 ### 2.3 未覆盖的语句实线 以下重要语句在现有样本中 **没有独立的测试程序**: | 语句 | 重要性 | 缺失原因 | 计划补充 | |:-----|:------:|:---------|:---------| | ADD (multiple forms) | P0 | 无独立样本 | ST-ADD | | SUBTRACT (multiple forms) | P0 | 无独立样本 | ST-SUB | | MULTIPLY (multiple forms) | P0 | 无独立样本 | ST-MUL | | COMPUTE (complex expr) | P0 | 样本仅简单 | ST-COM | | ACCEPT (FROM DATE/TIME) | P0 | 无独立样本 | ST-ACC | | INITIALIZE (REPLACING) | P0 | 无独立样本 | ST-INI | | STRING (complex delim) | P1 | CV01 已覆盖基本 | ST-STR | | UNSTRING | P1 | 无独立样本 | ST-UNS | | INSPECT (CONVERTING) | P1 | 无独立样本 | ST-INS | | SEARCH/SEARCH ALL | P1 | HINA 有引用 | ST-SRC | | READ (AT END/NOT AT END) | P1 | 嵌入样本中 | ST-READ | | WRITE (AFTER/BEFORE) | P1 | 无独立样本 | ST-WRI | | DELETE | P1 | 无样本 | ST-DEL | | START | P1 | 无样本 | ST-STRT | | REWRITE | P1 | 无样本 | ST-REW | | GO TO DEPENDING ON | P1 | 无样本 | ST-GOTO | | SET (TO TRUE/FALSE) | P1 | VL01 有引用 | ST-SET | | CALL (BY CONTENT/VALUE) | P1 | HINA025 仅 BY REF | ST-CALL | | CONTINUE | P2 | 低风险 | ST-CNT | | EXIT PROGRAM | P2 | 嵌入 | ST-EXIT | | ALTER | P2 | 已废弃 | ST-ALT | | SORT INPUT/OUTPUT PROCEDURE | P1 | ST01 仅 USING | ST-SORT | | MERGE OUTPUT PROCEDURE | P1 | ST02 仅 USING | ST-MRG | | RELEASE | P1 | SORT 子句 | ST-SORT | | RETURN | P1 | MERGE 子句 | ST-MRG | --- ## 3. 新增样本程序计划 ### 3.1 命名规则 ``` test-data/cobol/statement_/ ST-[-].cbl ``` 如: `test-data/cobol/statement_arithmetic/ST-ADD-TO-GIVING.cbl` ### 3.2 P0 语句 — 第一波 (30 程序) #### 算术组 (statement_arithmetic) | # | 文件名 | 测试的语句 | 语句变体 | 分支目标 | 期待结果 | |:-:|:-------|:-----------|:---------|:--------:|:---------| | 01 | ST-ADD-TO.cbl | ADD x TO y | 常量+变量, 变量+变量 | 2 | `add_to` 正确追踪 | | 02 | ST-ADD-GIVING.cbl | ADD TO GIVING | 单源/多源 | 2 | GIVING 目标正确 | | 03 | ST-ADD-ROUNDED.cbl | ADD ROUNDED | ROUNDED 子句 | 2 | 含 ROUNDED 标记 | | 04 | ST-SUB-FROM.cbl | SUBTRACT FROM | 常量, 变量 | 2 | `sub_from` 正确 | | 05 | ST-SUB-GIVING.cbl | SUBTRACT FROM GIVING | 含 GIVING | 2 | 含 REMAINDER 类似 | | 06 | ST-MUL-BY.cbl | MULTIPLY BY | 常量, 变量 | 2 | `mul_by` 正确 | | 07 | ST-MUL-GIVING.cbl | MULTIPLY BY GIVING | ROUNDED 可选 | 2 | GIVING 目标 | | 08 | ST-DIV-INTO-GIVING.cbl | DIVIDE INTO GIVING | DIVIDE, REMAINDER | 3 | REMAINDER 追踪 | | 09 | ST-DIV-BY-GIVING.cbl | DIVIDE BY GIVING | 变量, REMAINDER | 3 | 除法追踪 | | 10 | ST-COMPLEX.cbl | COMPUTE 复合 | 多运算符, 变量混合 | 3 | `compute` 解析 | #### 数据搬移组 (statement_move) | 11 | ST-MOVE-GROUP.cbl | MOVE 组级别 | 组 MOVE, 同名 | 2 | 组级赋值传播 | | 12 | ST-MOVE-CORR.cbl | MOVE CORRESPONDING | CORR 扩展 | 2 | 部分支持标记 | | 13 | ST-INIT-REPLACE.cbl | INITIALIZE REPLACING | NUMERIC/ALPHANUMERIC | 2 | REPLACING 正确 | | 14 | ST-INIT-MULTI.cbl | INITIALIZE 多字段 | 空格分隔目标 | 2 | 所有字段重置 | | 15 | ST-STRING-DELIM.cbl | STRING DELIMITED | DELIMITED BY SIZE/BY / | 3 | 字符串拼接 | | 16 | ST-UNSTRING-BASIC.cbl | UNSTRING INTO | 空格分隔, 多目标 | 3 | 分割追踪 | #### 条件/检测组 (statement_inspect) | 17 | ST-SEARCH-ALL.cbl | SEARCH ALL | OCCURS+SEARCH ALL | 3 | `has_search_all` | | 18 | ST-SEARCH-VARY.cbl | SEARCH VARYING | VARYING 下标 | 3 | 下标正确 | | 19 | ST-SEARCH-AT-END.cbl | SEARCH AT END | AT END 条件 | 3 | at_end_seq 非空 | | 20 | ST-INSPECT-CONVERT.cbl | INSPECT CONVERTING | CONVERTING + TALLYING | 3 | CONVERT 操作 | | 21 | ST-INSPECT-BEFORE.cbl | INSPECT BEFORE/AFTER | BEFORE/AFTER INITIAL | 4 | 条件截断 | | 22 | ST-ACCEPT-DATE.cbl | ACCEPT FROM DATE | DATE/TIME/DAY/YEAR | 4 | FROM 类型匹配 | #### 文件操作组 (statement_file) | 23 | ST-READ-AT-END.cbl | READ AT END | AT END, NOT AT END | 3 | `read_into` 含 AT END | | 24 | ST-READ-INTO.cbl | READ INTO | INTO 子句 | 2 | 多字段 INTO | | 25 | ST-WRITE-AFTER.cbl | WRITE AFTER | AFTER ADVANCING, FROM | 3 | `write_from` 含 ADV | | 26 | ST-REWRITE-FROM.cbl | REWRITE FROM | FROM 子句 | 2 | `rewrite_from` | | 27 | ST-DELETE.cbl | DELETE | 含 INVALID KEY | 3 | DELETE 语句识别 | | 28 | ST-START.cbl | START | KEY IS, INVALID KEY | 3 | START 语句识别 | #### 程序控制组 (statement_control) | 29 | ST-CALL-CONTENT.cbl | CALL BY CONTENT | BY CONTENT, BY VALUE | 3 | mechanism=content | | 30 | ST-CALL-VALUE.cbl | CALL BY VALUE | 混合 BY 子句 | 3 | mechanism=value | | 31 | ST-GOTO-DEPENDING.cbl | GO TO DEPENDING ON | DEPENDING ON 分支 | 4 | Goto DEPENDING | | 32 | ST-SET-88.cbl | SET TO TRUE/FALSE | 88-level 设置/清除 | 3 | `set_true`/`set_false` | ### 3.3 P1 语句 — 第二波 (12 程序) #### 排序合并组 (statement_sortmerge) | 33 | ST-SORT-INPUT-PROC.cbl | SORT INPUT PROCEDURE | INPUT PROCEDURE 段 | 4 | PROCEDURE 解析 | | 34 | ST-SORT-OUTPUT-PROC.cbl | SORT OUTPUT PROCEDURE | OUTPUT PROCEDURE | 4 | 两段式排序 | | 35 | ST-MERGE-OUTPUT.cbl | MERGE OUTPUT PROCEDURE | MERGE + OUTPUT | 4 | MERGE 完整 | | 36 | ST-RELEASE-RETURN.cbl | RELEASE / RETURN | 排序中释放/返回 | 3 | RELEASE 识别 | #### CICS 组 (statement_cics) | 37 | ST-CICS-RECV.cbl | EXEC CICS RECEIVE | RECEIVE MAP | 3 | CICS 关键词标记 | | 38 | ST-CICS-SEND.cbl | EXEC CICS SEND | SEND MAP, SEND TEXT | 3 | DFHCOMMA 模拟 | | 39 | ST-CICS-READ.cbl | EXEC CICS READ | READ FILE, INTO | 3 | CICS 文件操作 | | 40 | ST-CICS-WRITE.cbl | EXEC CICS WRITE | WRITE FILE, FROM | 3 | CICS 文件写 | #### SQL 组 (statement_sql) | 41 | ST-SQL-INSERT.cbl | EXEC SQL INSERT | INSERT INTO | 2 | SQL 操作标记 | | 42 | ST-SQL-UPDATE.cbl | EXEC SQL UPDATE | UPDATE WHERE | 2 | SQL 多种类型 | | 43 | ST-SQL-DELETE.cbl | EXEC SQL DELETE | DELETE FROM | 2 | SQL 覆盖 | | 44 | ST-SQL-DECLARE.cbl | EXEC SQL DECLARE | DECLARE CURSOR, OPEN, FETCH | 3 | 游标操作 | ### 3.4 P2 语句 — 第三波 (8 程序) | 45 | ST-ALTER.cbl | ALTER | ALTER X TO PROCEED TO Y | 3 | ALTER 语句标记 | | 46 | ST-CONTINUE.cbl | CONTINUE | 空操作 | 2 | CONTINUE 不影响流 | | 47 | ST-EXIT-PGM.cbl | EXIT PROGRAM | EXIT PROGRAM / PARAGRAPH | 3 | EXIT 识别 | | 48 | ST-EXECUTE.cbl | EXECUTE | 外部调用 | 2 | EXECUTE 标记 | | 49 | ST-USE.cbl | USE 声明 | USE BEFORE REPORTING | 3 | USE 语句识别 | | 50 | ST-DECLARATIVES.cbl | DECLARATIVES | DECLARATIVES/END DECLARATIVES | 3 | 声明段解析 | | 51 | ST-PERFORM-THROUGH.cbl | PERFORM THRU | THRU 段落范围 | 3 | 范围嵌入 | | 52 | ST-OPEN-VARIANTS.cbl | OPEN 所有变体 | INPUT/OUTPUT/I-O/EXTEND | 4 | 全部 open_dir | --- ## 4. 测试金字塔 ### 4.1 L0: 语句级单元测试 (cobol_testgen 解析层) 每类语句的解析逻辑应有独立的 pytest 测试: ```python # tests/parametrized/test_statements/ # test_arithmetic_statements.py # test_move_statements.py # test_file_statements.py # test_control_statements.py # test_search_statements.py # test_sort_statements.py ``` 每个测试模式(xUnit parametrized × 样本文件): ```python @pytest.mark.parametrize("cbl_file,expected", [ ("ST-ADD-TO.cbl", {"has_add": True, "branch_count": 2}), ("ST-ADD-GIVING.cbl", {"has_add": True, "has_giving": True}), ]) def test_statement_parse(cbl_file, expected): source = (FIXTURES_DIR / cbl_file).read_text("utf-8") struct = extract_structure(source) # assert 解析结果匹配 expected ``` #### L0 测试清单 | 测试文件 | 测试点 | 测试数 | |:---------|:-------|:------:| | `test_arithmetic_statements.py` | 10 算术语句解析正确性 | ~35 | | `test_move_statements.py` | 6 数据搬移语句解析 | ~20 | | `test_file_statements.py` | 6 文件操作语句 | ~25 | | `test_control_statements.py` | 7 程序控制语句 | ~20 | | `test_search_statements.py` | 3 SEARCH 变体 | ~12 | | `test_sort_statements.py` | 4 SORT/MERGE 变体 | ~15 | | `test_cics_sql.py` | 6 CICS/SQL 语句 | ~18 | | `test_special_statements.py` | 8 特殊语句 (ALTER/EXIT/CONTINUE/USE/DECLARATIVES) | ~20 | | **合计** | **50 样本程序** | **~165** | ### 4.2 L1: 数据生成验证 验证 `generate_data()` 能否为每类语句生成覆盖所有分支的测试数据: | # | 测试点 | 期待 | |:-:|:-------|:------| | DG-01 | 算术分支覆盖 | ADD/SUB/MULTIPLY/DIVIDE 每个变体 ≥ 1 条记录 | | DG-02 | IF-ELSE 全覆盖 | 2 分支 = 2 条记录, nested IF = 2^n 部分覆盖 | | DG-03 | EVALUATE 全覆盖 | N WHEN = N+1 条记录 (含 OTHER) | | DG-04 | SEARCH ALL 覆盖 | OCCURS N = N 条 + AT END | | DG-05 | PERFORM VARYING | 循环体 ≥ 1 次迭代 | | DG-06 | STRING 输入覆盖 | DELIMITED BY SIZE/BY X 变体 | | DG-07 | UNSTRING 输出覆盖 | 各目标字段分配正确 | | DG-08 | INITIALIZE 分支 | REPLACING 有/无 = 2 条 | | DG-09 | CALL 参数传递 | BY REFERENCE/CONTENT/VALUE 各 1 条 | | DG-10 | GO TO DEPENDING ON | N 分支 = N 条记录 | ### 4.3 L2: 分类器验证 验证 HINA pipeline 对每种语句的正确分类: | # | 程序类型 | 主要语句特征 | 期待分类 | 确信度 | |:-:|:---------|:------------|:--------|:------:| | CL-01 | 算术型 | DIVIDE/COMPUTE 为主 | 取决于上下文 | ≥0.85 | | CL-02 | 匹配型 | 2 INPUT + IF KEY = | マッチング | ≥0.90 | | CL-03 | 排序型 | SORT ON KEY | SORT | ≥0.95 | | CL-04 | 合并型 | MERGE ON KEY | MERGE | ≥0.95 | | CL-05 | CICS 型 | DFHCOMMAREA, MAP | online | ≥0.95 | | CL-06 | SQL 型 | EXEC SQL | DB操作 | ≥0.95 | | CL-07 | SEARCH 型 | SEARCH ALL | 匹配/内部表 | ≥0.80 | | CL-08 | 字符串型 | STRING/INSPECT | 取决于上下文 | ≥0.80 | | CL-09 | 校验型 | WS-ERR*, WS-PREV-KEY | 編集処理/項目チェック | ≥0.85 | | CL-10 | 子程序型 | CALL + LINKAGE | 子程序调用 | ≥0.90 | ### 4.4 L3: 回归测试 | # | 测试命令 | 期待 | |:-:|:---------|:------| | RE-01 | `pytest tests/ --ignore=e2e/ -v` | 所有现有测试通过 + 新增通过 | | RE-02 | `pytest tests/parametrized/test_statements/ -v` | 新增语句单元全部通过 | | RE-03 | 30 个 P0 样本 extract_structure | 每种语句返回非空 structure | | RE-04 | 30 个 P0 样本 generate_data | 每种语句生成 ≥1 条数据 | | RE-05 | 30 个 P0 样本 classify_program | 返回 category ≠ unknown | ### 4.5 执行计划 | 阶段 | 内容 | 预计工作量 | 新增测试数 | |:-----|:-----|:----------:|:---------:| | Phase A | P0 样本编写 (32 个 .cbl) | CC: ~20 min | — | | Phase B | L0 测试实现 (8 测试文件) | CC: ~25 min | ~165 | | Phase C | L1 数据生成验证 (10 测试点) | CC: ~10 min | ~10 | | Phase D | L2 分类器验证 (10 测试点) | CC: ~8 min | ~10 | | Phase E | P1 样本编写 + L0 补充 | CC: ~15 min | ~60 | | Phase F | P2 样本编写 + 完整回归 | CC: ~15 min | ~40 | | **合计** | | **CC: ~93 min** | **~285** | --- ## 5. 样本程序规范 ### 5.1 模板 每个样本程序必须包含: ```cobol * ==== TYPE: ST-ADD-TO ==== * FEATURE: ADD x TO y (constant / variable) * STATEMENT: ADD * BRANCHES: 2, DECISIONS: 1 * COVERAGE: IF divisibility check IDENTIFICATION DIVISION. PROGRAM-ID. STADDTO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-VALUE PIC 9(5) VALUE 100. 01 WS-RESULT PIC 9(5) VALUE 0. PROCEDURE DIVISION. MAIN-PROCEDURE. ADD 50 TO WS-VALUE. MOVE WS-VALUE TO WS-RESULT. IF WS-RESULT = 150 DISPLAY 'OK: 100 + 50 = 150' ELSE DISPLAY 'ERROR: WRONG VALUE'. STOP RUN. ``` ### 5.2 样本程序质量要求 每个样本: - 可被 `cobol_testgen preprocess` 正确预处理 - 有明确的分支决策点(至少 1 个 IF 或 EVALUATE) - 至少 2 个分支路径 - 语法正确的 COBOL(简化但符合语法) - 包含 `* BRANCHES: N` 元注释,便于自动验证 - 不使用外部文件操作(避免运行时环境依赖)除非测试文件操作 - 对 CICS/SQL 语句使用 `*> comment mock` 标记模拟 ### 5.3 自动验证机制 新增 `test-data/validate_statements.py` 自动验证所有样本: ```bash python test-data/validate_statements.py ``` 验证内容: 1. ✅ 每个样本能被 preprocess 正确处理 2. ✅ extract_structure 返回非空 structure 3. ✅ BRANCHES 元注释与 struct.total_branches 一致 4. ✅ generate_data 至少生成 1 条记录 5. ✅ 无未捕获异常 6. 报告: `通过/N 失败/M` 汇总 --- ## 6. 覆盖率矩阵 ### 6.1 语句 × 测试维度 覆盖矩阵 | COBOL 语句 | 样本 | L0 解析 | L1 数据生成 | L2 分类 | 状态 | |:-----------|:----:|:-------:|:-----------:|:-------:|:----:| | **条件分支** | | | | | | | IF | ✅ HINA005 等 | ✅ parser | ✅ | ✅ | ✅ | | IF (复合条件 AND/OR) | ST-IF-COMP | ✅ parser | ✅ | ✅ | 🔲 P0 | | IF (嵌套 3+ 层) | ST-IF-DEEP | ✅ parser | ⚠️ 部分 | ✅ | 🔲 P0 | | EVALUATE | ✅ HINA006 | ✅ parser | ✅ | ✅ | ✅ | | EVALUATE (ALSO) | ST-EVAL-ALSO | ✅ parser | ✅ | ✅ | 🔲 P0 | | EVALUATE (THRU) | ST-EVAL-THRU | ✅ parser | ✅ | ✅ | 🔲 P1 | | **循环控制** | | | | | | | PERFORM (para) | ✅ 全部样本 | ✅ parser | ✅ | ✅ | ✅ | | PERFORM VARYING | ST-PERF-VARY | ✅ parser | ✅ | ✅ | 🔲 P0 | | PERFORM UNTIL | ST-PERF-UNTIL | ✅ parser | ✅ | ✅ | 🔲 P0 | | PERFORM THRU | ST-PERF-THRU | ✅ parser | ✅ | ✅ | 🔲 P2 | | PERFORM TIMES | ST-PERF-TIMES | ✅ parser | ✅ | ✅ | 🔲 P1 | | **算术运算** | | | | | | | ADD (TO) | ST-ADD-TO | ✅ parser | ✅ | ✅ | 🔲 P0 | | ADD (GIVING) | ST-ADD-GIVING | ✅ parser | ✅ | ✅ | 🔲 P0 | | ADD (ROUNDED) | ST-ADD-ROUNDED | ✅ parser | ✅ | ✅ | 🔲 P0 | | SUBTRACT (FROM) | ST-SUB-FROM | ✅ parser | ✅ | ✅ | 🔲 P0 | | SUBTRACT (GIVING) | ST-SUB-GIVING | ✅ parser | ✅ | ✅ | 🔲 P0 | | MULTIPLY (BY) | ST-MUL-BY | ✅ parser | ✅ | ✅ | 🔲 P0 | | MULTIPLY (GIVING) | ST-MUL-GIVING | ✅ parser | ✅ | ✅ | 🔲 P0 | | DIVIDE (INTO) | DV01-03 | ✅ parser | ✅ | ✅ | ✅ | | DIVIDE (BY GIVING) | ST-DIV-BY-GIVING | ✅ parser | ✅ | ✅ | 🔲 P0 | | DIVIDE (REMAINDER) | DV01-03 | ✅ parser | ✅ | ✅ | ✅ | | COMPUTE (+ - * /) | ST-COMPLEX | ✅ parser | ✅ | ✅ | 🔲 P0 | | COMPUTE (ROUNDED) | ST-COMP-ROUND | ✅ parser | ✅ | ✅ | 🔲 P1 | | **文件操作** | | | | | | | OPEN (INPUT) | ✅ 现有 | ⚠️ 扫描 | ⚠️ 部分 | ✅ | ✅ | | OPEN (OUTPUT/I-O/EXT) | ST-OPEN-VARIANTS | ⚠️ 扫描 | ⚠️ 部分 | ✅ | 🔲 P2 | | READ (INTO) | ST-READ-INTO | ✅ parser | ✅ | ✅ | 🔲 P0 | | READ (AT END) | ST-READ-AT-END | ✅ parser | ✅ | ✅ | 🔲 P0 | | READ (NOT AT END) | ST-READ-AT-END | ✅ parser | ✅ | ✅ | 🔲 P1 | | WRITE (FROM) | ✅ 现有 | ✅ parser | ✅ | ✅ | ✅ | | WRITE (AFTER/BEFORE) | ST-WRITE-AFTER | ✅ parser | ✅ | ✅ | 🔲 P0 | | REWRITE (FROM) | ST-REWRITE-FROM | ✅ parser | ✅ | ✅ | 🔲 P0 | | DELETE (FILE) | ST-DELETE | ⚠️ 穿通 | 🔲 | 🔲 | 🔲 P0 | | START | ST-START | ⚠️ 穿通 | 🔲 | 🔲 | 🔲 P0 | | CLOSE | ✅ 现有 | ⚠️ 穿通 | 🔲 | ✅ | ✅ | | **数据搬移** | | | | | | | MOVE (字面值) | ✅ 现有 | ✅ parser | ✅ | ✅ | ✅ | | MOVE (变量间) | ✅ 现有 | ✅ parser | ✅ | ✅ | ✅ | | MOVE (组级) | ST-MOVE-GROUP | ✅ parser | ✅ | ✅ | 🔲 P0 | | MOVE CORRESPONDING | ST-MOVE-CORR | ❌ | 🔲 | 🔲 | 🔲 P2 | | INITIALIZE | ST-INI-MULTI | ✅ parser | ✅ | ✅ | 🔲 P0 | | INITIALIZE REPLACING | ST-INI-REPLACE | ✅ parser | ✅ | ✅ | 🔲 P0 | | STRING (DELIMITED BY) | ST-STRING-DELIM | ✅ parser | ✅ | ✅ | 🔲 P0 | | UNSTRING | ST-UNSTRING-BASIC | ✅ parser | ✅ | ✅ | 🔲 P0 | | **条件检测** | | | | | | | SEARCH ALL | ST-SEARCH-ALL | ✅ parser | ⚠️ 部分 | ✅ | 🔲 P0 | | SEARCH (VARYING) | ST-SEARCH-VARY | ✅ parser | ⚠️ 部分 | ✅ | 🔲 P1 | | SEARCH (AT END) | ST-SEARCH-AT-END | ✅ parser | ✅ | ✅ | 🔲 P1 | | SET (TO TRUE/FALSE) | ST-SET-88 | ✅ parser | ✅ | ✅ | 🔲 P0 | | INSPECT (TALLYING) | CV02 | ✅ parser | ✅ | ✅ | ✅ | | INSPECT (REPLACING) | CV02 | ✅ parser | ✅ | ✅ | ✅ | | INSPECT (CONVERTING) | ST-INSP-CONVERT | ✅ parser | ✅ | ✅ | 🔲 P1 | | INSPECT (BEFORE/AFTER) | ST-INSP-BEFORE | ✅ parser | ✅ | ✅ | 🔲 P1 | | ACCEPT (FROM DATE) | ST-ACCEPT-DATE | ✅ parser | ✅ | ✅ | 🔲 P0 | | ACCEPT (FROM TIME) | ST-ACCEPT-DATE | ✅ parser | ✅ | ✅ | 🔲 P0 | | **程序控制** | | | | | | | CALL (BY REFERENCE) | HINA025 | ✅ parser | ✅ | ✅ | ✅ | | CALL (BY CONTENT) | ST-CALL-CONTENT | ✅ parser | ✅ | ✅ | 🔲 P0 | | CALL (BY VALUE) | ST-CALL-VALUE | ✅ parser | ✅ | ✅ | 🔲 P0 | | GO TO | ✅ 现有 | ✅ parser | ✅ | ✅ | ✅ | | GO TO DEPENDING ON | ST-GOTO-DEPEND | ✅ parser | ✅ | ✅ | 🔲 P1 | | EXIT (PARAGRAPH) | ST-EXIT-PGM | ✅ parser | ✅ | ✅ | 🔲 P2 | | EXIT (PERFORM) | ✅ 现有 | ✅ parser | ✅ | ✅ | ✅ | | EXIT PROGRAM | ✅ 现有 | ✅ parser | ✅ | ✅ | ✅ | | GOBACK | ✅ 现有 | ✅ termin | ✅ | ✅ | ✅ | | STOP RUN | ✅ 全部 | ✅ termin | ✅ | ✅ | ✅ | | **排序合并** | | | | | | | SORT (USING/GIVING) | ST01 | ⚠️ 穿通 | 🔲 | ✅ cls | ✅ | | SORT (INPUT PROCEDURE) | ST-SORT-INPUT-PROC | ⚠️ 穿通 | 🔲 | ✅ cls | 🔲 P1 | | SORT (OUTPUT PROCEDURE) | ST-SORT-OUTPUT-PROC | ⚠️ 穿通 | 🔲 | ✅ cls | 🔲 P1 | | MERGE (USING/GIVING) | ST02 | ⚠️ 穿通 | 🔲 | ✅ cls | ✅ | | MERGE (OUTPUT PROCEDURE) | ST-MERGE-OUTPUT | ⚠️ 穿通 | 🔲 | ✅ cls | 🔲 P1 | | RELEASE | ST-RELEASE-RETURN | ⚠️ 穿通 | 🔲 | 🔲 | 🔲 P1 | | RETURN | ST-RELEASE-RETURN | ⚠️ 穿通 | 🔲 | 🔲 | 🔲 P1 | | **CICS 语句** | | | | | | | CICS RECEIVE | CI01 | ⚠️ 注释关键词 | 🔲 | ✅ | ✅ | | CICS SEND | ST-CICS-SEND | ⚠️ 注释关键词 | 🔲 | ✅ | 🔲 P1 | | CICS READ FILE | ST-CICS-READ | ⚠️ 注释关键词 | 🔲 | ✅ | 🔲 P1 | | CICS WRITE FILE | ST-CICS-WRITE | ⚠️ 注释关键词 | 🔲 | ✅ | 🔲 P1 | | CICS LINK | ST-CICS-LINK | ⚠️ 注释关键词 | 🔲 | ✅ | 🔲 P1 | | CICS XCTL | ST-CICS-XCTL | ⚠️ 注释关键词 | 🔲 | ✅ | 🔲 P1 | | CICS RETURN | ST-CICS-RETURN | ⚠️ 注释关键词 | 🔲 | ✅ | 🔲 P1 | | **SQL 语句** | | | | | | | EXEC SQL SELECT | DB01 | ⚠️ 注释关键词 | 🔲 | ✅ | ✅ | | EXEC SQL INSERT | ST-SQL-INSERT | ⚠️ 注释关键词 | 🔲 | ✅ | 🔲 P1 | | EXEC SQL UPDATE | ST-SQL-UPDATE | ⚠️ 注释关键词 | 🔲 | ✅ | 🔲 P1 | | EXEC SQL DELETE | ST-SQL-DELETE | ⚠️ 注释关键词 | 🔲 | ✅ | 🔲 P1 | | SQL CURSOR (DECLARE/FETCH) | ST-SQL-DECLARE | ⚠️ 注释关键词 | 🔲 | ✅ | 🔲 P1 | | EXEC SQL COMMIT | ST-SQL-TRANS | ⚠️ 注释关键词 | 🔲 | ✅ | 🔲 P2 | | EXEC SQL ROLLBACK | ST-SQL-TRANS | ⚠️ 注释关键词 | 🔲 | ✅ | 🔲 P2 | | **分类器关键字(需独立样本)** | | | | | | | IS INITIAL (PROGRAM-ID) | ST-CLS-INITIAL | ✅ parser | ✅ | ✅ cls | 🔲 P1 | | SYSIN (系统输入) | ST-CLS-SYSIN | ⚠️ 穿通 | 🔲 | ✅ cls | 🔲 P1 | | ORGANIZATION IS | ST-CLS-ORG | ⚠️ 穿通 | 🔲 | ✅ cls | 🔲 P1 | | ALTERNATE RECORD KEY | ST-CLS-ALTKEY | ⚠️ 穿通 | 🔲 | ✅ cls | 🔲 P1 | | **其他** | | | | | | | DISPLAY | ST-DISPLAY | ⚠️ 穿通 | 🔲 | 🔲 | 🔲 P2 | | CANCEL | ST-CANCEL | ⚠️ 穿通 | 🔲 | 🔲 | 🔲 P2 | | CONTINUE | ST-CONTINUE | ⚠️ 穿通 | 🔲 | 🔲 | 🔲 P2 | | ALTER | ST-ALTER | ⚠️ 穿通 | 🔲 | 🔲 | 🔲 P2 | | COMMIT / ROLLBACK | ST-TRANS | ⚠️ 穿通 | 🔲 | 🔲 | 🔲 P2 | | USE (Declaratives) | ST-USE-DECL | ❌ | 🔲 | 🔲 | 🔲 P2 | | ENTER (其他语言) | — | ❌ | 🔲 | 🔲 | 🔲 P3 | | EXHIBIT (命名DISPLAY) | — | ⚠️ 穿通 | 🔲 | 🔲 | 🔲 P3 | | GENERATE (Report Writer) | — | ❌ | 🔲 | 🔲 | 🔲 P3 | > **图例:** > - `✅ parser` = core.py 有 `_parse_*` 专用方法 > - `⚠️ 穿通` = 解析器无专用方法,跳过但不中断流程 > - `⚠️ 扫描` = structure 级别扫描(OPEN 方向检测),不是语句级解析 > - `⚠️ 注释关键词` = 使用 `*>` 注释模拟关键词,不实际编译 > - `✅ termin` = 终止符(STOP RUN/GOBACK/EXIT PROGRAM 在 terminators 中) > - `✅ cls` = 分类器(classifier.py)有关键词检测 > - `❌` = 完全不支持 > - `🔲` = 待实现或暂不适用 ### 6.2 总计 | 层级 | 现有覆盖 | P0 新增 | P1 新增 | P2 新增 | 目标总数 | |:-----|:--------:|:-------:|:-------:|:-------:|:--------:| | 样本程序 | 33 | 32 | 12 | 8 | **85** | | 被覆盖语句类型 | ~25 | 25 | 12 | 8 | **~70** | | L0 测试点 | ~50 | ~165 | ~60 | ~40 | **~315** | | L1 数据生成验证 | ~8 | ~10 | ~6 | ~4 | **~28** | | L2 分类验证 | ~10 | ~10 | ~6 | ~4 | **~30** | | **总测试点** | **~68** | **~185** | **~72** | **~48** | **~373** | --- ## 7. 实施步骤 ### Phase A: P0 样本编写 (32 个 .cbl) ```bash mkdir -p test-data/cobol/statement_arithmetic/ mkdir -p test-data/cobol/statement_move/ mkdir -p test-data/cobol/statement_file/ mkdir -p test-data/cobol/statement_control/ mkdir -p test-data/cobol/statement_inspect/ ``` 编写 32 个样本后运行验证脚本确保语法正确。 ### Phase B: L0 测试实现 ```bash mkdir -p tests/parametrized/test_statements/ ``` 8 个 parametrized 测试文件,覆盖 ~165 个测试点。 ### Phase C: L1 数据生成验证 ```bash # 验证所有 P0 样本 python -c " from cobol_testgen import extract_structure, generate_data import glob for f in glob.glob('test-data/cobol/statement_*/*.cbl'): src = open(f).read() s = extract_structure(src) d = generate_data(src) print(f'{f}: branches={s[\"total_branches\"]}, records={len(d)}') " ``` ### Phase D: L2 分类器验证 ```bash python -c " from hina.pipeline import classify_program import glob for f in glob.glob('test-data/cobol/statement_*/*.cbl'): src = open(f).read() r = classify_program(src) print(f'{f}: {r[\"category\"]} conf={r[\"confidence\"]:.2f}') " ``` ### Phase E-F: P1/P2 按优先级逐步补充。 --- ## 8. 已知限制 1. **CICS/SQL 语句**: 使用 `*>` 注释模拟,不实际编译。L0 仅测试关键词解析 2. **GO TO DEPENDING ON**: COBOL 85 标准,解析器支持但样本需跨段落跳转 3. **ALTER**: 已废弃但大型机遗产代码仍存在。解析器需补充 ALTER 语句节点 4. **DECLARATIVES**: 解析器 _BrParser 当前未处理 USE/DECLARATIVES 段 5. **MOVE CORRESPONDING**: 解析器支持 MOVE 但不支持 CORR 子句扩展 6. **MERGE OUTPUT PROCEDURE**: 解析器支持 MERGE 但不支持 PROCEDURE 扩展 7. **Windows 编码**: 样本统一 UTF-8,使用 `python -X utf8` 运行 --- ## 附录: 优先级依据 | 优先级 | 判定标准 | 语句 | |:-------|:---------|:------| | **P0** | 平台现有解析器已支持 + 缺失独立样本 | ADD/SUBTRACT/MULTIPLY/COMPUTE/ACCEPT/INITIALIZE/SEARCH/READ/WRITE 等 | | **P1** | 解析器支持但语法变体多 + 迁移场景常见 | CICS/SQL/SEARCH VARYING/INSPECT advanced/SORT/MERGE/分类器关键字样本 | | **P2** | 遗产代码较少 + 解析器部分/不支持 | ALTER/CONTINUE/USE/DECLARATIVES/EXECUTE/交易控制(CANCEL/COMMIT/ROLLBACK) | --- ## 9. Gap Analysis — 与完整 COBOL 85 标准的差异 ### 9.1 总览 以下为计划与 COBOL 85 标准 + 主流程迁移场景的完整差异分析。 | 维度 | 标准语句数 | 计划覆盖 | 不覆盖 | 覆盖率 | |:-----|:---------:|:--------:|:-----:|:-----:| | COBOL 85 过程语句 | ~42 | 40 | 2 (ENTER, GENERATE) | **95%** | | CICS 语句 (迁移相关) | ~10 | 7 | 3 | **70%** | | SQL 语句 (迁移相关) | ~10 | 7 | 3 | **70%** | | 分类器关键字样本 | ~11 | 7 | 4 | **64%** | ### 9.2 计划内但解析器需补充的语句 以下语句在计划中有样本,**但解析器 core.py 当前不支持**(pass-through 或缺失): | 语句 | 当前状态 | 需补充 | 影响 | |:-----|:--------:|:-------|:------| | DELETE FILE | ⚠️ pass-through | `_parse_delete()` | 解析器无法追踪文件删除操作 | | START | ⚠️ pass-through | `_parse_start()` | 解析器无法追踪文件定位 | | ALTER | ⚠️ pass-through | `_parse_alter()` | 覆盖遗留代码中的 ALTER 语句 | | CONTINUE | ⚠️ pass-through | `_parse_continue()` | 低风险,CONTINUE 是空操作 | | USE/DECLARATIVES | ❌ 无处理 | `_parse_use()` | 声明段解析,是大型机常见模式 | | SORT | ⚠️ pass-through | `_parse_sort()` | 解析器无法追踪排序过程 | | MERGE | ⚠️ pass-through | `_parse_merge_inline()` | 解析器无法追踪合并过程 | | RELEASE / RETURN | ⚠️ pass-through | SORT/MERGE 子句 | 排序合并子语句 | | MOVE CORRESPONDING | ❌ 无处理 | CORR 支持 | 低优先级,可延后 | ### 9.3 计划未覆盖的标准 COBOL 语句 | 语句 | 标准 | 不覆盖原因 | 建议 | |:-----|:----:|:-----------|:-----| | CANCEL | COBOL 85 | 释放程序内存,迁移中罕见 | **建议补充 P2** | | COMMIT | COBOL 85 | 事务控制。大型机批处理程序常用 | **建议补充 P2** | | ROLLBACK | COBOL 85 | 事务回滚,常与 COMMIT 搭配 | **建议补充 P2** | | DISPLAY | COBOL 85 | 输出语句,不产生分支。解析器 classify_field_roles 已扫描读取追踪 | **建议补充 P2**(低优先级,仅需 L0 验证样本) | | ENTER | COBOL 85 | 语言切换(汇编等),迁移中极罕见 | 可忽略 P3 | | EXHIBIT | COBOL 85 | 命名 DISPLAY 变体,已过时 | 可忽略 P3 | | GENERATE | COBOL 85 | Report Writer 功能,迁移不涉及 | 可忽略 P3 | ### 9.4 计划未覆盖的 CICS 语句 | 语句 | 用法 | 建议 | |:-----|:-----|:------| | **EXEC CICS LINK** | 程序间调用(最常用的 CICS 通信之一) | **建议补充 P1** | | **EXEC CICS XCTL** | 程序间转移控制 | **建议补充 P1** | | **EXEC CICS RETURN** | 返回至 CICS 调用链上层 | **建议补充 P1** | | EXEC CICS ADDRESS | 获取/设置工作区地址 | 可忽略 P3 | | EXEC CICS HANDLE | 异常条件处理 | 可忽略 P3 | ### 9.5 计划未覆盖的 SQL 语句 | 语句 | 用法 | 建议 | |:-----|:-----|:------| | **EXEC SQL COMMIT** | 事务提交(嵌入式 SQL 基本语句) | **建议补充 P2** | | **EXEC SQL ROLLBACK** | 事务回滚 | **建议补充 P2** | | EXEC SQL CONNECT | 数据库连接 | P3 | | EXEC SQL PREPARE | 动态 SQL 预编译 | P3 | ### 9.6 分类器关键字样本覆盖不足 HINA classifier 的 L1_RULES 中有 4 个关键字**当前没有任何独立的 COBOL 样本验证**: | 分类器关键字 | 匹配规则 | 现有样本 | 建议 | |:-------------|:---------|:--------:|:-----| | **IS INITIAL** | `PROGRAM-ID. X IS INITIAL.` | ❌ 无 | **P1 — 新增 ST-CLS-INITIAL.cbl** | | **SYSIN** | `SYSIN` 关键字 | ❌ 无 | **P1 — 新增 ST-CLS-SYSIN.cbl** | | **ORGANIZATION IS** | `ORGANIZATION IS INDEXED/RELATIVE` | ❌ 无 | **P1 — 新增 ST-CLS-ORG.cbl** | | **ALTERNATE RECORD KEY** | `ALTERNATE RECORD KEY IS ...` | ❌ 无 | **P1 — 新增 ST-CLS-ALTKEY.cbl** | 这些不会影响平台功能,但 **classifier 的测试套件缺少对这 4 个分类的确信度验证**。如果没有样本阻止回归,未来重构 keyword 匹配时可能无意中破坏这 4 个分类而测试不敏感。 ### 9.7 矩阵不准确性追踪 | 行 | 原值 | 实际值 | 修正版本 | |:---|:-----|:-------|:---------| | DELETE (FILE) | ✅ 解析支持 | ⚠️ 穿通 | v1.0 已修正 | | START | ✅ 解析支持 | ⚠️ 穿通 | v1.0 已修正 | | CLOSE | ✅ 解析支持 | ⚠️ 穿通 | v1.0 已修正 | | SORT | ✅ 解析支持 | ⚠️ 穿通 (关键词检测) | v1.0 已修正 | | MERGE | ✅ 解析支持 | ⚠️ 穿通 (关键词检测) | v1.0 已修正 | | RELEASE/RETURN | ✅ 解析支持 | ⚠️ 穿通 (SORT 子句) | v1.0 已修正 | | ALTER | ✅ 解析支持 | ⚠️ 穿通 (无解析器) | v1.0 已修正 | | CONTINUE | ✅ 解析支持 | ⚠️ 穿通 | v1.0 已修正 | | PERFORM 系列 | 矩阵缺失 | ✅ 解析支持 | v1.0 已添加 | | OPEN (OUTPUT/I-O) | ✅ 解析支持 | ⚠️ 扫描 (open_pattern) | v1.0 已修正 | | MOVE CORRESPONDING | ⚠️ 部分 | ❌ 不支持 | v1.0 已修正 | | USE/DECLARATIVES | ⚠️ 部分 | ❌ 无处理 | v1.0 已修正 | | EXECUTE | ⚠️ 部分 | ⚠️ 穿通 | v1.0 已修正 | ### 9.8 CICS/SQL 注释模拟限制 当前 CICS/SQL 样本使用 `*>` 注释关键词模拟: ``` *> EXEC CICS LINK PROGRAM('PGM01') *> COMMAREA(WS-COMMAREA) *> END-EXEC. ``` 这意味着: - `extract_structure()` **无法**从注释中提取分支结构 - 分类器 `classify_program()` 仍能检测关键词 → 正确分类 - 注释模拟样本**不经过 GnuCOBOL 编译检验语法正确性** 如果需要编译级验证,需要 WSL 中安装 IBM Enterprise COBOL 或 GnuCOBOL 的 CICS 支持库(不在当前范围)。 ### 9.9 建议的补充优先级 基于差异分析,建议的补充顺序: | 批次 | 内容 | 语句数 | 理由 | |:-----|:------|:------:|:------| | **立即 (当前 P0)** | 按现有计划执行 | 32 | 解析器已完全支持,仅缺样本 | | **P1 + 补充** | CICS LINK/XCTL/RETURN + 分类器关键字 4 个 | 7 | 迁移场景高频使用 + 分类器测试缺口 | | **P2 补充** | CANCEL/DISPLAY + SQL COMMIT/ROLLBACK | 4 | 标准语句缺失补全 | | **P3 (可忽略)** | ENTER/EXHIBIT/GENERATE/CICS ADDRESS/HANDLE | 5 | 极低使用率或已过时 |