import * as lst from "vscode-languageserver-types";
import { Range, TextEdit } from "vscode-languageserver-types";

//#region 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;
}

//#endregion
//#region src/types.ts
const errorSource = {
	Scan: 1,
	Parse: 2,
	Check: 4
};
const parseError = {
	ExpectationFailed: 0,
	TrailingData: 1,
	FailedListParsing: 2
};
const scanError = {
	ExpectationFailed: 0,
	Unterminated: 1
};
const checkError = {
	InvalidEdgeOperation: 0,
	InvalidShapeName: 1
};
const diagnosticCategory = {
	Error: 1,
	Warning: 2,
	Message: 3,
	Suggestion: 4
};
const syntaxKind = {
	Unknown: 0,
	EndOfFileToken: 1,
	NewLineTrivia: 2,
	WhitespaceTrivia: 3,
	HashCommentTrivia: 4,
	SingleLineCommentTrivia: 5,
	MultiLineCommentTrivia: 6,
	CommaToken: 7,
	SemicolonToken: 8,
	PlusToken: 9,
	OpenBraceToken: 10,
	CloseBraceToken: 11,
	OpenBracketToken: 12,
	CloseBracketToken: 13,
	ColonToken: 14,
	EqualsToken: 15,
	LessThan: 16,
	GreaterThan: 17,
	CompassNorthToken: 18,
	CompassNorthEastToken: 19,
	CompassEastToken: 20,
	CompassSouthEastToken: 21,
	CompassSouthToken: 22,
	CompassSouthWestToken: 23,
	CompassWestToken: 24,
	CompassNorthWestToken: 25,
	CompassCenterToken: 26,
	UnderscoreToken: 27,
	StringLiteral: 28,
	HtmlIdentifier: 29,
	TextIdentifier: 30,
	QuotedTextIdentifier: 31,
	NumericIdentifier: 32,
	GraphKeyword: 33,
	DigraphKeyword: 34,
	NodeKeyword: 35,
	EdgeKeyword: 36,
	SubgraphKeyword: 37,
	StrictKeyword: 38,
	DirectedEdgeOp: 39,
	UndirectedEdgeOp: 40,
	DirectedGraph: 41,
	UndirectedGraph: 42,
	NodeStatement: 43,
	EdgeStatement: 44,
	AttributeStatement: 45,
	IdEqualsIdStatement: 46,
	SubGraph: 47,
	SubGraphStatement: 48,
	EdgeRhs: 49,
	AttributeContainer: 50,
	Assignment: 51,
	NormalPortDeclaration: 52,
	CompassPortDeclaration: 53,
	NodeId: 54,
	Count: 55,
	FirstNode: 41,
	CompassBegin: 18,
	CompassEnd: 27,
	LastKeyword: 38
};
/** reverse lookup because we cannot make syntaxKind an enum */
const syntaxKindNames = {
	0: "Unknown",
	1: "EndOfFileToken",
	2: "NewLineTrivia",
	3: "WhitespaceTrivia",
	4: "HashCommentTrivia",
	5: "SingleLineCommentTrivia",
	6: "MultiLineCommentTrivia",
	7: "CommaToken",
	8: "SemicolonToken",
	9: "PlusToken",
	10: "OpenBraceToken",
	11: "CloseBraceToken",
	12: "OpenBracketToken",
	13: "CloseBracketToken",
	14: "ColonToken",
	15: "EqualsToken",
	16: "LessThan",
	17: "GreaterThan",
	18: "CompassNorthToken",
	19: "CompassNorthEastToken",
	20: "CompassEastToken",
	21: "CompassSouthEastToken",
	22: "CompassSouthToken",
	23: "CompassSouthWestToken",
	24: "CompassWestToken",
	25: "CompassNorthWestToken",
	26: "CompassCenterToken",
	27: "UnderscoreToken",
	28: "StringLiteral",
	29: "HtmlIdentifier",
	30: "TextIdentifier",
	31: "QuotedTextIdentifier",
	32: "NumericIdentifier",
	33: "GraphKeyword",
	34: "DigraphKeyword",
	35: "NodeKeyword",
	36: "EdgeKeyword",
	37: "SubgraphKeyword",
	38: "StrictKeyword",
	39: "DirectedEdgeOp",
	40: "UndirectedEdgeOp",
	41: "DirectedGraph",
	42: "UndirectedGraph",
	43: "NodeStatement",
	44: "EdgeStatement",
	45: "AttributeStatement",
	46: "IdEqualsIdStatement",
	47: "SubGraph",
	48: "SubGraphStatement",
	49: "EdgeRhs",
	50: "AttributeContainer",
	51: "Assignment",
	52: "NormalPortDeclaration",
	53: "CompassPortDeclaration",
	54: "NodeId",
	55: "Count"
};
const syntaxNodeFlags = {
	None: 0,
	ContainsErrors: 2,
	Synthesized: 4
};
const graphContext = {
	None: 0,
	Strict: 2,
	Directed: 4,
	Undirected: 8
};
const tokenFlags = {
	None: 0,
	Unterminated: 2,
	PrecedingLineBreak: 4
};
const characterCodes = {
	nullCharacter: 0,
	maxAsciiCharacter: 127,
	lineFeed: 10,
	carriageReturn: 13,
	lineSeparator: 8232,
	paragraphSeparator: 8233,
	nextLine: 133,
	space: 32,
	nonBreakingSpace: 160,
	enQuad: 8192,
	emQuad: 8193,
	enSpace: 8194,
	emSpace: 8195,
	threePerEmSpace: 8196,
	fourPerEmSpace: 8197,
	sixPerEmSpace: 8198,
	figureSpace: 8199,
	punctuationSpace: 8200,
	thinSpace: 8201,
	hairSpace: 8202,
	zeroWidthSpace: 8203,
	narrowNoBreakSpace: 8239,
	ideographicSpace: 12288,
	mathematicalSpace: 8287,
	ogham: 5760,
	_: 95,
	$: 36,
	_0: 48,
	_1: 49,
	_2: 50,
	_3: 51,
	_4: 52,
	_5: 53,
	_6: 54,
	_7: 55,
	_8: 56,
	_9: 57,
	a: 97,
	b: 98,
	c: 99,
	d: 100,
	e: 101,
	f: 102,
	g: 103,
	h: 104,
	i: 105,
	j: 106,
	k: 107,
	l: 108,
	m: 109,
	n: 110,
	o: 111,
	p: 112,
	q: 113,
	r: 114,
	s: 115,
	t: 116,
	u: 117,
	v: 118,
	w: 119,
	x: 120,
	y: 121,
	z: 122,
	A: 65,
	B: 66,
	C: 67,
	D: 68,
	E: 69,
	F: 70,
	G: 71,
	H: 72,
	I: 73,
	J: 74,
	K: 75,
	L: 76,
	M: 77,
	N: 78,
	O: 79,
	P: 80,
	Q: 81,
	R: 82,
	S: 83,
	T: 84,
	U: 85,
	V: 86,
	W: 87,
	X: 88,
	Y: 89,
	Z: 90,
	ampersand: 38,
	asterisk: 42,
	at: 64,
	backslash: 92,
	backtick: 96,
	bar: 124,
	caret: 94,
	closeBrace: 125,
	closeBracket: 93,
	closeParen: 41,
	colon: 58,
	comma: 44,
	dot: 46,
	doubleQuote: 34,
	equals: 61,
	exclamation: 33,
	greaterThan: 62,
	hash: 35,
	lessThan: 60,
	minus: 45,
	openBrace: 123,
	openBracket: 91,
	openParen: 40,
	percent: 37,
	plus: 43,
	question: 63,
	semicolon: 59,
	singleQuote: 39,
	slash: 47,
	tilde: 126,
	backspace: 8,
	formFeed: 12,
	byteOrderMark: 65279,
	tab: 9,
	verticalTab: 11
};

//#endregion
//#region 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 !== syntaxKind.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")) return quote(text.replace(/"/, "\\\"").replace(/\n/, "\\\n"));
	if (!isIdentifierStart(text.charCodeAt(0)) || text.includes(" ")) return quote(text);
	return text;
}
const quote = (s) => `"${s}"`;
function assertNever(v) {
	throw new Error(`Should not have reached this. Value: ${v ?? ""}`);
}

//#endregion
//#region src/scanner.ts
const textToToken = createMapFromTemplate({
	digraph: syntaxKind.DigraphKeyword,
	graph: syntaxKind.GraphKeyword,
	edge: syntaxKind.EdgeKeyword,
	node: syntaxKind.NodeKeyword,
	strict: syntaxKind.StrictKeyword,
	subgraph: syntaxKind.SubgraphKeyword,
	n: syntaxKind.CompassNorthToken,
	ne: syntaxKind.CompassNorthEastToken,
	e: syntaxKind.CompassEastToken,
	se: syntaxKind.CompassSouthEastToken,
	s: syntaxKind.CompassSouthToken,
	sw: syntaxKind.CompassSouthWestToken,
	w: syntaxKind.CompassWestToken,
	nw: syntaxKind.CompassNorthWestToken,
	c: syntaxKind.CompassCenterToken,
	"+": syntaxKind.PlusToken,
	"=": syntaxKind.EqualsToken,
	"->": syntaxKind.DirectedEdgeOp,
	"--": syntaxKind.UndirectedEdgeOp,
	"{": syntaxKind.OpenBraceToken,
	"}": syntaxKind.CloseBraceToken,
	"[": syntaxKind.OpenBracketToken,
	"]": syntaxKind.CloseBracketToken,
	";": syntaxKind.SemicolonToken,
	":": syntaxKind.ColonToken,
	_: syntaxKind.UnderscoreToken,
	",": syntaxKind.CommaToken,
	"<": syntaxKind.LessThan,
	">": syntaxKind.GreaterThan
});
function makeReverseMap(source) {
	const result = /* @__PURE__ */ new Map();
	source.forEach((value, key) => {
		result.set(value, key);
	});
	return result;
}
const tokenToText = makeReverseMap(textToToken);
function getTokenAsText(token) {
	return tokenToText.get(token);
}
function getTextAsToken(token) {
	return textToToken.get(token);
}
var DefaultScanner = class {
	end;
	pos;
	startPos;
	tokenPos;
	token;
	tokenValue;
	tokenFlags;
	isUnterminated;
	text;
	onError;
	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 = syntaxKind.Unknown;
		this.tokenValue = void 0;
		this.tokenFlags = tokenFlags.None;
	}
	scan(skipTrivia$1 = true) {
		this.startPos = this.pos;
		this.tokenFlags = tokenFlags.None;
		this.isUnterminated = false;
		while (true) {
			this.tokenPos = this.pos;
			if (this.pos >= this.end) return this.token = syntaxKind.EndOfFileToken;
			let ch = this.text.charCodeAt(this.pos);
			switch (ch) {
				case characterCodes.lineFeed:
				case characterCodes.carriageReturn:
					this.tokenFlags |= tokenFlags.PrecedingLineBreak;
					if (skipTrivia$1) {
						this.pos++;
						continue;
					}
					if (ch === characterCodes.carriageReturn && this.pos + 1 < this.end && this.text.charCodeAt(this.pos + 1) === characterCodes.lineFeed) this.pos += 2;
					else this.pos++;
					return this.token = syntaxKind.NewLineTrivia;
				case characterCodes.tab:
				case characterCodes.verticalTab:
				case characterCodes.formFeed:
				case characterCodes.space:
					if (skipTrivia$1) {
						this.pos++;
						continue;
					}
					while (this.pos < this.end && this.#isWhiteSpaceSingleLine(this.text.charCodeAt(this.pos))) this.pos++;
					return this.token = syntaxKind.WhitespaceTrivia;
				case characterCodes.hash: {
					const content = this.#scanHashCommentTrivia(skipTrivia$1);
					if (skipTrivia$1) continue;
					this.tokenValue = content;
					return this.token = syntaxKind.HashCommentTrivia;
				}
				case characterCodes.slash:
					if (this.pos + 1 < this.end) switch (this.text.charCodeAt(this.pos + 1)) {
						case characterCodes.slash: {
							const commentContent = this.#scanSingleLineCommentTrivia(skipTrivia$1);
							if (skipTrivia$1) continue;
							this.tokenValue = commentContent;
							return this.token = syntaxKind.SingleLineCommentTrivia;
						}
						case characterCodes.asterisk: {
							const commentContent = this.#scanMultiLineCommentTrivia(skipTrivia$1);
							if (skipTrivia$1) continue;
							this.tokenValue = commentContent;
							return this.token = syntaxKind.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.", scanError.ExpectationFailed);
					++this.pos;
					break;
				case characterCodes.openBrace:
					this.pos++;
					return this.token = syntaxKind.OpenBraceToken;
				case characterCodes.closeBrace:
					this.pos++;
					return this.token = syntaxKind.CloseBraceToken;
				case characterCodes.openBracket:
					this.pos++;
					return this.token = syntaxKind.OpenBracketToken;
				case characterCodes.closeBracket:
					this.pos++;
					return this.token = syntaxKind.CloseBracketToken;
				case characterCodes.plus:
					this.pos++;
					return this.token = syntaxKind.PlusToken;
				case characterCodes.equals:
					this.pos++;
					return this.token = syntaxKind.EqualsToken;
				case characterCodes._0:
				case characterCodes._1:
				case characterCodes._2:
				case characterCodes._3:
				case characterCodes._4:
				case characterCodes._5:
				case characterCodes._6:
				case characterCodes._7:
				case characterCodes._8:
				case characterCodes._9:
				case characterCodes.dot:
					this.tokenValue = this.#scanNumber();
					return this.token = syntaxKind.NumericIdentifier;
				case characterCodes.minus:
					switch (this.text.charCodeAt(this.pos + 1)) {
						case characterCodes.minus:
							this.pos += 2;
							return this.token = syntaxKind.UndirectedEdgeOp;
						case characterCodes.greaterThan:
							this.pos += 2;
							return this.token = syntaxKind.DirectedEdgeOp;
						case characterCodes._0:
						case characterCodes._1:
						case characterCodes._2:
						case characterCodes._3:
						case characterCodes._4:
						case characterCodes._5:
						case characterCodes._6:
						case characterCodes._7:
						case characterCodes._8:
						case characterCodes._9:
						case characterCodes.dot:
							this.tokenValue = this.#scanNumber();
							return this.token = syntaxKind.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 "--".`, scanError.ExpectationFailed);
							break;
						}
					}
					this.pos++;
					break;
				case characterCodes._:
					this.pos++;
					return this.token = syntaxKind.UnderscoreToken;
				case characterCodes.semicolon:
					this.pos++;
					return this.token = syntaxKind.SemicolonToken;
				case characterCodes.colon:
					this.pos++;
					return this.token = syntaxKind.ColonToken;
				case characterCodes.comma:
					this.pos++;
					return this.token = syntaxKind.CommaToken;
				case characterCodes.lessThan:
					this.tokenValue = this.#scanHtml();
					return this.token = syntaxKind.HtmlIdentifier;
				case characterCodes.doubleQuote:
					this.tokenValue = this.#scanString();
					return this.token = syntaxKind.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}".`, scanError.ExpectationFailed);
					this.pos++;
					break;
				}
			}
		}
	}
	#error(message, sub, category = diagnosticCategory.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 === characterCodes.space || ch === characterCodes.tab || ch === characterCodes.verticalTab || ch === characterCodes.formFeed || ch === characterCodes.nonBreakingSpace || ch === characterCodes.nextLine || ch === characterCodes.ogham || ch >= characterCodes.enQuad && ch <= characterCodes.zeroWidthSpace || ch === characterCodes.narrowNoBreakSpace || ch === characterCodes.mathematicalSpace || ch === characterCodes.ideographicSpace || ch === characterCodes.byteOrderMark;
	}
	#isAtMultiLineCommentEnd(pos) {
		return pos + 1 < this.end && this.text.charCodeAt(pos) === characterCodes.asterisk && this.text.charCodeAt(pos + 1) === characterCodes.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 |= tokenFlags.Unterminated;
				this.isUnterminated = true;
				this.#error("Unterminated html literal", scanError.Unterminated);
				break;
			}
			const ch = this.text.charCodeAt(this.pos);
			if (ch === characterCodes.lessThan) {
				++subTagsLevel;
				this.pos++;
				continue;
			}
			if (ch === characterCodes.greaterThan) {
				this.pos++;
				console.assert(subTagsLevel >= 0);
				if (subTagsLevel === 0) {
					result += this.text.substring(start, this.pos);
					break;
				}
				--subTagsLevel;
				continue;
			}
			this.pos++;
		}
		return result;
	}
	#scanString(allowEscapes = true) {
		const quote$1 = 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 |= tokenFlags.Unterminated;
				this.isUnterminated = true;
				this.#error("Unterminated string", scanError.Unterminated);
				break;
			}
			const ch = this.text.charCodeAt(this.pos);
			if (ch === characterCodes.backslash) hasBackslash = true;
			else if (hasBackslash) hasBackslash = false;
			else {
				if (ch === quote$1) {
					result += this.text.substring(start, this.pos);
					this.pos++;
					break;
				}
				if (isLineBreak(ch)) {
					result += this.text.substring(start, this.pos);
					this.tokenFlags |= tokenFlags.Unterminated;
					this.isUnterminated = true;
					this.#error("Unterminated string", scanError.Unterminated);
					break;
				}
			}
			this.pos++;
		}
		return result.replace(/\\"/g, "\"").replace(/\\(\r?\n)/g, "$1");
	}
	#scanNumber() {
		let result = "";
		let hadDot = false;
		let hadMinus = false;
		const start = this.pos;
		while (true) {
			switch (this.text.charCodeAt(this.pos)) {
				case characterCodes._0:
				case characterCodes._1:
				case characterCodes._2:
				case characterCodes._3:
				case characterCodes._4:
				case characterCodes._5:
				case characterCodes._6:
				case characterCodes._7:
				case characterCodes._8:
				case characterCodes._9: break;
				case characterCodes.dot:
					if (hadDot) {
						result += this.text.substring(start, this.pos);
						return result;
					}
					hadDot = true;
					hadMinus = true;
					break;
				case characterCodes.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 >= characterCodes.a && ch <= characterCodes.z || ch >= characterCodes.A && ch <= characterCodes.Z) {
				const lowerCaseToken = tokenValue.toLowerCase();
				const t = textToToken.get(lowerCaseToken);
				if (t !== void 0) {
					this.token = t;
					return t;
				}
			}
		}
		return this.token = syntaxKind.TextIdentifier;
	}
	lookAhead(callback) {
		return this.#speculationHelper(callback, true);
	}
	tryScan(callback) {
		return this.#speculationHelper(callback, 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 >= characterCodes.A && ch <= characterCodes.Z || ch >= characterCodes.a && ch <= characterCodes.z || ch >= characterCodes._0 && ch <= characterCodes._9 || ch === characterCodes._ || ch === characterCodes.lessThan || ch === characterCodes.doubleQuote;
}
function isIdentifierPart(ch) {
	return ch >= characterCodes.A && ch <= characterCodes.Z || ch >= characterCodes.a && ch <= characterCodes.z || ch >= characterCodes._0 && ch <= characterCodes._9 || ch === characterCodes.$ || ch === characterCodes._ || ch > characterCodes.maxAsciiCharacter;
}
function skipTrivia(text, pos) {
	while (true) {
		switch (text.charCodeAt(pos)) {
			case characterCodes.carriageReturn:
				if (text.charCodeAt(pos + 1) === characterCodes.lineFeed) ++pos;
				continue;
			case characterCodes.lineFeed:
			case characterCodes.tab:
			case characterCodes.verticalTab:
			case characterCodes.formFeed:
			case characterCodes.space:
				++pos;
				continue;
			case characterCodes.hash:
				++pos;
				while (pos < text.length) {
					if (isLineBreak(text.charCodeAt(pos))) break;
					++pos;
				}
				continue;
			case characterCodes.slash:
				if (pos + 1 < text.length) switch (text.charCodeAt(pos + 1)) {
					case characterCodes.slash:
						pos += 2;
						while (pos < text.length) {
							if (isLineBreak(text.charCodeAt(pos))) break;
							++pos;
						}
						continue;
					case characterCodes.asterisk:
						pos += 2;
						while (pos < text.length) {
							if (text.charCodeAt(pos) === characterCodes.asterisk && text.charCodeAt(pos + 1) === characterCodes.slash) {
								pos += 2;
								break;
							}
							++pos;
						}
						continue;
				}
				break;
		}
		return pos;
	}
}
function isLineBreak(ch) {
	return ch === characterCodes.lineFeed || ch === characterCodes.carriageReturn;
}

