1. A2L文件结构完整性检查
任务目标
检查A2L文件的基本结构完整性,验证必需部分(HEADER、MODULE、COMPU_METHOD等)是否存在且顺序正确。本案例以最小可复现的A2L片段为输入,通过Python脚本解析并输出结构检查结果。
实现方案
使用Python标准库编写一个轻量级结构检查器,不依赖第三方A2L解析库。核心逻辑:逐行扫描A2L文件,识别顶层关键字(以begin起始的块定义),维护一个期望顺序列表,检查必需块是否出现、是否重复、顺序是否错乱。
关键完整代码
import sys
import re
# A2L必需顶层块及其合法出现顺序(按ASAP2标准)
REQUIRED_BLOCKS = [
("ASAP2_VERSION", False), # (块名, 是否允许缺失)
("HEADER", False),
("MODULE", False),
("COMPU_METHOD", True), # 允许缺失(部分A2L可能无全局COMPU_METHOD)
]
# 实际解析时需跟踪MODULE内部,但本案例仅检查顶层结构
def check_a2l_structure(filepath):
errors = []
found_blocks = [] # 按出现顺序记录顶层块名
with open(filepath, 'r', encoding='utf-8', errors='replace') as f:
lines = f.readlines()
# 预处理:去除注释(/ * ... * / 和 //)
code_lines = []
in_block_comment = False
for line in lines:
line = line.strip()
if in_block_comment:
end_idx = line.find('*/')
if end_idx != -1:
line = line[end_idx+2:].strip()
in_block_comment = False
else:
continue
# 去掉行内块注释开始
while '/*' in line:
start_idx = line.find('/*')
end_idx = line.find('*/', start_idx)
if end_idx == -1:
line = line[:start_idx].strip()
in_block_comment = True
break
else:
line = (line[:start_idx] + ' ' + line[end_idx+2:]).strip()
# 去掉//注释
line = re.sub(r'//.*$', '', line).strip()
if line:
code_lines.append(line)
# 识别顶层块:行首为 "begin 块名" 且不在其他块内部
# 简化处理:通过缩进判断层级(A2L标准使用缩进表示嵌套)
# 顶层块缩进为0(行首无空格)
for line in code_lines:
if line.startswith('begin '):
indent = len(line) - len(line.lstrip())
if indent == 0:
block_name = line.split()[1].strip()
found_blocks.append(block_name)
# 检查必需块是否存在
required_names = [name for name, optional in REQUIRED_BLOCKS if not optional]
for name in required_names:
if name not in found_blocks:
errors.append(f"缺少必需块: {name}")
# 检查顺序(按REQUIRED_BLOCKS定义的顺序)
expected_order = [name for name, _ in REQUIRED_BLOCKS]
# 过滤掉文件中未出现的块,只比较实际出现的块的相对顺序
actual_order = [b for b in found_blocks if b in expected_order]
# 去重后检查顺序
seen = []
for b in actual_order:
if b not in seen:
seen.append(b)
# 检查seen是否满足expected_order的子序列关系
idx = 0
for b in seen:
while idx < len(expected_order) and expected_order[idx] != b:
idx += 1
if idx >= len(expected_order):
errors.append(f"块顺序错误: {b} 出现在不应出现的位置")
break
idx += 1
# 检查重复(同一块出现多次,MODULE除外——但标准中MODULE只能有一个)
from collections import Counter
counter = Counter(found_blocks)
for name, count in counter.items():
if count > 1 and name in ('HEADER', 'MODULE', 'ASAP2_VERSION'):
errors.append(f"块 {name} 重复出现 {count} 次")
return found_blocks, errors
if __name__ == "__main__":
if len(sys.argv) != 2:
print("用法: python a2l_check.py <文件路径>")
sys.exit(1)
blocks, errs = check_a2l_structure(sys.argv[1])
print("检测到的顶层块(按出现顺序):")
for b in blocks:
print(f" - {b}")
if errs:
print("\n结构错误:")
for e in errs:
print(f" [ERROR] {e}")
sys.exit(1)
else:
print("\n结构检查通过: 所有必需块存在且顺序正确")
sys.exit(0)
运行与验证
环境要求:Python 3.6+,无第三方依赖。
测试输入文件(保存为 sample.a2l):
ASAP2_VERSION 1 51
begin HEADER
VERSION "1.0"
end HEADER
begin MODULE
NAME "DemoModule"
begin COMPU_METHOD
NAME "CM_uint8"
CONVERSION 1 0 0 255
end COMPU_METHOD
end MODULE
运行命令:
python a2l_check.py sample.a2l
预期输出:
检测到的顶层块(按出现顺序):
- ASAP2_VERSION
- HEADER
- MODULE
结构检查通过: 所有必需块存在且顺序正确
验证方法:
- 将上述
sample.a2l保存后运行脚本,应看到“结构检查通过”且退出码为0。 - 修改测试文件(例如删除
HEADER块或将MODULE移到HEADER之前),重新运行,脚本应报告对应的缺失或顺序错误,退出码为1。
判定标准:脚本能正确识别缺失块、顺序错乱和重复块三类结构问题,且对合法文件不产生误报。