Move parser out to on demand (maybe move to on-startup, or on schedule, later)
This commit is contained in:
188
src/utils/parser.ts
Normal file
188
src/utils/parser.ts
Normal file
@@ -0,0 +1,188 @@
|
||||
export interface BitwiseOperation {
|
||||
bits: string;
|
||||
description: string;
|
||||
value?: string;
|
||||
footnoteRef?: string;
|
||||
}
|
||||
|
||||
export interface Note {
|
||||
ref: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface RegisterAccess {
|
||||
description?: string;
|
||||
operations: BitwiseOperation[];
|
||||
notes: Note[];
|
||||
}
|
||||
export interface Register {
|
||||
hex_address: string;
|
||||
dec_address: number | string;
|
||||
name: string;
|
||||
description: string;
|
||||
read?: RegisterAccess;
|
||||
write?: RegisterAccess;
|
||||
common?: RegisterAccess;
|
||||
text: string;
|
||||
notes: Note[];
|
||||
issue_4_only: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the content of the nextreg.txt file and returns an array of register objects.
|
||||
* @param fileContent The content of the nextreg.txt file.
|
||||
* @returns A promise that resolves to an array of Register objects.
|
||||
*/
|
||||
export async function parseNextReg(fileContent: string): Promise<Register[]> {
|
||||
const registers: Register[] = [];
|
||||
const paragraphs = fileContent.split(/\n\s*\n/);
|
||||
|
||||
for (const paragraph of paragraphs) {
|
||||
if (!paragraph.trim()) {
|
||||
continue;
|
||||
}
|
||||
processRegisterBlock(paragraph, registers);
|
||||
}
|
||||
|
||||
return registers;
|
||||
}
|
||||
|
||||
export function processRegisterBlock(paragraph: string, registers: Register[]) {
|
||||
const lines = paragraph.trim().split('\n');
|
||||
const firstLine = lines[0];
|
||||
|
||||
const registerMatch = firstLine.match(/([0-9a-fA-F,x]+)\s*\((.*?)\)\s*=>\s*(.*)/);
|
||||
|
||||
if (!registerMatch) {
|
||||
return;
|
||||
}
|
||||
|
||||
const hexAddresses = registerMatch[1].trim();
|
||||
const decAddresses = registerMatch[2].trim();
|
||||
const name = registerMatch[3] ? registerMatch[3].trim() : '';
|
||||
const description = lines.slice(1).join('\n').trim();
|
||||
|
||||
const hexList = hexAddresses.split(',').map(h => h.trim());
|
||||
const decList = decAddresses.includes('-') ? decAddresses.split('-') : decAddresses.split(',').map(d => d.trim());
|
||||
|
||||
const createRegister = (hex: string, dec: string | number, regName: string): Register => {
|
||||
const reg: Register = {
|
||||
hex_address: hex,
|
||||
dec_address: dec,
|
||||
name: regName,
|
||||
description: description,
|
||||
notes: [],
|
||||
text: "",
|
||||
issue_4_only: false
|
||||
};
|
||||
|
||||
const descriptionLines = description.split('\n');
|
||||
let currentAccess: 'read' | 'write' | 'common' | null = null;
|
||||
let accessData: RegisterAccess = { operations: [], notes: [] };
|
||||
|
||||
for (const line of descriptionLines) {
|
||||
if(line.includes('Issue 4 Only')) reg.issue_4_only = true;
|
||||
|
||||
const trimmedLine = line.trim();
|
||||
|
||||
if (trimmedLine.startsWith('//')) continue;
|
||||
|
||||
if (trimmedLine.startsWith('(R)')) {
|
||||
if (currentAccess) reg[currentAccess] = accessData;
|
||||
accessData = { operations: [], notes: [] };
|
||||
currentAccess = 'read';
|
||||
continue;
|
||||
}
|
||||
if (trimmedLine.startsWith('(W)')) {
|
||||
if (currentAccess) reg[currentAccess] = accessData;
|
||||
accessData = { operations: [], notes: [] };
|
||||
currentAccess = 'write';
|
||||
continue;
|
||||
}
|
||||
if (trimmedLine.startsWith('(R/W')) {
|
||||
if (currentAccess) reg[currentAccess] = accessData;
|
||||
accessData = { operations: [], notes: [] };
|
||||
currentAccess = 'common';
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith(trimmedLine)) {
|
||||
if (currentAccess) reg[currentAccess] = accessData;
|
||||
accessData = { operations: [], notes: [] };
|
||||
currentAccess = null;
|
||||
}
|
||||
|
||||
if (currentAccess) {
|
||||
const bitMatch = trimmedLine.match(/^(bits?|bit)\s+([\d:-]+)\s*=\s*(.*)/);
|
||||
const valueMatch = !line.match(/^\s+/) && trimmedLine.match(/^([01\s]+)\s*=\s*(.*)/);
|
||||
|
||||
if (bitMatch) {
|
||||
let bitDescription = bitMatch[3];
|
||||
const footnoteMatch = bitDescription.match(/(\*+)$/);
|
||||
let footnoteRef: string | undefined = undefined;
|
||||
if (footnoteMatch) {
|
||||
footnoteRef = footnoteMatch[1];
|
||||
bitDescription = bitDescription.substring(0, bitDescription.length - footnoteRef.length).trim();
|
||||
}
|
||||
accessData.operations.push({
|
||||
bits: bitMatch[2],
|
||||
description: bitDescription,
|
||||
footnoteRef: footnoteRef,
|
||||
});
|
||||
} else if (valueMatch) {
|
||||
accessData.operations.push({
|
||||
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 (line.match(/^\s+/) && accessData.operations.length > 0) {
|
||||
accessData.operations[accessData.operations.length - 1].description += `\n${line}`;
|
||||
} else {
|
||||
|
||||
if (!accessData.description) {
|
||||
accessData.description = '';
|
||||
}
|
||||
accessData.description += `\n${trimmedLine}`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (trimmedLine.startsWith('*')) {
|
||||
const noteMatch = trimmedLine.match(/^(\*+)\s*(.*)/);
|
||||
if (noteMatch) {
|
||||
reg.notes.push({
|
||||
ref: noteMatch[1],
|
||||
text: noteMatch[2],
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
reg.text += `${line}\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (currentAccess) {
|
||||
reg[currentAccess] = accessData;
|
||||
}
|
||||
|
||||
return reg;
|
||||
};
|
||||
|
||||
if (hexList.length > 1) {
|
||||
for (let i = 0; i < hexList.length; i++) {
|
||||
const hexAddr = hexList[i];
|
||||
const decAddr = decList[i] || decAddresses;
|
||||
const dec = isNaN(parseInt(decAddr, 10)) ? decAddr : parseInt(decAddr, 10);
|
||||
registers.push(createRegister(hexAddr, dec, `${name} (${hexAddr})`));
|
||||
}
|
||||
} else {
|
||||
const dec = isNaN(parseInt(decAddresses, 10)) ? decAddresses : parseInt(decAddresses, 10);
|
||||
registers.push(createRegister(hexAddresses, dec, name));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user