//#endregion
//#region src/parser.ts
const parsingContext = {
	None: 0,
	StatementList: 1,
	AttributeContainerList: 2,
	AssignmentList: 3,
	EdgeRhsList: 4,
	QuotedTextIdentifierConcatenation: 5,
	Count: 6
};
var Parser = class {
	currentToken = syntaxKind.Unknown;
	nodeCount;
	identifiers;
	identifierCount = 0;
	sourceText;
	scanner = new DefaultScanner();
	currentNodeHasError;
	currentContext;
	diagnostics;
	constructor() {
		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 = parsingContext.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() !== syntaxKind.EndOfFileToken) {
			graph = this.#parseGraph();
			if (this.#token() !== syntaxKind.EndOfFileToken) this.#parseErrorAtPosition(this.scanner.tokenPos, this.scanner.text.length - 1, "Content after the end of a graph declaration is invalid.", {
				source: errorSource.Parse,
				sub: parseError.TrailingData
			});
		}
		const result = {
			content: this.sourceText,
			graph,
			identifiers: this.identifiers,
			diagnostics: this.diagnostics
		};
		this.#resetState();
		return result;
	}
	#parseGraph() {
		const strictToken = this.#parseOptionalToken(syntaxKind.StrictKeyword);
		const keyword = this.#parseExpectedTokenOneOf(syntaxKind.DigraphKeyword, [syntaxKind.DigraphKeyword, syntaxKind.GraphKeyword]);
		const kind = keyword === void 0 || keyword.kind === syntaxKind.DigraphKeyword ? syntaxKind.DirectedGraph : syntaxKind.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(syntaxKind.OpenBraceToken);
		node.statements = this.#parseList(parsingContext.StatementList, () => this.#parseStatement());
		this.#parseExpectedToken(syntaxKind.CloseBraceToken);
		return this.#finishNode(node);
	}
	#parseIdentifier() {
		let result;
		const escapedIdTexts = [];
		switch (this.#token()) {
			case syntaxKind.TextIdentifier:
				result = this.#parseTextIdentifier();
				escapedIdTexts.push(result.text);
				break;
			case syntaxKind.StringLiteral:
				result = this.#parseQuotedTextIdentifierConcatenation();
				escapedIdTexts.push(...result.values.map((v) => v.text));
				break;
			case syntaxKind.HtmlIdentifier:
				result = this.#parseHtmlIdentifier();
				escapedIdTexts.push(result.htmlContent);
				break;
			case syntaxKind.NumericIdentifier:
				result = this.#parseNumericIdentifier();
				escapedIdTexts.push(result.text);
				break;
			default:
				this.#reportExpectedError([syntaxKind.TextIdentifier]);
				result = this.#createMissingNode(syntaxKind.TextIdentifier);
				break;
		}
		for (const i of escapedIdTexts) this.#registerIdentifier(i);
		return result;
	}
	#registerIdentifier(id) {
		this.identifierCount++;
		if (!this.identifiers.has(id)) this.identifiers.add(id);
	}
	#parseTextIdentifier() {
		const node = this.#createNode(syntaxKind.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(syntaxKind.QuotedTextIdentifier);
		node.values = this.#parseList(parsingContext.QuotedTextIdentifierConcatenation, () => this.#parseQuotedTextIdentifier(), true);
		return this.#finishNode(node);
	}
	#parseQuotedTextIdentifier() {
		const node = this.#createNode(syntaxKind.StringLiteral);
		if (this.#token() === syntaxKind.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() === syntaxKind.StringLiteral;
	}
	#parseHtmlIdentifier() {
		const node = this.#createNode(syntaxKind.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(syntaxKind.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 syntaxKind.GraphKeyword:
			case syntaxKind.NodeKeyword:
			case syntaxKind.EdgeKeyword: return this.#parseAttributeStatement();
			case syntaxKind.OpenBraceToken:
			case syntaxKind.SubgraphKeyword: {
				const subgraph = this.#parseSubGraph();
				if (this.#token() === syntaxKind.SemicolonToken) {
					const subgraphStatement$1 = this.#createNode(syntaxKind.SubGraphStatement, subgraph.pos);
					subgraphStatement$1.subgraph = subgraph;
					subgraphStatement$1.terminator = this.#parseExpectedToken(syntaxKind.SemicolonToken);
					return this.#finishNode(subgraphStatement$1);
				}
				if (this.#isEdgeOp()) return this.#parseEdgeStatement(subgraph);
				const subgraphStatement = this.#createNode(syntaxKind.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 syntaxKind.GraphKeyword:
			case syntaxKind.NodeKeyword:
			case syntaxKind.EdgeKeyword: {
				const node = this.#createNode(syntaxKind.AttributeStatement);
				node.subject = this.#parseTokenNode();
				if (this.#token() === syntaxKind.OpenBracketToken) node.attributes = this.#parseList(parsingContext.AttributeContainerList, () => this.#parseAttributeContainer());
				else {
					this.#reportExpectedError([syntaxKind.OpenBracketToken]);
					const missingStatement = this.#createMissingNode(syntaxKind.AttributeStatement);
					missingStatement.attributes = this.#createNodeArray([this.#createMissingNode(syntaxKind.AttributeContainer)], this.scanner.tokenPos, this.scanner.tokenPos);
				}
				node.terminator = this.#parseOptionalToken(syntaxKind.SemicolonToken);
				return this.#finishNode(node);
			}
			default: throw "This should never happen";
		}
	}
	#parseAttributeContainer() {
		if (this.#token() !== syntaxKind.OpenBracketToken) debugger;
		const node = this.#createNode(syntaxKind.AttributeContainer);
		node.openBracket = this.#parseExpectedToken(syntaxKind.OpenBracketToken);
		if (this.#isIdentifier() && this.#lookAhead(() => this.#isAssignmentStart())) node.assignments = this.#parseList(parsingContext.AssignmentList, () => this.#parseAssignment());
		else node.assignments = this.#createEmptyArray();
		node.closeBracket = this.#parseExpectedToken(syntaxKind.CloseBracketToken);
		return this.#finishNode(node);
	}
	#isAssignmentStart() {
		if (!this.#isIdentifier) debugger;
		this.#nextToken();
		return this.#token() === syntaxKind.EqualsToken;
	}
	#parseIdEqualsIdStatement() {
		if (!this.#isIdentifier) debugger;
		const leftIdentifier = this.#parseIdentifier();
		const node = this.#createNode(syntaxKind.IdEqualsIdStatement, leftIdentifier.pos);
		node.leftId = leftIdentifier;
		if (this.#token() !== syntaxKind.EqualsToken) debugger;
		this.#parseExpectedToken(syntaxKind.EqualsToken);
		node.rightId = this.#parseIdentifier();
		node.terminator = this.#parseOptionalToken(syntaxKind.SemicolonToken);
		return this.#finishNode(node);
	}
	#isIdEqualsIdStatement() {
		if (!this.#isIdentifier) debugger;
		this.#nextToken();
		return this.#token() === syntaxKind.EqualsToken;
	}
	#parseNodeStatement() {
		if (!this.#isIdentifier) debugger;
		const node = this.#createNode(syntaxKind.NodeStatement);
		node.id = this.#parseNodeId();
		if (this.#token() === syntaxKind.OpenBracketToken) node.attributes = this.#parseList(parsingContext.AttributeContainerList, () => this.#parseAttributeContainer());
		else node.attributes = this.#createEmptyArray();
		node.terminator = this.#parseOptionalToken(syntaxKind.SemicolonToken);
		return this.#finishNode(node);
	}
	#parseEdgeStatement(precedingItem) {
		console.assert(precedingItem.kind === syntaxKind.SubGraph || precedingItem.kind === syntaxKind.NodeId);
		console.assert(precedingItem.pos !== void 0);
		if (!this.#isEdgeOp()) debugger;
		const node = this.#createNode(syntaxKind.EdgeStatement, precedingItem.pos);
		node.source = precedingItem;
		node.rhs = this.#parseList(parsingContext.EdgeRhsList, () => this.#parseEdgeRhs());
		if (this.#token() === syntaxKind.OpenBracketToken) node.attributes = this.#parseList(parsingContext.AttributeContainerList, () => this.#parseAttributeContainer());
		else node.attributes = this.#createEmptyArray();
		node.terminator = this.#parseOptionalToken(syntaxKind.SemicolonToken);
		return this.#finishNode(node);
	}
	#parseEdgeRhs() {
		const node = this.#createNode(syntaxKind.EdgeRhs);
		node.operation = this.#parseExpectedTokenOneOf(syntaxKind.DirectedEdgeOp, [syntaxKind.DirectedEdgeOp, syntaxKind.UndirectedEdgeOp]);
		switch (this.#token()) {
			case syntaxKind.SubgraphKeyword:
			case syntaxKind.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 syntaxKind.QuotedTextIdentifier: {
				const literal = this.#createNode(syntaxKind.StringLiteral);
				literal.text = "";
				result.values = this.#createNodeArray([literal], result.pos, result.pos);
				break;
			}
			case syntaxKind.HtmlIdentifier:
				result.htmlContent = "";
				break;
			case syntaxKind.TextIdentifier:
			case syntaxKind.NumericIdentifier:
				result.text = "";
				break;
		}
		return this.#finishNode(result);
	}
	#parseAssignment() {
		if (!this.#isIdentifier) debugger;
		const node = this.#createNode(syntaxKind.Assignment);
		node.leftId = this.#parseIdentifier();
		this.#parseExpectedToken(syntaxKind.EqualsToken);
		node.rightId = this.#parseIdentifier();
		let terminator = this.#parseOptionalToken(syntaxKind.CommaToken);
		if (terminator === void 0) terminator = this.#parseOptionalToken(syntaxKind.SemicolonToken);
		node.terminator = terminator;
		return this.#finishNode(node);
	}
	#parseSubGraph() {
		console.assert(this.#token() === syntaxKind.SubgraphKeyword || this.#token() === syntaxKind.OpenBraceToken);
		const subGraph = this.#parseOptionalToken(syntaxKind.SubgraphKeyword);
		const subGraphStart = subGraph !== void 0 ? subGraph.pos : void 0;
		const node = this.#createNode(syntaxKind.SubGraph, subGraphStart);
		node.id = subGraph !== void 0 && this.#isIdentifier() ? this.#parseIdentifier() : void 0;
		this.#parseExpectedToken(syntaxKind.OpenBraceToken);
		node.statements = this.#parseList(parsingContext.StatementList, () => this.#parseStatement());
		this.#parseExpectedToken(syntaxKind.CloseBraceToken);
		return this.#finishNode(node);
	}
	#parseNodeId() {
		if (!this.#isIdentifier) debugger;
		const node = this.#createNode(syntaxKind.NodeId);
		node.id = this.#parseIdentifier();
		node.port = this.#token() === syntaxKind.ColonToken ? this.#parsePortDeclaration() : void 0;
		return this.#finishNode(node);
	}
	#parseCompassPortDeclaration() {
		console.assert(this.#token() === syntaxKind.ColonToken);
		const node = this.#createNode(syntaxKind.CompassPortDeclaration);
		node.colon = this.#parseTokenNode();
		node.compassPt = this.#parseTokenNode();
		return this.#finishNode(node);
	}
	#parseNormalPortDeclaration() {
		console.assert(this.#token() === syntaxKind.ColonToken);
		const node = this.#createNode(syntaxKind.NormalPortDeclaration);
		node.colon = this.#parseTokenNode();
		node.id = this.#parseIdentifier();
		node.compassPt = this.#token() === syntaxKind.ColonToken ? this.#parseCompassPortDeclaration() : void 0;
		return this.#finishNode(node);
	}
	#parsePortDeclaration() {
		console.assert(this.#token() === syntaxKind.ColonToken);
		if (this.#lookAhead(() => this.#isCompassPort())) return this.#parseCompassPortDeclaration();
		return this.#parseNormalPortDeclaration();
	}
	#isCompassPort() {
		console.assert(this.#token() === syntaxKind.ColonToken);
		if (this.#token() !== syntaxKind.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 parsingContext.StatementList: return "Assignment, node definition, graph/node/edge attribute or edge definition expected.";
			case parsingContext.AssignmentList: return "Assignment expected.";
			case parsingContext.EdgeRhsList: return "Edge operation expected.";
			case parsingContext.QuotedTextIdentifierConcatenation: return "Quoted identifier expected";
			case parsingContext.AttributeContainerList: return "Attribute marker expected.";
			case parsingContext.None: return "Wat, no parsing context";
			case parsingContext.Count: return "Wat, 'Count' parsing context";
			default: return assertNever(context);
		}
	}
	#isInSomeParsingContext() {
		for (let ctx = 0; ctx < parsingContext.Count; ctx++) if (this.currentContext & 1 << ctx) {
			if (this.#isListElement(ctx, true) || this.#isListTerminator(ctx)) return true;
		}
		return false;
	}
	#abortListParsing(context) {
		this.#parseErrorAtCurrentToken(this.#getContextParseError(context), parseError.FailedListParsing);
		if (this.#isInSomeParsingContext()) return true;
		this.#nextToken();
		return false;
	}
	#isListElement(context, _inErrorRecovery) {
		switch (context) {
			case parsingContext.AssignmentList: return this.#isIdentifier();
			case parsingContext.AttributeContainerList: return this.#token() === syntaxKind.OpenBracketToken;
			case parsingContext.EdgeRhsList: return this.#token() === syntaxKind.DirectedEdgeOp || this.#token() === syntaxKind.UndirectedEdgeOp;
			case parsingContext.QuotedTextIdentifierConcatenation: return this.#token() === syntaxKind.StringLiteral || this.#token() === syntaxKind.PlusToken;
			case parsingContext.StatementList: return this.#isIdentifier() || this.#token() === syntaxKind.SubgraphKeyword || this.#token() === syntaxKind.OpenBraceToken || this.#token() === syntaxKind.GraphKeyword || this.#token() === syntaxKind.EdgeKeyword || this.#token() === syntaxKind.NodeKeyword;
			default: throw "This should never happen";
		}
	}
	#isListTerminator(context) {
		const token = this.#token();
		if (token === syntaxKind.EndOfFileToken) return true;
		switch (context) {
			case parsingContext.StatementList: return token === syntaxKind.CloseBraceToken;
			case parsingContext.AttributeContainerList: return token !== syntaxKind.OpenBracketToken;
			case parsingContext.AssignmentList: return token === syntaxKind.CloseBracketToken;
			case parsingContext.EdgeRhsList: return token !== syntaxKind.DirectedEdgeOp && token !== syntaxKind.UndirectedEdgeOp;
			case parsingContext.QuotedTextIdentifierConcatenation: return token !== syntaxKind.PlusToken;
			default: throw "Unsupported parsing context";
		}
	}
	#createEmptyArray() {
		const startPos = this.scanner.startPos;
		return this.#createNodeArray([], startPos);
	}
	#finishNode(node, end) {
		node.end = end === void 0 ? this.scanner.startPos : end;
		if (this.currentNodeHasError) {
			this.currentNodeHasError = false;
			node.flags |= syntaxNodeFlags.ContainsErrors;
		}
		return node;
	}
	#createNode(kind, pos) {
		this.nodeCount++;
		const p = pos !== void 0 && pos >= 0 ? pos : this.scanner.startPos;
		if (isNodeKind(kind) || kind === syntaxKind.Unknown) return newNode(kind, p, p);
		return isIdentifier(kind) ? newIdentifier(kind, p, p) : newToken(kind, p, p);
	}
	#createNodeArray(elements, pos, end) {
		const length = elements.length;
		const array = length >= 1 && length <= 4 ? elements.slice() : elements;
		array.pos = pos;
		array.end = end === void 0 ? this.scanner.startPos : end;
		return array;
	}
	#parseTokenNode() {
		const node = this.#createNode(this.#token());
		this.#nextToken();
		return this.#finishNode(node);
	}
	#getLastError(diagnostics) {
		return diagnostics && diagnostics.length > 0 ? diagnostics[diagnostics.length - 1] : void 0;
	}
	#parseErrorAtPosition(start, end, message, code) {
		const ds = this.diagnostics;
		const lastError = this.#getLastError(ds);
		if (!lastError || start !== lastError.start) ds.push({
			category: diagnosticCategory.Error,
			start,
			end,
			message,
			code
		});
		this.currentNodeHasError = true;
	}
	#parseErrorAtCurrentToken(message, sub) {
		const error = {
			source: errorSource.Parse,
			sub
		};
		return this.#parseErrorAtPosition(this.scanner.tokenPos, this.scanner.pos, message, error);
	}
	#scanError(message, _category, sub, length) {
		const errorPos = this.scanner.pos;
		const err = {
			source: errorSource.Scan,
			sub
		};
		this.#parseErrorAtPosition(errorPos, errorPos + length, message, err);
	}
	#reportExpectedError(expectedKinds) {
		const found = this.#isIdentifier() ? "identifier" : this.#token() === syntaxKind.EndOfFileToken ? "end of file" : `"${getTokenAsText(this.#token())}"`;
		const expected = expectedKinds.map((k) => {
			if (isIdentifier(k)) return "identifier";
			if (k === syntaxKind.EndOfFileToken) return "end of file";
			return `"${getTokenAsText(k)}"`;
		});
		const lastExpected = expected.pop();
		const expectedJoined = expected.join(", ");
		const msg = expected.length > 0 ? `Expected ${expectedJoined} or ${lastExpected} but found ${found} instead.` : `Expected ${lastExpected} but found ${found} instead.`;
		this.#parseErrorAtCurrentToken(msg, parseError.ExpectationFailed);
	}
	#parseExpectedOneOf(...kinds) {
		if (kinds.length < 2) {
			console.assert(false);
			debugger;
		}
		for (const kind of kinds) if (this.#token() === kind) {
			this.#nextToken();
			return true;
		}
		this.#reportExpectedError(kinds);
		return false;
	}
	#parseExpectedTokenOneOf(fallback, kinds) {
		if (kinds.length < 2) {
			console.assert(false);
			debugger;
		}
		for (const kind of kinds) if (this.#token() === kind) {
			const node = this.#createNode(this.#token());
			this.#nextToken();
			return this.#finishNode(node);
		}
		this.#reportExpectedError(kinds);
		return this.#createMissingNode(fallback);
	}
	#parseExpectedToken(kind) {
		const tokenNode = this.#parseOptionalToken(kind);
		if (tokenNode !== void 0) return tokenNode;
		this.#reportExpectedError([kind]);
		return this.#createMissingNode(kind);
	}
	#parseExpected(kind) {
		const res = this.#parseOptional(kind);
		if (!res) this.#reportExpectedError([kind]);
		return res;
	}
	#parseOptionalToken(t) {
		if (this.#token() === t) return this.#parseTokenNode();
	}
	#parseOptional(t) {
		if (this.#token() === t) {
			this.#nextToken();
			return true;
		}
		return false;
	}
	#isEdgeOp() {
		switch (this.#token()) {
			case syntaxKind.DirectedEdgeOp:
			case syntaxKind.UndirectedEdgeOp: return true;
			default: return false;
		}
	}
	#isIdentifier() {
		switch (this.#token()) {
			case syntaxKind.TextIdentifier:
			case syntaxKind.NumericIdentifier:
			case syntaxKind.StringLiteral:
			case syntaxKind.HtmlIdentifier: return true;
			default: return false;
		}
	}
	#isCompassPortKind(kind) {
		return kind >= syntaxKind.CompassCenterToken && kind <= syntaxKind.CompassEnd;
	}
	#speculationHelper(callback, isLookAhead) {
		const saveToken = this.#token();
		const saveDiagnosticsLength = this.diagnostics.length;
		const result = isLookAhead ? this.scanner.lookAhead(callback) : this.scanner.tryScan(callback);
		if (!result || isLookAhead) {
			this.currentToken = saveToken;
			this.diagnostics.length = saveDiagnosticsLength;
		}
		return result;
	}
	/** Invokes the provided callback then unconditionally restores the parser to the state it
	* was in immediately prior to invoking the callback. The result of invoking the callback
	* is returned from this function.
	*/
	#lookAhead(callback) {
		return this.#speculationHelper(callback, true);
	}
	/** Invokes the provided callback. If the callback returns something falsy, then it restores
	* the parser to the state it was in immediately prior to invoking the callback. If the
	* callback returns something truthy, then the parser state is not rolled back. The result
	* of invoking the callback is returned from this function.
	*/
	#tryParse(callback) {
		return this.#speculationHelper(callback, false);
	}
};
function newNode(kind, pos, end) {
	return {
		kind,
		flags: syntaxNodeFlags.None,
		end,
		pos,
		parent: void 0
	};
}
const newIdentifier = newNode;
const newToken = newNode;
function isNodeKind(kind) {
	return kind >= syntaxKind.FirstNode;
}
function isIdentifier(kind) {
	return kind === syntaxKind.HtmlIdentifier || kind === syntaxKind.NumericIdentifier || kind === syntaxKind.TextIdentifier || kind === syntaxKind.QuotedTextIdentifier;
}
function isIdentifierNode(node) {
	return isIdentifier(node.kind);
}

