基于工业级编译技术的PLC数据结构解析与映射工具

项目概述

在工业控制与自动化系统中,PLC(可编程逻辑控制器)程序承载着关键的控制逻辑与数据结构。然而,这些结构往往深嵌于ST(结构化文本)或C99衍生代码中,难以直接可视化、调试或与上层信息系统交互。为此,我们开发了一款基于现代编译技术、专门用于解析PLC程序变量定义并自动生成标准化JSON描述文件的工具。

stDataCompiler 旨在打通工业控制底层数据与上层应用之间的“语义鸿沟”,通过自动化解析与映射,为系统集成、调试维护、数据可视化和测试验证提供一致、可靠的数据模型基础。

核心价值

  • 自动化解析:支持C99及类ST语法,自动提取结构体、联合体、枚举及复杂类型定义。
  • 内存布局可观测:智能识别变量内存类型(指针、数组、基本类型),输出带内存布局信息的结构化描述。
  • JSON标准化输出:生成易于集成和使用的JSON数据描述,支持嵌套结构与复杂数据类型。
  • 预处理兼容:完整处理 #include#define 等预处理指令,适应工业现场复杂的代码组织方式。
  • 工业级可靠:基于Flex/Bison构建词法、语法分析器,确保解析准确性与鲁棒性。

技术架构:从代码到数据的编译级流水线

stDataCompiler 借鉴经典编译器设计思想,构建了一条从原始代码到结构化描述的完整处理流水线。其核心流程如下:

工具依赖

输出层

处理层

输入层

输入文件

预处理结果

Token流

语法树

结构化数据

生成

可选

生成

生成

支持

PLC程序代码文件

预处理模块
matIECPreProc

词法分析器
lexC99.l

语法分析器
parserC99.y

抽象语法树
matIECAst

代码生成器
matIECGen

JSON描述文件

预处理后文件

Flex

Bison

Boost Wave

系统模块详解

1. 预处理模块(matIECPreProc)

基于 Boost.Wave 实现,负责对原始工业代码进行预处理,处理文件包含、宏展开与条件编译,为后续分析提供纯净的代码文本。

2. 词法分析器(lexC99.l)

使用 Flex 生成,将预处理后的源代码转换为 Token 流。精准识别 C99 关键字、标识符、常量及运算符,保留行列信息以支持精准错误定位。

3. 语法分析器(parserC99.y)

通过 Bison 构建,依据 C99 语法规则解析 Token 流,识别结构体、联合体、枚举等复合类型定义,并构建初步的抽象语法树(AST)。

4. 抽象语法树处理(matIECAst)

遍历 AST,提取类型定义、字段列表及内存布局信息,构建内部结构化数据模型。智能识别指针、数组等复杂类型,并解析数组维度等元信息。

5. 代码生成器(matIECGen)

将内部数据模型序列化为标准化 JSON 格式,包含类型名称、内存类别、嵌套结构等完整信息,输出为易于集成的描述文件。

关键技术实现

1. 词法规则设计

通过正则表达式精确定义各类 Token,确保工业代码中特殊符号、数字格式与注释的准确识别。

