diff --git a/src/utils/register_parsers/reg_default.ts b/src/utils/register_parsers/reg_default.ts index 89aeec8..ea37f6d 100644 --- a/src/utils/register_parsers/reg_default.ts +++ b/src/utils/register_parsers/reg_default.ts @@ -1,4 +1,4 @@ -import {Register, RegisterAccess, RegisterDetail} from "@/utils/register_parser"; +import {Register, RegisterAccess, RegisterDetail, Note} from "@/utils/register_parser"; export const parseDescriptionDefault = (reg: Register, description: string) => { const descriptionLines = description.split('\n'); @@ -7,7 +7,21 @@ export const parseDescriptionDefault = (reg: Register, description: string) => { // Prepare a new RegisterDetail for this description block const detail: RegisterDetail = { read: undefined, write: undefined, common: undefined, text: ''}; - for (const line of descriptionLines) { + // Footnote multiline state + let inFootnote = false; + let footnoteBaseIndent = 0; + let footnoteTarget: 'global' | 'access' | null = null; + let currentFootnote: Note | null = null; + + const endFootnoteIfActive = () => { + inFootnote = false; + footnoteBaseIndent = 0; + footnoteTarget = null; + currentFootnote = null; + }; + + for (let idx = 0; idx < descriptionLines.length; idx++) { + const line = descriptionLines[idx]; reg.source.push(line); const trimmedLine = line.trim(); @@ -18,7 +32,22 @@ export const parseDescriptionDefault = (reg: Register, description: string) => { if (line.includes('Issue 4 Only')) reg.issue_4_only = true; + // Handle multiline footnote continuation + if (inFootnote) { + if (spaces_at_start > footnoteBaseIndent && trimmedLine.length > 0) { + // continuation line; append preserving original line (trim left to the base indent) + const continuation = line.substring(footnoteBaseIndent + 1); // +1 to skip at least one extra indent + if (currentFootnote) { + currentFootnote.text += `\n${continuation.trimEnd()}`; + } + continue; + } else { + // indentation returned -> end footnote, and fall through to process this line normally + endFootnoteIfActive(); + } + } + // Access state markers if (trimmedLine.startsWith('(R)')) { if (currentAccess) { // finalize previous access block into detail @@ -44,6 +73,7 @@ export const parseDescriptionDefault = (reg: Register, description: string) => { currentAccess = 'common'; continue; } + // New top-level text block (no leading spaces) if (line.startsWith(trimmedLine)) { if (currentAccess) { detail[currentAccess] = accessData; @@ -52,6 +82,25 @@ export const parseDescriptionDefault = (reg: Register, description: string) => { currentAccess = null; } + // Start of a footnote (works both inside and outside an access block) + if (trimmedLine.startsWith('*')) { + const noteMatch = trimmedLine.match(/^(\*+)\s*(.*)/); + if (noteMatch) { + const note: Note = { ref: noteMatch[1], text: noteMatch[2] }; + if (currentAccess) { + accessData.notes.push(note); + footnoteTarget = 'access'; + } else { + reg.notes.push(note); + footnoteTarget = 'global'; + } + currentFootnote = note; + inFootnote = true; + footnoteBaseIndent = spaces_at_start; + continue; + } + } + if (currentAccess) { const bitMatch = trimmedLine.match(/^(bits?|bit)\s+([\d:-]+)\s*=\s*(.*)/); // const valueMatch = !line.match(/^\s+/) && trimmedLine.match(/^([01\s]+)\s*=\s*(.*)/); @@ -75,14 +124,6 @@ export const parseDescriptionDefault = (reg: Register, description: string) => { // bits: valueMatch[1].trim().replace(/\s/g, ''), // description: valueMatch[2].trim(), // }); - } else if (trimmedLine.startsWith('*')) { - const noteMatch = trimmedLine.match(/^(\*+)\s*(.*)/); - if (noteMatch) { - accessData.notes.push({ - ref: noteMatch[1], - text: noteMatch[2], - }); - } } else if (trimmedLine) { if(spaces_at_start == 2) { reg.text += `${line}\n`; @@ -98,19 +139,15 @@ export const parseDescriptionDefault = (reg: Register, description: string) => { } } } else { - if (trimmedLine.startsWith('*')) { - const noteMatch = trimmedLine.match(/^(\*+)\s*(.*)/); - if (noteMatch) { - reg.notes.push({ - ref: noteMatch[1], - text: noteMatch[2], - }); - } - } else if (trimmedLine) { + if (trimmedLine) { detail.text += `${line}\n`; } } } + // close any dangling footnote + if (inFootnote) { + endFootnoteIfActive(); + } if (currentAccess) { detail[currentAccess] = accessData; }