@flowscripter/mpeg-sdl-parser
Version:
ISO/IEC 14496-34 Syntactic Description Language (MPEG SDL) parser implemented in TypeScript
75 lines (62 loc) • 2.21 kB
text/typescript
import { LRParser as LezerParser } from "@lezer/lr";
import { debugEnabled } from "../util/logger.ts";
import { Text } from "@codemirror/state";
import type { Input } from "@lezer/common";
import { SyntacticParseError } from "../ParseError.ts";
// Generated by Lezer from the SDL grammar
import { parser } from "./parser.ts";
import { getContextTracker } from "./contextTracker.ts";
let lenientSdlParser: LezerParser | undefined;
let strictSdlParser: LezerParser | undefined;
/**
* Create an in memory lenient Lezer based parser using the SDL grammar and store it as a "singleton".
*/
export function createLenientSdlParser(): LezerParser {
if (!lenientSdlParser) {
if (debugEnabled) {
lenientSdlParser = parser.configure({
contextTracker: getContextTracker(parser),
});
} else {
lenientSdlParser = parser;
}
}
return lenientSdlParser;
}
/**
* Create an in memory strict Lezer based parser using the SDL grammar and store it as a "singleton".
*/
export function createStrictSdlParser(): LezerParser {
if (!strictSdlParser) {
strictSdlParser = createLenientSdlParser().configure({
strict: true,
});
// Wrap the parser's parse method to catch errors and wrap them in ParseError
const originalParseFunc = strictSdlParser.parse.bind(strictSdlParser);
strictSdlParser.parse = (input: Input | string, ...args) => {
try {
return originalParseFunc(input, ...args);
} catch (err) {
// parse position out of error message which takes the form "No parse at 0"
const errorMessage = (err as Error).message;
const match = errorMessage.match(/No parse at (\d+)/);
let position = 0;
if (match) {
const parsed = parseInt(match[1], 10);
position = isNaN(parsed) ? 0 : parsed;
}
let inputText: string;
if (typeof input === "string") {
inputText = input;
} else {
inputText = input.read(0, input.length);
}
const text = Text.of(
inputText.split("\n"),
);
throw SyntacticParseError.fromTextAndPosition(text, position);
}
};
}
return strictSdlParser;
}