//#endregion
//#region src/service/languageFacts.ts
const shapes = Object.freeze([
	"box",
	"polygon",
	"ellipse",
	"oval",
	"circle",
	"point",
	"egg",
	"triangle",
	"plaintext",
	"plain",
	"diamond",
	"trapezium",
	"parallelogram",
	"house",
	"pentagon",
	"hexagon",
	"septagon",
	"octagon",
	"doublecircle",
	"doubleoctagon",
	"tripleoctagon",
	"invtriangle",
	"invtrapezium",
	"invhouse",
	"Mdiamond",
	"Msquare",
	"Mcircle",
	"record",
	"rect",
	"rectangle",
	"square",
	"star",
	"none",
	"underline",
	"cylinder",
	"note",
	"tab",
	"folder",
	"box3d",
	"component",
	"promoter",
	"cds",
	"terminator",
	"utr",
	"primersite",
	"restrictionsite",
	"fivepoverhang",
	"threepoverhang",
	"noverhang",
	"assembly",
	"signature",
	"insulator",
	"ribosite",
	"rnastab",
	"proteasesite",
	"proteinstab",
	"rpromoter",
	"rarrow",
	"larrow",
	"lpromoter"
]);
const edgeAttributes = Object.freeze([
	"URL",
	"arrowhead",
	"arrowsize",
	"arrowtail",
	"color",
	"colorscheme",
	"comment",
	"constraint",
	"decorate",
	"dir",
	"edgeURL",
	"edgehref",
	"edgetarget",
	"edgetooltip",
	"fillcolor",
	"fontcolor",
	"fontname",
	"fontsize",
	"headURL",
	"head_lp",
	"headclip",
	"headhref",
	"headlabel",
	"headport",
	"headtarget",
	"headtooltip",
	"href",
	"id",
	"label",
	"labelURL",
	"labelangle",
	"labeldistance",
	"labelfloat",
	"labelfontcolor",
	"labelfontname",
	"labelfontsize",
	"labelhref",
	"labeltarget",
	"labeltooltip",
	"layer",
	"len",
	"lhead",
	"lp",
	"ltail",
	"minlen",
	"nojustify",
	"penwidth",
	"pos",
	"samehead",
	"sametail",
	"showboxes",
	"style",
	"tailURL",
	"tail_lp",
	"tailclip",
	"tailhref",
	"taillabel",
	"tailport",
	"tailtarget",
	"tailtooltip",
	"target",
	"tooltip",
	"weight",
	"xlabel",
	"xlp"
]);
const nodeAttributes = Object.freeze([
	"URL",
	"area",
	"color",
	"colorscheme",
	"comment",
	"distortion",
	"fillcolor",
	"fixedsize",
	"fontcolor",
	"fontname",
	"fontsize",
	"gradientangle",
	"group",
	"height",
	"href",
	"id",
	"image",
	"imagepos",
	"imagescale",
	"label",
	"labelloc",
	"layer",
	"margin",
	"nojustify",
	"ordering",
	"orientation",
	"penwidth",
	"peripheries",
	"pin",
	"pos",
	"rects",
	"regular",
	"root",
	"samplepoints",
	"shape",
	"shapefile",
	"showboxes",
	"sides",
	"skew",
	"sortv",
	"style",
	"target",
	"tooltip",
	"vertices",
	"width",
	"xlabel",
	"xlp",
	"z"
]);
const graphAttributes = Object.freeze([
	"Damping",
	"K",
	"URL",
	"_background",
	"bb",
	"bgcolor",
	"center",
	"charset",
	"clusterrank",
	"colorscheme",
	"comment",
	"compound",
	"concentrate",
	"defaultdist",
	"dim",
	"dimen",
	"diredgeconstraints",
	"dpi",
	"epsilon",
	"esep",
	"fontcolor",
	"fontname",
	"fontnames",
	"fontpath",
	"fontsize",
	"forcelabels",
	"gradientangle",
	"href",
	"id",
	"imagepath",
	"inputscale",
	"label",
	"label_scheme",
	"labeljust",
	"labelloc",
	"landscape",
	"layerlistsep",
	"layers",
	"layerselect",
	"layersep",
	"layout",
	"levels",
	"levelsgap",
	"lheight",
	"lp",
	"lwidth",
	"margin",
	"maxiter",
	"mclimit",
	"mindist",
	"mode",
	"model",
	"mosek",
	"newrank",
	"nodesep",
	"nojustify",
	"normalize",
	"notranslate",
	"nslimit",
	"nslimit1",
	"ordering",
	"orientation",
	"outputorder",
	"overlap",
	"overlap_scaling",
	"overlap_shrink",
	"pack",
	"packmode",
	"pad",
	"page",
	"pagedir",
	"quadtree",
	"quantum",
	"rankdir",
	"ranksep",
	"ratio",
	"remincross",
	"repulsiveforce",
	"resolution",
	"root",
	"rotate",
	"rotation",
	"scale",
	"searchsize",
	"sep",
	"showboxes",
	"size",
	"smoothing",
	"sortv",
	"splines",
	"start",
	"style",
	"stylesheet",
	"target",
	"truecolor",
	"viewport",
	"voro_margin",
	"xdotversion"
]);
const clusterAttributes = Object.freeze([
	"K",
	"URL",
	"area",
	"bgcolor",
	"color",
	"colorscheme",
	"fillcolor",
	"fontcolor",
	"fontname",
	"fontsize",
	"gradientangle",
	"href",
	"id",
	"label",
	"labeljust",
	"labelloc",
	"layer",
	"lheight",
	"lp",
	"lwidth",
	"margin",
	"nojustify",
	"pencolor",
	"penwidth",
	"peripheries",
	"sortv",
	"style",
	"target",
	"tooltip"
]);
const attributes = Array.from(new Set([
	...nodeAttributes,
	...edgeAttributes,
	...graphAttributes,
	...clusterAttributes
])).sort();
/**
* We only support the X11 color scheme
*/
const colors = Object.freeze({
	aliceblue: "#f0f8ff",
	antiquewhite: "#faebd7",
	antiquewhite1: "#ffefdb",
	antiquewhite2: "#eedfcc",
	antiquewhite3: "#cdc0b0",
	antiquewhite4: "#8b8378",
	aqua: "#00ffff",
	aquamarine: "#7fffd4",
	aquamarine1: "#7fffd4",
	aquamarine2: "#76eec6",
	aquamarine3: "#66cdaa",
	aquamarine4: "#458b74",
	azure: "#f0ffff",
	azure1: "#f0ffff",
	azure2: "#e0eeee",
	azure3: "#c1cdcd",
	azure4: "#838b8b",
	beige: "#f5f5dc",
	bisque: "#ffe4c4",
	bisque1: "#ffe4c4",
	bisque2: "#eed5b7",
	bisque3: "#cdb79e",
	bisque4: "#8b7d6b",
	black: "#000000",
	blanchedalmond: "#ffebcd",
	blue: "#0000ff",
	blue1: "#0000ff",
	blue2: "#0000ee",
	blue3: "#0000cd",
	blue4: "#00008b",
	blueviolet: "#8a2be2",
	brown: "#a52a2a",
	brown1: "#ff4040",
	brown2: "#ee3b3b",
	brown3: "#cd3333",
	brown4: "#8b2323",
	burlywood: "#deb887",
	burlywood1: "#ffd39b",
	burlywood2: "#eec591",
	burlywood3: "#cdaa7d",
	burlywood4: "#8b7355",
	cadetblue: "#5f9ea0",
	cadetblue1: "#98f5ff",
	cadetblue2: "#8ee5ee",
	cadetblue3: "#7ac5cd",
	cadetblue4: "#53868b",
	chartreuse: "#7fff00",
	chartreuse1: "#7fff00",
	chartreuse2: "#76ee00",
	chartreuse3: "#66cd00",
	chartreuse4: "#458b00",
	chocolate: "#d2691e",
	chocolate1: "#ff7f24",
	chocolate2: "#ee7621",
	chocolate3: "#cd661d",
	chocolate4: "#8b4513",
	coral: "#ff7f50",
	coral1: "#ff7256",
	coral2: "#ee6a50",
	coral3: "#cd5b45",
	coral4: "#8b3e2f",
	cornflowerblue: "#6495ed",
	cornsilk: "#fff8dc",
	cornsilk1: "#fff8dc",
	cornsilk2: "#eee8cd",
	cornsilk3: "#cdc8b1",
	cornsilk4: "#8b8878",
	crimson: "#dc143c",
	cyan: "#00ffff",
	cyan1: "#00ffff",
	cyan2: "#00eeee",
	cyan3: "#00cdcd",
	cyan4: "#008b8b",
	darkblue: "#00008b",
	darkcyan: "#008b8b",
	darkgoldenrod: "#b8860b",
	darkgoldenrod1: "#ffb90f",
	darkgoldenrod2: "#eead0e",
	darkgoldenrod3: "#cd950c",
	darkgoldenrod4: "#8b6508",
	darkgray: "#a9a9a9",
	darkgreen: "#006400",
	darkgrey: "#a9a9a9",
	darkkhaki: "#bdb76b",
	darkmagenta: "#8b008b",
	darkolivegreen: "#556b2f",
	darkolivegreen1: "#caff70",
	darkolivegreen2: "#bcee68",
	darkolivegreen3: "#a2cd5a",
	darkolivegreen4: "#6e8b3d",
	darkorange: "#ff8c00",
	darkorange1: "#ff7f00",
	darkorange2: "#ee7600",
	darkorange3: "#cd6600",
	darkorange4: "#8b4500",
	darkorchid: "#9932cc",
	darkorchid1: "#bf3eff",
	darkorchid2: "#b23aee",
	darkorchid3: "#9a32cd",
	darkorchid4: "#68228b",
	darkred: "#8b0000",
	darksalmon: "#e9967a",
	darkseagreen: "#8fbc8f",
	darkseagreen1: "#c1ffc1",
	darkseagreen2: "#b4eeb4",
	darkseagreen3: "#9bcd9b",
	darkseagreen4: "#698b69",
	darkslateblue: "#483d8b",
	darkslategray: "#2f4f4f",
	darkslategray1: "#97ffff",
	darkslategray2: "#8deeee",
	darkslategray3: "#79cdcd",
	darkslategray4: "#528b8b",
	darkslategrey: "#2f4f4f",
	darkturquoise: "#00ced1",
	darkviolet: "#9400d3",
	deeppink: "#ff1493",
	deeppink1: "#ff1493",
	deeppink2: "#ee1289",
	deeppink3: "#cd1076",
	deeppink4: "#8b0a50",
	deepskyblue: "#00bfff",
	deepskyblue1: "#00bfff",
	deepskyblue2: "#00b2ee",
	deepskyblue3: "#009acd",
	deepskyblue4: "#00688b",
	dimgray: "#696969",
	dimgrey: "#696969",
	dodgerblue: "#1e90ff",
	dodgerblue1: "#1e90ff",
	dodgerblue2: "#1c86ee",
	dodgerblue3: "#1874cd",
	dodgerblue4: "#104e8b",
	firebrick: "#b22222",
	firebrick1: "#ff3030",
	firebrick2: "#ee2c2c",
	firebrick3: "#cd2626",
	firebrick4: "#8b1a1a",
	floralwhite: "#fffaf0",
	forestgreen: "#228b22",
	fuchsia: "#ff00ff",
	gainsboro: "#dcdcdc",
	ghostwhite: "#f8f8ff",
	gold: "#ffd700",
	gold1: "#ffd700",
	gold2: "#eec900",
	gold3: "#cdad00",
	gold4: "#8b7500",
	goldenrod: "#daa520",
	goldenrod1: "#ffc125",
	goldenrod2: "#eeb422",
	goldenrod3: "#cd9b1d",
	goldenrod4: "#8b6914",
	gray: "#c0c0c0",
	gray0: "#000000",
	gray1: "#030303",
	gray10: "#1a1a1a",
	gray100: "#ffffff",
	gray11: "#1c1c1c",
	gray12: "#1f1f1f",
	gray13: "#212121",
	gray14: "#242424",
	gray15: "#262626",
	gray16: "#292929",
	gray17: "#2b2b2b",
	gray18: "#2e2e2e",
	gray19: "#303030",
	gray2: "#050505",
	gray20: "#333333",
	gray21: "#363636",
	gray22: "#383838",
	gray23: "#3b3b3b",
	gray24: "#3d3d3d",
	gray25: "#404040",
	gray26: "#424242",
	gray27: "#454545",
	gray28: "#474747",
	gray29: "#4a4a4a",
	gray3: "#080808",
	gray30: "#4d4d4d",
	gray31: "#4f4f4f",
	gray32: "#525252",
	gray33: "#545454",
	gray34: "#575757",
	gray35: "#595959",
	gray36: "#5c5c5c",
	gray37: "#5e5e5e",
	gray38: "#616161",
	gray39: "#636363",
	gray4: "#0a0a0a",
	gray40: "#666666",
	gray41: "#696969",
	gray42: "#6b6b6b",
	gray43: "#6e6e6e",
	gray44: "#707070",
	gray45: "#737373",
	gray46: "#757575",
	gray47: "#787878",
	gray48: "#7a7a7a",
	gray49: "#7d7d7d",
	gray5: "#0d0d0d",
	gray50: "#7f7f7f",
	gray51: "#828282",
	gray52: "#858585",
	gray53: "#878787",
	gray54: "#8a8a8a",
	gray55: "#8c8c8c",
	gray56: "#8f8f8f",
	gray57: "#919191",
	gray58: "#949494",
	gray59: "#969696",
	gray6: "#0f0f0f",
	gray60: "#999999",
	gray61: "#9c9c9c",
	gray62: "#9e9e9e",
	gray63: "#a1a1a1",
	gray64: "#a3a3a3",
	gray65: "#a6a6a6",
	gray66: "#a8a8a8",
	gray67: "#ababab",
	gray68: "#adadad",
	gray69: "#b0b0b0",
	gray7: "#121212",
	gray70: "#b3b3b3",
	gray71: "#b5b5b5",
	gray72: "#b8b8b8",
	gray73: "#bababa",
	gray74: "#bdbdbd",
	gray75: "#bfbfbf",
	gray76: "#c2c2c2",
	gray77: "#c4c4c4",
	gray78: "#c7c7c7",
	gray79: "#c9c9c9",
	gray8: "#141414",
	gray80: "#cccccc",
	gray81: "#cfcfcf",
	gray82: "#d1d1d1",
	gray83: "#d4d4d4",
	gray84: "#d6d6d6",
	gray85: "#d9d9d9",
	gray86: "#dbdbdb",
	gray87: "#dedede",
	gray88: "#e0e0e0",
	gray89: "#e3e3e3",
	gray9: "#171717",
	gray90: "#e5e5e5",
	gray91: "#e8e8e8",
	gray92: "#ebebeb",
	gray93: "#ededed",
	gray94: "#f0f0f0",
	gray95: "#f2f2f2",
	gray96: "#f5f5f5",
	gray97: "#f7f7f7",
	gray98: "#fafafa",
	gray99: "#fcfcfc",
	green: "#00ff00",
	green1: "#00ff00",
	green2: "#00ee00",
	green3: "#00cd00",
	green4: "#008b00",
	greenyellow: "#adff2f",
	grey: "#c0c0c0",
	grey0: "#000000",
	grey1: "#030303",
	grey10: "#1a1a1a",
	grey100: "#ffffff",
	grey11: "#1c1c1c",
	grey12: "#1f1f1f",
	grey13: "#212121",
	grey14: "#242424",
	grey15: "#262626",
	grey16: "#292929",
	grey17: "#2b2b2b",
	grey18: "#2e2e2e",
	grey19: "#303030",
	grey2: "#050505",
	grey20: "#333333",
	grey21: "#363636",
	grey22: "#383838",
	grey23: "#3b3b3b",
	grey24: "#3d3d3d",
	grey25: "#404040",
	grey26: "#424242",
	grey27: "#454545",
	grey28: "#474747",
	grey29: "#4a4a4a",
	grey3: "#080808",
	grey30: "#4d4d4d",
	grey31: "#4f4f4f",
	grey32: "#525252",
	grey33: "#545454",
	grey34: "#575757",
	grey35: "#595959",
	grey36: "#5c5c5c",
	grey37: "#5e5e5e",
	grey38: "#616161",
	grey39: "#636363",
	grey4: "#0a0a0a",
	grey40: "#666666",
	grey41: "#696969",
	grey42: "#6b6b6b",
	grey43: "#6e6e6e",
	grey44: "#707070",
	grey45: "#737373",
	grey46: "#757575",
	grey47: "#787878",
	grey48: "#7a7a7a",
	grey49: "#7d7d7d",
	grey5: "#0d0d0d",
	grey50: "#7f7f7f",
	grey51: "#828282",
	grey52: "#858585",
	grey53: "#878787",
	grey54: "#8a8a8a",
	grey55: "#8c8c8c",
	grey56: "#8f8f8f",
	grey57: "#919191",
	grey58: "#949494",
	grey59: "#969696",
	grey6: "#0f0f0f",
	grey60: "#999999",
	grey61: "#9c9c9c",
	grey62: "#9e9e9e",
	grey63: "#a1a1a1",
	grey64: "#a3a3a3",
	grey65: "#a6a6a6",
	grey66: "#a8a8a8",
	grey67: "#ababab",
	grey68: "#adadad",
	grey69: "#b0b0b0",
	grey7: "#121212",
	grey70: "#b3b3b3",
	grey71: "#b5b5b5",
	grey72: "#b8b8b8",
	grey73: "#bababa",
	grey74: "#bdbdbd",
	grey75: "#bfbfbf",
	grey76: "#c2c2c2",
	grey77: "#c4c4c4",
	grey78: "#c7c7c7",
	grey79: "#c9c9c9",
	grey8: "#141414",
	grey80: "#cccccc",
	grey81: "#cfcfcf",
	grey82: "#d1d1d1",
	grey83: "#d4d4d4",
	grey84: "#d6d6d6",
	grey85: "#d9d9d9",
	grey86: "#dbdbdb",
	grey87: "#dedede",
	grey88: "#e0e0e0",
	grey89: "#e3e3e3",
	grey9: "#171717",
	grey90: "#e5e5e5",
	grey91: "#e8e8e8",
	grey92: "#ebebeb",
	grey93: "#ededed",
	grey94: "#f0f0f0",
	grey95: "#f2f2f2",
	grey96: "#f5f5f5",
	grey97: "#f7f7f7",
	grey98: "#fafafa",
	grey99: "#fcfcfc",
	honeydew: "#f0fff0",
	honeydew1: "#f0fff0",
	honeydew2: "#e0eee0",
	honeydew3: "#c1cdc1",
	honeydew4: "#838b83",
	hotpink: "#ff69b4",
	hotpink1: "#ff6eb4",
	hotpink2: "#ee6aa7",
	hotpink3: "#cd6090",
	hotpink4: "#8b3a62",
	indianred: "#cd5c5c",
	indianred1: "#ff6a6a",
	indianred2: "#ee6363",
	indianred3: "#cd5555",
	indianred4: "#8b3a3a",
	indigo: "#4b0082",
	invis: "#fffffe",
	ivory: "#fffff0",
	ivory1: "#fffff0",
	ivory2: "#eeeee0",
	ivory3: "#cdcdc1",
	ivory4: "#8b8b83",
	khaki: "#f0e68c",
	khaki1: "#fff68f",
	khaki2: "#eee685",
	khaki3: "#cdc673",
	khaki4: "#8b864e",
	lavender: "#e6e6fa",
	lavenderblush: "#fff0f5",
	lavenderblush1: "#fff0f5",
	lavenderblush2: "#eee0e5",
	lavenderblush3: "#cdc1c5",
	lavenderblush4: "#8b8386",
	lawngreen: "#7cfc00",
	lemonchiffon: "#fffacd",
	lemonchiffon1: "#fffacd",
	lemonchiffon2: "#eee9bf",
	lemonchiffon3: "#cdc9a5",
	lemonchiffon4: "#8b8970",
	lightblue: "#add8e6",
	lightblue1: "#bfefff",
	lightblue2: "#b2dfee",
	lightblue3: "#9ac0cd",
	lightblue4: "#68838b",
	lightcoral: "#f08080",
	lightcyan: "#e0ffff",
	lightcyan1: "#e0ffff",
	lightcyan2: "#d1eeee",
	lightcyan3: "#b4cdcd",
	lightcyan4: "#7a8b8b",
	lightgoldenrod: "#eedd82",
	lightgoldenrod1: "#ffec8b",
	lightgoldenrod2: "#eedc82",
	lightgoldenrod3: "#cdbe70",
	lightgoldenrod4: "#8b814c",
	lightgoldenrodyellow: "#fafad2",
	lightgray: "#d3d3d3",
	lightgreen: "#90ee90",
	lightgrey: "#d3d3d3",
	lightpink: "#ffb6c1",
	lightpink1: "#ffaeb9",
	lightpink2: "#eea2ad",
	lightpink3: "#cd8c95",
	lightpink4: "#8b5f65",
	lightsalmon: "#ffa07a",
	lightsalmon1: "#ffa07a",
	lightsalmon2: "#ee9572",
	lightsalmon3: "#cd8162",
	lightsalmon4: "#8b5742",
	lightseagreen: "#20b2aa",
	lightskyblue: "#87cefa",
	lightskyblue1: "#b0e2ff",
	lightskyblue2: "#a4d3ee",
	lightskyblue3: "#8db6cd",
	lightskyblue4: "#607b8b",
	lightslateblue: "#8470ff",
	lightslategray: "#778899",
	lightslategrey: "#778899",
	lightsteelblue: "#b0c4de",
	lightsteelblue1: "#cae1ff",
	lightsteelblue2: "#bcd2ee",
	lightsteelblue3: "#a2b5cd",
	lightsteelblue4: "#6e7b8b",
	lightyellow: "#ffffe0",
	lightyellow1: "#ffffe0",
	lightyellow2: "#eeeed1",
	lightyellow3: "#cdcdb4",
	lightyellow4: "#8b8b7a",
	lime: "#00ff00",
	limegreen: "#32cd32",
	linen: "#faf0e6",
	magenta: "#ff00ff",
	magenta1: "#ff00ff",
	magenta2: "#ee00ee",
	magenta3: "#cd00cd",
	magenta4: "#8b008b",
	maroon: "#b03060",
	maroon1: "#ff34b3",
	maroon2: "#ee30a7",
	maroon3: "#cd2990",
	maroon4: "#8b1c62",
	mediumaquamarine: "#66cdaa",
	mediumblue: "#0000cd",
	mediumorchid: "#ba55d3",
	mediumorchid1: "#e066ff",
	mediumorchid2: "#d15fee",
	mediumorchid3: "#b452cd",
	mediumorchid4: "#7a378b",
	mediumpurple: "#9370db",
	mediumpurple1: "#ab82ff",
	mediumpurple2: "#9f79ee",
	mediumpurple3: "#8968cd",
	mediumpurple4: "#5d478b",
	mediumseagreen: "#3cb371",
	mediumslateblue: "#7b68ee",
	mediumspringgreen: "#00fa9a",
	mediumturquoise: "#48d1cc",
	mediumvioletred: "#c71585",
	midnightblue: "#191970",
	mintcream: "#f5fffa",
	mistyrose: "#ffe4e1",
	mistyrose1: "#ffe4e1",
	mistyrose2: "#eed5d2",
	mistyrose3: "#cdb7b5",
	mistyrose4: "#8b7d7b",
	moccasin: "#ffe4b5",
	navajowhite: "#ffdead",
	navajowhite1: "#ffdead",
	navajowhite2: "#eecfa1",
	navajowhite3: "#cdb38b",
	navajowhite4: "#8b795e",
	navy: "#000080",
	navyblue: "#000080",
	none: "#fffffe",
	oldlace: "#fdf5e6",
	olive: "#808000",
	olivedrab: "#6b8e23",
	olivedrab1: "#c0ff3e",
	olivedrab2: "#b3ee3a",
	olivedrab3: "#9acd32",
	olivedrab4: "#698b22",
	orange: "#ffa500",
	orange1: "#ffa500",
	orange2: "#ee9a00",
	orange3: "#cd8500",
	orange4: "#8b5a00",
	orangered: "#ff4500",
	orangered1: "#ff4500",
	orangered2: "#ee4000",
	orangered3: "#cd3700",
	orangered4: "#8b2500",
	orchid: "#da70d6",
	orchid1: "#ff83fa",
	orchid2: "#ee7ae9",
	orchid3: "#cd69c9",
	orchid4: "#8b4789",
	palegoldenrod: "#eee8aa",
	palegreen: "#98fb98",
	palegreen1: "#9aff9a",
	palegreen2: "#90ee90",
	palegreen3: "#7ccd7c",
	palegreen4: "#548b54",
	paleturquoise: "#afeeee",
	paleturquoise1: "#bbffff",
	paleturquoise2: "#aeeeee",
	paleturquoise3: "#96cdcd",
	paleturquoise4: "#668b8b",
	palevioletred: "#db7093",
	palevioletred1: "#ff82ab",
	palevioletred2: "#ee799f",
	palevioletred3: "#cd6889",
	palevioletred4: "#8b475d",
	papayawhip: "#ffefd5",
	peachpuff: "#ffdab9",
	peachpuff1: "#ffdab9",
	peachpuff2: "#eecbad",
	peachpuff3: "#cdaf95",
	peachpuff4: "#8b7765",
	peru: "#cd853f",
	pink: "#ffc0cb",
	pink1: "#ffb5c5",
	pink2: "#eea9b8",
	pink3: "#cd919e",
	pink4: "#8b636c",
	plum: "#dda0dd",
	plum1: "#ffbbff",
	plum2: "#eeaeee",
	plum3: "#cd96cd",
	plum4: "#8b668b",
	powderblue: "#b0e0e6",
	purple: "#a020f0",
	purple1: "#9b30ff",
	purple2: "#912cee",
	purple3: "#7d26cd",
	purple4: "#551a8b",
	rebeccapurple: "#663399",
	red: "#ff0000",
	red1: "#ff0000",
	red2: "#ee0000",
	red3: "#cd0000",
	red4: "#8b0000",
	rosybrown: "#bc8f8f",
	rosybrown1: "#ffc1c1",
	rosybrown2: "#eeb4b4",
	rosybrown3: "#cd9b9b",
	rosybrown4: "#8b6969",
	royalblue: "#4169e1",
	royalblue1: "#4876ff",
	royalblue2: "#436eee",
	royalblue3: "#3a5fcd",
	royalblue4: "#27408b",
	saddlebrown: "#8b4513",
	salmon: "#fa8072",
	salmon1: "#ff8c69",
	salmon2: "#ee8262",
	salmon3: "#cd7054",
	salmon4: "#8b4c39",
	sandybrown: "#f4a460",
	seagreen: "#2e8b57",
	seagreen1: "#54ff9f",
	seagreen2: "#4eee94",
	seagreen3: "#43cd80",
	seagreen4: "#2e8b57",
	seashell: "#fff5ee",
	seashell1: "#fff5ee",
	seashell2: "#eee5de",
	seashell3: "#cdc5bf",
	seashell4: "#8b8682",
	sienna: "#a0522d",
	sienna1: "#ff8247",
	sienna2: "#ee7942",
	sienna3: "#cd6839",
	sienna4: "#8b4726",
	silver: "#c0c0c0",
	skyblue: "#87ceeb",
	skyblue1: "#87ceff",
	skyblue2: "#7ec0ee",
	skyblue3: "#6ca6cd",
	skyblue4: "#4a708b",
	slateblue: "#6a5acd",
	slateblue1: "#836fff",
	slateblue2: "#7a67ee",
	slateblue3: "#6959cd",
	slateblue4: "#473c8b",
	slategray: "#708090",
	slategray1: "#c6e2ff",
	slategray2: "#b9d3ee",
	slategray3: "#9fb6cd",
	slategray4: "#6c7b8b",
	slategrey: "#708090",
	snow: "#fffafa",
	snow1: "#fffafa",
	snow2: "#eee9e9",
	snow3: "#cdc9c9",
	snow4: "#8b8989",
	springgreen: "#00ff7f",
	springgreen1: "#00ff7f",
	springgreen2: "#00ee76",
	springgreen3: "#00cd66",
	springgreen4: "#008b45",
	steelblue: "#4682b4",
	steelblue1: "#63b8ff",
	steelblue2: "#5cacee",
	steelblue3: "#4f94cd",
	steelblue4: "#36648b",
	tan: "#d2b48c",
	tan1: "#ffa54f",
	tan2: "#ee9a49",
	tan3: "#cd853f",
	tan4: "#8b5a2b",
	teal: "#008080",
	thistle: "#d8bfd8",
	thistle1: "#ffe1ff",
	thistle2: "#eed2ee",
	thistle3: "#cdb5cd",
	thistle4: "#8b7b8b",
	tomato: "#ff6347",
	tomato1: "#ff6347",
	tomato2: "#ee5c42",
	tomato3: "#cd4f39",
	tomato4: "#8b3626",
	transparent: "#fffffe",
	turquoise: "#40e0d0",
	turquoise1: "#00f5ff",
	turquoise2: "#00e5ee",
	turquoise3: "#00c5cd",
	turquoise4: "#00868b",
	violet: "#ee82ee",
	violetred: "#d02090",
	violetred1: "#ff3e96",
	violetred2: "#ee3a8c",
	violetred3: "#cd3278",
	violetred4: "#8b2252",
	webgray: "#808080",
	webgreen: "#008000",
	webgrey: "#808080",
	webmaroon: "#800000",
	webpurple: "#800080",
	wheat: "#f5deb3",
	wheat1: "#ffe7ba",
	wheat2: "#eed8ae",
	wheat3: "#cdba96",
	wheat4: "#8b7e66",
	white: "#ffffff",
	whitesmoke: "#f5f5f5",
	x11gray: "#bebebe",
	x11green: "#00ff00",
	x11grey: "#bebebe",
	x11maroon: "#b03060",
	x11purple: "#a020f0",
	yellow: "#ffff00",
	yellow1: "#ffff00",
	yellow2: "#eeee00",
	yellow3: "#cdcd00",
	yellow4: "#8b8b00",
	yellowgreen: "#9acd32"
});

