Files
AutoBOM/docs/Test_PP_06_FullIntegration_流程详解.md
Misaka_Company 3a93459002
All checks were successful
NTFY Notification / notify (push) Successful in 5s
feat: add preprocessing module for BOM condition transformation
Add M05_PreProcessor module to handle value mapping and condition
simplification for "接头" category before parsing.

Features:
- Value mapping: azxs codes (A0/AT/AH→径向, B0/BT/BZ/BH→下轴向,
  Z0/ZT/ZZ/ZH→中轴向) and lcfw ranges (M01-M11→低压, M12-M16→高压)
- OR condition merging: automatically removes duplicate OR segments
- Smart parentheses handling: removes parentheses for single atoms,
  preserves them when needed for logical structure
- Recursive nested expression processing
- Graceful degradation when "对照表" worksheet is missing

Integration:
- Modified M01_Main to initialize preprocessor after M03_Logic
- Preprocessing applied only for "接头" category
- Updated M99_TestRunner with 8 comprehensive test cases
- All tests passing (50 total: 42 core + 8 preprocessing)

Documentation:
- Added detailed flow documentation for Test_PP_06_FullIntegration
  with mermaid diagrams in docs/Test_PP_06_FullIntegration_流程详解.md
- Updated CLAUDE.md with preprocessing module description and
  documentation guidelines (docs/ vs reference_docs/)

Example transformation:
  Input:  gclj=M16 AND (azxs=A0 OR azxs=AT) AND (lcfw=M01 OR lcfw=M15)
  Output: gclj=M16 AND azxs=径向 AND (lcfw=低压 OR lcfw=高压)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-09 16:24:41 +08:00

20 KiB
Raw Blame History

Test_PP_06_FullIntegration 流程详解

目录

  1. 测试概述
  2. 测试场景
  3. 完整执行流程
  4. 详细步骤分析
  5. 关键数据结构
  6. 映射表说明

测试概述

测试名称: Test_PP_06_FullIntegration (完整集成测试)

测试目的: 验证预处理模块与逻辑解析模块的完整集成,确保:

  1. 值映射功能正确azxs 和 lcfw
  2. 嵌套 OR 条件正确简化
  3. 复杂表达式的括号正确处理
  4. 预处理后的结果能被 M03_Logic 正确解析

涉及模块:

  • M05_PreProcessor (预处理模块)
  • M03_Logic (逻辑解析模块)
  • clsErrorLogger (错误日志)

测试场景

输入条件

gclj=M16 AND (azxs=A0 OR azxs=AT) AND (lcfw=M01 OR lcfw=M15)

预期预处理结果

gclj=M16 AND azxs=径向 AND (lcfw=低压 OR lcfw=高压)

预期解析结果

生成 2 行数据:

  • 行 1: gclj=M16, azxs=径向, lcfw=低压
  • 行 2: gclj=M16, azxs=径向, lcfw=高压

关键验证点

  1. azxs=A0 OR azxs=ATazxs=径向 (两个值映射相同,去重)
  2. (lcfw=M01 OR lcfw=M15)(lcfw=低压 OR lcfw=高压) (值映射,保留括号)
  3. ✓ 最终生成 2 行数据

完整执行流程

流程总览

