UNPKG

@flowscripter/mpeg-sdl-parser

Version:

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

128 lines (113 loc) 3.15 kB
import type { Doc } from "prettier"; import { doc } from "prettier"; import type { Token } from "../ast/token/Token"; import type { Trivia } from "../ast/token/Trivia"; const { hardline, indent, join } = doc.builders; function getCommentString(trivia: Trivia): string { if (!trivia.text.startsWith("//")) { throw new Error( "Logic Error: Expected comment to start with // : " + JSON.stringify(trivia), ); } // Remove leading "//" from the comment text const commentText = trivia.text.replace(/^\s*\/\/\s*/, "").trim(); return "// " + commentText; } /** * Returns a doc for the leading trivia of a token. * @param token The token to get the leading trivia for. * @param indentLeadingTriviaAsIndentIsCompleting Whether to indent the leading trivia as if it is completing a line. * * Note that if indentLeadingTriviaAsIndentIsCompleting is true, the leading trivia will include a hardline as this * is required to perform the indent. */ function getLeadingTriviaDoc( token: Token, indentLeadingTriviaAsIndentIsCompleting: boolean, ): Doc[] { if (!token.leadingTrivia.length) { if (indentLeadingTriviaAsIndentIsCompleting) { return [hardline]; } return []; } const elements = join( hardline, token.leadingTrivia.map((trivia) => getCommentString(trivia)), ); if (indentLeadingTriviaAsIndentIsCompleting) { return [ indent( [hardline, elements], ), hardline, ]; } return [ elements, hardline, ]; } function getTrailingTriviaDoc(token: Token): Doc[] { if (!token.trailingTrivia.length) { return []; } return [ " ", join( hardline, token.trailingTrivia.map((trivia) => getCommentString(trivia)), ), hardline, ]; } export function getDocWithTrivia( token: Token, indentLeadingTriviaAsIndentIsCompleting = false, ): Doc[] { const leadingTriviaDoc = getLeadingTriviaDoc( token, indentLeadingTriviaAsIndentIsCompleting, ); const trailingTriviaDoc = getTrailingTriviaDoc(token); const doc = []; if (leadingTriviaDoc.length > 0) { doc.push(leadingTriviaDoc); } doc.push(token.text); if (trailingTriviaDoc.length > 0) { doc.push(trailingTriviaDoc); } return doc; } export function addCommaSeparatorsToDoc( valuesDoc: Doc[], commaSeparatorTokens: Token[] | undefined, ): Doc[] { if (commaSeparatorTokens === undefined) { if (valuesDoc.length > 1) { throw new Error( `Logic Error: Number of values: ${valuesDoc.length} and no comma separators provided`, ); } return valuesDoc; } if (valuesDoc.length !== commaSeparatorTokens.length + 1) { throw new Error( `Logic Error: Number of values: ${valuesDoc.length} and comma separators: ${commaSeparatorTokens.length} are not as expected`, ); } const result: Doc[] = []; for (let i = 0; i < valuesDoc.length; i++) { if (i < commaSeparatorTokens.length) { result.push([ valuesDoc[i], getDocWithTrivia(commaSeparatorTokens[i]), ]); } else { result.push(valuesDoc[i]); } } return result; }