UNPKG

@flowscripter/mpeg-sdl-parser

Version:

ISO/IEC 14496-34 Syntactic Description Language (MPEG SDL) parser implemented in TypeScript

104 lines (95 loc) 2.82 kB
import type { Text } from "@codemirror/state"; import { TreeCursor } from "@lezer/common"; import type { Location } from "./Location.ts"; import { getLocationFromTextPosition } from "./util/locationUtils.ts"; /** * Base error class. */ export abstract class ParseError extends Error { protected constructor( public errorMessage: string, public location?: Location, ) { super( errorMessage + (location ? ` => { row: ${location.row}, column: ${location.column}, position: ${location.position} }` : ""), ); } } /** * Indicates an internal logic error in the parsing implementation. */ export class InternalParseError extends ParseError { constructor(errorMessage: string, location?: Location) { super(`INTERNAL ERROR: ${errorMessage}`, location); } } /** * Indicates a syntactic error when parsing. */ export class SyntacticParseError extends ParseError { constructor( errorMessage: string, location?: Location, public errorLine?: string, public preceedingLines?: string[], ) { super(`SYNTACTIC ERROR: ${errorMessage}`, location); } /** * Helper function to create a SyntacticParseError from the text and a cursor. * * @param text The text to parse. * @param cursor The cursor position in the text. */ static fromTextAndCursor( text: Text, cursor: TreeCursor, ): SyntacticParseError { if (!cursor.type.isError) { throw new InternalParseError( "Expected cursor to be an error token, but it is not", ); } // if the error token has a child, the child is an unexpected token const unexpectedToken = cursor.firstChild(); return this.fromTextAndPosition( text, cursor.from, unexpectedToken ? "Unexpected token" : "Missing expected token", ); } /** * Helper function to create a SyntacticParseError from the text and a position. * * @param text The text to parse. * @param position The position in the text, 0-based. * @param message The error message, defaults to "Parse error". */ static fromTextAndPosition( text: Text, position: number, message: string = "Parse error", ): SyntacticParseError { const line = text.lineAt(position); const location = getLocationFromTextPosition(text, position); const preceedingLines = []; // Collect up to two preceding lines if available if (location.row > 1) { // First preceding line (if exists) preceedingLines.push(text.line(location.row - 1).text); // Second preceding line (if exists) if (location.row > 2) { preceedingLines.unshift(text.line(location.row - 2).text); } } return new SyntacticParseError( message, location, line.text, preceedingLines, ); } }