flowchart TD
    Start[开始测试] --> Setup[初始化测试环境]
    Setup --> LoadMapping[加载映射表]
    LoadMapping --> CallPreprocessor[调用 PreprocessCondition]
    CallPreprocessor --> CheckCategory{类别 = 接头?}
    CheckCategory -->|否| ReturnOriginal[返回原条件]
    CheckCategory -->|是| ProcessNested[递归处理嵌套表达式]
    ProcessNested --> ProcessFirstBracket[处理第一个括号<br/>azxs=A0 OR azxs=AT]
    ProcessFirstBracket --> ApplyPreprocess1[应用预处理]
    ApplyPreprocess1 --> ReplaceAzxs[值替换: azxs映射]
    ReplaceAzxs --> MergeOR1[合并重复OR]
    MergeOR1 --> CheckParens1{需要括号?}
    CheckParens1 -->|否| NoParens1[去掉括号<br/>azxs=径向]
    CheckParens1 -->|是| KeepParens1[保留括号]
    NoParens1 --> ProcessSecondBracket[处理第二个括号<br/>lcfw=M01 OR lcfw=M15]
    KeepParens1 --> ProcessSecondBracket
    ProcessSecondBracket --> ApplyPreprocess2[应用预处理]
    ApplyPreprocess2 --> ReplaceLcfw[值替换: lcfw映射]
    ReplaceLcfw --> MergeOR2[合并重复OR检查]
    MergeOR2 --> CheckParens2{需要括号?}
    CheckParens2 -->|否| NoParens2[去掉括号]
    CheckParens2 -->|是| KeepParens2[保留括号<br/>lcfw=低压 OR lcfw=高压]
    NoParens2 --> FinalProcess[最终AND分段处理]
    KeepParens2 --> FinalProcess
    FinalProcess --> ReturnPreprocessed[返回预处理结果]
    ReturnPreprocessed --> ParseRule[M03_Logic.ParseRule解析]
    ParseRule --> SplitTopLevelOR{顶层OR分割}
    SplitTopLevelOR --> SplitOR[分割: 2个OR分段]
    SplitOR --> ParseEachOR[解析每个OR分段]
    ParseEachOR --> VerifyResults{验证结果}
    VerifyResults -->|count=2| Success[测试通过]
    VerifyResults -->|count≠2| Failure[测试失败]

函数调用时序图

sequenceDiagram
    participant Test as Test_PP_06
    participant PP as M05_PreProcessor
    participant Logic as M03_Logic
    participant Mapping as 映射表

    Test->>PP: InitPreProcessor(logger, wsMapping)
    PP->>Mapping: LoadLcfwMapping()
    Mapping-->>PP: lcfw映射表加载
    PP->>Mapping: LoadAzxsMapping()
    Mapping-->>PP: azxs映射表加载

    Test->>PP: PreprocessCondition(inputCond, "接头", 1)

    Note over PP: 步骤1: 类别检查
    alt 类别 != "接头"
        PP-->>Test: 返回原条件
    else 类别 == "接头"
        PP->>PP: ApplyPreprocessing()

        Note over PP: 步骤2: 递归处理嵌套括号
        PP->>PP: ProcessAndSimplifyNested()

        Note over PP: 处理 (azxs=A0 OR azxs=AT)
        PP->>PP: 提取括号内容
        PP->>PP: ApplyPreprocessing(azxs=A0 OR azxs=AT)
        PP->>PP: 分割OR: [azxs=A0, azxs=AT]
        PP->>PP: ProcessAndSegment(azxs=A0)
        PP->>Mapping: 查询 azxs="A0"
        Mapping-->>PP: 返回 "径向"
        PP->>PP: ProcessAndSegment(azxs=AT)
        PP->>Mapping: 查询 azxs="AT"
        Mapping-->>PP: 返回 "径向"
        PP->>PP: MergeDuplicateORs()
        Note over PP: 两段相同 → 返回一段
        PP->>PP: SimplifyIfAllSame()
        Note over PP: 检查: 无顶层OR → 去掉括号
        PP-->>PP: azxs=径向

        Note over PP: 处理 (lcfw=M01 OR lcfw=M15)
        PP->>PP: 提取括号内容
        PP->>PP: ApplyPreprocessing(lcfw=M01 OR lcfw=M15)
        PP->>PP: 分割OR: [lcfw=M01, lcfw=M15]
        PP->>PP: ProcessAndSegment(lcfw=M01)
        PP->>Mapping: 查询 lcfw="M01"
        Mapping-->>PP: 返回 "低压"
        PP->>PP: ProcessAndSegment(lcfw=M15)
        PP->>Mapping: 查询 lcfw="M15"
        Mapping-->>PP: 返回 "高压"
        PP->>PP: MergeDuplicateORs()
        Note over PP: 两段不同 → 保留两段
        PP->>PP: SimplifyIfAllSame()
        Note over PP: 检查: 有顶层OR → 保留括号
        PP-->>PP: (lcfw=低压 OR lcfw=高压)

        Note over PP: 步骤3: 最终AND处理
        PP->>PP: ProcessAndSegment(完整表达式)
        PP-->>Test: gclj=M16 AND azxs=径向 AND (lcfw=低压 OR lcfw=高压)
    end

    Test->>Logic: ParseRule(preprocessed, 1)

    Note over Logic: 步骤4: 逻辑解析
    Logic->>Logic: RecursiveParse()

    Note over Logic: 查找顶层OR
    Logic->>Logic: FindSplitIndex(OR)
    Note over Logic: 找到: (lcfw=低压 OR lcfw=高压) 之前

    Logic->>Logic: 递归解析左段
    Note over Logic: gclj=M16 AND azxs=径向
    Logic->>Logic: 解析AND → 笛卡尔积
    Logic-->>Logic: Row1: {gclj:M16, azxs:径向}

    Logic->>Logic: 递归解析右段
    Note over Logic: lcfw=低压 OR lcfw=高压
    Logic->>Logic: 解析OR → 并集
    Logic-->>Logic: Row2: {lcfw:低压}, Row3: {lcfw:高压}

    Logic->>Logic: CartesianProduct(Row1, Row2)
    Note over Logic: 笛卡尔积: 1 × 2 = 2行
    Logic-->>Logic: RowA: {gclj:M16, azxs:径向, lcfw:低压}
    Logic-->>Logic: RowB: {gclj:M16, azxs:径向, lcfw:高压}

    Logic-->>Test: Collection(2行)

    Note over Test: 步骤5: 验证结果
    Test->>Test: col.count == 2 ?
    Test->>Test: row("gclj") == "M16" ?
    Test->>Test: row("azxs") == "径向" ?
    Test->>Test: row("lcfw") == "低压" ?

    Test-->>Test: ✓ 测试通过

