UNPKG

dot-language-support

Version:

Parser and language service for graphviz (dot) files

1,279 lines (1,275 loc) 123 kB
// src/core.ts function createMapFromTemplate(template) { const map = /* @__PURE__ */ new Map(); for (const key in template) { if (key in template) { map.set(key, template[key]); } } return map; } // src/types.ts var ErrorSource = /* @__PURE__ */ ((ErrorSource2) => { ErrorSource2[ErrorSource2["Scan"] = 1] = "Scan"; ErrorSource2[ErrorSource2["Parse"] = 2] = "Parse"; ErrorSource2[ErrorSource2["Check"] = 4] = "Check"; return ErrorSource2; })(ErrorSource || {}); var ParseError = /* @__PURE__ */ ((ParseError2) => { ParseError2[ParseError2["ExpectationFailed"] = 0] = "ExpectationFailed"; ParseError2[ParseError2["TrailingData"] = 1] = "TrailingData"; ParseError2[ParseError2["FailedListParsing"] = 2] = "FailedListParsing"; return ParseError2; })(ParseError || {}); var ScanError = /* @__PURE__ */ ((ScanError2) => { ScanError2[ScanError2["ExpectationFailed"] = 0] = "ExpectationFailed"; ScanError2[ScanError2["Unterminated"] = 1] = "Unterminated"; return ScanError2; })(ScanError || {}); var CheckError = /* @__PURE__ */ ((CheckError2) => { CheckError2[CheckError2["InvalidEdgeOperation"] = 0] = "InvalidEdgeOperation"; CheckError2[CheckError2["InvalidShapeName"] = 1] = "InvalidShapeName"; return CheckError2; })(CheckError || {}); var DiagnosticCategory = /* @__PURE__ */ ((DiagnosticCategory2) => { DiagnosticCategory2[DiagnosticCategory2["Error"] = 1] = "Error"; DiagnosticCategory2[DiagnosticCategory2["Warning"] = 2] = "Warning"; DiagnosticCategory2[DiagnosticCategory2["Message"] = 3] = "Message"; DiagnosticCategory2[DiagnosticCategory2["Suggestion"] = 4] = "Suggestion"; return DiagnosticCategory2; })(DiagnosticCategory || {}); var SyntaxKind = /* @__PURE__ */ ((SyntaxKind2) => { SyntaxKind2[SyntaxKind2["Unknown"] = 0] = "Unknown"; SyntaxKind2[SyntaxKind2["EndOfFileToken"] = 1] = "EndOfFileToken"; SyntaxKind2[SyntaxKind2["NewLineTrivia"] = 2] = "NewLineTrivia"; SyntaxKind2[SyntaxKind2["WhitespaceTrivia"] = 3] = "WhitespaceTrivia"; SyntaxKind2[SyntaxKind2["HashCommentTrivia"] = 4] = "HashCommentTrivia"; SyntaxKind2[SyntaxKind2["SingleLineCommentTrivia"] = 5] = "SingleLineCommentTrivia"; SyntaxKind2[SyntaxKind2["MultiLineCommentTrivia"] = 6] = "MultiLineCommentTrivia"; SyntaxKind2[SyntaxKind2["CommaToken"] = 7] = "CommaToken"; SyntaxKind2[SyntaxKind2["SemicolonToken"] = 8] = "SemicolonToken"; SyntaxKind2[SyntaxKind2["PlusToken"] = 9] = "PlusToken"; SyntaxKind2[SyntaxKind2["OpenBraceToken"] = 10] = "OpenBraceToken"; SyntaxKind2[SyntaxKind2["CloseBraceToken"] = 11] = "CloseBraceToken"; SyntaxKind2[SyntaxKind2["OpenBracketToken"] = 12] = "OpenBracketToken"; SyntaxKind2[SyntaxKind2["CloseBracketToken"] = 13] = "CloseBracketToken"; SyntaxKind2[SyntaxKind2["ColonToken"] = 14] = "ColonToken"; SyntaxKind2[SyntaxKind2["EqualsToken"] = 15] = "EqualsToken"; SyntaxKind2[SyntaxKind2["LessThan"] = 16] = "LessThan"; SyntaxKind2[SyntaxKind2["GreaterThan"] = 17] = "GreaterThan"; SyntaxKind2[SyntaxKind2["CompassNorthToken"] = 18] = "CompassNorthToken"; SyntaxKind2[SyntaxKind2["CompassNorthEastToken"] = 19] = "CompassNorthEastToken"; SyntaxKind2[SyntaxKind2["CompassEastToken"] = 20] = "CompassEastToken"; SyntaxKind2[SyntaxKind2["CompassSouthEastToken"] = 21] = "CompassSouthEastToken"; SyntaxKind2[SyntaxKind2["CompassSouthToken"] = 22] = "CompassSouthToken"; SyntaxKind2[SyntaxKind2["CompassSouthWestToken"] = 23] = "CompassSouthWestToken"; SyntaxKind2[SyntaxKind2["CompassWestToken"] = 24] = "CompassWestToken"; SyntaxKind2[SyntaxKind2["CompassNorthWestToken"] = 25] = "CompassNorthWestToken"; SyntaxKind2[SyntaxKind2["CompassCenterToken"] = 26] = "CompassCenterToken"; SyntaxKind2[SyntaxKind2["UnderscoreToken"] = 27] = "UnderscoreToken"; SyntaxKind2[SyntaxKind2["StringLiteral"] = 28] = "StringLiteral"; SyntaxKind2[SyntaxKind2["HtmlIdentifier"] = 29] = "HtmlIdentifier"; SyntaxKind2[SyntaxKind2["TextIdentifier"] = 30] = "TextIdentifier"; SyntaxKind2[SyntaxKind2["QuotedTextIdentifier"] = 31] = "QuotedTextIdentifier"; SyntaxKind2[SyntaxKind2["NumericIdentifier"] = 32] = "NumericIdentifier"; SyntaxKind2[SyntaxKind2["GraphKeyword"] = 33] = "GraphKeyword"; SyntaxKind2[SyntaxKind2["DigraphKeyword"] = 34] = "DigraphKeyword"; SyntaxKind2[SyntaxKind2["NodeKeyword"] = 35] = "NodeKeyword"; SyntaxKind2[SyntaxKind2["EdgeKeyword"] = 36] = "EdgeKeyword"; SyntaxKind2[SyntaxKind2["SubgraphKeyword"] = 37] = "SubgraphKeyword"; SyntaxKind2[SyntaxKind2["StrictKeyword"] = 38] = "StrictKeyword"; SyntaxKind2[SyntaxKind2["DirectedEdgeOp"] = 39] = "DirectedEdgeOp"; SyntaxKind2[SyntaxKind2["UndirectedEdgeOp"] = 40] = "UndirectedEdgeOp"; SyntaxKind2[SyntaxKind2["DirectedGraph"] = 41] = "DirectedGraph"; SyntaxKind2[SyntaxKind2["UndirectedGraph"] = 42] = "UndirectedGraph"; SyntaxKind2[SyntaxKind2["NodeStatement"] = 43] = "NodeStatement"; SyntaxKind2[SyntaxKind2["EdgeStatement"] = 44] = "EdgeStatement"; SyntaxKind2[SyntaxKind2["AttributeStatement"] = 45] = "AttributeStatement"; SyntaxKind2[SyntaxKind2["IdEqualsIdStatement"] = 46] = "IdEqualsIdStatement"; SyntaxKind2[SyntaxKind2["SubGraph"] = 47] = "SubGraph"; SyntaxKind2[SyntaxKind2["SubGraphStatement"] = 48] = "SubGraphStatement"; SyntaxKind2[SyntaxKind2["EdgeRhs"] = 49] = "EdgeRhs"; SyntaxKind2[SyntaxKind2["AttributeContainer"] = 50] = "AttributeContainer"; SyntaxKind2[SyntaxKind2["Assignment"] = 51] = "Assignment"; SyntaxKind2[SyntaxKind2["NormalPortDeclaration"] = 52] = "NormalPortDeclaration"; SyntaxKind2[SyntaxKind2["CompassPortDeclaration"] = 53] = "CompassPortDeclaration"; SyntaxKind2[SyntaxKind2["NodeId"] = 54] = "NodeId"; SyntaxKind2[SyntaxKind2["Count"] = 55] = "Count"; SyntaxKind2[SyntaxKind2["FirstNode"] = 41 /* DirectedGraph */] = "FirstNode"; SyntaxKind2[SyntaxKind2["CompassBegin"] = 18 /* CompassNorthToken */] = "CompassBegin"; SyntaxKind2[SyntaxKind2["CompassEnd"] = 27 /* UnderscoreToken */] = "CompassEnd"; SyntaxKind2[SyntaxKind2["LastKeyword"] = 38 /* StrictKeyword */] = "LastKeyword"; return SyntaxKind2; })(SyntaxKind || {}); var SyntaxNodeFlags = /* @__PURE__ */ ((SyntaxNodeFlags2) => { SyntaxNodeFlags2[SyntaxNodeFlags2["None"] = 0] = "None"; SyntaxNodeFlags2[SyntaxNodeFlags2["ContainsErrors"] = 2] = "ContainsErrors"; SyntaxNodeFlags2[SyntaxNodeFlags2["Synthesized"] = 4] = "Synthesized"; return SyntaxNodeFlags2; })(SyntaxNodeFlags || {}); var GraphContext = /* @__PURE__ */ ((GraphContext2) => { GraphContext2[GraphContext2["None"] = 0] = "None"; GraphContext2[GraphContext2["Strict"] = 2] = "Strict"; GraphContext2[GraphContext2["Directed"] = 4] = "Directed"; GraphContext2[GraphContext2["Undirected"] = 8] = "Undirected"; return GraphContext2; })(GraphContext || {}); var TokenFlags = /* @__PURE__ */ ((TokenFlags2) => { TokenFlags2[TokenFlags2["None"] = 0] = "None"; TokenFlags2[TokenFlags2["Unterminated"] = 2] = "Unterminated"; TokenFlags2[TokenFlags2["PrecedingLineBreak"] = 4] = "PrecedingLineBreak"; return TokenFlags2; })(TokenFlags || {}); var CharacterCodes = /* @__PURE__ */ ((CharacterCodes2) => { CharacterCodes2[CharacterCodes2["nullCharacter"] = 0] = "nullCharacter"; CharacterCodes2[CharacterCodes2["maxAsciiCharacter"] = 127] = "maxAsciiCharacter"; CharacterCodes2[CharacterCodes2["lineFeed"] = 10] = "lineFeed"; CharacterCodes2[CharacterCodes2["carriageReturn"] = 13] = "carriageReturn"; CharacterCodes2[CharacterCodes2["lineSeparator"] = 8232] = "lineSeparator"; CharacterCodes2[CharacterCodes2["paragraphSeparator"] = 8233] = "paragraphSeparator"; CharacterCodes2[CharacterCodes2["nextLine"] = 133] = "nextLine"; CharacterCodes2[CharacterCodes2["space"] = 32] = "space"; CharacterCodes2[CharacterCodes2["nonBreakingSpace"] = 160] = "nonBreakingSpace"; CharacterCodes2[CharacterCodes2["enQuad"] = 8192] = "enQuad"; CharacterCodes2[CharacterCodes2["emQuad"] = 8193] = "emQuad"; CharacterCodes2[CharacterCodes2["enSpace"] = 8194] = "enSpace"; CharacterCodes2[CharacterCodes2["emSpace"] = 8195] = "emSpace"; CharacterCodes2[CharacterCodes2["threePerEmSpace"] = 8196] = "threePerEmSpace"; CharacterCodes2[CharacterCodes2["fourPerEmSpace"] = 8197] = "fourPerEmSpace"; CharacterCodes2[CharacterCodes2["sixPerEmSpace"] = 8198] = "sixPerEmSpace"; CharacterCodes2[CharacterCodes2["figureSpace"] = 8199] = "figureSpace"; CharacterCodes2[CharacterCodes2["punctuationSpace"] = 8200] = "punctuationSpace"; CharacterCodes2[CharacterCodes2["thinSpace"] = 8201] = "thinSpace"; CharacterCodes2[CharacterCodes2["hairSpace"] = 8202] = "hairSpace"; CharacterCodes2[CharacterCodes2["zeroWidthSpace"] = 8203] = "zeroWidthSpace"; CharacterCodes2[CharacterCodes2["narrowNoBreakSpace"] = 8239] = "narrowNoBreakSpace"; CharacterCodes2[CharacterCodes2["ideographicSpace"] = 12288] = "ideographicSpace"; CharacterCodes2[CharacterCodes2["mathematicalSpace"] = 8287] = "mathematicalSpace"; CharacterCodes2[CharacterCodes2["ogham"] = 5760] = "ogham"; CharacterCodes2[CharacterCodes2["_"] = 95] = "_"; CharacterCodes2[CharacterCodes2["$"] = 36] = "$"; CharacterCodes2[CharacterCodes2["_0"] = 48] = "_0"; CharacterCodes2[CharacterCodes2["_1"] = 49] = "_1"; CharacterCodes2[CharacterCodes2["_2"] = 50] = "_2"; CharacterCodes2[CharacterCodes2["_3"] = 51] = "_3"; CharacterCodes2[CharacterCodes2["_4"] = 52] = "_4"; CharacterCodes2[CharacterCodes2["_5"] = 53] = "_5"; CharacterCodes2[CharacterCodes2["_6"] = 54] = "_6"; CharacterCodes2[CharacterCodes2["_7"] = 55] = "_7"; CharacterCodes2[CharacterCodes2["_8"] = 56] = "_8"; CharacterCodes2[CharacterCodes2["_9"] = 57] = "_9"; CharacterCodes2[CharacterCodes2["a"] = 97] = "a"; CharacterCodes2[CharacterCodes2["b"] = 98] = "b"; CharacterCodes2[CharacterCodes2["c"] = 99] = "c"; CharacterCodes2[CharacterCodes2["d"] = 100] = "d"; CharacterCodes2[CharacterCodes2["e"] = 101] = "e"; CharacterCodes2[CharacterCodes2["f"] = 102] = "f"; CharacterCodes2[CharacterCodes2["g"] = 103] = "g"; CharacterCodes2[CharacterCodes2["h"] = 104] = "h"; CharacterCodes2[CharacterCodes2["i"] = 105] = "i"; CharacterCodes2[CharacterCodes2["j"] = 106] = "j"; CharacterCodes2[CharacterCodes2["k"] = 107] = "k"; CharacterCodes2[CharacterCodes2["l"] = 108] = "l"; CharacterCodes2[CharacterCodes2["m"] = 109] = "m"; CharacterCodes2[CharacterCodes2["n"] = 110] = "n"; CharacterCodes2[CharacterCodes2["o"] = 111] = "o"; CharacterCodes2[CharacterCodes2["p"] = 112] = "p"; CharacterCodes2[CharacterCodes2["q"] = 113] = "q"; CharacterCodes2[CharacterCodes2["r"] = 114] = "r"; CharacterCodes2[CharacterCodes2["s"] = 115] = "s"; CharacterCodes2[CharacterCodes2["t"] = 116] = "t"; CharacterCodes2[CharacterCodes2["u"] = 117] = "u"; CharacterCodes2[CharacterCodes2["v"] = 118] = "v"; CharacterCodes2[CharacterCodes2["w"] = 119] = "w"; CharacterCodes2[CharacterCodes2["x"] = 120] = "x"; CharacterCodes2[CharacterCodes2["y"] = 121] = "y"; CharacterCodes2[CharacterCodes2["z"] = 122] = "z"; CharacterCodes2[CharacterCodes2["A"] = 65] = "A"; CharacterCodes2[CharacterCodes2["B"] = 66] = "B"; CharacterCodes2[CharacterCodes2["C"] = 67] = "C"; CharacterCodes2[CharacterCodes2["D"] = 68] = "D"; CharacterCodes2[CharacterCodes2["E"] = 69] = "E"; CharacterCodes2[CharacterCodes2["F"] = 70] = "F"; CharacterCodes2[CharacterCodes2["G"] = 71] = "G"; CharacterCodes2[CharacterCodes2["H"] = 72] = "H"; CharacterCodes2[CharacterCodes2["I"] = 73] = "I"; CharacterCodes2[CharacterCodes2["J"] = 74] = "J"; CharacterCodes2[CharacterCodes2["K"] = 75] = "K"; CharacterCodes2[CharacterCodes2["L"] = 76] = "L"; CharacterCodes2[CharacterCodes2["M"] = 77] = "M"; CharacterCodes2[CharacterCodes2["N"] = 78] = "N"; CharacterCodes2[CharacterCodes2["O"] = 79] = "O"; CharacterCodes2[CharacterCodes2["P"] = 80] = "P"; CharacterCodes2[CharacterCodes2["Q"] = 81] = "Q"; CharacterCodes2[CharacterCodes2["R"] = 82] = "R"; CharacterCodes2[CharacterCodes2["S"] = 83] = "S"; CharacterCodes2[CharacterCodes2["T"] = 84] = "T"; CharacterCodes2[CharacterCodes2["U"] = 85] = "U"; CharacterCodes2[CharacterCodes2["V"] = 86] = "V"; CharacterCodes2[CharacterCodes2["W"] = 87] = "W"; CharacterCodes2[CharacterCodes2["X"] = 88] = "X"; CharacterCodes2[CharacterCodes2["Y"] = 89] = "Y"; CharacterCodes2[CharacterCodes2["Z"] = 90] = "Z"; CharacterCodes2[CharacterCodes2["ampersand"] = 38] = "ampersand"; CharacterCodes2[CharacterCodes2["asterisk"] = 42] = "asterisk"; CharacterCodes2[CharacterCodes2["at"] = 64] = "at"; CharacterCodes2[CharacterCodes2["backslash"] = 92] = "backslash"; CharacterCodes2[CharacterCodes2["backtick"] = 96] = "backtick"; CharacterCodes2[CharacterCodes2["bar"] = 124] = "bar"; CharacterCodes2[CharacterCodes2["caret"] = 94] = "caret"; CharacterCodes2[CharacterCodes2["closeBrace"] = 125] = "closeBrace"; CharacterCodes2[CharacterCodes2["closeBracket"] = 93] = "closeBracket"; CharacterCodes2[CharacterCodes2["closeParen"] = 41] = "closeParen"; CharacterCodes2[CharacterCodes2["colon"] = 58] = "colon"; CharacterCodes2[CharacterCodes2["comma"] = 44] = "comma"; CharacterCodes2[CharacterCodes2["dot"] = 46] = "dot"; CharacterCodes2[CharacterCodes2["doubleQuote"] = 34] = "doubleQuote"; CharacterCodes2[CharacterCodes2["equals"] = 61] = "equals"; CharacterCodes2[CharacterCodes2["exclamation"] = 33] = "exclamation"; CharacterCodes2[CharacterCodes2["greaterThan"] = 62] = "greaterThan"; CharacterCodes2[CharacterCodes2["hash"] = 35] = "hash"; CharacterCodes2[CharacterCodes2["lessThan"] = 60] = "lessThan"; CharacterCodes2[CharacterCodes2["minus"] = 45] = "minus"; CharacterCodes2[CharacterCodes2["openBrace"] = 123] = "openBrace"; CharacterCodes2[CharacterCodes2["openBracket"] = 91] = "openBracket"; CharacterCodes2[CharacterCodes2["openParen"] = 40] = "openParen"; CharacterCodes2[CharacterCodes2["percent"] = 37] = "percent"; CharacterCodes2[CharacterCodes2["plus"] = 43] = "plus"; CharacterCodes2[CharacterCodes2["question"] = 63] = "question"; CharacterCodes2[CharacterCodes2["semicolon"] = 59] = "semicolon"; CharacterCodes2[CharacterCodes2["singleQuote"] = 39] = "singleQuote"; CharacterCodes2[CharacterCodes2["slash"] = 47] = "slash"; CharacterCodes2[CharacterCodes2["tilde"] = 126] = "tilde"; CharacterCodes2[CharacterCodes2["backspace"] = 8] = "backspace"; CharacterCodes2[CharacterCodes2["formFeed"] = 12] = "formFeed"; CharacterCodes2[CharacterCodes2["byteOrderMark"] = 65279] = "byteOrderMark"; CharacterCodes2[CharacterCodes2["tab"] = 9] = "tab"; CharacterCodes2[CharacterCodes2["verticalTab"] = 11] = "verticalTab"; return CharacterCodes2; })(CharacterCodes || {}); // src/service/util.ts function getStart(sourceFile, node) { return getTokenPosOfNode(sourceFile, node); } function getTokenPosOfNode(sourceFile, node) { if (nodeIsMissing(node)) return node.pos; return skipTrivia(sourceFile.content, node.pos); } function nodeIsMissing(node) { return node === void 0 ? true : node.pos === node.end && node.pos >= 0 && node.kind !== 1 /* EndOfFileToken */; } function syntaxNodesToRanges(doc, sourceFile, nodes) { return nodes.map((node) => syntaxNodeToRange(doc, sourceFile, node)); } function syntaxNodeToRange(doc, sourceFile, node) { const start = getStart(sourceFile, node); return { start: doc.positionAt(start), end: doc.positionAt(node.end) }; } function escapeIdentifierText(text) { if (text === "") return quote(""); if (text.includes('"') || text.includes("\n")) { const esc = text.replace(/"/, '\\"').replace(/\n/, "\\\n"); return quote(esc); } const ch = text.charCodeAt(0); if (!isIdentifierStart(ch) || text.includes(" ")) return quote(text); return text; } var quote = (s) => `"${s}"`; function assertNever(v) { throw new Error(`Should not have reached this. Value: ${v ?? ""}`); } // src/scanner.ts var textToToken = createMapFromTemplate({ digraph: 34 /* DigraphKeyword */, graph: 33 /* GraphKeyword */, edge: 36 /* EdgeKeyword */, node: 35 /* NodeKeyword */, strict: 38 /* StrictKeyword */, subgraph: 37 /* SubgraphKeyword */, n: 18 /* CompassNorthToken */, ne: 19 /* CompassNorthEastToken */, e: 20 /* CompassEastToken */, se: 21 /* CompassSouthEastToken */, s: 22 /* CompassSouthToken */, sw: 23 /* CompassSouthWestToken */, w: 24 /* CompassWestToken */, nw: 25 /* CompassNorthWestToken */, c: 26 /* CompassCenterToken */, "+": 9 /* PlusToken */, "=": 15 /* EqualsToken */, "->": 39 /* DirectedEdgeOp */, "--": 40 /* UndirectedEdgeOp */, "{": 10 /* OpenBraceToken */, "}": 11 /* CloseBraceToken */, "[": 12 /* OpenBracketToken */, "]": 13 /* CloseBracketToken */, ";": 8 /* SemicolonToken */, ":": 14 /* ColonToken */, _: 27 /* UnderscoreToken */, ",": 7 /* CommaToken */, "<": 16 /* LessThan */, ">": 17 /* GreaterThan */ }); function makeReverseMap(source) { const result = /* @__PURE__ */ new Map(); source.forEach((value, key) => { result.set(value, key); }); return result; } var tokenToText = makeReverseMap(textToToken); function getTokenAsText(token) { return tokenToText.get(token); } function getTextAsToken(token) { return textToToken.get(token); } var DefaultScanner = class { setText(newText, start = 0, length) { this.text = newText || ""; this.end = length === void 0 ? this.text.length : start + length; this.#setTextPos(start || 0); } setErrorCallback(cb) { this.onError = cb; } #setTextPos(textPos) { console.assert(textPos >= 0); this.pos = textPos; this.startPos = textPos; this.tokenPos = textPos; this.token = 0 /* Unknown */; this.tokenValue = void 0; this.tokenFlags = 0 /* None */; } scan(skipTrivia2 = true) { this.startPos = this.pos; this.tokenFlags = 0 /* None */; this.isUnterminated = false; while (true) { this.tokenPos = this.pos; if (this.pos >= this.end) { return this.token = 1 /* EndOfFileToken */; } let ch = this.text.charCodeAt(this.pos); switch (ch) { case 10 /* lineFeed */: case 13 /* carriageReturn */: this.tokenFlags |= 4 /* PrecedingLineBreak */; if (skipTrivia2) { this.pos++; continue; } if (ch === 13 /* carriageReturn */ && this.pos + 1 < this.end && this.text.charCodeAt(this.pos + 1) === 10 /* lineFeed */) { this.pos += 2; } else { this.pos++; } return this.token = 2 /* NewLineTrivia */; case 9 /* tab */: case 11 /* verticalTab */: case 12 /* formFeed */: case 32 /* space */: if (skipTrivia2) { this.pos++; continue; } while (this.pos < this.end && this.#isWhiteSpaceSingleLine(this.text.charCodeAt(this.pos))) this.pos++; return this.token = 3 /* WhitespaceTrivia */; case 35 /* hash */: { const content = this.#scanHashCommentTrivia(skipTrivia2); if (skipTrivia2) continue; this.tokenValue = content; return this.token = 4 /* HashCommentTrivia */; } case 47 /* slash */: { if (this.pos + 1 < this.end) { const nextChar = this.text.charCodeAt(this.pos + 1); switch (nextChar) { case 47 /* slash */: { const commentContent = this.#scanSingleLineCommentTrivia(skipTrivia2); if (skipTrivia2) continue; this.tokenValue = commentContent; return this.token = 5 /* SingleLineCommentTrivia */; } case 42 /* asterisk */: { const commentContent = this.#scanMultiLineCommentTrivia(skipTrivia2); if (skipTrivia2) continue; this.tokenValue = commentContent; return this.token = 6 /* MultiLineCommentTrivia */; } } } this.#error( 'Unexpected "/". Did you mean to start a comment like "/*" or "//"? If you wanted to use it as an identifier, put it in double quotes.', 0 /* ExpectationFailed */ ); ++this.pos; break; } case 123 /* openBrace */: this.pos++; return this.token = 10 /* OpenBraceToken */; case 125 /* closeBrace */: this.pos++; return this.token = 11 /* CloseBraceToken */; case 91 /* openBracket */: this.pos++; return this.token = 12 /* OpenBracketToken */; case 93 /* closeBracket */: this.pos++; return this.token = 13 /* CloseBracketToken */; case 43 /* plus */: this.pos++; return this.token = 9 /* PlusToken */; case 61 /* equals */: this.pos++; return this.token = 15 /* EqualsToken */; case 48 /* _0 */: case 49 /* _1 */: case 50 /* _2 */: case 51 /* _3 */: case 52 /* _4 */: case 53 /* _5 */: case 54 /* _6 */: case 55 /* _7 */: case 56 /* _8 */: case 57 /* _9 */: case 46 /* dot */: this.tokenValue = this.#scanNumber(); return this.token = 32 /* NumericIdentifier */; case 45 /* minus */: { const nextChar = this.text.charCodeAt(this.pos + 1); switch (nextChar) { case 45 /* minus */: this.pos += 2; return this.token = 40 /* UndirectedEdgeOp */; case 62 /* greaterThan */: this.pos += 2; return this.token = 39 /* DirectedEdgeOp */; case 48 /* _0 */: case 49 /* _1 */: case 50 /* _2 */: case 51 /* _3 */: case 52 /* _4 */: case 53 /* _5 */: case 54 /* _6 */: case 55 /* _7 */: case 56 /* _8 */: case 57 /* _9 */: case 46 /* dot */: this.tokenValue = this.#scanNumber(); return this.token = 32 /* NumericIdentifier */; default: { const chr = this.text.charAt(this.pos + 1); this.#error( `Unexpected "${chr}". Did you mean to define an edge? Depending on the type of graph you are defining, use "->" or "--".`, 0 /* ExpectationFailed */ ); break; } } this.pos++; break; } // TODO: Remove UnderscoreToken case 95 /* _ */: this.pos++; return this.token = 27 /* UnderscoreToken */; case 59 /* semicolon */: this.pos++; return this.token = 8 /* SemicolonToken */; case 58 /* colon */: this.pos++; return this.token = 14 /* ColonToken */; case 44 /* comma */: this.pos++; return this.token = 7 /* CommaToken */; case 60 /* lessThan */: this.tokenValue = this.#scanHtml(); return this.token = 29 /* HtmlIdentifier */; case 34 /* doubleQuote */: this.tokenValue = this.#scanString(); return this.token = 28 /* StringLiteral */; default: { if (isIdentifierStart(ch)) { this.pos++; while (this.pos < this.end && isIdentifierPart(ch = this.text.charCodeAt(this.pos))) this.pos++; const value = this.text.substring(this.tokenPos, this.pos); this.tokenValue = value; return this.token = this.#getIdentifierToken(value); } if (this.#isWhiteSpaceSingleLine(ch)) { this.pos++; continue; } const chr = this.text.charAt(this.pos); this.#error( `Unexpected "${chr}". Did you mean to start an identifier? Node names cannot start with "${chr}".`, 0 /* ExpectationFailed */ ); this.pos++; break; } } } } #error(message, sub, category = 1 /* Error */, errPos = this.pos, length = 0) { const cb = this.onError; if (cb) { const posSave = this.pos; this.pos = errPos; cb(message, category, sub, length); this.pos = posSave; } } #isWhiteSpaceSingleLine(ch) { return ch === 32 /* space */ || ch === 9 /* tab */ || ch === 11 /* verticalTab */ || ch === 12 /* formFeed */ || ch === 160 /* nonBreakingSpace */ || ch === 133 /* nextLine */ || ch === 5760 /* ogham */ || ch >= 8192 /* enQuad */ && ch <= 8203 /* zeroWidthSpace */ || ch === 8239 /* narrowNoBreakSpace */ || ch === 8287 /* mathematicalSpace */ || ch === 12288 /* ideographicSpace */ || ch === 65279 /* byteOrderMark */; } #isAtMultiLineCommentEnd(pos) { return pos + 1 < this.end && this.text.charCodeAt(pos) === 42 /* asterisk */ && this.text.charCodeAt(pos + 1) === 47 /* slash */; } #scanHashCommentTrivia(skip) { ++this.pos; const start = this.pos; while (this.pos < this.end && !isLineBreak(this.text.charCodeAt(this.pos))) this.pos++; return skip ? void 0 : this.text.substring(start, this.pos); } #scanSingleLineCommentTrivia(skip) { this.pos += 2; const start = this.pos; while (this.pos < this.end && !isLineBreak(this.text.charCodeAt(this.pos))) this.pos++; return skip ? void 0 : this.text.substring(start, this.pos); } #scanMultiLineCommentTrivia(skip) { this.pos += 2; const start = this.pos; while (this.pos < this.end && !this.#isAtMultiLineCommentEnd(this.pos)) this.pos++; const commentEnd = this.pos; if (this.#isAtMultiLineCommentEnd(this.pos)) { this.pos += 2; } return skip ? void 0 : this.text.substring(start, commentEnd); } #scanHtml() { this.pos++; let result = ""; const start = this.pos; let subTagsLevel = 0; while (true) { if (this.pos >= this.end) { result += this.text.substring(start, this.pos); this.tokenFlags |= 2 /* Unterminated */; this.isUnterminated = true; this.#error("Unterminated html literal", 1 /* Unterminated */); break; } const ch = this.text.charCodeAt(this.pos); if (ch === 60 /* lessThan */) { ++subTagsLevel; this.pos++; continue; } if (ch === 62 /* greaterThan */) { this.pos++; console.assert(subTagsLevel >= 0); if (subTagsLevel === 0) { result += this.text.substring(start, this.pos); break; } --subTagsLevel; continue; } this.pos++; } return result; } // biome-ignore lint/correctness/noUnusedFunctionParameters: todo #scanString(allowEscapes = true) { const quote2 = this.text.charCodeAt(this.pos); this.pos++; let result = ""; const start = this.pos; let hasBackslash = false; while (true) { if (this.pos >= this.end) { result += this.text.substring(start, this.pos); this.tokenFlags |= 2 /* Unterminated */; this.isUnterminated = true; this.#error("Unterminated string", 1 /* Unterminated */); break; } const ch = this.text.charCodeAt(this.pos); if (ch === 92 /* backslash */) { hasBackslash = true; } else { if (hasBackslash) { hasBackslash = false; } else { if (ch === quote2) { result += this.text.substring(start, this.pos); this.pos++; break; } if (isLineBreak(ch)) { result += this.text.substring(start, this.pos); this.tokenFlags |= 2 /* Unterminated */; this.isUnterminated = true; this.#error("Unterminated string", 1 /* Unterminated */); break; } } } this.pos++; } const removedEscapes = result.replace(/\\"/g, '"').replace(/\\(\r?\n)/g, "$1"); return removedEscapes; } #scanNumber() { let result = ""; let hadDot = false; let hadMinus = false; const start = this.pos; while (true) { const ch = this.text.charCodeAt(this.pos); switch (ch) { case 48 /* _0 */: case 49 /* _1 */: case 50 /* _2 */: case 51 /* _3 */: case 52 /* _4 */: case 53 /* _5 */: case 54 /* _6 */: case 55 /* _7 */: case 56 /* _8 */: case 57 /* _9 */: break; case 46 /* dot */: if (hadDot) { result += this.text.substring(start, this.pos); return result; } hadDot = true; hadMinus = true; break; case 45 /* minus */: if (this.pos !== start || hadMinus) { result += this.text.substring(start, this.pos); return result; } hadMinus = true; break; default: result += this.text.substring(start, this.pos); return result; } ++this.pos; } } #getIdentifierToken(tokenValue) { const len = tokenValue.length; if (len >= 4 && len <= 8) { const ch = tokenValue.charCodeAt(0); if (ch >= 97 /* a */ && ch <= 122 /* z */ || ch >= 65 /* A */ && ch <= 90 /* Z */) { const lowerCaseToken = tokenValue.toLowerCase(); const t = textToToken.get(lowerCaseToken); if (t !== void 0) { this.token = t; return t; } } } return this.token = 30 /* TextIdentifier */; } lookAhead(callback) { return this.#speculationHelper( callback, /*isLookahead*/ true ); } tryScan(callback) { return this.#speculationHelper( callback, /*isLookahead*/ false ); } #speculationHelper(callback, isLookahead) { const savePos = this.pos; const saveStartPos = this.startPos; const saveTokenPos = this.tokenPos; const saveToken = this.token; const saveTokenValue = this.tokenValue; const saveTokenFlags = this.tokenFlags; const result = callback(); if (!result || isLookahead) { this.pos = savePos; this.startPos = saveStartPos; this.tokenPos = saveTokenPos; this.token = saveToken; this.tokenValue = saveTokenValue; this.tokenFlags = saveTokenFlags; } return result; } }; function isIdentifierStart(ch) { return ch >= 65 /* A */ && ch <= 90 /* Z */ || ch >= 97 /* a */ && ch <= 122 /* z */ || ch >= 48 /* _0 */ && ch <= 57 /* _9 */ || ch === 95 /* _ */ || ch === 60 /* lessThan */ || ch === 34 /* doubleQuote */; } function isIdentifierPart(ch) { return ch >= 65 /* A */ && ch <= 90 /* Z */ || ch >= 97 /* a */ && ch <= 122 /* z */ || ch >= 48 /* _0 */ && ch <= 57 /* _9 */ || ch === 36 /* $ */ || ch === 95 /* _ */ || ch > 127 /* maxAsciiCharacter */; } function skipTrivia(text, pos) { while (true) { const ch = text.charCodeAt(pos); switch (ch) { case 13 /* carriageReturn */: if (text.charCodeAt(pos + 1) === 10 /* lineFeed */) ++pos; continue; case 10 /* lineFeed */: case 9 /* tab */: case 11 /* verticalTab */: case 12 /* formFeed */: case 32 /* space */: ++pos; continue; case 35 /* hash */: { ++pos; while (pos < text.length) { if (isLineBreak(text.charCodeAt(pos))) break; ++pos; } continue; } case 47 /* slash */: if (pos + 1 < text.length) { const nextChar = text.charCodeAt(pos + 1); switch (nextChar) { case 47 /* slash */: { pos += 2; while (pos < text.length) { if (isLineBreak(text.charCodeAt(pos))) break; ++pos; } continue; } case 42 /* asterisk */: { pos += 2; while (pos < text.length) { if (text.charCodeAt(pos) === 42 /* asterisk */ && text.charCodeAt(pos + 1) === 47 /* slash */) { pos += 2; break; } ++pos; } continue; } } } break; } return pos; } } function isLineBreak(ch) { return ch === 10 /* lineFeed */ || ch === 13 /* carriageReturn */; } // src/parser.ts var ParsingContext = /* @__PURE__ */ ((ParsingContext2) => { ParsingContext2[ParsingContext2["None"] = 0] = "None"; ParsingContext2[ParsingContext2["StatementList"] = 1] = "StatementList"; ParsingContext2[ParsingContext2["AttributeContainerList"] = 2] = "AttributeContainerList"; ParsingContext2[ParsingContext2["AssignmentList"] = 3] = "AssignmentList"; ParsingContext2[ParsingContext2["EdgeRhsList"] = 4] = "EdgeRhsList"; ParsingContext2[ParsingContext2["QuotedTextIdentifierConcatenation"] = 5] = "QuotedTextIdentifierConcatenation"; ParsingContext2[ParsingContext2["Count"] = 6] = "Count"; return ParsingContext2; })(ParsingContext || {}); var Parser = class { // TODO constructor() { this.currentToken = 0 /* Unknown */; this.identifierCount = 0; this.scanner = new DefaultScanner(); this.#resetState(); } #resetState() { this.sourceText = ""; this.scanner.setText(this.sourceText); this.scanner.setErrorCallback(this.#scanError.bind(this)); this.identifierCount = 0; this.identifiers = /* @__PURE__ */ new Set(); this.nodeCount = 0; this.diagnostics = []; this.currentNodeHasError = false; this.currentContext = 0 /* None */; } #nextToken() { this.currentToken = this.scanner.scan(true); return this.currentToken; } #token() { return this.currentToken; } #getLinesFromFile(sourceText) { return sourceText.split(/\r?\n/); } parse(sourceText) { this.sourceText = sourceText; this.scanner.setText(this.sourceText); this.#nextToken(); let graph; if (this.#token() !== 1 /* EndOfFileToken */) { graph = this.#parseGraph(); if (this.#token() !== 1 /* EndOfFileToken */) { this.#parseErrorAtPosition( this.scanner.tokenPos, this.scanner.text.length - 1, "Content after the end of a graph declaration is invalid.", { source: 2 /* Parse */, sub: 1 /* TrailingData */ } ); } } const result = { content: this.sourceText, graph, identifiers: this.identifiers, diagnostics: this.diagnostics }; this.#resetState(); return result; } #parseGraph() { const strictToken = this.#parseOptionalToken(38 /* StrictKeyword */); const keyword = this.#parseExpectedTokenOneOf(34 /* DigraphKeyword */, [ 34 /* DigraphKeyword */, 33 /* GraphKeyword */ ]); const kind = keyword === void 0 || keyword.kind === 34 /* DigraphKeyword */ ? 41 /* DirectedGraph */ : 42 /* UndirectedGraph */; const graphStart = strictToken ? strictToken.pos : keyword.pos; const node = this.#createNode(kind, graphStart); node.strict = strictToken; node.keyword = keyword; node.id = this.#isIdentifier() ? this.#parseIdentifier() : void 0; this.#parseExpectedToken(10 /* OpenBraceToken */); node.statements = this.#parseList( 1 /* StatementList */, () => this.#parseStatement() ); this.#parseExpectedToken(11 /* CloseBraceToken */); return this.#finishNode(node); } #parseIdentifier() { let result; const escapedIdTexts = []; switch (this.#token()) { case 30 /* TextIdentifier */: result = this.#parseTextIdentifier(); escapedIdTexts.push(result.text); break; case 28 /* StringLiteral */: result = this.#parseQuotedTextIdentifierConcatenation(); escapedIdTexts.push(...result.values.map((v) => v.text)); break; case 29 /* HtmlIdentifier */: result = this.#parseHtmlIdentifier(); escapedIdTexts.push(result.htmlContent); break; case 32 /* NumericIdentifier */: result = this.#parseNumericIdentifier(); escapedIdTexts.push(result.text); break; default: this.#reportExpectedError([30 /* TextIdentifier */]); result = this.#createMissingNode(30 /* TextIdentifier */); break; } for (const i of escapedIdTexts) { this.#registerIdentifier(i); } return result; } #registerIdentifier(id) { this.identifierCount++; const has = this.identifiers.has(id); if (!has) this.identifiers.add(id); } #parseTextIdentifier() { const node = this.#createNode(30 /* TextIdentifier */); const text = this.scanner.tokenValue; this.#nextToken(); if (text === void 0) throw "Satisfy type checker"; node.text = text; return this.#finishNode(node); } #parseQuotedTextIdentifierConcatenation() { const node = this.#createNode(31 /* QuotedTextIdentifier */); node.values = this.#parseList( 5 /* QuotedTextIdentifierConcatenation */, () => this.#parseQuotedTextIdentifier(), /* at least one */ true ); return this.#finishNode(node); } #parseQuotedTextIdentifier() { const node = this.#createNode(28 /* StringLiteral */); if (this.#token() === 9 /* PlusToken */) this.#nextToken(); const text = this.scanner.tokenValue; this.#nextToken(); if (text === void 0) throw "Satisfy type checker"; node.text = text; return this.#finishNode(node); } #isQuotedStringFollowing() { this.#nextToken(); return this.#token() === 28 /* StringLiteral */; } #parseHtmlIdentifier() { const node = this.#createNode(29 /* HtmlIdentifier */); const text = this.scanner.tokenValue; this.#nextToken(); if (text === void 0) throw "Satisfy type checker"; node.htmlContent = text; return this.#finishNode(node); } #parseNumericIdentifier() { const node = this.#createNode(32 /* NumericIdentifier */); const text = this.scanner.tokenValue; this.#nextToken(); if (text === void 0) throw "Satisfy type checker"; node.text = text; node.value = Number(text); return this.#finishNode(node); } #parseStatement() { switch (this.#token()) { case 33 /* GraphKeyword */: case 35 /* NodeKeyword */: case 36 /* EdgeKeyword */: return this.#parseAttributeStatement(); case 10 /* OpenBraceToken */: case 37 /* SubgraphKeyword */: { const subgraph = this.#parseSubGraph(); if (this.#token() === 8 /* SemicolonToken */) { const subgraphStatement2 = this.#createNode( 48 /* SubGraphStatement */, subgraph.pos ); subgraphStatement2.subgraph = subgraph; subgraphStatement2.terminator = this.#parseExpectedToken( 8 /* SemicolonToken */ ); return this.#finishNode(subgraphStatement2); } if (this.#isEdgeOp()) return this.#parseEdgeStatement(subgraph); const subgraphStatement = this.#createNode( 48 /* SubGraphStatement */, subgraph.pos ); subgraphStatement.subgraph = subgraph; return this.#finishNode(subgraphStatement); } default: { if (!this.#isIdentifier) debugger; if (this.#lookAhead(() => this.#isIdEqualsIdStatement())) { return this.#parseIdEqualsIdStatement(); } const ns = this.#parseNodeStatement(); if (ns.terminator !== void 0 || ns.attributes.length !== 0) return ns; if (this.#isEdgeOp()) return this.#parseEdgeStatement(ns.id); return ns; } } } #parseAttributeStatement() { switch (this.#token()) { case 33 /* GraphKeyword */: case 35 /* NodeKeyword */: case 36 /* EdgeKeyword */: { const node = this.#createNode(45 /* AttributeStatement */); node.subject = this.#parseTokenNode(); if (this.#token() === 12 /* OpenBracketToken */) { node.attributes = this.#parseList( 2 /* AttributeContainerList */, () => this.#parseAttributeContainer() ); } else { this.#reportExpectedError([12 /* OpenBracketToken */]); const missingStatement = this.#createMissingNode( 45 /* AttributeStatement */ ); missingStatement.attributes = this.#createNodeArray( [this.#createMissingNode(50 /* AttributeContainer */)], this.scanner.tokenPos, this.scanner.tokenPos ); } node.terminator = this.#parseOptionalToken(8 /* SemicolonToken */); return this.#finishNode(node); } default: throw "This should never happen"; } } #parseAttributeContainer() { if (this.#token() !== 12 /* OpenBracketToken */) debugger; const node = this.#createNode(50 /* AttributeContainer */); node.openBracket = this.#parseExpectedToken(12 /* OpenBracketToken */); if (this.#isIdentifier() && this.#lookAhead(() => this.#isAssignmentStart())) { node.assignments = this.#parseList( 3 /* AssignmentList */, () => this.#parseAssignment() ); } else { node.assignments = this.#createEmptyArray(); } node.closeBracket = this.#parseExpectedToken(13 /* CloseBracketToken */); return this.#finishNode(node); } #isAssignmentStart() { if (!this.#isIdentifier) debugger; this.#nextToken(); return this.#token() === 15 /* EqualsToken */; } #parseIdEqualsIdStatement() { if (!this.#isIdentifier) debugger; const leftIdentifier = this.#parseIdentifier(); const node = this.#createNode( 46 /* IdEqualsIdStatement */, leftIdentifier.pos ); node.leftId = leftIdentifier; if (this.#token() !== 15 /* EqualsToken */) debugger; this.#parseExpectedToken(15 /* EqualsToken */); node.rightId = this.#parseIdentifier(); node.terminator = this.#parseOptionalToken(8 /* SemicolonToken */); return this.#finishNode(node); } #isIdEqualsIdStatement() { if (!this.#isIdentifier) debugger; this.#nextToken(); return this.#token() === 15 /* EqualsToken */; } #parseNodeStatement() { if (!this.#isIdentifier) debugger; const node = this.#createNode(43 /* NodeStatement */); node.id = this.#parseNodeId(); if (this.#token() === 12 /* OpenBracketToken */) { node.attributes = this.#parseList( 2 /* AttributeContainerList */, () => this.#parseAttributeContainer() ); } else { node.attributes = this.#createEmptyArray(); } node.terminator = this.#parseOptionalToken(8 /* SemicolonToken */); return this.#finishNode(node); } #parseEdgeStatement(precedingItem) { console.assert( precedingItem.kind === 47 /* SubGraph */ || precedingItem.kind === 54 /* NodeId */ ); console.assert(precedingItem.pos !== void 0); if (!this.#isEdgeOp()) debugger; const node = this.#createNode(44 /* EdgeStatement */, precedingItem.pos); node.source = precedingItem; node.rhs = this.#parseList(4 /* EdgeRhsList */, () => this.#parseEdgeRhs()); if (this.#token() === 12 /* OpenBracketToken */) { node.attributes = this.#parseList( 2 /* AttributeContainerList */, () => this.#parseAttributeContainer() ); } else { node.attributes = this.#createEmptyArray(); } node.terminator = this.#parseOptionalToken(8 /* SemicolonToken */); return this.#finishNode(node); } #parseEdgeRhs() { const node = this.#createNode(49 /* EdgeRhs */); const op = this.#parseExpectedTokenOneOf(39 /* DirectedEdgeOp */, [ 39 /* DirectedEdgeOp */, 40 /* UndirectedEdgeOp */ ]); node.operation = op; switch (this.#token()) { case 37 /* SubgraphKeyword */: case 10 /* OpenBraceToken */: node.target = this.#parseSubGraph(); break; default: { node.target = this.#parseNodeId(); break; } } return this.#finishNode(node); } #createMissingNode(kind) { const result = this.#createNode(kind); if (isIdentifierNode(result)) { switch (result.kind) { case 31 /* QuotedTextIdentifier */: { const literal = this.#createNode(28 /* StringLiteral */); literal.text = ""; const values = this.#createNodeArray([literal], result.pos, result.pos); result.values = values; break; } case 29 /* HtmlIdentifier */: result.htmlContent = ""; break; case 30 /* TextIdentifier */: case 32 /* NumericIdentifier */: result.text = ""; break; } } return this.#finishNode(result); } #parseAssignment() { if (!this.#isIdentifier) debugger; const node = this.#createNode(51 /* Assignment */); node.leftId = this.#parseIdentifier(); this.#parseExpectedToken(15 /* EqualsToken */); node.rightId = this.#parseIdentifier(); let terminator = this.#parseOptionalToken( 7 /* CommaToken */ ); if (terminator === void 0) terminator = this.#parseOptionalToken(8 /* SemicolonToken */); node.terminator = terminator; return this.#finishNode(node); } #parseSubGraph() { console.assert( this.#token() === 37 /* SubgraphKeyword */ || this.#token() === 10 /* OpenBraceToken */ ); const subGraph = this.#parseOptionalToken(37 /* SubgraphKeyword */); const subGraphStart = subGraph !== void 0 ? subGraph.pos : void 0; const node = this.#createNode(47 /* SubGraph */, subGraphStart); const identifier = subGraph !== void 0 && this.#isIdentifier() ? this.#parseIdentifier() : void 0; node.id = identifier; this.#parseExpectedToken(10 /* OpenBraceToken */); node.statements = this.#parseList( 1 /* StatementList */, () => this.#parseStatement() ); this.#parseExpectedToken(11 /* CloseBraceToken */); return this.#finishNode(node); } #parseNodeId() { if (!this.#isIdentifier) debugger; const node = this.#createNode(54 /* NodeId */); node.id = this.#parseIdentifier(); node.port = this.#token() === 14 /* ColonToken */ ? this.#parsePortDeclaration() : void 0; return this.#finishNode(node); } #parseCompassPortDeclaration() { console.assert(this.#token() === 14 /* ColonToken */); const node = this.#createNode(53 /* CompassPortDeclaration */); node.colon = this.#parseTokenNode(); node.compassPt = this.#parseTokenNode(); return this.#finishNode(node); } #parseNormalPortDeclaration() { console.assert(this.#token() === 14 /* ColonToken */); const node = this.#createNode(52 /* NormalPortDeclaration */); node.colon = this.#parseTokenNode(); node.id = this.#parseIdentifier(); node.compassPt = this.#token() === 14 /* ColonToken */ ? this.#parseCompassPortDeclaration() : void 0; return this.#finishNode(node); } #parsePortDeclaration() { console.assert(this.#token() === 14 /* ColonToken */); if (this.#lookAhead(() => this.#isCompassPort())) return this.#parseCompassPortDeclaration(); return this.#parseNormalPortDeclaration(); } #isCompassPort() { console.assert(this.#token() === 14 /* ColonToken */); if (this.#token() !== 14 /* ColonToken */) return false; this.#nextToken(); return this.#isCompassPortKind(this.#token()); } #parseList(context, parseElement, atLeastOne = false) { const saveParsingContext = this.currentContext; this.currentContext |= 1 << context; let isListTerminated = atLeastOne ? false : this.#isListTerminator(context); const startPos = this.scanner.startPos; const elements = []; while (!isListTerminated) { if (this.#isListElement(context, false)) { const element = parseElement(); elements.push(element); isListTerminated = this.#isListTerminator(context); continue; } if (this.#abortListParsing(context)) break; } this.currentContext = saveParsingContext; return this.#createNodeArray(elements, startPos); } #getContextParseError(context) { switch (context) { case 1 /* StatementList */: return "Assignment, node definition, graph/node/edge attribute or edge definition expected."; case 3 /* AssignmentList */: return "Assignment expected."; case 4 /* EdgeRhsList */: return "Edge operation expected."; case 5 /* QuotedTextIdentifierConcatenation */: return "Quoted identifier expected"; case 2 /* AttributeContainerList */: return "Attribute marker expected."; // TODO: Was besseres finden case 0 /* None */: return "Wat, no parsing context"; case 6 /* Count */: return "Wat, 'Count' parsing context"; default: return assertNever(context); } } #isInSomeParsingContext() { for (let ctx = 0; ctx < 6 /* Count */; ctx++) { if (this.currentContext & 1 << ctx) { if (this.#isListElement( ctx, /*inErrorRecovery*/ true ) || this.#isListTerminator(ctx)) { return true; } } } return false; } #abortListParsing(context) { this.#parseErrorAtCurrentToken( this.#getContextParseError(context), 2 /* FailedListParsing */ ); if (this.#isInSomeParsingContext()) { return true; } this.#nextToken(); return false; } #isListElement(context, _inErrorRecovery) { switch (context) { case 3 /* AssignmentList */: return this.#isIdentifier(); case 2 /* AttributeContainerList */: return this.#token() === 12 /* OpenBracketToken */; case 4 /* EdgeRhsList */: return this.#token() === 39 /* DirectedEdgeOp */ || this.#token() === 40 /* UndirectedEdgeOp */; case 5 /* QuotedTextIdentifierConcatenation */: return this.#token() === 28 /* StringLiteral */ || this.#t