//#endregion
//#region src/visitor.ts
function visitNode(cbNode, node) {
	return node && cbNode(node);
}
function visitNodes(cbNode, cbNodes, nodes) {
	if (nodes) {
		if (cbNodes) return cbNodes(nodes);
		for (const node of nodes) {
			const result = cbNode(node);
			if (result) return result;
		}
	}
}
function forEachChild(node, cbNode, cbNodes) {
	if (!node || node.kind <= syntaxKind.LastKeyword) return;
	switch (node.kind) {
		case syntaxKind.DirectedGraph:
		case syntaxKind.UndirectedGraph: return visitNodes(cbNode, cbNodes, node.statements) || visitNode(cbNode, node.strict) || visitNode(cbNode, node.id);
		case syntaxKind.AttributeStatement: return visitNodes(cbNode, cbNodes, node.attributes) || visitNode(cbNode, node.subject) || visitNode(cbNode, node.terminator);
		case syntaxKind.EdgeStatement: return visitNodes(cbNode, cbNodes, node.attributes) || visitNodes(cbNode, cbNodes, node.rhs) || visitNode(cbNode, node.source) || visitNode(cbNode, node.terminator);
		case syntaxKind.NodeStatement: return visitNodes(cbNode, cbNodes, node.attributes) || visitNode(cbNode, node.id) || visitNode(cbNode, node.terminator);
		case syntaxKind.SubGraph: return visitNodes(cbNode, cbNodes, node.statements) || visitNode(cbNode, node.id);
		case syntaxKind.SubGraphStatement: return visitNode(cbNode, node.subgraph) || visitNode(cbNode, node.terminator);
		case syntaxKind.IdEqualsIdStatement: return visitNode(cbNode, node.leftId) || visitNode(cbNode, node.rightId) || visitNode(cbNode, node.terminator);
		case syntaxKind.QuotedTextIdentifier: return visitNodes(cbNode, cbNodes, node.values);
		case syntaxKind.EdgeRhs: return visitNode(cbNode, node.operation) || visitNode(cbNode, node.target);
		case syntaxKind.AttributeContainer: return visitNodes(cbNode, cbNodes, node.assignments);
		case syntaxKind.Assignment: return visitNode(cbNode, node.leftId) || visitNode(cbNode, node.rightId) || visitNode(cbNode, node.terminator);
		case syntaxKind.NormalPortDeclaration: return visitNode(cbNode, node.colon) || visitNode(cbNode, node.id) || visitNode(cbNode, node.compassPt);
		case syntaxKind.CompassPortDeclaration: return visitNode(cbNode, node.colon) || visitNode(cbNode, node.compassPt);
		case syntaxKind.NodeId: return visitNode(cbNode, node.port) || visitNode(cbNode, node.id);
		default: return;
	}
}