详细步骤分析

步骤 1: 初始化测试环境

Private Sub Test_PP_06_FullIntegration()
    SetupPreProcessorTest

执行动作:

  1. 查找 [对照表] 工作表
  2. 创建 clsErrorLogger 实例
  3. 初始化 M03_Logic 模块
  4. 初始化 M05_PreProcessor 模块

数据结构初始化:

Set g_LcfwMapping = CreateObject("Scripting.Dictionary")
Set g_AzxsMapping = CreateObject("Scripting.Dictionary")

步骤 2: 加载映射表

LoadAzxsMapping() 执行流程:

flowchart LR
    Start[开始加载azxs映射] --> Read[读取 D列:E列<br/>行3到最后]
    Read --> Process[逐行处理]
    Process --> Check{有数据?}
    Check -->|是| Extract[提取key和value<br/>例: D3=A0, E3=径向]
    Check -->|否| Next[下一行]
    Extract --> Add[添加到Dictionary<br/>g_AzxsMapping.Add A0, 径向]
    Add --> Next
    Next --> More{还有行?}
    More -->|是| Process
    More -->|否| End[结束]

加载的 azxs 映射数据:

g_AzxsMapping = {
    "A0": "径向",
    "AT": "径向",
    "AH": "径向",
    "B0": "下轴向",
    "BT": "下轴向",
    "BZ": "下轴向",
    "BH": "下轴向",
    "Z0": "中轴向",
    "ZT": "中轴向",
    "ZZ": "中轴向",
    "ZH": "中轴向"
}

LoadLcfwMapping() 执行流程:

g_LcfwMapping = {
    "M01": "低压",
    "M02": "低压",
    "M03": "低压",
    "M04": "低压",
    "M05": "低压",
    "M06": "低压",
    "M07": "低压",
    "M08": "低压",
    "M09": "低压",
    "M10": "低压",
    "M11": "低压",
    "M12": "高压",      // 假设M12映射到高压
    "M13": "高压",      // 假设M13映射到高压
    "M14": "高压",
    "M15": "高压",
    "M16": "高压"
}

