多模态AI 基于工业级编译技术的PLC数据结构解析与映射工具
本项目开发了一个基于工业级编译技术的PLC数据结构解析工具(stDataCompiler),能够自动解析PLC程序中的变量定义并生成标准化JSON描述文件。该工具采用Flex/Bison构建词法语法分析器,支持C99及类ST语法,可准确提取结构体、联合体、枚举等复杂类型定义,并智能识别内存类型(指针、数组等)。核心功能包括预处理兼容、内存布局描述和JSON标准化输出,有效解决了工业控制系统中数据结
基于工业级编译技术的PLC数据结构解析与映射工具
项目概述
在工业控制与自动化系统中,PLC(可编程逻辑控制器)程序承载着关键的控制逻辑与数据结构。然而,这些结构往往深嵌于ST(结构化文本)或C99衍生代码中,难以直接可视化、调试或与上层信息系统交互。为此,我们开发了一款基于现代编译技术、专门用于解析PLC程序变量定义并自动生成标准化JSON描述文件的工具。
stDataCompiler 旨在打通工业控制底层数据与上层应用之间的“语义鸿沟”,通过自动化解析与映射,为系统集成、调试维护、数据可视化和测试验证提供一致、可靠的数据模型基础。
核心价值
- 自动化解析:支持C99及类ST语法,自动提取结构体、联合体、枚举及复杂类型定义。
- 内存布局可观测:智能识别变量内存类型(指针、数组、基本类型),输出带内存布局信息的结构化描述。
- JSON标准化输出:生成易于集成和使用的JSON数据描述,支持嵌套结构与复杂数据类型。
- 预处理兼容:完整处理
#include、#define等预处理指令,适应工业现场复杂的代码组织方式。 - 工业级可靠:基于Flex/Bison构建词法、语法分析器,确保解析准确性与鲁棒性。
技术架构:从代码到数据的编译级流水线
stDataCompiler 借鉴经典编译器设计思想,构建了一条从原始代码到结构化描述的完整处理流水线。其核心流程如下:
系统模块详解
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);
}
工作流程
- 输入解析:读取PLC程序源文件(.c, .st 或类似结构)。
- 预处理:展开宏、处理包含文件,生成可用于分析的中间代码。
- 词法分析:将代码转换为标记流,识别基础语法单元。
- 语法分析:根据语法规则构建AST,识别所有数据类型定义。
- 语义提取:遍历AST,提取结构体、字段、类型及内存布局信息。
- 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 标准的深度集成,并探索与实时数据库、数字孪生平台的无缝对接,持续为工业智能化赋能。
更多推荐



所有评论(0)