//#endregion
//#region src/checker.ts
function checkSourceFile(file) {
	const g = file.graph;
	if (g) {
		const messages = checkGraphSemantics(file, g);
		if (messages) file.diagnostics.push.apply(file.diagnostics, messages);
	}
}
function rangeContainsOffset(range, offset, inclusiveEnd) {
	return inclusiveEnd ? range.pos <= offset && offset <= range.end : range.pos <= offset && offset < range.end;
}
function findNodeAtOffset(root, offset, inclusiveEnd = false) {
	if (root.pos === offset && root.pos === root.end) return root;
	if (rangeContainsOffset(root, offset, inclusiveEnd)) {
		const narrowerChild = forEachChild(root, (child) => findNodeAtOffset(child, offset, inclusiveEnd));
		return narrowerChild ? narrowerChild : root;
	}
}
function getAllowedEdgeOperation(graph) {
	return graph.kind === syntaxKind.DirectedGraph ? syntaxKind.DirectedEdgeOp : syntaxKind.UndirectedEdgeOp;
}
function checkGraphSemantics(file, root) {
	const expectedEdgeOp = getAllowedEdgeOperation(root);
	const invalidEdgeRhses = findEdgeErrors(expectedEdgeOp, root);
	const invalidShapes = checkShapeLabelValues(root);
	return [...invalidEdgeRhses === void 0 || invalidEdgeRhses.length === 0 ? [] : createEdgeViolationDiagnostics(file, expectedEdgeOp, invalidEdgeRhses), ...invalidShapes];
}
function forEachAssignmentTransitive(root, cb) {
	forEachChild(root, (child) => {
		if (child.kind === syntaxKind.Assignment) {
			cb(child);
			return;
		}
		forEachChild(child, (c) => forEachAssignmentTransitive(c, cb));
	});
}
function checkShapeLabelValues(root) {
	const invalidShapes = [];
	forEachAssignmentTransitive(root, (assignment) => {
		const { leftId, rightId } = assignment;
		if (leftId.kind !== syntaxKind.TextIdentifier || rightId.kind !== syntaxKind.TextIdentifier) return;
		if (leftId.text.trim().toLocaleLowerCase() !== "shape") return;
		const rightText = rightId.text.trim();
		const shapeCandidate = rightText.toLowerCase();
		if (shapes.includes(shapeCandidate)) return;
		invalidShapes.push({
			category: diagnosticCategory.Warning,
			code: createCheckerError(checkError.InvalidShapeName),
			message: `Unknown shape "${rightText}".`,
			start: rightId.pos,
			end: rightId.end
		});
	});
	return invalidShapes;
}
/**
* TOOD: Refactor to use findAllSatements internally
* @param node
*/
function findAllEdges(node) {
	const allEdges = [];
	forEachChild(node, (child) => {
		if (isEdgeStatement(child)) {
			if (child.rhs && child.rhs.length > 0) for (const edgeRhs of child.rhs) allEdges.push(edgeRhs);
		}
		const childEdges = findAllEdges(child);
		if (childEdges && childEdges.length > 0) allEdges.push.apply(allEdges, childEdges);
	});
	return allEdges;
}
function findOptionalSemicolons(node) {
	return findAllStatements(node).map((p) => p.terminator).filter((t) => !!t);
}
function isStatement(node) {
	return node.kind === syntaxKind.SubGraphStatement || node.kind === syntaxKind.EdgeStatement || node.kind === syntaxKind.NodeStatement || node.kind === syntaxKind.IdEqualsIdStatement || node.kind === syntaxKind.AttributeStatement;
}
function findAllStatements(node, kind) {
	const allStatements = [];
	forEachChild(node, (child) => {
		if (kind === void 0 && isStatement(child) || child.kind === kind) allStatements.push(child);
		const childStatements = findAllStatements(child, kind);
		if (childStatements && childStatements.length > 0) allStatements.push.apply(allStatements, childStatements);
	});
	return allStatements;
}
function findEdgeErrors(expectedEdgeOp, node) {
	const edges = findAllEdges(node);
	const wrongEdges = edges && edges.length > 0 ? edges.filter((e) => e.operation.kind !== expectedEdgeOp) : void 0;
	if (wrongEdges && wrongEdges.length > 0) {
		for (const edge of wrongEdges) edge.operation.flags |= syntaxNodeFlags.ContainsErrors;
		return wrongEdges;
	}
}
function createEdgeViolationDiagnostics(file, expectedEdgeOp, violators) {
	const message = `Invalid edge operation, use "${expectedEdgeOp === syntaxKind.UndirectedEdgeOp ? "--" : "->"}" in ${expectedEdgeOp === syntaxKind.UndirectedEdgeOp ? "undirected" : "directed"} graph`;
	const code = createCheckerError(checkError.InvalidEdgeOperation);
	const category = diagnosticCategory.Error;
	for (const edge of violators) edge.operation.flags |= syntaxNodeFlags.ContainsErrors;
	return violators.map((edge) => {
		return {
			message,
			code,
			category,
			start: getStart(file, edge.operation),
			end: edge.operation.end
		};
	});
}
function isAttrStatement(node) {
	return node.kind === syntaxKind.AttributeStatement;
}
function isEdgeStatement(node) {
	return node.kind === syntaxKind.EdgeStatement;
}
function isNodeId(node) {
	return node.kind === syntaxKind.NodeId;
}
function edgeStatementHasAttributes(es) {
	return es.attributes && es.attributes.length > 0 && es.attributes.some((a) => a.assignments && a.assignments.length > 0);
}
function getIdentifierText(n) {
	switch (n.kind) {
		case syntaxKind.HtmlIdentifier: return n.htmlContent;
		case syntaxKind.TextIdentifier: return n.text;
		case syntaxKind.NumericIdentifier: return n.text;
		case syntaxKind.QuotedTextIdentifier: return n.concatenation;
		default: return assertNever(n);
	}
}
function createCheckerError(sub) {
	return {
		source: errorSource.Check,
		sub
	};
}
function nodeContainsErrors(node) {
	return (node.flags & syntaxNodeFlags.ContainsErrors) === syntaxNodeFlags.ContainsErrors;
}

