Files
hangshuo652 7ac887c776 feat: complete INSPECT/SEARCH support, fix PERFORM/EVAL coverage marking
- Add INSPECT (TALLYING/REPLACING/CONVERTING) with BEFORE/AFTER INITIAL
- Add SEARCH/SEARCH ALL with element-assignment path enumeration
- Fix _mark_perform compound condition marking via evaluate_tree
- Fix EVALUATE TRUE prior_false to collect all MC/DC false sets
- Add impossible path filtering (Pass A.5) with trace-to-root conflict detection
- Fix multi-line PERFORM VARYING parsing (VARYING/FROM/BY/UNTIL on separate lines)
- Remove dead code: agents.py LLM parser (replaced by rule-based _BrParser)
- 59 unit tests passing, 5 integration programs verified
2026-06-10 22:56:22 +08:00

164 lines
4.1 KiB
Python

"""COBOL数据模型 — 所有层共享,无外部依赖"""
from dataclasses import dataclass, field
# ── 字段定义 ──
@dataclass
class PicInfo:
type: str = 'unknown' # "numeric" | "alphanumeric" | "alphabetic"
digits: int = 0
decimal: int = 0
length: int = 0
signed: bool = False
@dataclass
class FieldDef:
name: str
level: int
pic: str | None = None
pic_info: PicInfo | None = None
is_filler: bool = False
occurs_count: int = 0
occurs_depending: str | None = None
redefines: str | None = None
usage: str | None = None # "COMP" | "COMP-3" | "BINARY" | "PACKED-DECIMAL" | ...
value: str | None = None
values: list[str] | None = None
is_88: bool = False
parent: str | None = None
section: str | None = None
# ── 分支树 ──
class BrSeq:
def __init__(self):
self.children = []
def add(self, child):
self.children.append(child)
class BrIf:
def __init__(self, condition):
self.condition = condition
self.cond_tree = None # 由 core.py 在解析时赋值
self.true_seq = BrSeq()
self.false_seq = BrSeq()
class BrEval:
def __init__(self, subject):
self.subject = subject
self.subjects = [] # ALSO 多主体: ['WS-A', 'WS-B'],空=普通模式
self.when_list = []
self.other_seq = BrSeq()
self.has_other = False
class BrPerform:
def __init__(self, perf_type, condition=None, target=None, thru=None, times=None,
varying_var=None, varying_from=None, varying_by=None):
self.perf_type = perf_type
self.condition = condition
self.target = target
self.thru = thru
self.times = times
self.varying_var = varying_var
self.varying_from = varying_from
self.varying_by = varying_by
self.body_seq = BrSeq()
class Assign:
"""赋值节点:MOVE/COMPUTE/ADD/SUBTRACT/MULTIPLY/DIVIDE"""
def __init__(self, target: str, source_info: dict):
self.target = target
self.source_info = source_info
class CallNode:
"""CALL 子程序调用节点(黑盒模式)"""
def __init__(self, program_name: str, using_params: list = None):
self.program_name = program_name
self.using_params = using_params or []
# using_params: [{"name": "WS-A", "mechanism": "reference"}, ...]
# mechanism: "reference" | "content" | "value"
# ── 条件树 ──
class CondLeaf:
def __init__(self, field, op, value):
self.field = field
self.op = op
self.value = value
class CondNot:
def __init__(self, child):
self.child = child
class CondAnd:
def __init__(self, left, right):
self.left = left
self.right = right
class CondOr:
def __init__(self, left, right):
self.left = left
self.right = right
class BrSearch:
"""SEARCH / SEARCH ALL 表查找"""
def __init__(self, table_name, is_all=False, varying=None):
self.table_name = table_name
self.is_all = is_all
self.varying = varying.upper() if varying else None
self.at_end_seq = BrSeq()
self.when_list = [] # [(condition_text, BrSeq)]
self.cond_trees = [] # [cond_tree, ...]
self.has_at_end = False
class GoTo:
"""GO TO 节点:无条件跳转到指定段落"""
def __init__(self, target: str, body_seq: 'BrSeq' = None):
self.target = target
self.body_seq = body_seq or BrSeq()
class ExitNode:
"""控制流退出节点:EXIT PARAGRAPH / EXIT PERFORM / EXIT SECTION / EXIT PROGRAM"""
def __init__(self, exit_type: str):
self.exit_type = exit_type
# ── 约束路径 ──
Constraint = tuple # (field, op, value, want_true)
Path = list[Constraint]
# ── 解析错误 ──
@dataclass
class ParseError:
line: int
message: str
severity: str = 'warning'
@dataclass
class ProcParseResult:
tree: BrSeq | None = None
assignments: dict = field(default_factory=dict)
errors: list[ParseError] = field(default_factory=list)
fallback_to_ai: bool = False