const { createAliasMap, createEnumTypeMap, findEnums, findStruct, findStructs, normalizeLookupName, normalizeTypeText, parseDeclarator, splitDeclarators, stripComments } = require('./struct-c-syntax.js') const { parseStructFields } = require('./struct-layout.js') const STRUCT_VARIABLE_QUALIFIERS = { code: true, const: true, data: true, extern: true, idata: true, pdata: true, static: true, volatile: true, xdata: true } function parseStructDefinition(sourceText) { const source = stripComments(sourceText) const enums = findEnums(source) const enumTypes = createEnumTypeMap(enums) const aliases = createAliasMap(source, enums) const structInfo = findStruct(source) if (!structInfo) { throw new Error('未找到结构体定义') } const registers = parseStructFields(structInfo.body, aliases, enumTypes) if (!registers.length) { throw new Error('结构体中没有可识别的变量定义') } return { name: structInfo.name || 'Struct', registers, structName: structInfo.name || 'Struct' } } function getStructNameAliases(structInfo, aliases) { const names = [structInfo.name] if (structInfo.tagName) names.push(`struct ${structInfo.tagName}`) Object.keys(aliases || {}).forEach((aliasName) => { if (aliases[aliasName] === structInfo.name) names.push(aliasName) }) return names.filter(Boolean) } function normalizeVariableTypeText(typeText, aliases) { const normalized = normalizeTypeText(typeText) if (!normalized) return '' const tokens = normalized .split(/\s+/) .filter((token) => !STRUCT_VARIABLE_QUALIFIERS[token]) const compact = tokens.join(' ') if (aliases && aliases[compact]) return aliases[compact] return compact } function parseStructVariables(source, structs, aliases) { const variablesByName = {} structs.forEach((structInfo) => { const structNames = getStructNameAliases(structInfo, aliases) structNames.forEach((structName) => { const escaped = structName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') const variablePattern = new RegExp(`(^|[;\\n{}])\\s*([A-Za-z_][\\w\\s]*?\\s+)?${escaped}\\s+([^;{}()]+);`, 'g') let match while ((match = variablePattern.exec(source))) { const prefix = normalizeVariableTypeText(match[2] || '', aliases) if (prefix) continue splitDeclarators(match[3]).forEach((declaratorText) => { const field = parseDeclarator(declaratorText) if (!field) return const variableInfo = { arrayDimensions: field.arrayDimensions, name: field.name, registers: structInfo.registers, structName: structInfo.name } variablesByName[field.name] = variableInfo variablesByName[field.name.replace(/^_+/, '').toLowerCase()] = variableInfo variablesByName[normalizeLookupName(field.name)] = variableInfo }) } }) }) return variablesByName } function getEnumVariableTypeNames(enumInfo = {}) { return (Array.isArray(enumInfo.typeNames) ? enumInfo.typeNames : []) .concat(enumInfo.name, enumInfo.typedefName, enumInfo.tagName ? `enum ${enumInfo.tagName}` : '') .filter(Boolean) } function parseEnumVariables(source, enums, aliases) { const variablesByName = {} enums.forEach((enumInfo) => { getEnumVariableTypeNames(enumInfo).forEach((enumTypeName) => { const escaped = enumTypeName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') const variablePattern = new RegExp(`(^|[;\\n{}])\\s*([A-Za-z_][\\w\\s]*?\\s+)?${escaped}\\s+([^;{}()]+);`, 'g') let match while ((match = variablePattern.exec(source))) { const prefix = normalizeVariableTypeText(match[2] || '', aliases) if (prefix) continue splitDeclarators(match[3]).forEach((declaratorText) => { const field = parseDeclarator(declaratorText) if (!field) return variablesByName[field.name] = enumInfo variablesByName[field.name.replace(/^_+/, '').toLowerCase()] = enumInfo variablesByName[normalizeLookupName(field.name)] = enumInfo }) } }) }) return variablesByName } function parseStructCatalog(sourceText) { const source = stripComments(sourceText) const enums = findEnums(source) const enumTypes = createEnumTypeMap(enums) const aliases = createAliasMap(source, enums) const structs = findStructs(source).map((structInfo) => ({ ...structInfo, registers: parseStructFields(structInfo.body, aliases, enumTypes) })).filter((structInfo) => structInfo.registers.length) if (!structs.length && !enums.length) { throw new Error('未找到可识别的结构体或枚举定义') } return { enums, enumVariablesByName: parseEnumVariables(source, enums, aliases), structs, variablesByName: parseStructVariables(source, structs, aliases) } } module.exports = { parseStructCatalog, parseStructDefinition, stripComments }