//#endregion
//#region src/binder.ts
const binder = createBinder();
function bindSourceFile(file) {
	binder.bind(file);
}
function createBinder() {
	let parent;
	let symbolTable;
	let colorTable;
	let gc = graphContext.None;
	function bind(node) {
		if (!node) return;
		const saveParent = parent;
		const saveContext = gc;
		node.parent = saveParent;
		node.graphContext = saveContext;
		parent = node;
		innerBind(node);
		parent = saveParent;
		gc = saveContext;
	}
	function innerBind(node) {
		switch (node.kind) {
			case syntaxKind.DirectedGraph:
			case syntaxKind.UndirectedGraph: return bindGraph(node);
			case syntaxKind.AttributeStatement: return bindAttributeStatement(node);
			case syntaxKind.EdgeStatement: return bindEdgeStatement(node);
			case syntaxKind.NodeStatement: return bindNodeStatement(node);
			case syntaxKind.SubGraph: return bindSubGraph(node);
			case syntaxKind.SubGraphStatement: return bindSubGraphStatement(node);
			case syntaxKind.IdEqualsIdStatement: return bindIdEqualsIdStatement(node);
			case syntaxKind.QuotedTextIdentifier: return bindQuotedTextIdentifier(node);
			case syntaxKind.EdgeRhs: return bindEdgeRhs(node);
			case syntaxKind.AttributeContainer: return bindAttributeContainer(node);
			case syntaxKind.Assignment: return bindAssignment(node);
			case syntaxKind.NormalPortDeclaration: return bindNormalPortDeclaration(node);
			case syntaxKind.CompassPortDeclaration: return bindCompassPortDeclaration(node);
			case syntaxKind.NodeId: return bindNodeId(node);
			default: if (node.kind >= syntaxKind.FirstNode) throw "TODO";
		}
	}
	function bindGraph(node) {
		if (node.strict) gc |= graphContext.Strict;
		switch (node.kind) {
			case syntaxKind.DirectedGraph:
				gc |= graphContext.Directed;
				break;
			case syntaxKind.UndirectedGraph:
				gc |= graphContext.Undirected;
				break;
		}
		if (node.id) {
			ensureGlobalSymbol(node.id);
			bind(node.id);
		}
		if (node.strict) bind(node.strict);
		bindChildren(node.statements);
	}
	function bindAttributeStatement(node) {
		bind(node.subject);
		bindChildren(node.attributes);
		if (node.terminator) bind(node.terminator);
	}
	function bindEdgeStatement(node) {
		bindChildren(node.attributes);
		bindChildren(node.rhs);
		bind(node.source);
		if (node.terminator) bind(node.terminator);
	}
	function bindNodeStatement(node) {
		bind(node.id);
		bindChildren(node.attributes);
		if (node.terminator) bind(node.terminator);
	}
	function bindSubGraph(node) {
		if (node.id) bind(node.id);
		bindChildren(node.statements);
	}
	function bindSubGraphStatement(node) {
		bind(node.subgraph);
		if (node.terminator) bind(node.terminator);
	}
	function bindIdEqualsIdStatement(node) {
		bind(node.leftId);
		bind(node.rightId);
		if (node.rightId && !nodeContainsErrors(node.rightId)) {
			if (isAttributeName("color", node.leftId)) ensureGlobalColor(node.rightId);
			else if (isAttributeName("fillcolor", node.leftId)) ensureGlobalColor(node.rightId);
			else if (isAttributeName("bgcolor", node.leftId)) ensureGlobalColor(node.rightId);
			else if (isAttributeName("fontcolor", node.leftId)) ensureGlobalColor(node.rightId);
		}
		if (node.terminator) bind(node.terminator);
	}
	function bindQuotedTextIdentifier(node) {
		bindChildren(node.values);
		node.concatenation = node.values.map((v) => v.text).join("");
	}
	function bindEdgeRhs(node) {
		bind(node.operation);
		bind(node.target);
	}
	function bindAttributeContainer(node) {
		bind(node.openBracket);
		bindChildren(node.assignments);
		bind(node.closeBracket);
	}
	function bindAssignment(node) {
		const attrContainer = node.parent;
		console.assert(!!attrContainer);
		const superParentStatement = attrContainer.parent;
		console.assert(!!superParentStatement);
		bind(node.leftId);
		let carrierIdentifier;
		switch (superParentStatement.kind) {
			case syntaxKind.NodeStatement:
				carrierIdentifier = superParentStatement.id.id;
				break;
			case syntaxKind.EdgeStatement: break;
			case syntaxKind.SubGraphStatement: break;
			case syntaxKind.AttributeStatement: break;
		}
		if (carrierIdentifier) ensureMemberSymbol(node.leftId, carrierIdentifier);
		bind(node.rightId);
		if (node.rightId && !nodeContainsErrors(node.rightId)) {
			if (isAttributeName("color", node.leftId)) ensureGlobalColor(node.rightId);
		}
		if (node.terminator) bind(node.terminator);
	}
	function bindNormalPortDeclaration(node) {
		bind(node.colon);
		ensureGlobalSymbol(node.id);
		bind(node.id);
		if (node.compassPt) bind(node.compassPt);
	}
	function bindCompassPortDeclaration(node) {
		bind(node.colon);
		if (node.compassPt) bind(node.compassPt);
	}
	function bindNodeId(node) {
		ensureGlobalSymbol(node.id);
		bind(node.id);
		if (node.port) bind(node.port);
	}
	function bindChildren(nodes) {
		for (const n of nodes) bind(n);
	}
	function createSymbolTable() {
		return /* @__PURE__ */ new Map();
	}
	function createColorTable() {
		return /* @__PURE__ */ new Map();
	}
	function ensureMemberSymbol(node, carrier) {
		if (node && carrier && isIdentifierNode(node)) {
			const name = getIdentifierText(node);
			if (name === void 0) return;
			const carrierSymbol = carrier.symbol;
			if (carrierSymbol === void 0) throw "carrierSymbol is undefined";
			let symbols = carrierSymbol.members;
			if (symbols === void 0) carrierSymbol.members = symbols = createSymbolTable();
			ensureSymbolOnTable(name, node, symbols);
			return;
		}
		console.warn("ensureSymbol called on non-identifier node");
		debugger;
	}
	function ensureGlobalSymbol(node) {
		if (node && isIdentifierNode(node)) {
			const symbols = symbolTable;
			const name = getIdentifierText(node);
			if (name === void 0) return;
			if (symbols === void 0) throw "symbolTable is undefined";
			ensureSymbolOnTable(name, node, symbols);
			return;
		}
		console.warn("ensureSymbol called on non-identifier node");
		debugger;
	}
	function ensureSymbolOnTable(name, node, symbols) {
		if (!name) return;
		let sym = symbols.get(name);
		if (sym === void 0) {
			sym = createSymbol(name, node);
			symbols.set(name, sym);
		} else if (!sym.references) sym.references = [node];
		else sym.references.push(node);
		node.symbol = sym;
	}
	function ensureGlobalColor(node) {
		if (node && isIdentifierNode(node)) {
			const colors$1 = colorTable;
			const name = getIdentifierText(node);
			if (name === void 0) return;
			if (colors$1 === void 0) throw "symbolTable is undefined";
			const color = createColor(node);
			colors$1.set(name, color);
			return;
		}
		console.warn("ensureSymbol called on non-identifier node");
		debugger;
	}
	function createSymbol(name, node) {
		if (!name) throw "name is falsy";
		if (!node) throw "node is undefined or null";
		return {
			name,
			firstMention: node,
			references: void 0
		};
	}
	function createColor(node) {
		return { node };
	}
	/**
	* @param name Pass lower cased
	*/
	function isAttributeName(name, id) {
		return id ? getIdentifierText(id).trim().toLowerCase() === name : false;
	}
	return { bind: (file) => {
		symbolTable = createSymbolTable();
		colorTable = createColorTable();
		const { graph } = file;
		if (graph) bind(graph);
		file.symbols = symbolTable;
		file.colors = colorTable;
	} };
}

