@flowscripter/mpeg-sdl-parser
Version:
ISO/IEC 14496-34 Syntactic Description Language (MPEG SDL) parser implemented in TypeScript
71 lines (61 loc) • 2.15 kB
text/typescript
import { Text } from "@codemirror/state";
import type { TreeCursor } from "@lezer/common";
import {
getChildNodesAndTokens,
isAbstractNode,
} from "../../util/nodeFactoryUtils";
import { NumberLiteral } from "../node/NumberLiteral";
import { NumberLiteralKind } from "../node/enum/number_literal_kind";
import { InternalParseError } from "../../ParseError";
import { NodeKind } from "../node/enum/node_kind";
const ESCAPED_BACKSLASH_REGEX = /\\\\/g;
const ESCAPED_SINGLE_QUOTE_REGEX = /\\'/g;
const MAXIMUM_MULTIPLE_CHARACTER_LITERAL_LENGTH = 10;
function parseUnsignedIntFromMultipleCharacterLiteral(literal: string): number {
if (literal.length > MAXIMUM_MULTIPLE_CHARACTER_LITERAL_LENGTH) {
throw new InternalParseError(
`Multiple character number literal exceeds maximum length of ${MAXIMUM_MULTIPLE_CHARACTER_LITERAL_LENGTH}: ${literal}`,
);
}
let value = 0;
for (let i = 0; i < literal.length; i++) {
const charCode = literal.charCodeAt(i);
if (charCode < 0x20 || charCode > 0x7E) {
throw new InternalParseError(
`Invalid character ${
literal.charCodeAt(i)
} in multiple character number literal: ${literal}`,
);
}
value = (value << 8) + charCode;
}
return value;
}
export function getMultipleCharacterLiteral(
cursor: TreeCursor,
text: Text,
): NumberLiteral {
const childNodesAndTokens = getChildNodesAndTokens(cursor, text);
const literals = [];
let literalText = "";
for (const childNodeOrToken of childNodesAndTokens) {
if (isAbstractNode(childNodeOrToken)) {
throw new InternalParseError(
`Unexpected node kind: ${NodeKind[childNodeOrToken.nodeKind]}`,
);
} else {
const tokenText = childNodeOrToken.text;
if (tokenText !== "'") {
literalText += tokenText.replaceAll(ESCAPED_SINGLE_QUOTE_REGEX, "'")
.replaceAll(ESCAPED_BACKSLASH_REGEX, "\\");
}
literals.push(childNodeOrToken);
}
}
const value = parseUnsignedIntFromMultipleCharacterLiteral(literalText);
return new NumberLiteral(
NumberLiteralKind.MULTIPLE_CHARACTER,
value,
literals,
);
}