fix: rewrite parser to correctly parse parent_subsystem and module hierarchy
This commit is contained in:
@@ -46,148 +46,219 @@ function extractYamlBlock(markdown: string, sectionName: string): string {
|
|||||||
return match ? match[1].trim() : '';
|
return match ? match[1].trim() : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseSubsystemList(yaml: string): Subsystem[] {
|
function parseSubsystems(yaml: string): Subsystem[] {
|
||||||
const subsystems: Subsystem[] = [];
|
const subsystems: Subsystem[] = [];
|
||||||
const lines = yaml.split('\n');
|
const lines = yaml.split('\n');
|
||||||
let currentSubsystem: Partial<Subsystem> | null = null;
|
|
||||||
let currentField = '';
|
let current: Partial<Subsystem> = {};
|
||||||
let currentList: string[] = [];
|
let currentField: string | null = null;
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
if (line.includes('- name:')) {
|
const trimmed = line.trim();
|
||||||
if (currentSubsystem && currentSubsystem.name) {
|
|
||||||
|
if (trimmed.startsWith('subsystems:')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trimmed.startsWith('- name:')) {
|
||||||
|
if (current.name) {
|
||||||
subsystems.push({
|
subsystems.push({
|
||||||
id: currentSubsystem.name,
|
id: current.name,
|
||||||
name: currentSubsystem.name,
|
name: current.name,
|
||||||
responsibilities: currentSubsystem.responsibilities || [],
|
responsibilities: current.responsibilities || [],
|
||||||
provides: currentSubsystem.provides || [],
|
provides: current.provides || [],
|
||||||
depends_on: currentSubsystem.depends_on || [],
|
depends_on: current.depends_on || [],
|
||||||
boundary: currentSubsystem.boundary
|
boundary: current.boundary
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
currentSubsystem = { name: line.split('- name:')[1].trim() };
|
current = {
|
||||||
currentField = '';
|
name: trimmed.replace('- name:', '').trim(),
|
||||||
currentList = [];
|
responsibilities: [],
|
||||||
} else if (currentSubsystem && line.includes('responsibilities:')) {
|
provides: [],
|
||||||
|
depends_on: []
|
||||||
|
};
|
||||||
|
currentField = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!current.name) continue;
|
||||||
|
|
||||||
|
if (trimmed.startsWith('responsibilities:')) {
|
||||||
currentField = 'responsibilities';
|
currentField = 'responsibilities';
|
||||||
currentList = [];
|
continue;
|
||||||
} else if (currentSubsystem && line.includes('provides:')) {
|
}
|
||||||
|
|
||||||
|
if (trimmed.startsWith('provides:')) {
|
||||||
currentField = 'provides';
|
currentField = 'provides';
|
||||||
currentList = [];
|
const match = trimmed.match(/\[(.*?)\]/);
|
||||||
} else if (currentSubsystem && line.includes('depends_on:')) {
|
|
||||||
currentField = 'depends_on';
|
|
||||||
currentList = [];
|
|
||||||
} else if (currentSubsystem && line.includes('boundary:')) {
|
|
||||||
currentField = 'boundary';
|
|
||||||
currentSubsystem.boundary = { inputs: [], outputs: [] };
|
|
||||||
} else if (currentSubsystem && currentField === 'responsibilities' && line.includes('-')) {
|
|
||||||
const val = line.replace('-', '').trim().replace(/"/g, '');
|
|
||||||
if (val) currentList.push(val);
|
|
||||||
currentSubsystem.responsibilities = [...currentList];
|
|
||||||
} else if (currentSubsystem && currentField === 'provides' && line.includes('[')) {
|
|
||||||
const match = line.match(/\[(.*?)\]/);
|
|
||||||
if (match) {
|
if (match) {
|
||||||
currentSubsystem.provides = match[1].split(',').map(s => s.trim());
|
current.provides = match[1].split(',').map(s => s.trim());
|
||||||
}
|
|
||||||
} else if (currentSubsystem && currentField === 'depends_on' && line.includes('[')) {
|
|
||||||
const match = line.match(/\[(.*?)\]/);
|
|
||||||
if (match && match[1].trim()) {
|
|
||||||
currentSubsystem.depends_on = match[1].split(',').map(s => s.trim());
|
|
||||||
} else {
|
} else {
|
||||||
currentSubsystem.depends_on = [];
|
current.provides = [];
|
||||||
}
|
}
|
||||||
} else if (currentSubsystem && currentField === 'boundary' && line.includes('inputs:')) {
|
continue;
|
||||||
const match = line.match(/\[(.*?)\]/);
|
}
|
||||||
|
|
||||||
|
if (trimmed.startsWith('depends_on:')) {
|
||||||
|
currentField = 'depends_on';
|
||||||
|
const match = trimmed.match(/\[(.*?)\]/);
|
||||||
|
if (match && match[1].trim()) {
|
||||||
|
current.depends_on = match[1].split(',').map(s => s.trim());
|
||||||
|
} else {
|
||||||
|
current.depends_on = [];
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trimmed.startsWith('boundary:')) {
|
||||||
|
currentField = 'boundary';
|
||||||
|
current.boundary = { inputs: [], outputs: [] };
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentField === 'responsibilities' && trimmed.startsWith('-')) {
|
||||||
|
const val = trimmed.replace('-', '').trim().replace(/"/g, '');
|
||||||
|
if (val) {
|
||||||
|
current.responsibilities = current.responsibilities || [];
|
||||||
|
current.responsibilities.push(val);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentField === 'boundary' && trimmed.startsWith('inputs:')) {
|
||||||
|
const match = trimmed.match(/\[(.*?)\]/);
|
||||||
if (match) {
|
if (match) {
|
||||||
currentSubsystem.boundary!.inputs = match[1].split(',').map(s => s.trim());
|
current.boundary!.inputs = match[1].split(',').map(s => s.trim());
|
||||||
}
|
}
|
||||||
} else if (currentSubsystem && currentField === 'boundary' && line.includes('outputs:')) {
|
continue;
|
||||||
const match = line.match(/\[(.*?)\]/);
|
}
|
||||||
|
|
||||||
|
if (currentField === 'boundary' && trimmed.startsWith('outputs:')) {
|
||||||
|
const match = trimmed.match(/\[(.*?)\]/);
|
||||||
if (match) {
|
if (match) {
|
||||||
currentSubsystem.boundary!.outputs = match[1].split(',').map(s => s.trim());
|
current.boundary!.outputs = match[1].split(',').map(s => s.trim());
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentSubsystem && currentSubsystem.name) {
|
if (current.name) {
|
||||||
subsystems.push({
|
subsystems.push({
|
||||||
id: currentSubsystem.name,
|
id: current.name,
|
||||||
name: currentSubsystem.name,
|
name: current.name,
|
||||||
responsibilities: currentSubsystem.responsibilities || [],
|
responsibilities: current.responsibilities || [],
|
||||||
provides: currentSubsystem.provides || [],
|
provides: current.provides || [],
|
||||||
depends_on: currentSubsystem.depends_on || [],
|
depends_on: current.depends_on || [],
|
||||||
boundary: currentSubsystem.boundary
|
boundary: current.boundary
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return subsystems;
|
return subsystems;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseModuleList(yaml: string): Module[] {
|
function parseModules(yaml: string): Module[] {
|
||||||
const modules: Module[] = [];
|
const modules: Module[] = [];
|
||||||
const lines = yaml.split('\n');
|
const lines = yaml.split('\n');
|
||||||
let currentModule: Partial<Module> | null = null;
|
|
||||||
let currentApi: { fn: string; params: { name: string; type: string }[]; returns?: { type: string } } | null = null;
|
let current: Partial<Module> = {};
|
||||||
|
let currentApi: Module['public_api'][0] | null = null;
|
||||||
let inPublicApi = false;
|
let inPublicApi = false;
|
||||||
let currentField = '';
|
let inParams = false;
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
if (line.includes('- name:') && line.includes('parent_subsystem:')) {
|
const trimmed = line.trim();
|
||||||
if (currentModule && currentModule.name && currentModule.parent_subsystem) {
|
|
||||||
|
if (trimmed.startsWith('modules:')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trimmed.startsWith('- name:')) {
|
||||||
|
if (current.name && current.parent_subsystem) {
|
||||||
modules.push({
|
modules.push({
|
||||||
id: currentModule.name,
|
id: current.name,
|
||||||
name: currentModule.name,
|
name: current.name,
|
||||||
parent_subsystem: currentModule.parent_subsystem,
|
parent_subsystem: current.parent_subsystem,
|
||||||
responsibility: currentModule.responsibility || '',
|
responsibility: current.responsibility || '',
|
||||||
public_api: currentModule.public_api || []
|
public_api: current.public_api || []
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const nameMatch = line.match(/- name:\s*(\S+)/);
|
current = {
|
||||||
const parentMatch = line.match(/parent_subsystem:\s*(\S+)/);
|
name: trimmed.replace('- name:', '').trim(),
|
||||||
currentModule = {
|
parent_subsystem: '',
|
||||||
name: nameMatch ? nameMatch[1] : '',
|
responsibility: '',
|
||||||
parent_subsystem: parentMatch ? parentMatch[1] : '',
|
|
||||||
public_api: []
|
public_api: []
|
||||||
};
|
};
|
||||||
inPublicApi = false;
|
inPublicApi = false;
|
||||||
} else if (currentModule && line.includes('responsibility:')) {
|
inParams = false;
|
||||||
const match = line.match(/responsibility:\s*"(.+)"/);
|
currentApi = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!current.name) continue;
|
||||||
|
|
||||||
|
if (trimmed.startsWith('parent_subsystem:')) {
|
||||||
|
current.parent_subsystem = trimmed.replace('parent_subsystem:', '').trim();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trimmed.startsWith('responsibility:')) {
|
||||||
|
const match = trimmed.match(/responsibility:\s*"(.+)"/);
|
||||||
if (match) {
|
if (match) {
|
||||||
currentModule.responsibility = match[1];
|
current.responsibility = match[1];
|
||||||
}
|
}
|
||||||
} else if (currentModule && line.includes('public_api:')) {
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trimmed.startsWith('public_api:')) {
|
||||||
inPublicApi = true;
|
inPublicApi = true;
|
||||||
} else if (currentModule && inPublicApi && line.includes('- fn:')) {
|
continue;
|
||||||
const fnMatch = line.match(/- fn:\s*(\S+)/);
|
}
|
||||||
if (fnMatch) {
|
|
||||||
currentApi = { fn: fnMatch[1], params: [] };
|
if (inPublicApi && trimmed.startsWith('- fn:')) {
|
||||||
currentModule.public_api = currentModule.public_api || [];
|
currentApi = {
|
||||||
currentModule.public_api.push(currentApi);
|
fn: trimmed.replace('- fn:', '').trim(),
|
||||||
}
|
params: []
|
||||||
} else if (currentModule && currentApi && line.includes('params:')) {
|
};
|
||||||
currentField = 'params';
|
current.public_api = current.public_api || [];
|
||||||
} else if (currentModule && currentApi && line.includes('returns:')) {
|
current.public_api.push(currentApi);
|
||||||
currentField = 'returns';
|
inParams = false;
|
||||||
const returnsMatch = line.match(/returns:\s*type:\s*(\S+)/);
|
continue;
|
||||||
if (returnsMatch) {
|
}
|
||||||
currentApi.returns = { type: returnsMatch[1] };
|
|
||||||
}
|
if (currentApi && trimmed.startsWith('params:')) {
|
||||||
} else if (currentModule && currentApi && currentField === 'params' && line.includes('name:')) {
|
inParams = true;
|
||||||
const nameMatch = line.match(/name:\s*(\S+)/);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentApi && inParams && trimmed.startsWith('- name:')) {
|
||||||
|
const nameMatch = trimmed.match(/- name:\s*(\S+)/);
|
||||||
const typeMatch = line.match(/type:\s*(\S+)/);
|
const typeMatch = line.match(/type:\s*(\S+)/);
|
||||||
if (nameMatch && typeMatch) {
|
if (nameMatch && typeMatch) {
|
||||||
currentApi.params.push({ name: nameMatch[1], type: typeMatch[1] });
|
currentApi.params.push({
|
||||||
|
name: nameMatch[1],
|
||||||
|
type: typeMatch[1]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentApi && trimmed.startsWith('returns:')) {
|
||||||
|
const match = trimmed.match(/returns:\s*type:\s*(\S+)/);
|
||||||
|
if (match) {
|
||||||
|
currentApi.returns = { type: match[1] };
|
||||||
|
}
|
||||||
|
inParams = false;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentModule && currentModule.name) {
|
if (current.name && current.parent_subsystem) {
|
||||||
modules.push({
|
modules.push({
|
||||||
id: currentModule.name,
|
id: current.name,
|
||||||
name: currentModule.name,
|
name: current.name,
|
||||||
parent_subsystem: currentModule.parent_subsystem || '',
|
parent_subsystem: current.parent_subsystem,
|
||||||
responsibility: currentModule.responsibility || '',
|
responsibility: current.responsibility || '',
|
||||||
public_api: currentModule.public_api || []
|
public_api: current.public_api || []
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,22 +279,22 @@ export function parseBlueprintFromMd(markdown: string): BlueprintData {
|
|||||||
|
|
||||||
const metaLines = metaYaml.split('\n');
|
const metaLines = metaYaml.split('\n');
|
||||||
for (const line of metaLines) {
|
for (const line of metaLines) {
|
||||||
if (line.includes('name:')) {
|
const trimmed = line.trim();
|
||||||
meta.name = line.split('name:')[1].trim().replace(/"/g, '');
|
if (trimmed.startsWith('name:')) {
|
||||||
} else if (line.includes('version:')) {
|
meta.name = trimmed.replace('name:', '').trim().replace(/"/g, '');
|
||||||
const ver = line.split('version:')[1].trim();
|
} else if (trimmed.startsWith('version:')) {
|
||||||
meta.version = ver;
|
meta.version = trimmed.replace('version:', '').trim();
|
||||||
} else if (line.includes('type:')) {
|
} else if (trimmed.startsWith('type:')) {
|
||||||
meta.type = line.split('type:')[1].trim().replace(/"/g, '');
|
meta.type = trimmed.replace('type:', '').trim().replace(/"/g, '');
|
||||||
} else if (line.includes('description:')) {
|
} else if (trimmed.startsWith('description:')) {
|
||||||
meta.description = line.split('description:')[1].trim().replace(/"/g, '');
|
meta.description = trimmed.replace('description:', '').trim().replace(/"/g, '');
|
||||||
} else if (line.includes('target_runtime:')) {
|
} else if (trimmed.startsWith('target_runtime:')) {
|
||||||
meta.target_runtime = line.split('target_runtime:')[1].trim().replace(/"/g, '');
|
meta.target_runtime = trimmed.replace('target_runtime:', '').trim().replace(/"/g, '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const subsystems = parseSubsystemList(structureYaml);
|
const subsystems = parseSubsystems(structureYaml);
|
||||||
const modules = parseModuleList(structureYaml);
|
const modules = parseModules(structureYaml);
|
||||||
|
|
||||||
return { meta, subsystems, modules };
|
return { meta, subsystems, modules };
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user