//#endregion
//#region src/service/command/common.ts
function createChangeToEdit(start, end, changeTo) {
	return TextEdit.replace(Range.create(start, end), changeTo);
}
function getEdgeStr(op) {
	return op === syntaxKind.DirectedEdgeOp ? "->" : "--";
}
function getGraphKeywordStr(g) {
	return g === syntaxKind.DigraphKeyword ? "digraph" : "graph";
}
function getOppositeKind(g) {
	return g === syntaxKind.DigraphKeyword ? syntaxKind.GraphKeyword : syntaxKind.DigraphKeyword;
}
function getOppositeEdgeOp(g) {
	return g === syntaxKind.DirectedEdgeOp ? syntaxKind.UndirectedEdgeOp : syntaxKind.DirectedEdgeOp;
}
function getAllowedOp(g) {
	return g === syntaxKind.DigraphKeyword ? syntaxKind.DirectedEdgeOp : syntaxKind.UndirectedEdgeOp;
}

//#endregion
//#region src/service/command/ChangeAllOtherEdgeOpsAndFixGraphCommand.ts
function create$3(edgeOffsets, changeEdgesTo, graphOffset, changeFromGraph, changeGraphTo) {
	const toGraph = getGraphKeywordStr(changeGraphTo);
	const title = changeGraphTo === changeFromGraph ? `Fix all edges to match ${toGraph}` : `Convert ${getGraphKeywordStr(changeFromGraph)} to ${toGraph}`;
	const edgeStr = getEdgeStr(changeEdgesTo);
	return {
		title,
		command: commandIds.ConvertGraphType,
		arguments: [
			edgeOffsets,
			edgeStr,
			graphOffset,
			toGraph
		]
	};
}
function execute$3(doc, _sourceFile, cmd) {
	if (!isChangeAllOtherEdgeOpsAndFixGraphCommand(cmd)) return void 0;
	const [edgeOffsets, changeEdgeTo, graphOffset, changeGraphTo] = cmd.arguments;
	const edits = edgeOffsets.map((o) => {
		return createChangeToEdit(doc.positionAt(o.start), doc.positionAt(o.end), changeEdgeTo);
	});
	const graphStart = doc.positionAt(graphOffset.start);
	const graphEnd = doc.positionAt(graphOffset.end);
	edits.push(createChangeToEdit(graphStart, graphEnd, changeGraphTo));
	return {
		label: `Convert graph to "${changeGraphTo}"`,
		edit: { changes: { [doc.uri]: edits } }
	};
}
function isChangeAllOtherEdgeOpsAndFixGraphCommand(cmd) {
	return cmd.command === commandIds.ConvertGraphType && !!cmd.arguments && cmd.arguments.length === 4;
}

//#endregion
//#region src/service/command/ChangeEdgeOpCommand.ts
function create$2(startOffset, endOffset, changeTo, changeFrom) {
	const from = getEdgeStr(changeFrom);
	const to = getEdgeStr(changeTo);
	return {
		title: `Change "${from}" to "${to}".`,
		command: commandIds.ChangeEdgeOp,
		arguments: [
			startOffset,
			endOffset,
			to
		]
	};
}
function execute$2(doc, _sourceFile, cmd) {
	if (!isChangeEdgeOpCommand(cmd)) return void 0;
	const [startOffset, endOffset, changeTo] = cmd.arguments;
	const startPos = doc.positionAt(startOffset);
	const endPos = doc.positionAt(endOffset);
	return {
		label: `Change of invalid edge to "${changeTo}"'"`,
		edit: { changes: { [doc.uri]: [lst.TextEdit.replace(lst.Range.create(startPos, endPos), changeTo)] } }
	};
}
function isChangeEdgeOpCommand(cmd) {
	return cmd.command === commandIds.ChangeEdgeOp && !!cmd.arguments && cmd.arguments.length === 3;
}

//#endregion
//#region src/service/command/ConsolidateDescendantsCommand.ts
function create$1(statements, below) {
	const first = statements[0];
	const from = getIdentifierText(first.source.id);
	return {
		title: below ? `Convert edges below from "${from}" to subgraph` : `Convert edges from "${from}" to subgraph`,
		command: commandIds.ConsolidateDescendants,
		arguments: statements.map((s) => s.pos)
	};
}
function execute$1(doc, sourceFile, cmd) {
	if (!isConsolidateDescendantsCommand(cmd)) return void 0;
	const g = sourceFile.graph;
	if (!g) return void 0;
	const candidates = cmd.arguments.map((i) => findNodeAtOffset(g, i).parent.parent);
	const first = candidates.shift();
	const from = getIdentifierText(first.source.id);
	const edits = [];
	const firstRight = first.rhs[0];
	const firstRightTargetStart = getStart(sourceFile, firstRight.target);
	const firstRightTargetEnd = firstRight.target.end;
	const contents = [sourceFile.content.substring(firstRightTargetStart, firstRightTargetEnd)];
	for (const descendant of candidates) {
		const rightItem = descendant.rhs[0];
		const rightItemTargetStart = rightItem.target.pos;
		const rightItemTargetEnd = rightItem.target.end;
		const rightItemContent = sourceFile.content.substring(rightItemTargetStart, rightItemTargetEnd);
		edits.push({
			newText: "",
			range: {
				start: doc.positionAt(descendant.pos),
				end: doc.positionAt(rightItemTargetStart)
			}
		});
		edits.push({
			newText: "",
			range: {
				start: doc.positionAt(rightItemTargetStart),
				end: doc.positionAt(rightItemTargetEnd)
			}
		});
		if (descendant.terminator !== void 0) edits.push({
			newText: "",
			range: {
				start: doc.positionAt(getStart(sourceFile, descendant.terminator)),
				end: doc.positionAt(descendant.terminator.end)
			}
		});
		contents.push(rightItemContent);
	}
	const toInsert = `{ ${contents.map((s) => s.trim()).join(" ")} }`;
	edits.push({
		newText: toInsert,
		range: {
			start: doc.positionAt(firstRightTargetStart),
			end: doc.positionAt(firstRightTargetEnd)
		}
	});
	return {
		label: `Convert edges from "${from}" to subgraph.`,
		edit: { changes: { [doc.uri]: edits } }
	};
}
function isConsolidateDescendantsCommand(cmd) {
	return cmd.command === commandIds.ConsolidateDescendants && !!cmd.arguments && cmd.arguments.length > 1;
}

//#endregion
//#region src/service/command/RemoveSemicolons.ts
function create() {
	return {
		title: "Remove optional semicolons",
		command: commandIds.RemoveSemicolons,
		arguments: void 0
	};
}
function execute(doc, sourceFile, cmd) {
	if (!isRemoveSemicolonsCommand(cmd)) return void 0;
	const g = sourceFile.graph;
	if (!g) return void 0;
	const edits = findOptionalSemicolons(g).map((s) => {
		const end = s.end;
		const start = end - 1;
		return createChangeToEdit(doc.positionAt(start), doc.positionAt(end), "");
	});
	return {
		label: "Remove optional semicolons",
		edit: { changes: { [doc.uri]: edits } }
	};
}
function isRemoveSemicolonsCommand(cmd) {
	return cmd.command === commandIds.RemoveSemicolons && (!cmd.arguments || cmd.arguments.length === 0 || cmd.arguments.every((e) => e === void 0));
}

//#endregion
//#region src/service/codeAction.ts
function getCodeActions(doc, sourceFile, range, _context) {
	let actions = getActionsFromDiagnostics(doc, sourceFile, range);
	const general = getGeneralRefactorings(doc, sourceFile, range);
	if (general) if (!actions) actions = general;
	else actions.push.apply(actions, general);
	return actions;
}
function getActionsFromDiagnostics(doc, file, range) {
	const ds = file.diagnostics;
	if (!ds || ds.length === 0) return void 0;
	const rangeStartOffset = doc.offsetAt(range.start);
	const rangeEndOffset = doc.offsetAt(range.end);
	const res = [];
	for (const d of ds) if (isInRange(rangeStartOffset, rangeEndOffset, d.start, d.end)) {
		const commands = getCommandsForDiagnostic(doc, file, d);
		if (commands && commands.length > 0) res.push.apply(res, commands);
	}
	return res.length === 0 ? void 0 : res;
}
function getGeneralRefactorings(doc, file, range) {
	if (!file.graph) return void 0;
	const g = file.graph;
	const kw = g.keyword;
	const rangeStartOffset = doc.offsetAt(range.start);
	const rangeEndOffset = doc.offsetAt(range.end);
	const keywordStart = getStart(file, kw);
	const res = [];
	if (isInRange(rangeStartOffset, rangeEndOffset, keywordStart, kw.end)) {
		if (!subtreeContainsErrors(g)) {
			const convertGraph = convertGraphTypeCommand(file, g, getOppositeKind(kw.kind));
			res.push(convertGraph);
		}
	}
	if (rangeStartOffset === rangeEndOffset) {
		const candidates = [];
		let clickedNode = findNodeAtOffset(g, rangeStartOffset);
		if (clickedNode && !!clickedNode.parent) {
			if (clickedNode.kind === syntaxKind.SemicolonToken) res.push(create());
			if (isIdentifierNode(clickedNode)) clickedNode = clickedNode.parent;
			const clickedEdgeStatement = clickedNode.parent;
			if (clickedEdgeStatement && !subtreeContainsErrors(clickedEdgeStatement)) {
				if (isEdgeStatement(clickedEdgeStatement) && clickedEdgeStatement.rhs.length === 1 && isNodeId(clickedEdgeStatement.source) && !edgeStatementHasAttributes(clickedEdgeStatement)) {
					candidates.push(clickedEdgeStatement);
					const source = clickedEdgeStatement.source;
					const sourceText = getIdentifierText(source.id);
					const graphParent = clickedEdgeStatement.parent;
					if (graphParent) {
						let hasVisitedStatement = false;
						let hasVisitedNodeModifier = false;
						forEachChild(graphParent, (statement) => {
							if (statement === clickedEdgeStatement) {
								hasVisitedStatement = true;
								return;
							}
							if (hasVisitedNodeModifier) return;
							if (hasVisitedStatement) {
								if (isAttrStatement(statement) || subtreeContainsErrors(statement)) {
									hasVisitedNodeModifier = true;
									return true;
								}
							}
							if (hasVisitedStatement) {
								if (isEdgeStatement(statement) && statement.rhs.length === 1 && !edgeStatementHasAttributes(statement)) {
									const statementSource = statement.source;
									if (isNodeId(statementSource)) {
										if (sourceText === getIdentifierText(statementSource.id)) candidates.push(statement);
									}
								}
							}
						});
					}
				}
				if (candidates.length > 1) {
					const action = create$1(candidates, true);
					res.push(action);
				}
			}
		}
	}
	return res.length === 0 ? void 0 : res;
}
function getCommandsForDiagnostic(doc, file, d) {
	switch (d.code.source) {
		case errorSource.Scan: return getScannerErrorCommand(doc, file, d, d.code);
		case errorSource.Parse: return getParserErrorCommand(doc, file, d, d.code);
		case errorSource.Check: return getCheckerErrorCommand(doc, file, d, d.code);
		default: return assertNever(d.code);
	}
}
function getScannerErrorCommand(_doc, _file, d, code) {
	console.assert(d.code.source === errorSource.Scan);
	console.assert(code.source === errorSource.Scan);
}
function getParserErrorCommand(_doc, _file, d, code) {
	console.assert(d.code.source === errorSource.Parse);
	console.assert(code.source === errorSource.Parse);
}
function getCheckerErrorCommand(_doc, file, d, code) {
	console.assert(d.code.source === errorSource.Check);
	console.assert(code.source === errorSource.Check);
	switch (code.sub) {
		case checkError.InvalidEdgeOperation: {
			const graph = file.graph;
			if (!graph) return void 0;
			const allowedOp = getAllowedEdgeOperation(graph);
			const wrongOp = getOppositeEdgeOp(allowedOp);
			const kwk = graph.keyword.kind;
			return [
				create$2(d.start, d.end, allowedOp, wrongOp),
				convertGraphTypeCommand(file, graph, kwk),
				convertGraphTypeCommand(file, graph, getOppositeKind(kwk))
			];
		}
		case checkError.InvalidShapeName: return;
	}
}
function convertGraphTypeCommand(file, graph, changeToGraphType) {
	const changeToEdgeOp = getAllowedOp(changeToGraphType);
	const edgeOffsets = findAllEdges(graph).filter((e) => e.operation.kind !== changeToEdgeOp).map((e) => ({
		start: getStart(file, e.operation),
		end: e.operation.end
	}));
	const graphTypeOffset = {
		start: getStart(file, graph.keyword),
		end: graph.keyword.end
	};
	return create$3(edgeOffsets, changeToEdgeOp, graphTypeOffset, graph.keyword.kind, changeToGraphType);
}
function isInRange(rangeStartOffset, rangeEndOffset, startOffset, endOffset) {
	if (rangeStartOffset === rangeEndOffset) return startOffset <= rangeStartOffset && rangeEndOffset <= endOffset;
	if (rangeStartOffset === startOffset && rangeEndOffset === endOffset) return true;
	return false;
}
const commandIds = {
	ChangeEdgeOp: "DOT.changeEdgeOp",
	ConvertGraphType: "DOT.convertGraphType",
	ConsolidateDescendants: "DOT.consolidateDescendants",
	RemoveSemicolons: "DOT.removeSemicolons"
};
const commandHandlers = {
	[commandIds.ChangeEdgeOp]: execute$2,
	[commandIds.ConvertGraphType]: execute$3,
	[commandIds.ConsolidateDescendants]: execute$1,
	[commandIds.RemoveSemicolons]: execute
};
function getAvailableCommands() {
	return Object.keys(commandHandlers);
}
function executeCommand(doc, sourceFile, cmd) {
	const handler = commandHandlers[cmd.command];
	return handler === void 0 ? void 0 : handler(doc, sourceFile, cmd);
}
function subtreeContainsErrors(node) {
	if (nodeContainsErrors(node)) return true;
	let hasError = false;
	forEachChild(node, (child) => {
		if (nodeContainsErrors(child)) hasError = true;
		if (!hasError) hasError = subtreeContainsErrors(child);
	});
	return hasError;
}

