const TYPE_ALIASES = { bit: 'uint8_t', bool: 'uint8_t', char: 'int8_t', double: 'float', float: 'float', int: 'int16_t', int8: 'int8_t', int8_t: 'int8_t', int16: 'int16_t', int16_t: 'int16_t', int32: 'int32_t', int32_t: 'int32_t', long: 'int32_t', short: 'int16_t', 'signed char': 'int8_t', 'signed int': 'int16_t', 'signed long': 'int32_t', 'signed short': 'int16_t', uint8: 'uint8_t', uint8_t: 'uint8_t', uint16: 'uint16_t', uint16_t: 'uint16_t', uint32: 'uint32_t', uint32_t: 'uint32_t', 'unsigned char': 'uint8_t', 'unsigned int': 'uint16_t', 'unsigned long': 'uint32_t', 'unsigned short': 'uint16_t' } const TYPE_QUALIFIERS = { _I: true, _IO: true, _O: true, const: true, extern: true, register: true, static: true, volatile: true } const STRUCT_PATTERNS = [ /typedef\s+struct(?:\s+[A-Za-z_]\w*)?\s*\{([\s\S]*?)\}\s*([A-Za-z_]\w*)\s*;/g, /struct\s+([A-Za-z_]\w*)\s*\{([\s\S]*?)\}\s*;/g ] function normalizeLookupName(value) { return String(value || '') .replace(/^_+/, '') .replace(/[^A-Za-z0-9]/g, '') .toLowerCase() } function stripComments(source) { return String(source || '') .replace(/\/\*[\s\S]*?\*\//g, '') .replace(/\/\/.*$/gm, '') } function normalizeTypeText(typeText) { return String(typeText || '') .replace(/\*/g, ' ') .replace(/\s+/g, ' ') .trim() } function resolveType(typeText, aliases) { const normalized = normalizeTypeText(typeText) if (!normalized) return '' const compact = normalized .split(/\s+/) .filter((token) => !TYPE_QUALIFIERS[token]) .join(' ') .trim() if (!compact || /^struct\b/.test(compact) || /^enum\b/.test(compact) || compact.indexOf('*') >= 0) { return '' } if (aliases[compact]) return aliases[compact] const tokens = compact.split(/\s+/).filter(Boolean) for (const token of tokens) { if (aliases[token]) return aliases[token] } return '' } function createAliasMap(source) { const aliases = { ...TYPE_ALIASES } const definePattern = /^\s*#\s*define\s+([A-Za-z_]\w*)\s+([A-Za-z_]\w*)\s*$/gm let defineMatch while ((defineMatch = definePattern.exec(source))) { const name = defineMatch[1] const value = defineMatch[2] if (aliases[value]) aliases[name] = aliases[value] } const typedefPattern = /typedef\s+(?!struct\b)([^;{}]+?)\s+([A-Za-z_]\w*)\s*;/g let typedefMatch while ((typedefMatch = typedefPattern.exec(source))) { const resolvedType = resolveType(typedefMatch[1], aliases) if (resolvedType) aliases[typedefMatch[2]] = resolvedType } const typedefStructPattern = /typedef\s+struct(?:\s+([A-Za-z_]\w*))?\s*\{[\s\S]*?\}\s*([A-Za-z_]\w*)\s*;/g let structTypedefMatch while ((structTypedefMatch = typedefStructPattern.exec(source))) { const tagName = structTypedefMatch[1] const typedefName = structTypedefMatch[2] if (tagName && typedefName) aliases[`struct ${tagName}`] = typedefName } return aliases } function findStruct(source) { for (const pattern of STRUCT_PATTERNS) { pattern.lastIndex = 0 const match = pattern.exec(source) if (!match) continue if (pattern === STRUCT_PATTERNS[0]) { return { body: match[1], name: match[2] } } return { body: match[2], name: match[1] } } return null } function findStructs(source) { const structs = [] STRUCT_PATTERNS.forEach((pattern) => { pattern.lastIndex = 0 let match while ((match = pattern.exec(source))) { if (pattern === STRUCT_PATTERNS[0]) { structs.push({ body: match[1], name: match[2] }) } else { structs.push({ body: match[2], name: match[1], tagName: match[1] }) } } }) const seen = {} return structs.filter((item) => { const key = item.name if (!key || seen[key]) return false seen[key] = true return true }) } function parseArrayDimensions(suffix) { const dimensions = [] const pattern = /\[([^\]]*)\]/g let match while ((match = pattern.exec(suffix || ''))) { const text = String(match[1] || '').trim() const value = Number(text) if (!Number.isInteger(value) || value < 1) { throw new Error('数组长度需为正整数') } dimensions.push(value) } return dimensions } function splitDeclarations(body) { return String(body || '') .split(';') .map((item) => item.trim()) .filter(Boolean) } function splitDeclarators(statement) { return String(statement || '') .split(',') .map((item) => item.trim()) .filter(Boolean) } function parseFirstDeclarator(text) { const match = String(text || '').match(/^(.+?)\s+(\**\s*(?:[A-Za-z_]\w*)?(?:\s*\[[^\]]*\])*(?:\s*:\s*\d+)?)$/) if (!match) return null return { declarator: match[2], typeText: match[1] } } function parseDeclarator(text) { const rawText = String(text || '') const bitWidthMatch = rawText.match(/:\s*(\d+)\s*$/) const cleaned = rawText .replace(/=.*/, '') .replace(/:\s*\d+\s*$/, '') .replace(/\*/g, '') .trim() if (!cleaned && bitWidthMatch) { return { arrayDimensions: [], bitWidth: Number(bitWidthMatch[1]), name: '' } } const match = cleaned.match(/^([A-Za-z_]\w*)\s*((?:\[[^\]]*\])*)$/) if (!match) return null return { arrayDimensions: parseArrayDimensions(match[2]), bitWidth: bitWidthMatch ? Number(bitWidthMatch[1]) : null, name: match[1] } } module.exports = { createAliasMap, findStruct, findStructs, normalizeLookupName, normalizeTypeText, parseDeclarator, parseFirstDeclarator, resolveType, splitDeclarations, splitDeclarators, stripComments }