dot-language-support
Version:
Parser and language service for graphviz (dot) files
1,279 lines (1,275 loc) • 123 kB
JavaScript
// 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