//#endregion
//#region src/service/colorProvider.ts
const colorMap = colors;
function getDocumentColors(doc, sourceFile) {
	const cs = sourceFile.colors;
	return cs ? colorTableToColorInformation(doc, sourceFile, cs) : void 0;
}
function getColorRepresentations(_doc, _sourceFile, color, range) {
	return !color || !range ? void 0 : [{ label: `"${getColorStringFromColor(color)}"` }];
}
function colorTableToColorInformation(doc, sf, colors$1) {
	if (!colors$1 || colors$1.size === 0) return [];
	const res = [];
	for (const [name, value] of colors$1) {
		if (!name || !value) continue;
		const color = getColorFromName(name);
		if (color) res.push({
			range: syntaxNodeToRange(doc, sf, value.node),
			color
		});
	}
	return res;
}
function getColorFromName(name) {
	if (name.charAt(0) === "#") return getHexCodeColor(name);
	const colorAlias = colorMap[name.toLowerCase()];
	return colorAlias ? getHexCodeColor(colorAlias) : void 0;
}
function getHexCodeColor(colorCode) {
	const hexCode = colorCode.charAt(0) === "#" ? colorCode.substring(1) : colorCode;
	const colorInt = Number.parseInt(hexCode, 16);
	return {
		red: (colorInt >> 16 & 255) / 255,
		green: (colorInt >> 8 & 255) / 255,
		blue: (colorInt & 255) / 255,
		alpha: hexCode.length === 8 ? (colorInt >> 24 & 255) / 255 : 1
	};
}
function getColorStringFromColor(c) {
	const red = c.red * 255 | 0;
	const green = c.green * 255 | 0;
	const blue = c.blue * 255 | 0;
	return `#${numberToPaddedString(red)}${numberToPaddedString(green)}${numberToPaddedString(blue)}`;
}
function numberToPaddedString(n) {
	const s = n.toString(16);
	return (s.length === 1 ? `0${s}` : s).toLowerCase();
}

//#endregion
//#region src/service/completion.ts
function getCompletions(doc, sourceFile, position) {
	const symbols = sourceFile.symbols;
	if (!symbols) throw "sourceFile is not bound";
	const g = sourceFile.graph;
	if (!g) return [];
	const offset = doc.offsetAt(position);
	const node = findNodeAtOffset(g, offset, true);
	if (!node) return [];
	const prevOffsetNode = findNodeAtOffset(g, offset - 1, true);
	const parent = node.parent;
	const prevOffsetNodeParent = prevOffsetNode?.parent;
	if (parent?.parent && isEdgeStatement(parent.parent) || prevOffsetNodeParent?.parent && isEdgeStatement(prevOffsetNodeParent.parent)) return getNodeCompletions(symbols);
	if (node.kind === syntaxKind.AttributeContainer) {
		if (node.openBracket.end - 1 > offset - 1) return getNodeCompletions(symbols, prevOffsetNode?.kind === syntaxKind.TextIdentifier && prevOffsetNode.symbol ? [prevOffsetNode.symbol.name] : void 0);
	}
	if (node.kind === syntaxKind.TextIdentifier && parent?.kind === syntaxKind.NodeId) return getNodeCompletions(symbols, node.symbol ? [node.symbol.name] : void 0);
	if (node.kind === syntaxKind.AttributeContainer || node.kind === syntaxKind.CommaToken && parent?.kind === syntaxKind.Assignment) return getAttributeCompletions(position);
	const prevNode = findNodeAtOffset(g, node.pos - 1, true);
	if (!prevNode) return [];
	if (isIdentifierNode(prevNode)) {
		const p = prevNode.parent;
		if (p) switch (p.kind) {
			case syntaxKind.NodeId: return getNodeCompletions(symbols);
			case syntaxKind.Assignment: return getAssignmentCompletion(p);
		}
	}
	if (node.flags & syntaxNodeFlags.ContainsErrors || node.end === node.pos) {
		const attribute = prevNode;
		if (!attribute) return [];
		if (!attribute.parent) throw "sourceFile is not bound";
		const parent$1 = attribute.parent;
		if (parent$1.kind === syntaxKind.Assignment) return getAssignmentCompletion(parent$1);
	}
	return [];
}
function getAssignmentCompletion(assignment) {
	const property = getIdentifierText(assignment.leftId);
	if (!property) return [];
	switch (property.toLowerCase()) {
		case "shape": return getShapeCompletions();
		case "color": return getColorCompletions();
		default: return [];
	}
}
function getShapeCompletions() {
	const kind = lst.CompletionItemKind.EnumMember;
	return shapes.map((s) => ({
		kind,
		label: escapeIdentifierText(s)
	}));
}
function getColorCompletions() {
	const kind = lst.CompletionItemKind.Color;
	const colors$1 = colors;
	return Object.keys(colors$1).map((label) => ({
		kind,
		label,
		documentation: colors$1[label]
	}));
}
function getAttributeCompletions(posistion) {
	const kind = lst.CompletionItemKind.Property;
	const range = {
		start: posistion,
		end: posistion
	};
	return attributes.map((label) => ({
		kind,
		label,
		textEdit: {
			range,
			newText: `${escapeIdentifierText(label)}=`
		}
	}));
}
function getNodeCompletions(symbols, exlucdedSymbols) {
	const res = [];
	for (const [key, value] of symbols) {
		if (exlucdedSymbols?.includes(key)) continue;
		let kind = lst.CompletionItemKind.Variable;
		const a = value.firstMention.parent;
		if (a) switch (a.kind) {
			case syntaxKind.DirectedGraph:
			case syntaxKind.UndirectedGraph:
				kind = lst.CompletionItemKind.Class;
				break;
		}
		res.push({
			label: escapeIdentifierText(key),
			kind
		});
	}
	return res;
}

//#endregion
//#region src/service/hover.ts
function hover(doc, sourceFile, position) {
	const offset = doc.offsetAt(position);
	const g = sourceFile.graph;
	if (!g) return void 0;
	const node = findNodeAtOffset(g, offset);
	if (node === void 0) return void 0;
	return getNodeHover(doc, sourceFile, node);
}
function getNodeHover(doc, sf, n) {
	const contents = getHoverContents(n);
	if (contents) return {
		contents,
		range: syntaxNodeToRange(doc, sf, n)
	};
}
function getAssignedLabel(statement) {
	const assignedLabel = statement.attributes.flatMap((a) => a.assignments)?.find((a) => getIdentifierText(a.leftId) === "label");
	return assignedLabel?.rightId ? getIdentifierText(assignedLabel.rightId) : void 0;
}
function getHoverContents(n) {
	if (isIdentifierNode(n)) {
		const parent = n.parent;
		if (parent) {
			switch (parent.kind) {
				case syntaxKind.NodeId:
					if (n.symbol?.references) {
						const labelMentions = (n.symbol?.references).map((e) => e.symbol?.members?.get("label")?.firstMention.parent);
						for (let i = labelMentions.length; i >= 0; i--) {
							const s = labelMentions[i];
							if (s?.rightId) return `(node) ${getIdentifierText(n)}: ${getIdentifierText(s.rightId)}`;
						}
					} else if (parent.parent?.kind === syntaxKind.NodeStatement) {
						const label = getAssignedLabel(parent.parent);
						if (label) return `(node) ${getIdentifierText(n)}: ${label}`;
					}
					return `(node) ${getIdentifierText(n)}`;
				case syntaxKind.Assignment: {
					const assignment = parent;
					return `(assignment) \`${getIdentifierText(assignment.leftId)}\` = \`${getIdentifierText(assignment.rightId)}\``;
				}
				case syntaxKind.DirectedGraph: return getGraphHover(parent);
				case syntaxKind.UndirectedGraph: return getGraphHover(parent);
				case syntaxKind.SubGraphStatement: {
					const sg = parent.subgraph;
					return sg.id ? `(sub graph) ${getIdentifierText(sg.id)}` : "(sub graph)";
				}
				case syntaxKind.SubGraph: {
					const sg = parent;
					return sg.id ? `(sub graph) ${getIdentifierText(sg.id)}` : "(sub graph)";
				}
				case syntaxKind.IdEqualsIdStatement: {
					const idEqId = parent;
					return `(graph property) \`${getIdentifierText(idEqId.leftId)}\` = \`${getIdentifierText(idEqId.rightId)}\``;
				}
				case syntaxKind.EdgeRhs: return getEdgeHover(parent);
			}
			return syntaxKindNames[parent.kind];
		}
		const fallback = syntaxKindNames[n.kind];
		return fallback ? `(${fallback.toLowerCase()})` : void 0;
	}
	switch (n.kind) {
		case syntaxKind.GraphKeyword:
		case syntaxKind.DigraphKeyword:
		case syntaxKind.StrictKeyword: return getGraphHover(n.parent);
		case syntaxKind.DirectedGraph:
		case syntaxKind.UndirectedGraph: return getGraphHover(n);
		case syntaxKind.DirectedEdgeOp:
		case syntaxKind.UndirectedEdgeOp: return getEdgeHover(n.parent);
		default: return;
	}
}
function getGraphHover(g) {
	const direction = g.kind === syntaxKind.DirectedGraph ? "directed" : "undirected";
	const graphId = g.id;
	const strict = g.strict ? "strict " : "";
	return graphId ? `(${strict}${direction} graph) ${getIdentifierText(graphId)}` : `(${strict}${direction} graph)`;
}
function getEdgeHover(n) {
	const p = n.parent;
	if (!p || p.rhs.length === 0) return void 0;
	let source;
	for (const curr of p.rhs) {
		if (curr === n) break;
		source = curr.target;
	}
	if (source === void 0) source = p.source;
	const edgeOpStr = getEdgeStr(n.operation.kind);
	return source === void 0 ? void 0 : `(edge) ${getEdgeSourceOrTargetText(source)} ${edgeOpStr} ${getEdgeSourceOrTargetText(n.target)}`;
}
function getEdgeSourceOrTargetText(n) {
	return n.kind === syntaxKind.NodeId ? getIdentifierText(n.id) : n.id !== void 0 ? `${getIdentifierText(n.id)}` : "sub graph";
}

//#endregion
//#region src/service/reference.ts
function findReferences(doc, sourceFile, position, context) {
	if (!sourceFile.symbols) throw "sourceFile is not bound";
	const g = sourceFile.graph;
	if (!g) return [];
	const node = findNodeAtOffset(g, doc.offsetAt(position));
	if (!node) return [];
	if (isIdentifierNode(node)) {
		const nodeSymbol = node.symbol;
		if (!nodeSymbol) throw "node.symbol is not bound";
		const refs = nodeSymbol.references || [];
		let symbolRefs;
		if (context.includeDeclaration) symbolRefs = [nodeSymbol.firstMention, ...refs];
		else if (nodeSymbol.firstMention === node) symbolRefs = refs;
		else symbolRefs = [nodeSymbol.firstMention, ...refs.filter((r) => r !== node)];
		const ranges = syntaxNodesToRanges(doc, sourceFile, symbolRefs);
		const uri = doc.uri;
		return ranges.map((range) => {
			return {
				uri,
				range
			};
		});
	}
	debugger;
	return [];
}
function findDefinition(doc, sourceFile, position) {
	if (!sourceFile.symbols) throw "sourceFile is not bound";
	const g = sourceFile.graph;
	if (!g) return void 0;
	const node = findNodeAtOffset(g, doc.offsetAt(position));
	if (!node) return void 0;
	if (isIdentifierNode(node)) {
		const nodeSymbol = node.symbol;
		if (!nodeSymbol) throw "node.symbol is not bound";
		const firstMention = nodeSymbol.firstMention;
		if (!firstMention) return void 0;
		const range = syntaxNodeToRange(doc, sourceFile, firstMention);
		return {
			uri: doc.uri,
			range
		};
	}
	debugger;
}

//#endregion
//#region src/service/rename.ts
function renameSymbol(doc, sourceFile, position, newName) {
	if (!sourceFile.symbols) throw "sourceFile is not bound";
	if (!newName) return void 0;
	const g = sourceFile.graph;
	if (!g) return void 0;
	const node = findNodeAtOffset(g, doc.offsetAt(position));
	if (!node) return void 0;
	const parent = node.parent;
	if (isIdentifierNode(node) && isRenamableIdentifier(node) && !!parent && isRenameableNode(parent)) {
		const nodeSymbol = node.symbol;
		if (!nodeSymbol) throw "node.symbol is not bound";
		const r = nodeSymbol.references;
		const ranges = syntaxNodesToRanges(doc, sourceFile, r ? [nodeSymbol.firstMention, ...r] : [nodeSymbol.firstMention]);
		return { changes: { [doc.uri]: ranges.map((r$1) => TextEdit.replace(r$1, newName)) } };
	}
	debugger;
}
function isRenameableNode(node) {
	return node.kind === syntaxKind.NodeId || node.kind === syntaxKind.DirectedGraph || node.kind === syntaxKind.UndirectedGraph;
}
function isRenamableIdentifier(node) {
	return node.kind !== syntaxKind.QuotedTextIdentifier;
}

//#endregion
//#region src/error.ts
const diagnosicSource = "DOT";
const subErrorCodeLength = 3;
function formatError(error) {
	const subCode = (error.sub | 0).toString().padStart(subErrorCodeLength, "0");
	return diagnosicSource + error.source + subCode;
}

//#endregion
//#region src/service/validation.ts
function convertDiagnostic(document, source) {
	return {
		range: {
			start: document.positionAt(source.start),
			end: document.positionAt(source.end)
		},
		severity: source.category,
		code: formatError(source.code),
		source: diagnosicSource,
		message: source.message
	};
}
function validateDocument(doc, sourceFile) {
	const diagnostics = sourceFile.diagnostics;
	if (!diagnostics || diagnostics.length <= 0) return [];
	return diagnostics.map((d) => convertDiagnostic(doc, d));
}

//#endregion
//#region src/service/service.ts
function parseDocument(doc) {
	const parser = new Parser();
	const content = typeof doc === "string" ? doc : doc.getText();
	const sourceFile = parser.parse(content);
	bindSourceFile(sourceFile);
	checkSourceFile(sourceFile);
	return sourceFile;
}
function createService() {
	return {
		parseDocument,
		validateDocument,
		hover,
		findReferences,
		findDefinition,
		renameSymbol,
		getCompletions,
		getDocumentColors,
		getColorRepresentations,
		getCodeActions,
		executeCommand,
		getAvailableCommands
	};
}

//#endregion
export { DefaultScanner, Parser, characterCodes, checkError, createService, diagnosticCategory, errorSource, forEachChild, getTextAsToken, getTokenAsText, graphContext, isIdentifier, isIdentifierNode, isIdentifierStart, isLineBreak, parseError, parsingContext, scanError, skipTrivia, syntaxKind, syntaxKindNames, syntaxNodeFlags, tokenFlags };