@flowscripter/mpeg-sdl-parser
Version:
ISO/IEC 14496-34 Syntactic Description Language (MPEG SDL) parser implemented in TypeScript
117 lines (101 loc) • 3.5 kB
text/typescript
import { AstPath, type Doc, doc } from "prettier";
import { getDocWithTrivia } from "./print_utils";
import type { AbstractNode } from "../ast/node/AbstractNode";
import type { AlignedModifier } from "../ast/node/AlignedModifier";
import { NumberLiteralKind } from "../ast/node/enum/number_literal_kind";
import type { LengthAttribute } from "../ast/node/LengthAttribute";
import type { NumberLiteral } from "../ast/node/NumberLiteral";
import type { Identifier } from "../ast/node/Identifier";
const { join } = doc.builders;
export function printAlignedModifier(
path: AstPath<AlignedModifier>,
print: (path: AstPath<AbstractNode>) => Doc,
): Doc {
const alignedModifier = path.node;
const elements = [];
elements.push(getDocWithTrivia(alignedModifier.alignedKeyword));
if (!alignedModifier.isDefault8BitCount) {
elements.push(
getDocWithTrivia(alignedModifier.openParenthesisPunctuator!),
);
elements.push(
path.call(
print,
"bitCountModifier" as keyof AlignedModifier["bitCountModifier"],
),
),
elements.push(
getDocWithTrivia(alignedModifier.closeParenthesisPunctuator!),
);
}
return elements;
}
export function printIdentifier(path: AstPath<Identifier>): Doc {
const identifier = path.node;
return getDocWithTrivia(identifier.literal);
}
export function printLengthAttribute(
path: AstPath<LengthAttribute>,
print: (path: AstPath<AbstractNode>) => Doc,
): Doc {
const node = path.node;
return [
getDocWithTrivia(node.openParenthesisPunctuator),
path.call(print, "length"),
getDocWithTrivia(node.closeParenthesisPunctuator),
];
}
export function printMultipleCharacterNumberLiteral(
path: AstPath<NumberLiteral>,
): Doc {
const multipleCharacterNumberLiteral = path.node;
const multipleCharacterNumberLiterals = [];
let opened = false;
let currentLiteral = [] as Doc[];
let containsContent = false;
for (const literal of multipleCharacterNumberLiteral.literals) {
if (literal.text === "'") {
if (!opened) {
currentLiteral.push(...getDocWithTrivia(literal));
opened = true;
} else {
currentLiteral.push(...getDocWithTrivia(literal));
// avoid empty multiple character number literals after the first one
if ((multipleCharacterNumberLiterals.length === 0) || containsContent) {
multipleCharacterNumberLiterals.push(currentLiteral);
}
// reset state
currentLiteral = [];
containsContent = false;
opened = false;
}
} else if (literal.text.length > 0) {
currentLiteral.push(literal.text);
containsContent = true;
}
}
return join(
" ",
multipleCharacterNumberLiterals,
);
}
export function printNumberLiteral(path: AstPath<NumberLiteral>): Doc {
const numberLiteral = path.node;
const numberLiteralKind = numberLiteral.numberLiteralKind;
switch (numberLiteralKind) {
case NumberLiteralKind.BINARY:
case NumberLiteralKind.HEXADECIMAL:
case NumberLiteralKind.INTEGER:
case NumberLiteralKind.DECIMAL:
case NumberLiteralKind.FLOATING_POINT:
return getDocWithTrivia(numberLiteral.literals[0]);
case NumberLiteralKind.MULTIPLE_CHARACTER:
return printMultipleCharacterNumberLiteral(path);
default: {
const exhaustiveCheck: never = numberLiteralKind;
throw new Error(
"Unreachable code reached, numberLiteralKind == " + exhaustiveCheck,
);
}
}
}