UNPKG

bramble-parser

Version:

Bramble is a lightweight recursive descent parser that processes .havenfs files, returning a structured Json tree that can be used to construct an in-memory FS representation. The parser is based on line-based grammar, chunk headers, and metadata declarat

199 lines (165 loc) 5.42 kB
import { ErrorCode } from '../common'; import { HavenException } from '../errors'; import { FileParser } from './fileParser'; import { DirectoryParser } from './directoryParser'; import { ReferenceParser } from './referenceParser'; import { HistoryParser } from './historyParser'; import { LibrarieParser } from './libParser'; import { TagmapParser } from './tagmapParser'; export class BrambleFSParser { private chunkMap: ChunkMap[]; private nodes: HavenFSNode[]; private libraries: Map<string, HavenLibrarie[]>; private tagmap: HavenTagmap[]; private references: HavenReference[]; private history: HavenHistoryTree[]; constructor(chunkMap: ChunkMap[]) { this.chunkMap = chunkMap; this.nodes = []; this.libraries = new Map<string, HavenLibrarie[]>(); this.tagmap = []; this.references = []; this.history = []; } parse(): void { for (const chunk of this.chunkMap) { switch (chunk.type) { case 'files': new FileParser(this.nodes, chunk.entries); break; case 'libraries': new LibrarieParser(this.libraries, this.nodes, chunk.entries); break; case 'tagmap': new TagmapParser(this.tagmap, this.nodes, chunk.entries); break; case 'directories': new DirectoryParser(this.nodes, chunk.entries); break; case 'refs': new ReferenceParser(this.references, this.nodes, chunk.entries); break; case 'history': new HistoryParser(this.history, chunk.entries); break; default: const position = { line: 0, column: 0 }; new HavenException(`Unknown chunk type ${chunk.type}`, position, ErrorCode.UNKNOWN_CHUNK_TYPE); break; } } } linkData(): void { const nodeMap = new Map<string, HavenFSNode>(); for (const node of this.nodes) { nodeMap.set(node.id, node); } for (const ref of this.references) { const fromNode = nodeMap.get(ref.from); if (!fromNode) { const position = { line: 0, column: 0 }; new HavenException(`Reference 'from' ID ${ref.from} not found`, position, ErrorCode.MISSING_TOKEN); return; } if (!fromNode.references) { fromNode.references = []; } fromNode.references.push(ref); } for (const hist of this.history) { const histNode = nodeMap.get(hist.id); if (!histNode) { const position = { line: 0, column: 0 }; new HavenException(`History ID ${hist.id} not found`, position, ErrorCode.MISSING_TOKEN); return; } if (!histNode.history) { histNode.history = []; } histNode.history.push(hist); } } public toJSON(): string { return JSON.stringify(this.nodes); } public getJSON() { return this.nodes; } public getTagmap() { return this.tagmap; } public getLibraries() { return this.libraries; } public run() { this.parse(); this.linkData(); } public debugLibraries(): void { console.log('='.repeat(60)); console.log(`Total Libraries: ${this.libraries.size}`); console.log('='.repeat(60)); for (const [libId, entries] of this.libraries) { console.log(`Library ID: ${libId}`); for (const entry of entries) { console.log(` - name: ${entry.name}, tagId: ${entry.tagId}`); } console.log('-'.repeat(40)); } } public debugTagmap(): void { console.log('='.repeat(60)); console.log(`Total Libraries: ${this.libraries.size}`); console.log('='.repeat(60)); for (const tag of this.tagmap) { console.log(`ID: ${tag.id}`); console.log(`Name: ${tag.tag.name}`); console.log(`Color: ${tag.tag.color}`); console.log(`File reference: ${tag.fileRef}`) console.log('-'.repeat(40)); } } public debugFS(): void { console.log('='.repeat(60)); console.log(`Total Nodes: ${this.nodes.length}`); console.log('='.repeat(60)); for (const node of this.nodes) { console.log(`ID: ${node.id}`); console.log(`Type: ${node.type}`); console.log(`Name: ${node.name}`); console.log(`Parent: ${node.parent}`); if (node.size !== undefined) console.log(`Size: ${node.size}`); if (node.libs?.length) { console.log(`Libs id:`); for (const [_, lib] of Object.entries(node.libs)) { console.log(` - ${lib}`); } } if (node.tags?.length) { console.log(`Tags id:`); for (const [_, tag] of Object.entries(node.tags)) { console.log(` - ${tag}`); } } if (node.metadata) { console.log(`Metadata:`); for (const [key, value] of Object.entries(node.metadata)) { console.log(` - ${key}: ${value}`); } } if (node.references) { console.log(`References (${node.references.length}):`); for (const ref of node.references) { console.log(` - To: ${ref.to}, Type: ${ref.type}${ref.context ? `, Context: ${ref.context}` : ''}`); } } if (node.history) { console.log(`History (${node.history.length}):`); for (const h of node.history) { console.log(` - [${h.timestamp}] User: ${h.user}, Action: ${h.action}, Hash: ${h.hash}`); } } console.log('-'.repeat(60)); } } }