步骤 3: 预处理入口

inputCond = "gclj=M16 AND (azxs=A0 OR azxs=AT) AND (lcfw=M01 OR lcfw=M15)"
preprocessed = M05_PreProcessor.PreprocessCondition(inputCond, "接头", 1)

PreprocessCondition() 执行流程:

flowchart TD
    Start[PreprocessCondition] --> CheckInit{初始化?}
    CheckInit -->|否| Return1[返回原条件]
    CheckInit -->|是| CheckCat{类别=接头?}
    CheckCat -->|否| Return2[返回原条件]
    CheckCat -->|是| Apply[ApplyPreprocessing]
    Apply --> Return3[返回预处理结果]

检查结果:

  • ✓ 已初始化: g_IsInitialized = True
  • ✓ 类别匹配: strCategory = "接头"
  • → 继续执行 ApplyPreprocessing()

步骤 4: 递归处理嵌套表达式

4.1 ProcessAndSimplifyNested() 处理第一个括号

输入字符串: gclj=M16 AND (azxs=A0 OR azxs=AT) AND (lcfw=M01 OR lcfw=M15)

逐字符处理流程:

flowchart TD
    Start[开始处理] --> P0[处理字符 1-12<br/>gclj=M16 AND]
    P0 --> P1[字符 13: 遇到左括号]
    P1 --> B1[bracketLevel = 1<br/>进入括号模式]
    B1 --> Collect[收集字符 14-28<br/>azxs=A0 OR azxs=AT]
    Collect --> B2[字符 29: 遇到右括号]
    B2 --> Recurse[递归处理括号内容]
    Recurse --> Recurse1[ProcessAndSimplifyNested<br/>无嵌套括号]
    Recurse1 --> Apply1[ApplyPreprocessing]
    Apply1 --> Split1[SplitTopLevel OR]
    Split1 --> Seg1[分段: azxs=A0]
    Split1 --> Seg2[分段: azxs=AT]
    Seg1 --> Proc1[ProcessAndSegment]
    Seg2 --> Proc2[ProcessAndSegment]
    Proc1 --> Atom1[ProcessAtom: azxs=A0]
    Proc2 --> Atom2[ProcessAtom: azxs=AT]
    Atom1 --> Map1[查询: A0→径向]
    Atom2 --> Map2[查询: AT→径向]
    Map1 --> Res1[azxs=径向]
    Map2 --> Res2[azxs=径向]
    Res1 --> Merge[MergeDuplicateORs]
    Res2 --> Merge
    Merge --> Simplify[SimplifyIfAllSame]
    Simplify --> Check{两段相同?}
    Check -->|是| Single[返回单段<br/>azxs=径向]
    Check -->|否| Both[保留OR]
    Single --> Need{需要括号?}
    Both --> Need
    Need --> HasOp[HasTopLevelOperator]
    HasOp --> NoOp[无顶层操作符]
    NoOp --> NoParens[needsParens = False]
    NoParens --> Append[添加到结果<br/>azxs=径向]
    Append --> Continue[继续处理后续字符]

第一个括号处理结果:

(azxs=A0 OR azxs=AT) → azxs=径向

为什么去掉括号?

  • 处理后内容: azxs=径向
  • 检查顶层操作符: 无 OR, 无 AND
  • 结论: 单个原子,不需要括号

4.2 ProcessAndSimplifyNested() 处理第二个括号

输入字符串: (lcfw=M01 OR lcfw=M15)

处理流程:

