dot-language-support 2.2.1 → 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/dependabot.yml +5 -1
- package/.github/workflows/CD.yml +6 -3
- package/.github/workflows/CI.yml +7 -4
- package/.github/workflows/auto-merge.yaml +26 -0
- package/biome.json +50 -0
- package/lib/cjs/binder.d.ts +1 -1
- package/lib/cjs/binder.js +2 -5
- package/lib/cjs/checker.d.ts +1 -1
- package/lib/cjs/checker.js +34 -30
- package/lib/cjs/core.js +2 -3
- package/lib/cjs/error.js +3 -5
- package/lib/cjs/parser.d.ts +4 -61
- package/lib/cjs/parser.js +580 -616
- package/lib/cjs/scanner.d.ts +2 -13
- package/lib/cjs/scanner.js +316 -317
- package/lib/cjs/service/codeAction.d.ts +3 -3
- package/lib/cjs/service/codeAction.js +28 -32
- package/lib/cjs/service/colorProvider.d.ts +3 -3
- package/lib/cjs/service/colorProvider.js +13 -24
- package/lib/cjs/service/command/ChangeAllOtherEdgeOpsAndFixGraphCommand.d.ts +4 -4
- package/lib/cjs/service/command/ChangeAllOtherEdgeOpsAndFixGraphCommand.js +5 -6
- package/lib/cjs/service/command/ChangeEdgeOpCommand.d.ts +3 -3
- package/lib/cjs/service/command/ChangeEdgeOpCommand.js +5 -8
- package/lib/cjs/service/command/ConsolidateDescendantsCommand.d.ts +4 -4
- package/lib/cjs/service/command/ConsolidateDescendantsCommand.js +12 -13
- package/lib/cjs/service/command/RemoveSemicolons.d.ts +4 -4
- package/lib/cjs/service/command/RemoveSemicolons.js +8 -11
- package/lib/cjs/service/command/common.d.ts +4 -4
- package/lib/cjs/service/command/common.js +12 -10
- package/lib/cjs/service/completion.d.ts +2 -2
- package/lib/cjs/service/completion.js +17 -18
- package/lib/cjs/service/hover.d.ts +2 -2
- package/lib/cjs/service/hover.js +12 -16
- package/lib/cjs/service/languageFacts.js +1 -6
- package/lib/cjs/service/reference.d.ts +2 -2
- package/lib/cjs/service/reference.js +4 -8
- package/lib/cjs/service/rename.d.ts +3 -3
- package/lib/cjs/service/rename.js +10 -8
- package/lib/cjs/service/service.d.ts +3 -3
- package/lib/cjs/service/service.js +7 -8
- package/lib/cjs/service/util.d.ts +1 -1
- package/lib/cjs/service/util.js +10 -13
- package/lib/cjs/service/validation.d.ts +3 -3
- package/lib/cjs/service/validation.js +1 -2
- package/lib/cjs/tester.js +1 -1
- package/lib/cjs/visitor.d.ts +1 -1
- package/lib/cjs/visitor.js +32 -34
- package/lib/esm/binder.d.ts +1 -1
- package/lib/esm/binder.js +1 -3
- package/lib/esm/checker.d.ts +1 -1
- package/lib/esm/checker.js +21 -16
- package/lib/esm/core.js +1 -1
- package/lib/esm/error.js +1 -3
- package/lib/esm/parser.d.ts +4 -61
- package/lib/esm/parser.js +320 -306
- package/lib/esm/scanner.d.ts +2 -13
- package/lib/esm/scanner.js +153 -152
- package/lib/esm/service/codeAction.d.ts +3 -3
- package/lib/esm/service/codeAction.js +26 -29
- package/lib/esm/service/colorProvider.d.ts +3 -3
- package/lib/esm/service/colorProvider.js +11 -21
- package/lib/esm/service/command/ChangeAllOtherEdgeOpsAndFixGraphCommand.d.ts +4 -4
- package/lib/esm/service/command/ChangeAllOtherEdgeOpsAndFixGraphCommand.js +4 -4
- package/lib/esm/service/command/ChangeEdgeOpCommand.d.ts +3 -3
- package/lib/esm/service/command/ChangeEdgeOpCommand.js +3 -5
- package/lib/esm/service/command/ConsolidateDescendantsCommand.d.ts +4 -4
- package/lib/esm/service/command/ConsolidateDescendantsCommand.js +11 -11
- package/lib/esm/service/command/RemoveSemicolons.d.ts +4 -4
- package/lib/esm/service/command/RemoveSemicolons.js +6 -8
- package/lib/esm/service/command/common.d.ts +4 -4
- package/lib/esm/service/command/common.js +7 -4
- package/lib/esm/service/completion.d.ts +2 -2
- package/lib/esm/service/completion.js +16 -16
- package/lib/esm/service/hover.d.ts +2 -2
- package/lib/esm/service/hover.js +8 -14
- package/lib/esm/service/languageFacts.js +1 -6
- package/lib/esm/service/reference.d.ts +2 -2
- package/lib/esm/service/reference.js +3 -6
- package/lib/esm/service/rename.d.ts +3 -3
- package/lib/esm/service/rename.js +9 -6
- package/lib/esm/service/service.d.ts +3 -3
- package/lib/esm/service/service.js +7 -7
- package/lib/esm/service/util.d.ts +1 -1
- package/lib/esm/service/util.js +5 -7
- package/lib/esm/service/validation.d.ts +3 -3
- package/lib/esm/service/validation.js +1 -1
- package/lib/esm/tester.js +1 -1
- package/lib/esm/visitor.d.ts +1 -1
- package/lib/esm/visitor.js +32 -33
- package/package.json +17 -12
package/lib/esm/parser.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DefaultScanner, getTokenAsText } from "./scanner.js";
|
|
2
2
|
import { assertNever } from "./service/util.js";
|
|
3
|
-
import {
|
|
3
|
+
import { DiagnosticCategory, SyntaxKind, } from "./types";
|
|
4
4
|
export var ParsingContext;
|
|
5
5
|
(function (ParsingContext) {
|
|
6
6
|
ParsingContext[ParsingContext["None"] = 0] = "None";
|
|
@@ -22,12 +22,12 @@ export class Parser {
|
|
|
22
22
|
currentContext;
|
|
23
23
|
diagnostics;
|
|
24
24
|
constructor() {
|
|
25
|
-
this
|
|
25
|
+
this.#resetState();
|
|
26
26
|
}
|
|
27
|
-
resetState() {
|
|
27
|
+
#resetState() {
|
|
28
28
|
this.sourceText = "";
|
|
29
29
|
this.scanner.setText(this.sourceText);
|
|
30
|
-
this.scanner.setErrorCallback(this
|
|
30
|
+
this.scanner.setErrorCallback(this.#scanError.bind(this));
|
|
31
31
|
this.identifierCount = 0;
|
|
32
32
|
this.identifiers = new Set();
|
|
33
33
|
this.nodeCount = 0;
|
|
@@ -35,24 +35,25 @@ export class Parser {
|
|
|
35
35
|
this.currentNodeHasError = false;
|
|
36
36
|
this.currentContext = ParsingContext.None;
|
|
37
37
|
}
|
|
38
|
-
nextToken() {
|
|
39
|
-
|
|
38
|
+
#nextToken() {
|
|
39
|
+
this.currentToken = this.scanner.scan(true);
|
|
40
|
+
return this.currentToken;
|
|
40
41
|
}
|
|
41
|
-
token() {
|
|
42
|
+
#token() {
|
|
42
43
|
return this.currentToken;
|
|
43
44
|
}
|
|
44
|
-
getLinesFromFile(sourceText) {
|
|
45
|
+
#getLinesFromFile(sourceText) {
|
|
45
46
|
return sourceText.split(/\r?\n/);
|
|
46
47
|
}
|
|
47
48
|
parse(sourceText) {
|
|
48
49
|
this.sourceText = sourceText;
|
|
49
50
|
this.scanner.setText(this.sourceText);
|
|
50
|
-
this
|
|
51
|
+
this.#nextToken();
|
|
51
52
|
let graph = undefined;
|
|
52
|
-
if (this
|
|
53
|
-
graph = this
|
|
54
|
-
if (this
|
|
55
|
-
this
|
|
53
|
+
if (this.#token() !== SyntaxKind.EndOfFileToken) {
|
|
54
|
+
graph = this.#parseGraph();
|
|
55
|
+
if (this.#token() !== SyntaxKind.EndOfFileToken) {
|
|
56
|
+
this.#parseErrorAtPosition(this.scanner.tokenPos, this.scanner.text.length - 1, "Content after the end of a graph declaration is invalid.", { source: 2, sub: 1 });
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
const result = {
|
|
@@ -61,258 +62,267 @@ export class Parser {
|
|
|
61
62
|
identifiers: this.identifiers,
|
|
62
63
|
diagnostics: this.diagnostics,
|
|
63
64
|
};
|
|
64
|
-
this
|
|
65
|
+
this.#resetState();
|
|
65
66
|
return result;
|
|
66
67
|
}
|
|
67
|
-
parseGraph() {
|
|
68
|
-
const strictToken = this
|
|
69
|
-
const keyword = this
|
|
68
|
+
#parseGraph() {
|
|
69
|
+
const strictToken = this.#parseOptionalToken(SyntaxKind.StrictKeyword);
|
|
70
|
+
const keyword = this.#parseExpectedTokenOneOf(SyntaxKind.DigraphKeyword, [
|
|
71
|
+
SyntaxKind.DigraphKeyword,
|
|
72
|
+
SyntaxKind.GraphKeyword,
|
|
73
|
+
]);
|
|
70
74
|
const kind = keyword === undefined || keyword.kind === SyntaxKind.DigraphKeyword
|
|
71
75
|
? SyntaxKind.DirectedGraph
|
|
72
76
|
: SyntaxKind.UndirectedGraph;
|
|
73
77
|
const graphStart = strictToken ? strictToken.pos : keyword.pos;
|
|
74
|
-
const node = this
|
|
78
|
+
const node = this.#createNode(kind, graphStart);
|
|
75
79
|
node.strict = strictToken;
|
|
76
80
|
node.keyword = keyword;
|
|
77
|
-
node.id = this
|
|
78
|
-
this
|
|
79
|
-
node.statements = this
|
|
80
|
-
this
|
|
81
|
-
return this
|
|
81
|
+
node.id = this.#isIdentifier() ? this.#parseIdentifier() : undefined;
|
|
82
|
+
this.#parseExpectedToken(SyntaxKind.OpenBraceToken);
|
|
83
|
+
node.statements = this.#parseList(ParsingContext.StatementList, () => this.#parseStatement());
|
|
84
|
+
this.#parseExpectedToken(SyntaxKind.CloseBraceToken);
|
|
85
|
+
return this.#finishNode(node);
|
|
82
86
|
}
|
|
83
|
-
parseIdentifier() {
|
|
87
|
+
#parseIdentifier() {
|
|
84
88
|
let result;
|
|
85
|
-
|
|
86
|
-
switch (this
|
|
89
|
+
const escapedIdTexts = new Array();
|
|
90
|
+
switch (this.#token()) {
|
|
87
91
|
case SyntaxKind.TextIdentifier:
|
|
88
|
-
result = this
|
|
92
|
+
result = this.#parseTextIdentifier();
|
|
89
93
|
escapedIdTexts.push(result.text);
|
|
90
94
|
break;
|
|
91
95
|
case SyntaxKind.StringLiteral:
|
|
92
|
-
result = this
|
|
96
|
+
result = this.#parseQuotedTextIdentifierConcatenation();
|
|
93
97
|
escapedIdTexts.push(...result.values.map(v => v.text));
|
|
94
98
|
break;
|
|
95
99
|
case SyntaxKind.HtmlIdentifier:
|
|
96
|
-
result = this
|
|
100
|
+
result = this.#parseHtmlIdentifier();
|
|
97
101
|
escapedIdTexts.push(result.htmlContent);
|
|
98
102
|
break;
|
|
99
103
|
case SyntaxKind.NumericIdentifier:
|
|
100
|
-
result = this
|
|
104
|
+
result = this.#parseNumericIdentifier();
|
|
101
105
|
escapedIdTexts.push(result.text);
|
|
102
106
|
break;
|
|
103
107
|
default:
|
|
104
|
-
this
|
|
105
|
-
result = this
|
|
108
|
+
this.#reportExpectedError([SyntaxKind.TextIdentifier]);
|
|
109
|
+
result = this.#createMissingNode(SyntaxKind.TextIdentifier);
|
|
106
110
|
break;
|
|
107
111
|
}
|
|
108
|
-
|
|
112
|
+
for (const i of escapedIdTexts) {
|
|
113
|
+
this.#registerIdentifier(i);
|
|
114
|
+
}
|
|
109
115
|
return result;
|
|
110
116
|
}
|
|
111
|
-
registerIdentifier(id) {
|
|
117
|
+
#registerIdentifier(id) {
|
|
112
118
|
this.identifierCount++;
|
|
113
119
|
const has = this.identifiers.has(id);
|
|
114
120
|
if (!has)
|
|
115
121
|
this.identifiers.add(id);
|
|
116
122
|
}
|
|
117
|
-
parseTextIdentifier() {
|
|
118
|
-
const node = this
|
|
123
|
+
#parseTextIdentifier() {
|
|
124
|
+
const node = this.#createNode(SyntaxKind.TextIdentifier);
|
|
119
125
|
const text = this.scanner.tokenValue;
|
|
120
|
-
this
|
|
126
|
+
this.#nextToken();
|
|
121
127
|
if (text === undefined)
|
|
122
128
|
throw "Satisfy type checker";
|
|
123
129
|
node.text = text;
|
|
124
|
-
return this
|
|
130
|
+
return this.#finishNode(node);
|
|
125
131
|
}
|
|
126
|
-
parseQuotedTextIdentifierConcatenation() {
|
|
127
|
-
const node = this
|
|
128
|
-
node.values = this
|
|
129
|
-
return this
|
|
132
|
+
#parseQuotedTextIdentifierConcatenation() {
|
|
133
|
+
const node = this.#createNode(SyntaxKind.QuotedTextIdentifier);
|
|
134
|
+
node.values = this.#parseList(ParsingContext.QuotedTextIdentifierConcatenation, () => this.#parseQuotedTextIdentifier(), true);
|
|
135
|
+
return this.#finishNode(node);
|
|
130
136
|
}
|
|
131
|
-
parseQuotedTextIdentifier() {
|
|
132
|
-
const node = this
|
|
133
|
-
if (this
|
|
134
|
-
this
|
|
137
|
+
#parseQuotedTextIdentifier() {
|
|
138
|
+
const node = this.#createNode(SyntaxKind.StringLiteral);
|
|
139
|
+
if (this.#token() === SyntaxKind.PlusToken)
|
|
140
|
+
this.#nextToken();
|
|
135
141
|
const text = this.scanner.tokenValue;
|
|
136
|
-
this
|
|
142
|
+
this.#nextToken();
|
|
137
143
|
if (text === undefined)
|
|
138
144
|
throw "Satisfy type checker";
|
|
139
145
|
node.text = text;
|
|
140
|
-
return this
|
|
146
|
+
return this.#finishNode(node);
|
|
141
147
|
}
|
|
142
|
-
isQuotedStringFollowing() {
|
|
143
|
-
this
|
|
144
|
-
return this
|
|
148
|
+
#isQuotedStringFollowing() {
|
|
149
|
+
this.#nextToken();
|
|
150
|
+
return this.#token() === SyntaxKind.StringLiteral;
|
|
145
151
|
}
|
|
146
|
-
parseHtmlIdentifier() {
|
|
147
|
-
const node = this
|
|
152
|
+
#parseHtmlIdentifier() {
|
|
153
|
+
const node = this.#createNode(SyntaxKind.HtmlIdentifier);
|
|
148
154
|
const text = this.scanner.tokenValue;
|
|
149
|
-
this
|
|
155
|
+
this.#nextToken();
|
|
150
156
|
if (text === undefined)
|
|
151
157
|
throw "Satisfy type checker";
|
|
152
158
|
node.htmlContent = text;
|
|
153
|
-
return this
|
|
159
|
+
return this.#finishNode(node);
|
|
154
160
|
}
|
|
155
|
-
parseNumericIdentifier() {
|
|
156
|
-
const node = this
|
|
161
|
+
#parseNumericIdentifier() {
|
|
162
|
+
const node = this.#createNode(SyntaxKind.NumericIdentifier);
|
|
157
163
|
const text = this.scanner.tokenValue;
|
|
158
|
-
this
|
|
164
|
+
this.#nextToken();
|
|
159
165
|
if (text === undefined)
|
|
160
166
|
throw "Satisfy type checker";
|
|
161
167
|
node.text = text;
|
|
162
168
|
node.value = Number(text);
|
|
163
|
-
return this
|
|
169
|
+
return this.#finishNode(node);
|
|
164
170
|
}
|
|
165
|
-
parseStatement() {
|
|
166
|
-
switch (this
|
|
171
|
+
#parseStatement() {
|
|
172
|
+
switch (this.#token()) {
|
|
167
173
|
case SyntaxKind.GraphKeyword:
|
|
168
174
|
case SyntaxKind.NodeKeyword:
|
|
169
175
|
case SyntaxKind.EdgeKeyword:
|
|
170
|
-
return this
|
|
176
|
+
return this.#parseAttributeStatement();
|
|
171
177
|
case SyntaxKind.OpenBraceToken:
|
|
172
|
-
case SyntaxKind.SubgraphKeyword:
|
|
173
|
-
const subgraph = this
|
|
174
|
-
if (this
|
|
175
|
-
const subgraphStatement = this
|
|
178
|
+
case SyntaxKind.SubgraphKeyword: {
|
|
179
|
+
const subgraph = this.#parseSubGraph();
|
|
180
|
+
if (this.#token() === SyntaxKind.SemicolonToken) {
|
|
181
|
+
const subgraphStatement = this.#createNode(SyntaxKind.SubGraphStatement, subgraph.pos);
|
|
176
182
|
subgraphStatement.subgraph = subgraph;
|
|
177
|
-
subgraphStatement.terminator = this
|
|
178
|
-
return this
|
|
183
|
+
subgraphStatement.terminator = this.#parseExpectedToken(SyntaxKind.SemicolonToken);
|
|
184
|
+
return this.#finishNode(subgraphStatement);
|
|
179
185
|
}
|
|
180
|
-
if (this
|
|
181
|
-
return this
|
|
182
|
-
const subgraphStatement = this
|
|
186
|
+
if (this.#isEdgeOp())
|
|
187
|
+
return this.#parseEdgeStatement(subgraph);
|
|
188
|
+
const subgraphStatement = this.#createNode(SyntaxKind.SubGraphStatement, subgraph.pos);
|
|
183
189
|
subgraphStatement.subgraph = subgraph;
|
|
184
|
-
return this
|
|
190
|
+
return this.#finishNode(subgraphStatement);
|
|
191
|
+
}
|
|
185
192
|
default: {
|
|
186
|
-
if (!this
|
|
193
|
+
if (!this.#isIdentifier)
|
|
187
194
|
debugger;
|
|
188
|
-
if (this
|
|
189
|
-
return this
|
|
195
|
+
if (this.#lookAhead(() => this.#isIdEqualsIdStatement())) {
|
|
196
|
+
return this.#parseIdEqualsIdStatement();
|
|
190
197
|
}
|
|
191
|
-
const ns = this
|
|
198
|
+
const ns = this.#parseNodeStatement();
|
|
192
199
|
if (ns.terminator !== undefined || ns.attributes.length !== 0)
|
|
193
200
|
return ns;
|
|
194
|
-
if (this
|
|
195
|
-
return this
|
|
201
|
+
if (this.#isEdgeOp())
|
|
202
|
+
return this.#parseEdgeStatement(ns.id);
|
|
196
203
|
return ns;
|
|
197
204
|
}
|
|
198
205
|
}
|
|
199
206
|
}
|
|
200
|
-
parseAttributeStatement() {
|
|
201
|
-
switch (this
|
|
207
|
+
#parseAttributeStatement() {
|
|
208
|
+
switch (this.#token()) {
|
|
202
209
|
case SyntaxKind.GraphKeyword:
|
|
203
210
|
case SyntaxKind.NodeKeyword:
|
|
204
|
-
case SyntaxKind.EdgeKeyword:
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
node.attributes = this.parseList(ParsingContext.AttributeContainerList, () => this.parseAttributeContainer());
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
this.reportExpectedError([SyntaxKind.OpenBracketToken]);
|
|
213
|
-
const missingStatement = this.createMissingNode(SyntaxKind.AttributeStatement);
|
|
214
|
-
missingStatement.attributes = this.createNodeArray([this.createMissingNode(SyntaxKind.AttributeContainer)], this.scanner.tokenPos, this.scanner.tokenPos);
|
|
215
|
-
}
|
|
216
|
-
node.terminator = this.parseOptionalToken(SyntaxKind.SemicolonToken);
|
|
217
|
-
return this.finishNode(node);
|
|
211
|
+
case SyntaxKind.EdgeKeyword: {
|
|
212
|
+
const node = this.#createNode(SyntaxKind.AttributeStatement);
|
|
213
|
+
node.subject = this.#parseTokenNode();
|
|
214
|
+
if (this.#token() === SyntaxKind.OpenBracketToken) {
|
|
215
|
+
node.attributes = this.#parseList(ParsingContext.AttributeContainerList, () => this.#parseAttributeContainer());
|
|
218
216
|
}
|
|
219
|
-
|
|
217
|
+
else {
|
|
218
|
+
this.#reportExpectedError([SyntaxKind.OpenBracketToken]);
|
|
219
|
+
const missingStatement = this.#createMissingNode(SyntaxKind.AttributeStatement);
|
|
220
|
+
missingStatement.attributes = this.#createNodeArray([this.#createMissingNode(SyntaxKind.AttributeContainer)], this.scanner.tokenPos, this.scanner.tokenPos);
|
|
221
|
+
}
|
|
222
|
+
node.terminator = this.#parseOptionalToken(SyntaxKind.SemicolonToken);
|
|
223
|
+
return this.#finishNode(node);
|
|
224
|
+
}
|
|
225
|
+
default:
|
|
226
|
+
throw "This should never happen";
|
|
220
227
|
}
|
|
221
228
|
}
|
|
222
|
-
parseAttributeContainer() {
|
|
223
|
-
if (this
|
|
229
|
+
#parseAttributeContainer() {
|
|
230
|
+
if (this.#token() !== SyntaxKind.OpenBracketToken)
|
|
224
231
|
debugger;
|
|
225
|
-
const node = this
|
|
226
|
-
node.openBracket = this
|
|
227
|
-
if (this
|
|
228
|
-
node.assignments = this
|
|
232
|
+
const node = this.#createNode(SyntaxKind.AttributeContainer);
|
|
233
|
+
node.openBracket = this.#parseExpectedToken(SyntaxKind.OpenBracketToken);
|
|
234
|
+
if (this.#isIdentifier() && this.#lookAhead(() => this.#isAssignmentStart())) {
|
|
235
|
+
node.assignments = this.#parseList(ParsingContext.AssignmentList, () => this.#parseAssignment());
|
|
229
236
|
}
|
|
230
237
|
else {
|
|
231
|
-
node.assignments = this
|
|
238
|
+
node.assignments = this.#createEmptyArray();
|
|
232
239
|
}
|
|
233
|
-
node.closeBracket = this
|
|
234
|
-
return this
|
|
240
|
+
node.closeBracket = this.#parseExpectedToken(SyntaxKind.CloseBracketToken);
|
|
241
|
+
return this.#finishNode(node);
|
|
235
242
|
}
|
|
236
|
-
isAssignmentStart() {
|
|
237
|
-
if (!this
|
|
243
|
+
#isAssignmentStart() {
|
|
244
|
+
if (!this.#isIdentifier)
|
|
238
245
|
debugger;
|
|
239
|
-
this
|
|
240
|
-
return this
|
|
246
|
+
this.#nextToken();
|
|
247
|
+
return this.#token() === SyntaxKind.EqualsToken;
|
|
241
248
|
}
|
|
242
|
-
parseIdEqualsIdStatement() {
|
|
243
|
-
if (!this
|
|
249
|
+
#parseIdEqualsIdStatement() {
|
|
250
|
+
if (!this.#isIdentifier)
|
|
244
251
|
debugger;
|
|
245
|
-
const leftIdentifier = this
|
|
246
|
-
const node = this
|
|
252
|
+
const leftIdentifier = this.#parseIdentifier();
|
|
253
|
+
const node = this.#createNode(SyntaxKind.IdEqualsIdStatement, leftIdentifier.pos);
|
|
247
254
|
node.leftId = leftIdentifier;
|
|
248
|
-
if (this
|
|
255
|
+
if (this.#token() !== SyntaxKind.EqualsToken)
|
|
249
256
|
debugger;
|
|
250
|
-
this
|
|
251
|
-
node.rightId = this
|
|
252
|
-
node.terminator = this
|
|
253
|
-
return this
|
|
257
|
+
this.#parseExpectedToken(SyntaxKind.EqualsToken);
|
|
258
|
+
node.rightId = this.#parseIdentifier();
|
|
259
|
+
node.terminator = this.#parseOptionalToken(SyntaxKind.SemicolonToken);
|
|
260
|
+
return this.#finishNode(node);
|
|
254
261
|
}
|
|
255
|
-
isIdEqualsIdStatement() {
|
|
256
|
-
if (!this
|
|
262
|
+
#isIdEqualsIdStatement() {
|
|
263
|
+
if (!this.#isIdentifier)
|
|
257
264
|
debugger;
|
|
258
|
-
this
|
|
259
|
-
return this
|
|
265
|
+
this.#nextToken();
|
|
266
|
+
return this.#token() === SyntaxKind.EqualsToken;
|
|
260
267
|
}
|
|
261
|
-
parseNodeStatement() {
|
|
262
|
-
if (!this
|
|
268
|
+
#parseNodeStatement() {
|
|
269
|
+
if (!this.#isIdentifier)
|
|
263
270
|
debugger;
|
|
264
|
-
const node = this
|
|
265
|
-
node.id = this
|
|
266
|
-
if (this
|
|
267
|
-
node.attributes = this
|
|
271
|
+
const node = this.#createNode(SyntaxKind.NodeStatement);
|
|
272
|
+
node.id = this.#parseNodeId();
|
|
273
|
+
if (this.#token() === SyntaxKind.OpenBracketToken) {
|
|
274
|
+
node.attributes = this.#parseList(ParsingContext.AttributeContainerList, () => this.#parseAttributeContainer());
|
|
268
275
|
}
|
|
269
276
|
else {
|
|
270
|
-
node.attributes = this
|
|
277
|
+
node.attributes = this.#createEmptyArray();
|
|
271
278
|
}
|
|
272
|
-
node.terminator = this
|
|
273
|
-
return this
|
|
279
|
+
node.terminator = this.#parseOptionalToken(SyntaxKind.SemicolonToken);
|
|
280
|
+
return this.#finishNode(node);
|
|
274
281
|
}
|
|
275
|
-
parseEdgeStatement(precedingItem) {
|
|
282
|
+
#parseEdgeStatement(precedingItem) {
|
|
276
283
|
console.assert(precedingItem.kind === SyntaxKind.SubGraph || precedingItem.kind === SyntaxKind.NodeId);
|
|
277
284
|
console.assert(precedingItem.pos !== undefined);
|
|
278
|
-
if (!this
|
|
285
|
+
if (!this.#isEdgeOp())
|
|
279
286
|
debugger;
|
|
280
|
-
const node = this
|
|
287
|
+
const node = this.#createNode(SyntaxKind.EdgeStatement, precedingItem.pos);
|
|
281
288
|
node.source = precedingItem;
|
|
282
|
-
node.rhs = this
|
|
283
|
-
if (this
|
|
284
|
-
node.attributes = this
|
|
289
|
+
node.rhs = this.#parseList(ParsingContext.EdgeRhsList, () => this.#parseEdgeRhs());
|
|
290
|
+
if (this.#token() === SyntaxKind.OpenBracketToken) {
|
|
291
|
+
node.attributes = this.#parseList(ParsingContext.AttributeContainerList, () => this.#parseAttributeContainer());
|
|
285
292
|
}
|
|
286
293
|
else {
|
|
287
|
-
node.attributes = this
|
|
294
|
+
node.attributes = this.#createEmptyArray();
|
|
288
295
|
}
|
|
289
|
-
node.terminator = this
|
|
290
|
-
return this
|
|
291
|
-
}
|
|
292
|
-
parseEdgeRhs() {
|
|
293
|
-
const node = this
|
|
294
|
-
const op = this
|
|
296
|
+
node.terminator = this.#parseOptionalToken(SyntaxKind.SemicolonToken);
|
|
297
|
+
return this.#finishNode(node);
|
|
298
|
+
}
|
|
299
|
+
#parseEdgeRhs() {
|
|
300
|
+
const node = this.#createNode(SyntaxKind.EdgeRhs);
|
|
301
|
+
const op = this.#parseExpectedTokenOneOf(SyntaxKind.DirectedEdgeOp, [
|
|
302
|
+
SyntaxKind.DirectedEdgeOp,
|
|
303
|
+
SyntaxKind.UndirectedEdgeOp,
|
|
304
|
+
]);
|
|
295
305
|
node.operation = op;
|
|
296
|
-
switch (this
|
|
306
|
+
switch (this.#token()) {
|
|
297
307
|
case SyntaxKind.SubgraphKeyword:
|
|
298
308
|
case SyntaxKind.OpenBraceToken:
|
|
299
|
-
node.target = this
|
|
309
|
+
node.target = this.#parseSubGraph();
|
|
300
310
|
break;
|
|
301
311
|
default: {
|
|
302
|
-
node.target = this
|
|
312
|
+
node.target = this.#parseNodeId();
|
|
303
313
|
break;
|
|
304
314
|
}
|
|
305
315
|
}
|
|
306
|
-
return this
|
|
316
|
+
return this.#finishNode(node);
|
|
307
317
|
}
|
|
308
|
-
createMissingNode(kind) {
|
|
309
|
-
const result = this
|
|
318
|
+
#createMissingNode(kind) {
|
|
319
|
+
const result = this.#createNode(kind);
|
|
310
320
|
if (isIdentifierNode(result)) {
|
|
311
321
|
switch (result.kind) {
|
|
312
322
|
case SyntaxKind.QuotedTextIdentifier: {
|
|
313
|
-
const literal = this
|
|
323
|
+
const literal = this.#createNode(SyntaxKind.StringLiteral);
|
|
314
324
|
literal.text = "";
|
|
315
|
-
const values = this
|
|
325
|
+
const values = this.#createNodeArray([literal], result.pos, result.pos);
|
|
316
326
|
result.values = values;
|
|
317
327
|
break;
|
|
318
328
|
}
|
|
@@ -325,95 +335,94 @@ export class Parser {
|
|
|
325
335
|
break;
|
|
326
336
|
}
|
|
327
337
|
}
|
|
328
|
-
return this
|
|
338
|
+
return this.#finishNode(result);
|
|
329
339
|
}
|
|
330
|
-
parseAssignment() {
|
|
331
|
-
if (!this
|
|
340
|
+
#parseAssignment() {
|
|
341
|
+
if (!this.#isIdentifier)
|
|
332
342
|
debugger;
|
|
333
|
-
const node = this
|
|
334
|
-
node.leftId = this
|
|
335
|
-
this
|
|
336
|
-
node.rightId = this
|
|
337
|
-
let terminator = this
|
|
343
|
+
const node = this.#createNode(SyntaxKind.Assignment);
|
|
344
|
+
node.leftId = this.#parseIdentifier();
|
|
345
|
+
this.#parseExpectedToken(SyntaxKind.EqualsToken);
|
|
346
|
+
node.rightId = this.#parseIdentifier();
|
|
347
|
+
let terminator = this.#parseOptionalToken(SyntaxKind.CommaToken);
|
|
338
348
|
if (terminator === undefined)
|
|
339
|
-
terminator = this
|
|
349
|
+
terminator = this.#parseOptionalToken(SyntaxKind.SemicolonToken);
|
|
340
350
|
node.terminator = terminator;
|
|
341
|
-
return this
|
|
351
|
+
return this.#finishNode(node);
|
|
342
352
|
}
|
|
343
|
-
parseSubGraph() {
|
|
344
|
-
console.assert(this
|
|
345
|
-
|
|
353
|
+
#parseSubGraph() {
|
|
354
|
+
console.assert(this.#token() === SyntaxKind.SubgraphKeyword ||
|
|
355
|
+
this.#token() === SyntaxKind.OpenBraceToken);
|
|
356
|
+
const subGraph = this.#parseOptionalToken(SyntaxKind.SubgraphKeyword);
|
|
346
357
|
const subGraphStart = subGraph !== undefined ? subGraph.pos : undefined;
|
|
347
|
-
const node = this
|
|
348
|
-
|
|
349
|
-
? this.parseIdentifier()
|
|
350
|
-
: undefined;
|
|
358
|
+
const node = this.#createNode(SyntaxKind.SubGraph, subGraphStart);
|
|
359
|
+
const identifier = subGraph !== undefined && this.#isIdentifier() ? this.#parseIdentifier() : undefined;
|
|
351
360
|
node.id = identifier;
|
|
352
|
-
this
|
|
353
|
-
node.statements = this
|
|
354
|
-
this
|
|
355
|
-
return this
|
|
361
|
+
this.#parseExpectedToken(SyntaxKind.OpenBraceToken);
|
|
362
|
+
node.statements = this.#parseList(ParsingContext.StatementList, () => this.#parseStatement());
|
|
363
|
+
this.#parseExpectedToken(SyntaxKind.CloseBraceToken);
|
|
364
|
+
return this.#finishNode(node);
|
|
356
365
|
}
|
|
357
|
-
parseNodeId() {
|
|
358
|
-
if (!this
|
|
366
|
+
#parseNodeId() {
|
|
367
|
+
if (!this.#isIdentifier)
|
|
359
368
|
debugger;
|
|
360
|
-
const node = this
|
|
361
|
-
node.id = this
|
|
362
|
-
node.port =
|
|
363
|
-
? this
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
node.
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
node.
|
|
378
|
-
node.
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
return this
|
|
383
|
-
}
|
|
384
|
-
parsePortDeclaration() {
|
|
385
|
-
console.assert(this
|
|
386
|
-
if (this
|
|
387
|
-
return this
|
|
388
|
-
return this
|
|
389
|
-
}
|
|
390
|
-
isCompassPort() {
|
|
391
|
-
console.assert(this
|
|
392
|
-
if (this
|
|
369
|
+
const node = this.#createNode(SyntaxKind.NodeId);
|
|
370
|
+
node.id = this.#parseIdentifier();
|
|
371
|
+
node.port =
|
|
372
|
+
this.#token() === SyntaxKind.ColonToken ? this.#parsePortDeclaration() : undefined;
|
|
373
|
+
return this.#finishNode(node);
|
|
374
|
+
}
|
|
375
|
+
#parseCompassPortDeclaration() {
|
|
376
|
+
console.assert(this.#token() === SyntaxKind.ColonToken);
|
|
377
|
+
const node = this.#createNode(SyntaxKind.CompassPortDeclaration);
|
|
378
|
+
node.colon = this.#parseTokenNode();
|
|
379
|
+
node.compassPt = this.#parseTokenNode();
|
|
380
|
+
return this.#finishNode(node);
|
|
381
|
+
}
|
|
382
|
+
#parseNormalPortDeclaration() {
|
|
383
|
+
console.assert(this.#token() === SyntaxKind.ColonToken);
|
|
384
|
+
const node = this.#createNode(SyntaxKind.NormalPortDeclaration);
|
|
385
|
+
node.colon = this.#parseTokenNode();
|
|
386
|
+
node.id = this.#parseIdentifier();
|
|
387
|
+
node.compassPt =
|
|
388
|
+
this.#token() === SyntaxKind.ColonToken
|
|
389
|
+
? this.#parseCompassPortDeclaration()
|
|
390
|
+
: undefined;
|
|
391
|
+
return this.#finishNode(node);
|
|
392
|
+
}
|
|
393
|
+
#parsePortDeclaration() {
|
|
394
|
+
console.assert(this.#token() === SyntaxKind.ColonToken);
|
|
395
|
+
if (this.#lookAhead(() => this.#isCompassPort()))
|
|
396
|
+
return this.#parseCompassPortDeclaration();
|
|
397
|
+
return this.#parseNormalPortDeclaration();
|
|
398
|
+
}
|
|
399
|
+
#isCompassPort() {
|
|
400
|
+
console.assert(this.#token() === SyntaxKind.ColonToken);
|
|
401
|
+
if (this.#token() !== SyntaxKind.ColonToken)
|
|
393
402
|
return false;
|
|
394
|
-
this
|
|
395
|
-
return this
|
|
403
|
+
this.#nextToken();
|
|
404
|
+
return this.#isCompassPortKind(this.#token());
|
|
396
405
|
}
|
|
397
|
-
parseList(context, parseElement, atLeastOne = false) {
|
|
406
|
+
#parseList(context, parseElement, atLeastOne = false) {
|
|
398
407
|
const saveParsingContext = this.currentContext;
|
|
399
408
|
this.currentContext |= 1 << context;
|
|
400
|
-
let isListTerminated = atLeastOne ? false : this
|
|
409
|
+
let isListTerminated = atLeastOne ? false : this.#isListTerminator(context);
|
|
401
410
|
const startPos = this.scanner.startPos;
|
|
402
411
|
const elements = new Array();
|
|
403
412
|
while (!isListTerminated) {
|
|
404
|
-
if (this
|
|
413
|
+
if (this.#isListElement(context, false)) {
|
|
405
414
|
const element = parseElement();
|
|
406
415
|
elements.push(element);
|
|
407
|
-
isListTerminated = this
|
|
416
|
+
isListTerminated = this.#isListTerminator(context);
|
|
408
417
|
continue;
|
|
409
418
|
}
|
|
410
|
-
if (this
|
|
419
|
+
if (this.#abortListParsing(context))
|
|
411
420
|
break;
|
|
412
421
|
}
|
|
413
422
|
this.currentContext = saveParsingContext;
|
|
414
|
-
return this
|
|
423
|
+
return this.#createNodeArray(elements, startPos);
|
|
415
424
|
}
|
|
416
|
-
getContextParseError(context) {
|
|
425
|
+
#getContextParseError(context) {
|
|
417
426
|
switch (context) {
|
|
418
427
|
case ParsingContext.StatementList:
|
|
419
428
|
return "Assignment, node definition, graph/node/edge attribute or edge definition expected.";
|
|
@@ -433,48 +442,50 @@ export class Parser {
|
|
|
433
442
|
return assertNever(context);
|
|
434
443
|
}
|
|
435
444
|
}
|
|
436
|
-
isInSomeParsingContext() {
|
|
445
|
+
#isInSomeParsingContext() {
|
|
437
446
|
for (let ctx = 0; ctx < ParsingContext.Count; ctx++) {
|
|
438
447
|
if (this.currentContext & (1 << ctx)) {
|
|
439
|
-
if (this
|
|
448
|
+
if (this.#isListElement(ctx, true) ||
|
|
449
|
+
this.#isListTerminator(ctx)) {
|
|
440
450
|
return true;
|
|
441
451
|
}
|
|
442
452
|
}
|
|
443
453
|
}
|
|
444
454
|
return false;
|
|
445
455
|
}
|
|
446
|
-
abortListParsing(context) {
|
|
447
|
-
this
|
|
448
|
-
if (this
|
|
456
|
+
#abortListParsing(context) {
|
|
457
|
+
this.#parseErrorAtCurrentToken(this.#getContextParseError(context), 2);
|
|
458
|
+
if (this.#isInSomeParsingContext()) {
|
|
449
459
|
return true;
|
|
450
460
|
}
|
|
451
|
-
this
|
|
461
|
+
this.#nextToken();
|
|
452
462
|
return false;
|
|
453
463
|
}
|
|
454
|
-
isListElement(context, _inErrorRecovery) {
|
|
464
|
+
#isListElement(context, _inErrorRecovery) {
|
|
455
465
|
switch (context) {
|
|
456
466
|
case ParsingContext.AssignmentList:
|
|
457
|
-
return this
|
|
467
|
+
return this.#isIdentifier();
|
|
458
468
|
case ParsingContext.AttributeContainerList:
|
|
459
|
-
return this
|
|
469
|
+
return this.#token() === SyntaxKind.OpenBracketToken;
|
|
460
470
|
case ParsingContext.EdgeRhsList:
|
|
461
|
-
return this
|
|
462
|
-
|
|
471
|
+
return (this.#token() === SyntaxKind.DirectedEdgeOp ||
|
|
472
|
+
this.#token() === SyntaxKind.UndirectedEdgeOp);
|
|
463
473
|
case ParsingContext.QuotedTextIdentifierConcatenation:
|
|
464
|
-
return this
|
|
465
|
-
|
|
474
|
+
return (this.#token() === SyntaxKind.StringLiteral ||
|
|
475
|
+
this.#token() === SyntaxKind.PlusToken);
|
|
466
476
|
case ParsingContext.StatementList:
|
|
467
|
-
return this
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
default:
|
|
477
|
+
return (this.#isIdentifier() ||
|
|
478
|
+
this.#token() === SyntaxKind.SubgraphKeyword ||
|
|
479
|
+
this.#token() === SyntaxKind.OpenBraceToken ||
|
|
480
|
+
this.#token() === SyntaxKind.GraphKeyword ||
|
|
481
|
+
this.#token() === SyntaxKind.EdgeKeyword ||
|
|
482
|
+
this.#token() === SyntaxKind.NodeKeyword);
|
|
483
|
+
default:
|
|
484
|
+
throw "This should never happen";
|
|
474
485
|
}
|
|
475
486
|
}
|
|
476
|
-
isListTerminator(context) {
|
|
477
|
-
const token = this
|
|
487
|
+
#isListTerminator(context) {
|
|
488
|
+
const token = this.#token();
|
|
478
489
|
if (token === SyntaxKind.EndOfFileToken)
|
|
479
490
|
return true;
|
|
480
491
|
switch (context) {
|
|
@@ -488,15 +499,16 @@ export class Parser {
|
|
|
488
499
|
return token !== SyntaxKind.DirectedEdgeOp && token !== SyntaxKind.UndirectedEdgeOp;
|
|
489
500
|
case ParsingContext.QuotedTextIdentifierConcatenation:
|
|
490
501
|
return token !== SyntaxKind.PlusToken;
|
|
491
|
-
default:
|
|
502
|
+
default:
|
|
503
|
+
throw "Unsupported parsing context";
|
|
492
504
|
}
|
|
493
505
|
}
|
|
494
|
-
createEmptyArray() {
|
|
506
|
+
#createEmptyArray() {
|
|
495
507
|
const startPos = this.scanner.startPos;
|
|
496
508
|
const elements = new Array();
|
|
497
|
-
return this
|
|
509
|
+
return this.#createNodeArray(elements, startPos);
|
|
498
510
|
}
|
|
499
|
-
finishNode(node, end) {
|
|
511
|
+
#finishNode(node, end) {
|
|
500
512
|
node.end = end === undefined ? this.scanner.startPos : end;
|
|
501
513
|
if (this.currentNodeHasError) {
|
|
502
514
|
this.currentNodeHasError = false;
|
|
@@ -504,33 +516,33 @@ export class Parser {
|
|
|
504
516
|
}
|
|
505
517
|
return node;
|
|
506
518
|
}
|
|
507
|
-
createNode(kind, pos) {
|
|
519
|
+
#createNode(kind, pos) {
|
|
508
520
|
this.nodeCount++;
|
|
509
521
|
const p = pos !== undefined && pos >= 0 ? pos : this.scanner.startPos;
|
|
510
522
|
if (isNodeKind(kind) || kind === SyntaxKind.Unknown)
|
|
511
523
|
return newNode(kind, p, p);
|
|
512
|
-
return isIdentifier(kind)
|
|
513
|
-
? newIdentifier(kind, p, p)
|
|
514
|
-
: newToken(kind, p, p);
|
|
524
|
+
return isIdentifier(kind) ? newIdentifier(kind, p, p) : newToken(kind, p, p);
|
|
515
525
|
}
|
|
516
|
-
createNodeArray(elements, pos, end) {
|
|
526
|
+
#createNodeArray(elements, pos, end) {
|
|
517
527
|
const length = elements.length;
|
|
518
|
-
const array = (length >= 1 && length <= 4 ? elements.slice() : elements);
|
|
528
|
+
const array = ((length >= 1 && length <= 4 ? elements.slice() : elements));
|
|
519
529
|
array.pos = pos;
|
|
520
530
|
array.end = end === undefined ? this.scanner.startPos : end;
|
|
521
531
|
return array;
|
|
522
532
|
}
|
|
523
|
-
parseTokenNode() {
|
|
524
|
-
const node = this
|
|
525
|
-
this
|
|
526
|
-
return this
|
|
533
|
+
#parseTokenNode() {
|
|
534
|
+
const node = this.#createNode(this.#token());
|
|
535
|
+
this.#nextToken();
|
|
536
|
+
return this.#finishNode(node);
|
|
527
537
|
}
|
|
528
|
-
getLastError(diagnostics) {
|
|
529
|
-
return diagnostics && diagnostics.length > 0
|
|
538
|
+
#getLastError(diagnostics) {
|
|
539
|
+
return diagnostics && diagnostics.length > 0
|
|
540
|
+
? diagnostics[diagnostics.length - 1]
|
|
541
|
+
: undefined;
|
|
530
542
|
}
|
|
531
|
-
parseErrorAtPosition(start, end, message, code) {
|
|
543
|
+
#parseErrorAtPosition(start, end, message, code) {
|
|
532
544
|
const ds = this.diagnostics;
|
|
533
|
-
const lastError = this
|
|
545
|
+
const lastError = this.#getLastError(ds);
|
|
534
546
|
if (!lastError || start !== lastError.start) {
|
|
535
547
|
ds.push({
|
|
536
548
|
category: DiagnosticCategory.Error,
|
|
@@ -542,32 +554,34 @@ export class Parser {
|
|
|
542
554
|
}
|
|
543
555
|
this.currentNodeHasError = true;
|
|
544
556
|
}
|
|
545
|
-
parseErrorAtCurrentToken(message, sub) {
|
|
557
|
+
#parseErrorAtCurrentToken(message, sub) {
|
|
546
558
|
const error = {
|
|
547
559
|
source: 2,
|
|
548
560
|
sub,
|
|
549
561
|
};
|
|
550
|
-
return this
|
|
562
|
+
return this.#parseErrorAtPosition(this.scanner.tokenPos, this.scanner.pos, message, error);
|
|
551
563
|
}
|
|
552
|
-
scanError(message, _category, sub, length) {
|
|
564
|
+
#scanError(message, _category, sub, length) {
|
|
553
565
|
const errorPos = this.scanner.pos;
|
|
554
566
|
const err = {
|
|
555
567
|
source: 1,
|
|
556
568
|
sub,
|
|
557
569
|
};
|
|
558
|
-
this
|
|
570
|
+
this.#parseErrorAtPosition(errorPos, errorPos + length, message, err);
|
|
559
571
|
}
|
|
560
|
-
reportExpectedError(expectedKinds) {
|
|
561
|
-
const found = this
|
|
572
|
+
#reportExpectedError(expectedKinds) {
|
|
573
|
+
const found = this.#isIdentifier()
|
|
562
574
|
? "identifier"
|
|
563
|
-
: this
|
|
575
|
+
: this.#token() === SyntaxKind.EndOfFileToken
|
|
564
576
|
? "end of file"
|
|
565
|
-
: `"${getTokenAsText(this
|
|
577
|
+
: `"${getTokenAsText(this.#token())}"`;
|
|
566
578
|
const expected = expectedKinds.map(k => {
|
|
567
|
-
if (isIdentifier(k))
|
|
579
|
+
if (isIdentifier(k)) {
|
|
568
580
|
return "identifier";
|
|
569
|
-
|
|
581
|
+
}
|
|
582
|
+
if (k === SyntaxKind.EndOfFileToken) {
|
|
570
583
|
return "end of file";
|
|
584
|
+
}
|
|
571
585
|
return `"${getTokenAsText(k)}"`;
|
|
572
586
|
});
|
|
573
587
|
const lastExpected = expected.pop();
|
|
@@ -575,65 +589,65 @@ export class Parser {
|
|
|
575
589
|
const msg = expected.length > 0
|
|
576
590
|
? `Expected ${expectedJoined} or ${lastExpected} but found ${found} instead.`
|
|
577
591
|
: `Expected ${lastExpected} but found ${found} instead.`;
|
|
578
|
-
this
|
|
592
|
+
this.#parseErrorAtCurrentToken(msg, 0);
|
|
579
593
|
}
|
|
580
|
-
parseExpectedOneOf(...kinds) {
|
|
594
|
+
#parseExpectedOneOf(...kinds) {
|
|
581
595
|
if (kinds.length < 2) {
|
|
582
596
|
console.assert(false);
|
|
583
597
|
debugger;
|
|
584
598
|
}
|
|
585
599
|
for (const kind of kinds) {
|
|
586
|
-
if (this
|
|
587
|
-
this
|
|
600
|
+
if (this.#token() === kind) {
|
|
601
|
+
this.#nextToken();
|
|
588
602
|
return true;
|
|
589
603
|
}
|
|
590
604
|
}
|
|
591
|
-
this
|
|
605
|
+
this.#reportExpectedError(kinds);
|
|
592
606
|
return false;
|
|
593
607
|
}
|
|
594
|
-
parseExpectedTokenOneOf(fallback, kinds) {
|
|
608
|
+
#parseExpectedTokenOneOf(fallback, kinds) {
|
|
595
609
|
if (kinds.length < 2) {
|
|
596
610
|
console.assert(false);
|
|
597
611
|
debugger;
|
|
598
612
|
}
|
|
599
613
|
for (const kind of kinds) {
|
|
600
|
-
if (this
|
|
601
|
-
const node = this
|
|
602
|
-
this
|
|
603
|
-
return this
|
|
614
|
+
if (this.#token() === kind) {
|
|
615
|
+
const node = this.#createNode(this.#token());
|
|
616
|
+
this.#nextToken();
|
|
617
|
+
return this.#finishNode(node);
|
|
604
618
|
}
|
|
605
619
|
}
|
|
606
|
-
this
|
|
607
|
-
return this
|
|
620
|
+
this.#reportExpectedError(kinds);
|
|
621
|
+
return this.#createMissingNode(fallback);
|
|
608
622
|
}
|
|
609
|
-
parseExpectedToken(kind) {
|
|
610
|
-
const tokenNode = this
|
|
623
|
+
#parseExpectedToken(kind) {
|
|
624
|
+
const tokenNode = this.#parseOptionalToken(kind);
|
|
611
625
|
if (tokenNode !== undefined)
|
|
612
626
|
return tokenNode;
|
|
613
|
-
this
|
|
614
|
-
return this
|
|
627
|
+
this.#reportExpectedError([kind]);
|
|
628
|
+
return this.#createMissingNode(kind);
|
|
615
629
|
}
|
|
616
|
-
parseExpected(kind) {
|
|
617
|
-
const res = this
|
|
630
|
+
#parseExpected(kind) {
|
|
631
|
+
const res = this.#parseOptional(kind);
|
|
618
632
|
if (!res)
|
|
619
|
-
this
|
|
633
|
+
this.#reportExpectedError([kind]);
|
|
620
634
|
return res;
|
|
621
635
|
}
|
|
622
|
-
parseOptionalToken(t) {
|
|
623
|
-
if (this
|
|
624
|
-
return this
|
|
636
|
+
#parseOptionalToken(t) {
|
|
637
|
+
if (this.#token() === t) {
|
|
638
|
+
return this.#parseTokenNode();
|
|
625
639
|
}
|
|
626
640
|
return undefined;
|
|
627
641
|
}
|
|
628
|
-
parseOptional(t) {
|
|
629
|
-
if (this
|
|
630
|
-
this
|
|
642
|
+
#parseOptional(t) {
|
|
643
|
+
if (this.#token() === t) {
|
|
644
|
+
this.#nextToken();
|
|
631
645
|
return true;
|
|
632
646
|
}
|
|
633
647
|
return false;
|
|
634
648
|
}
|
|
635
|
-
isEdgeOp() {
|
|
636
|
-
switch (this
|
|
649
|
+
#isEdgeOp() {
|
|
650
|
+
switch (this.#token()) {
|
|
637
651
|
case SyntaxKind.DirectedEdgeOp:
|
|
638
652
|
case SyntaxKind.UndirectedEdgeOp:
|
|
639
653
|
return true;
|
|
@@ -641,8 +655,8 @@ export class Parser {
|
|
|
641
655
|
return false;
|
|
642
656
|
}
|
|
643
657
|
}
|
|
644
|
-
isIdentifier() {
|
|
645
|
-
switch (this
|
|
658
|
+
#isIdentifier() {
|
|
659
|
+
switch (this.#token()) {
|
|
646
660
|
case SyntaxKind.TextIdentifier:
|
|
647
661
|
case SyntaxKind.NumericIdentifier:
|
|
648
662
|
case SyntaxKind.StringLiteral:
|
|
@@ -652,11 +666,11 @@ export class Parser {
|
|
|
652
666
|
return false;
|
|
653
667
|
}
|
|
654
668
|
}
|
|
655
|
-
isCompassPortKind(kind) {
|
|
669
|
+
#isCompassPortKind(kind) {
|
|
656
670
|
return kind >= SyntaxKind.CompassCenterToken && kind <= SyntaxKind.CompassEnd;
|
|
657
671
|
}
|
|
658
|
-
speculationHelper(callback, isLookAhead) {
|
|
659
|
-
const saveToken = this
|
|
672
|
+
#speculationHelper(callback, isLookAhead) {
|
|
673
|
+
const saveToken = this.#token();
|
|
660
674
|
const saveDiagnosticsLength = this.diagnostics.length;
|
|
661
675
|
const result = isLookAhead
|
|
662
676
|
? this.scanner.lookAhead(callback)
|
|
@@ -667,11 +681,11 @@ export class Parser {
|
|
|
667
681
|
}
|
|
668
682
|
return result;
|
|
669
683
|
}
|
|
670
|
-
lookAhead(callback) {
|
|
671
|
-
return this
|
|
684
|
+
#lookAhead(callback) {
|
|
685
|
+
return this.#speculationHelper(callback, true);
|
|
672
686
|
}
|
|
673
|
-
tryParse(callback) {
|
|
674
|
-
return this
|
|
687
|
+
#tryParse(callback) {
|
|
688
|
+
return this.#speculationHelper(callback, false);
|
|
675
689
|
}
|
|
676
690
|
}
|
|
677
691
|
function newNode(kind, pos, end) {
|
|
@@ -689,10 +703,10 @@ function isNodeKind(kind) {
|
|
|
689
703
|
return kind >= SyntaxKind.FirstNode;
|
|
690
704
|
}
|
|
691
705
|
export function isIdentifier(kind) {
|
|
692
|
-
return kind === SyntaxKind.HtmlIdentifier
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
706
|
+
return (kind === SyntaxKind.HtmlIdentifier ||
|
|
707
|
+
kind === SyntaxKind.NumericIdentifier ||
|
|
708
|
+
kind === SyntaxKind.TextIdentifier ||
|
|
709
|
+
kind === SyntaxKind.QuotedTextIdentifier);
|
|
696
710
|
}
|
|
697
711
|
export function isIdentifierNode(node) {
|
|
698
712
|
return isIdentifier(node.kind);
|