collab/mermaid/packages/parser/src/parse.tsblame
View source
6dd74de1import type { LangiumParser, ParseResult } from 'langium';
6dd74de2
6dd74de3import type { Info, Packet, Pie, Architecture, GitGraph, Radar, Treemap } from './index.js';
6dd74de4
6dd74de5export type DiagramAST = Info | Packet | Pie | Architecture | GitGraph | Radar;
6dd74de6
6dd74de7const parsers: Record<string, LangiumParser> = {};
6dd74de8const initializers = {
6dd74de9 info: async () => {
6dd74de10 const { createInfoServices } = await import('./language/info/index.js');
6dd74de11 const parser = createInfoServices().Info.parser.LangiumParser;
6dd74de12 parsers.info = parser;
6dd74de13 },
6dd74de14 packet: async () => {
6dd74de15 const { createPacketServices } = await import('./language/packet/index.js');
6dd74de16 const parser = createPacketServices().Packet.parser.LangiumParser;
6dd74de17 parsers.packet = parser;
6dd74de18 },
6dd74de19 pie: async () => {
6dd74de20 const { createPieServices } = await import('./language/pie/index.js');
6dd74de21 const parser = createPieServices().Pie.parser.LangiumParser;
6dd74de22 parsers.pie = parser;
6dd74de23 },
6dd74de24 architecture: async () => {
6dd74de25 const { createArchitectureServices } = await import('./language/architecture/index.js');
6dd74de26 const parser = createArchitectureServices().Architecture.parser.LangiumParser;
6dd74de27 parsers.architecture = parser;
6dd74de28 },
6dd74de29 gitGraph: async () => {
6dd74de30 const { createGitGraphServices } = await import('./language/gitGraph/index.js');
6dd74de31 const parser = createGitGraphServices().GitGraph.parser.LangiumParser;
6dd74de32 parsers.gitGraph = parser;
6dd74de33 },
6dd74de34 radar: async () => {
6dd74de35 const { createRadarServices } = await import('./language/radar/index.js');
6dd74de36 const parser = createRadarServices().Radar.parser.LangiumParser;
6dd74de37 parsers.radar = parser;
6dd74de38 },
6dd74de39 treemap: async () => {
6dd74de40 const { createTreemapServices } = await import('./language/treemap/index.js');
6dd74de41 const parser = createTreemapServices().Treemap.parser.LangiumParser;
6dd74de42 parsers.treemap = parser;
6dd74de43 },
6dd74de44} as const;
6dd74de45
6dd74de46export async function parse(diagramType: 'info', text: string): Promise<Info>;
6dd74de47export async function parse(diagramType: 'packet', text: string): Promise<Packet>;
6dd74de48export async function parse(diagramType: 'pie', text: string): Promise<Pie>;
6dd74de49export async function parse(diagramType: 'architecture', text: string): Promise<Architecture>;
6dd74de50export async function parse(diagramType: 'gitGraph', text: string): Promise<GitGraph>;
6dd74de51export async function parse(diagramType: 'radar', text: string): Promise<Radar>;
6dd74de52export async function parse(diagramType: 'treemap', text: string): Promise<Treemap>;
6dd74de53
6dd74de54export async function parse<T extends DiagramAST>(
6dd74de55 diagramType: keyof typeof initializers,
6dd74de56 text: string
6dd74de57): Promise<T> {
6dd74de58 const initializer = initializers[diagramType];
6dd74de59 if (!initializer) {
6dd74de60 throw new Error(`Unknown diagram type: ${diagramType}`);
6dd74de61 }
6dd74de62 if (!parsers[diagramType]) {
6dd74de63 await initializer();
6dd74de64 }
6dd74de65 const parser: LangiumParser = parsers[diagramType];
6dd74de66 const result: ParseResult<T> = parser.parse<T>(text);
6dd74de67 if (result.lexerErrors.length > 0 || result.parserErrors.length > 0) {
6dd74de68 throw new MermaidParseError(result);
6dd74de69 }
6dd74de70 return result.value;
6dd74de71}
6dd74de72
6dd74de73export class MermaidParseError extends Error {
6dd74de74 constructor(public result: ParseResult<DiagramAST>) {
6dd74de75 const lexerErrors: string = result.lexerErrors
6dd74de76 .map((err) => {
6dd74de77 const line = err.line !== undefined && !isNaN(err.line) ? err.line : '?';
6dd74de78 const column = err.column !== undefined && !isNaN(err.column) ? err.column : '?';
6dd74de79 return `Lexer error on line ${line}, column ${column}: ${err.message}`;
6dd74de80 })
6dd74de81 .join('\n');
6dd74de82 const parserErrors: string = result.parserErrors
6dd74de83 .map((err) => {
6dd74de84 const line =
6dd74de85 err.token.startLine !== undefined && !isNaN(err.token.startLine)
6dd74de86 ? err.token.startLine
6dd74de87 : '?';
6dd74de88 const column =
6dd74de89 err.token.startColumn !== undefined && !isNaN(err.token.startColumn)
6dd74de90 ? err.token.startColumn
6dd74de91 : '?';
6dd74de92 return `Parse error on line ${line}, column ${column}: ${err.message}`;
6dd74de93 })
6dd74de94 .join('\n');
6dd74de95 super(`Parsing failed: ${lexerErrors} ${parserErrors}`);
6dd74de96 }
6dd74de97}