flowchart TD
    Start[处理 lcfw括号] --> Extract[提取内容]
    Extract --> Content[内容: lcfw=M01 OR lcfw=M15]
    Content --> Recursive[递归处理<br/>ProcessAndSimplifyNested]
    Recursive --> Apply[ApplyPreprocessing]
    Apply --> Split[SplitTopLevel OR]
    Split --> Segments[分段: 2个元素]
    Segments --> Seg1[分段1: lcfw=M01]
    Segments --> Seg2[分段2: lcfw=M15]
    Seg1 --> Process1[ProcessAndSegment M01]
    Seg2 --> Process2[ProcessAndSegment M15]
    Process1 --> Map1[查询映射: M01→低压]
    Process2 --> Map2[查询映射: M15→高压]
    Map1 --> Merge1[MergeDuplicateORs]
    Map2 --> Merge1
    Merge1 --> CheckSame{两段相同?}
    CheckSame -->|否| KeepBoth[保留两段]
    KeepBoth --> Simplify[SimplifyIfAllSame]
    Simplify --> CheckParens{需要括号?}
    CheckParens --> HasOR[HasTopLevelOperator检查]
    HasOR --> HasResult[返回 True: 有顶层OR]
    HasResult --> AddParens[添加括号]
    AddParens --> Final[最终结果<br/>lcfw=低压 OR lcfw=高压]

第二个括号处理结果:

(lcfw=M01 OR lcfw=M15) → (lcfw=低压 OR lcfw=高压)

为什么保留括号?

  • 处理后内容: lcfw=低压 OR lcfw=高压
  • 检查顶层操作符: 有 OR
  • 结论: 有顶层操作符,需要括号以保持正确逻辑结构

步骤 5: 最终表达式组装

当前状态:

  • 原始: gclj=M16 AND (azxs=A0 OR azxs=AT) AND (lcfw=M01 OR lcfw=M15)
  • 第一个括号处理后: gclj=M16 AND azxs=径向 AND (lcfw=M01 OR lcfw=M15)
  • 第二个括号处理后: gclj=M16 AND azxs=径向 AND (lcfw=低压 OR lcfw=高压)

最终预处理结果:

gclj=M16 AND azxs=径向 AND (lcfw=低压 OR lcfw=高压)

步骤 6: M03_Logic.ParseRule 解析

6.1 递归解析流程

flowchart TD
    Start[ParseRule] --> Clean[CleanString]
    Clean --> Recursive[RecursiveParse]
    Recursive --> FindOR[FindSplitIndex OR]
    FindOR --> FoundOR{找到OR}
    FoundOR -->|是| SplitOR[分割位置]
    FoundOR -->|否| FindAND[FindSplitIndex AND]

    SplitOR --> Left[左段解析]
    SplitOR --> Right[右段解析]

    Left --> ParseLeft[RecursiveParse左段]
    ParseLeft --> FindAND1[FindSplitIndex AND]
    FindAND1 --> FoundAND1{找到AND}
    FoundAND1 -->|是| SplitAND[分割AND]
    SplitAND --> LeftLeft[元素1 gclj=M16]
    SplitAND --> LeftRight[元素2 azxs=径向]
    LeftLeft --> Atom1[ParseAtom字典1]
    LeftRight --> Atom2[ParseAtom字典2]
    Atom1 --> Merge1[MergeDictionaries]
    Atom2 --> Merge1
    Merge1 --> Result1[合并结果<br/>gclj为M16和azxs为径向]

    Right --> ParseRight[RecursiveParse右段]
    ParseRight --> FindOR2[FindSplitIndex OR]
    FindOR2 --> FoundOR2{找到OR}
    FoundOR2 -->|是| SplitOR2[分割OR]
    SplitOR2 --> RightLeft[元素1 lcfw=低压]
    SplitOR2 --> RightRight[元素2 lcfw=高压]
    RightLeft --> Atom3[ParseAtom字典3]
    RightRight --> Atom4[ParseAtom字典4]
    Atom3 --> Union1[UnionCollections]
    Atom4 --> Union1
    Union1 --> Result2[Collection集合<br/>包含2个字典元素]

    Result1 --> Cartesian[笛卡尔积计算]
    Result2 --> Cartesian
    Cartesian --> Final[最终结果<br/>2行数据]