/* 正则定义示例 */
DIGIT       [0-9]
LETTER      [a-zA-Z_]
HEX         [0-9a-fA-F]
OCT         [0-7]
ESC         \\(['"\?abfnrtv\\]|{OCT}{1,3}|x{HEX}+)

/* 关键字识别 */
"struct"            { return STRUCT; }
"union"             { return UNION; }
"enum"              { return ENUM; }
"int"               { return INT; }
"char"              { return CHAR; }

2. 语法规则与AST构建

明确定义复杂类型的语法结构,并在解析过程中逐步构建层次清晰的语法树节点。

struct_definition
    : STRUCT IDENTIFIER LBRACE field_list RBRACE SEMICOLON {
        add_struct($2, tmp_field_list);
        tmp_field_list = NULL;
    }
    ;

3. 内存类型智能推断

在AST处理阶段,通过字段名称与语法模式识别其内存表示形式。

std::string name_str = current_field->name;
if (name_str.find('*') != std::string::npos) {
    field_item.m_mem_type__ = emClassMemType::emPointer;
} else if (name_str.find('[') != std::string::npos) {
    field_item.m_mem_type__ = emClassMemType::emArray;
    // 解析数组大小
    size_t array_size_pos = name_str.find('[');
    std::string array_size_str = name_str.substr(array_size_pos + 1, 
                                                  name_str.find(']') - array_size_pos - 1);
    field_item.m_array_size__ = std::stoi(array_size_str);
}

工作流程

  1. 输入解析:读取PLC程序源文件(.c, .st 或类似结构)。
  2. 预处理:展开宏、处理包含文件,生成可用于分析的中间代码。
  3. 词法分析:将代码转换为标记流,识别基础语法单元。
  4. 语法分析:根据语法规则构建AST,识别所有数据类型定义。
  5. 语义提取:遍历AST,提取结构体、字段、类型及内存布局信息。
  6. JSON生成:将提取的信息转换为结构化JSON并写入输出文件。

输入输出示例

输入代码示例

struct Point {
    int x;
    int y;
};

struct Rectangle {
    struct Point origin;
    int width;
    int height;
    char* name;
    int coordinates[4];
};

输出JSON示例

[
  {
    "name": "Point",
    "type": "struct",
    "mem_type": "pointer",
    "sub_items": [
      {
        "name": "x",
        "type": "int",
        "mem_type": "pointer"
      },
      {
        "name": "y",
        "type": "int",
        "mem_type": "pointer"
      }
    ]
  },
  {
    "name": "Rectangle",
    "type": "struct",
    "mem_type": "pointer",
    "sub_items": [
      {
        "name": "origin",
        "type": "struct",
        "mem_type": "pointer"
      },
      {
        "name": "width",
        "type": "int",
        "mem_type": "pointer"
      },
      {
        "name": "height",
        "type": "int",
        "mem_type": "pointer"
      },
      {
        "name": "name",
        "type": "char",
        "mem_type": "pointer"
      },
      {
        "name": "coordinates",
        "type": "int",
        "mem_type": "array",
        "array_size": 4
      }
    ]
  }
]

技术亮点

  • 工业级词法/语法分析:基于 Flex/Bison,解析准确率高,支持复杂工业代码模式。
  • 跨标准兼容:实现自有内存管理函数(如 my_strdup),确保在 C11/C17 等环境中的稳定运行。
  • 完整内存布局描述:不仅解析类型,还识别其内存表示方式(指针、数组、值类型)。
  • 错误定位友好:在词法分析阶段保留行列号,便于快速定位源码错误。
  • 模块化与可扩展:各处理阶段解耦清晰,便于后续支持更多语言特性或输出格式。

应用场景

  • 工业控制系统集成:为 SCADA、MES 等上层系统提供 PLC 数据结构的自动映射描述,简化系统对接。
  • 调试与诊断:可视化 PLC 内部数据结构,辅助在线调试与故障诊断。
  • 自动化测试:基于数据结构描述自动生成测试用例或模拟数据。
  • 文档自动化:自动生成数据字典或接口文档,提升项目交付效率。
  • ** legacy 系统现代化**:帮助老旧系统进行数据结构梳理与接口标准化。

总结

stDataCompiler 不仅仅是一个解析工具,更是连接工业控制底层逻辑与信息化上层应用的关键桥梁。它将编译器的严谨性与工业场景的实际需求相结合,实现了从“代码即数据”到“数据可观测、可交互”的转变。

在未来,我们计划进一步扩展其语法支持范围,增强与 IEC 61131-3 标准的深度集成,并探索与实时数据库、数字孪生平台的无缝对接,持续为工业智能化赋能。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