6.2 笛卡尔积计算

输入:

  • 左段: 1行 → [{gclj: "M16", azxs: "径向"}]
  • 右段: 2行 → [{lcfw: "低压"}, {lcfw: "高压"}]

笛卡尔积过程:

flowchart LR
    Left[左段: 1行<br/>gclj=M16, azxs=径向] --> Combine
    Right[右段: 2行<br/>lcfw=低压, lcfw=高压] --> Combine
    Combine[笛卡尔积 1×2] --> Row1[行1:<br/>gclj=M16<br/>azxs=径向<br/>lcfw=低压]
    Combine --> Row2[行2:<br/>gclj=M16<br/>azxs=径向<br/>lcfw=高压]

最终结果:

Collection {
    [1] Dictionary {gclj: "M16", azxs: "径向", lcfw: "低压"},
    [2] Dictionary {gclj: "M16", azxs: "径向", lcfw: "高压"}
}

步骤 7: 结果验证

Assert_Equal col.count, 2, "PP06_Count_After_Preprocessing"      ' ✓ 通过
Assert_Equal row("gclj"), "M16", "PP06_gclj_Value"                ' ✓ 通过
Assert_Equal row("azxs"), "径向", "PP06_azxs_Mapped_Value"        ' ✓ 通过
Assert_Equal row("lcfw"), "低压", "PP06_lcfw_Mapped_Value"        ' ✓ 通过

关键数据结构

1. 映射表 Dictionary

' azxs 映射表
g_AzxsMapping: Scripting.Dictionary
    Key: "A0"   → Value: "径向"
    Key: "AT"   → Value: "径向"
    Key: "AH"   → Value: "径向"
    Key: "B0"   → Value: "下轴向"
    ...

' lcfw 映射表
g_LcfwMapping: Scripting.Dictionary
    Key: "M01"  → Value: "低压"
    Key: "M15"  → Value: "高压"
    ...

2. 原子解析结果

' ParseAtom 返回的 Dictionary
ParseAtom("azxs=A0") → Dictionary {
    "key": "azxs",
    "value": "A0",
    "operator": "="
}

' ProcessAtom 处理后
ProcessAtom("azxs=A0") → "azxs=径向"

3. Collection 数据流

graph LR
    A[SplitTopLevel OR] --> B[Collection: 2个元素]
    B --> C["Element 1: azxs=A0"]
    B --> D["Element 2: azxs=AT"]
    C --> E[ProcessAndSegment]
    D --> F[ProcessAndSegment]
    E --> G["azxs=径向"]
    F --> H["azxs=径向"]
    G --> I[MergeDuplicateORs]
    H --> I
    I --> J[Collection: 1个元素<br/>azxs=径向]

4. 最终解析结果

' M03_Logic.ParseRule 返回的 Collection
Collection {
    [1] Dictionary {
        "gclj": "M16",
        "azxs": "径向",
        "lcfw": "低压"
    },
    [2] Dictionary {
        "gclj": "M16",
        "azxs": "径向",
        "lcfw": "高压"
    }
}

映射表说明

azxs (安装形式) 映射规则

原始值 对应值 说明
A0, AT, AH 径向 径向安装
B0, BT, BZ, BH 下轴向 下轴向安装
Z0, ZT, ZZ, ZH 中轴向 中轴向安装

测试用例: azxs=A0 OR azxs=AT

  • A0 → 径向
  • AT → 径向
  • 两个映射结果相同 → OR 去重 → azxs=径向

lcfw (量程范围) 映射规则

原始值 对应值 说明
M01-M11 低压 低压量程
M12-M16 高压 高压量程

测试用例: lcfw=M01 OR lcfw=M15

  • M01 → 低压
  • M15 → 高压
  • 两个映射结果不同 → OR 保留 → lcfw=低压 OR lcfw=高压

关键函数说明

1. SplitTopLevel()

功能: 顶层分割,尊重括号嵌套

示例:

输入: "A AND (B OR C) AND D"
分割符: " AND "
输出: ["A", "(B OR C)", "D"]

算法:

  • 遍历字符串,跟踪 bracketLevel
  • 只在 bracketLevel = 0 时匹配分隔符

2. ProcessAtom()

功能: 处理单个原子,应用值映射

流程:

flowchart TD
    Input[输入: azxs=A0] --> Parse[ParseAtom]
    Parse --> Dict[Dictionary: key=azxs, value=A0, operator==]
    Dict --> CheckKey{检查key}
    CheckKey -->|azxs| QueryAz[g_AzxsMapping.Exists]
    CheckKey -->|lcfw| QueryLc[g_LcfwMapping.Exists]
    CheckKey -->|其他| Keep[保持原值]
    QueryAz --> FoundAz{找到?}
    FoundAz -->|是| ReplaceAz[替换为映射值]
    FoundAz -->|否| Keep
    QueryLc --> FoundLc{找到?}
    FoundLc -->|是| ReplaceLc[替换为映射值]
    FoundLc -->|否| Keep
    ReplaceAz --> Rebuild[重建: key+operator+value]
    ReplaceLc --> Rebuild
    Keep --> Rebuild
    Rebuild --> Output[输出: azxs=径向]

3. SimplifyIfAllSame()

功能: 检查所有 OR 分段是否相同,相同则去重

示例:

输入: "azxs=径向 OR azxs=径向"
分段: ["azxs=径向", "azxs=径向"]
检查: 两段相同
输出: "azxs=径向"

4. HasTopLevelOperator()

功能: 检查字符串是否有顶层操作符

示例:

输入: "lcfw=低压 OR lcfw=高压"
检查: " OR " 在 bracketLevel=0 时出现
输出: True (需要括号)

测试覆盖的场景

场景 输入 预期输出 测试点
值映射 azxs=A0 azxs=径向 ✓ azxs映射正确
OR去重 azxs=A0 OR azxs=AT azxs=径向 ✓ 相同映射值去重
括号保留 (lcfw=M01 OR lcfw=M15) (lcfw=低压 OR lcfw=高压) ✓ 不同映射值保留括号
复杂表达式 gclj=M16 AND (azxs=A0 OR azxs=AT) AND (...) 完整表达式 ✓ 多个嵌套括号处理
解析集成 预处理结果 2行数据 ✓ 与M03_Logic集成

常见问题

Q1: 为什么第一个括号去掉了,第二个括号保留了?

A:

  • 第一个括号 (azxs=A0 OR azxs=AT)azxs=径向

    • 处理后是单个原子,无顶层操作符 → 不需要括号
  • 第二个括号 (lcfw=M01 OR lcfw=M15)lcfw=低压 OR lcfw=高压

    • 处理后仍有顶层 OR → 需要括号保持逻辑结构

Q2: 为什么最终生成2行而不是4行

A:

原始: (azxs=A0 OR azxs=AT) AND (lcfw=M01 OR lcfw=M15)
理论上: 2 × 2 = 4行

预处理后: azxs=径向 AND (lcfw=低压 OR lcfw=高压)
实际: 1 × 2 = 2行

原因: 第一个OR的两个值映射相同去重后变为1个值

Q3: 如果映射值不同会怎样?

A:

输入: (azxs=A0 OR azxs=B0)
映射: A0→径向, B0→下轴向
输出: (azxs=径向 OR azxs=下轴向)
结果: 保留括号生成2行

总结

Test_PP_06_FullIntegration 测试验证了预处理模块的完整功能:

  1. 值映射: azxs 和 lcfw 的值正确映射
  2. OR去重: 相同映射值的OR条件正确合并
  3. 括号处理: 根据处理后内容的复杂度智能决定是否保留括号
  4. 逻辑集成: 预处理结果能被M03_Logic正确解析
  5. 结果正确: 最终生成正确的行数和数据

该测试确保了预处理模块在实际使用中的正确性和可靠性。