brighterscript 0.42.0 → 0.45.0
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/CHANGELOG.md +49 -0
- package/dist/Cache.d.ts +3 -8
- package/dist/Cache.js +9 -14
- package/dist/Cache.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +21 -1
- package/dist/DiagnosticMessages.js +20 -0
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/LanguageServer.d.ts +1 -6
- package/dist/LanguageServer.js +3 -12
- package/dist/LanguageServer.js.map +1 -1
- package/dist/PluginInterface.d.ts +3 -3
- package/dist/PluginInterface.js +3 -0
- package/dist/PluginInterface.js.map +1 -1
- package/dist/Program.d.ts +68 -25
- package/dist/Program.js +169 -76
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.js +6 -6
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +18 -11
- package/dist/Scope.js +41 -14
- package/dist/Scope.js.map +1 -1
- package/dist/XmlScope.d.ts +3 -3
- package/dist/astUtils/AstEditor.d.ts +6 -0
- package/dist/astUtils/AstEditor.js +10 -0
- package/dist/astUtils/AstEditor.js.map +1 -1
- package/dist/astUtils/AstEditor.spec.js +37 -0
- package/dist/astUtils/AstEditor.spec.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +5 -2
- package/dist/astUtils/reflection.js +14 -2
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +6 -6
- package/dist/astUtils/reflection.spec.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +3 -1
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +15 -18
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/bscPlugin/BscPlugin.d.ts +4 -1
- package/dist/bscPlugin/BscPlugin.js +21 -2
- package/dist/bscPlugin/BscPlugin.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +3 -3
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +18 -16
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +9 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +97 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
- package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.d.ts → BrsFileSemanticTokensProcessor.spec.d.ts} +0 -0
- package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.js → BrsFileSemanticTokensProcessor.spec.js} +32 -4
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +36 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
- package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +11 -0
- package/dist/bscPlugin/validation/ScopeValidator.js +94 -0
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
- package/dist/files/BrsFile.Class.spec.js +218 -114
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +27 -8
- package/dist/files/BrsFile.js +216 -95
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +338 -190
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/XmlFile.d.ts +11 -5
- package/dist/files/XmlFile.js +15 -9
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +118 -114
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +29 -27
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/index.d.ts +12 -3
- package/dist/index.js +21 -4
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +50 -9
- package/dist/lexer/Lexer.js +1 -2
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/lexer/Lexer.spec.js +470 -462
- package/dist/lexer/Lexer.spec.js.map +1 -1
- package/dist/lexer/TokenKind.d.ts +2 -0
- package/dist/lexer/TokenKind.js +5 -0
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/parser/Expression.d.ts +1 -1
- package/dist/parser/Expression.js +10 -10
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +32 -31
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +23 -2
- package/dist/parser/Parser.js +445 -254
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +86 -24
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/SGParser.spec.js +1 -1
- package/dist/parser/SGParser.spec.js.map +1 -1
- package/dist/parser/Statement.d.ts +54 -2
- package/dist/parser/Statement.js +162 -9
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/Statement.spec.js +5 -5
- package/dist/parser/Statement.spec.js.map +1 -1
- package/dist/parser/tests/Parser.spec.d.ts +3 -3
- package/dist/parser/tests/Parser.spec.js +4 -4
- package/dist/parser/tests/Parser.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/For.spec.js +40 -40
- package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.js +22 -21
- package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/If.spec.js +100 -99
- package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/While.spec.js +25 -25
- package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
- package/dist/parser/tests/expression/Additive.spec.js +21 -21
- package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
- package/dist/parser/tests/expression/ArrayLiterals.spec.js +91 -91
- package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +102 -102
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/Boolean.spec.js +15 -15
- package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
- package/dist/parser/tests/expression/Call.spec.js +22 -21
- package/dist/parser/tests/expression/Call.spec.js.map +1 -1
- package/dist/parser/tests/expression/Exponential.spec.js +11 -11
- package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
- package/dist/parser/tests/expression/Function.spec.js +171 -171
- package/dist/parser/tests/expression/Function.spec.js.map +1 -1
- package/dist/parser/tests/expression/Indexing.spec.js +50 -50
- package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
- package/dist/parser/tests/expression/Multiplicative.spec.js +25 -25
- package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +17 -17
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/PrefixUnary.spec.js +26 -26
- package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
- package/dist/parser/tests/expression/Primary.spec.js +27 -27
- package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +4 -3
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/Relational.spec.js +25 -25
- package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +8 -8
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +7 -7
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
- package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
- package/dist/parser/tests/statement/Declaration.spec.js +20 -20
- package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
- package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
- package/dist/parser/tests/statement/Enum.spec.js +774 -0
- package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
- package/dist/parser/tests/statement/Function.spec.js +121 -120
- package/dist/parser/tests/statement/Function.spec.js.map +1 -1
- package/dist/parser/tests/statement/Goto.spec.js +9 -8
- package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
- package/dist/parser/tests/statement/Increment.spec.js +22 -22
- package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
- package/dist/parser/tests/statement/InterfaceStatement.spec.js +12 -0
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/LibraryStatement.spec.js +7 -7
- package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Misc.spec.js +71 -70
- package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +17 -17
- package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.js +33 -33
- package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Set.spec.js +53 -53
- package/dist/parser/tests/statement/Set.spec.js.map +1 -1
- package/dist/parser/tests/statement/Stop.spec.js +7 -6
- package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
- package/dist/preprocessor/Chunk.d.ts +1 -1
- package/dist/preprocessor/Preprocessor.d.ts +1 -1
- package/dist/preprocessor/Preprocessor.js +7 -7
- package/dist/preprocessor/Preprocessor.js.map +1 -1
- package/dist/types/FunctionType.d.ts +2 -2
- package/dist/types/FunctionType.js +3 -3
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/FunctionType.spec.js +2 -2
- package/dist/types/FunctionType.spec.js.map +1 -1
- package/dist/util.d.ts +27 -1
- package/dist/util.js +96 -29
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.js +20 -27
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +2 -1
- package/dist/astUtils/index.d.ts +0 -7
- package/dist/astUtils/index.js +0 -26
- package/dist/astUtils/index.js.map +0 -1
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +0 -63
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
- package/dist/lexer/index.d.ts +0 -3
- package/dist/lexer/index.js +0 -18
- package/dist/lexer/index.js.map +0 -1
- package/dist/parser/index.d.ts +0 -3
- package/dist/parser/index.js +0 -16
- package/dist/parser/index.js.map +0 -1
- package/dist/preprocessor/index.d.ts +0 -3
- package/dist/preprocessor/index.js +0 -16
- package/dist/preprocessor/index.js.map +0 -1
package/dist/parser/Parser.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.References = exports.ParseMode = exports.Parser = void 0;
|
|
4
|
-
const
|
|
4
|
+
const Token_1 = require("../lexer/Token");
|
|
5
|
+
const Lexer_1 = require("../lexer/Lexer");
|
|
6
|
+
const TokenKind_1 = require("../lexer/TokenKind");
|
|
5
7
|
const Statement_1 = require("./Statement");
|
|
6
8
|
const DiagnosticMessages_1 = require("../DiagnosticMessages");
|
|
7
9
|
const util_1 = require("../util");
|
|
@@ -10,7 +12,7 @@ const Logger_1 = require("../Logger");
|
|
|
10
12
|
const reflection_1 = require("../astUtils/reflection");
|
|
11
13
|
const visitors_1 = require("../astUtils/visitors");
|
|
12
14
|
const creators_1 = require("../astUtils/creators");
|
|
13
|
-
const
|
|
15
|
+
const Cache_1 = require("../Cache");
|
|
14
16
|
class Parser {
|
|
15
17
|
constructor() {
|
|
16
18
|
/**
|
|
@@ -51,7 +53,7 @@ class Parser {
|
|
|
51
53
|
this._references = undefined;
|
|
52
54
|
}
|
|
53
55
|
addPropertyHints(item) {
|
|
54
|
-
if ((0,
|
|
56
|
+
if ((0, Token_1.isToken)(item)) {
|
|
55
57
|
const name = item.text;
|
|
56
58
|
this._references.propertyHints[name.toLowerCase()] = name;
|
|
57
59
|
}
|
|
@@ -79,7 +81,7 @@ class Parser {
|
|
|
79
81
|
static parse(toParse, options) {
|
|
80
82
|
let tokens;
|
|
81
83
|
if (typeof toParse === 'string') {
|
|
82
|
-
tokens =
|
|
84
|
+
tokens = Lexer_1.Lexer.scan(toParse).tokens;
|
|
83
85
|
}
|
|
84
86
|
else {
|
|
85
87
|
tokens = toParse;
|
|
@@ -97,9 +99,9 @@ class Parser {
|
|
|
97
99
|
this.tokens = tokens;
|
|
98
100
|
this.options = this.sanitizeParseOptions(options);
|
|
99
101
|
this.allowedLocalIdentifiers = [
|
|
100
|
-
...
|
|
102
|
+
...TokenKind_1.AllowedLocalIdentifiers,
|
|
101
103
|
//when in plain brightscript mode, the BrighterScript source literals can be used as regular variables
|
|
102
|
-
...(this.options.mode === ParseMode.BrightScript ?
|
|
104
|
+
...(this.options.mode === ParseMode.BrightScript ? TokenKind_1.BrighterScriptSourceLiterals : [])
|
|
103
105
|
];
|
|
104
106
|
this.current = 0;
|
|
105
107
|
this.diagnostics = [];
|
|
@@ -170,16 +172,16 @@ class Parser {
|
|
|
170
172
|
}
|
|
171
173
|
declaration() {
|
|
172
174
|
try {
|
|
173
|
-
if (this.checkAny(
|
|
175
|
+
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
174
176
|
return this.functionDeclaration(false);
|
|
175
177
|
}
|
|
176
178
|
if (this.checkLibrary()) {
|
|
177
179
|
return this.libraryStatement();
|
|
178
180
|
}
|
|
179
|
-
if (this.check(
|
|
181
|
+
if (this.check(TokenKind_1.TokenKind.At) && this.checkNext(TokenKind_1.TokenKind.Identifier)) {
|
|
180
182
|
return this.annotationExpression();
|
|
181
183
|
}
|
|
182
|
-
if (this.check(
|
|
184
|
+
if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
183
185
|
return this.commentStatement();
|
|
184
186
|
}
|
|
185
187
|
//catch certain global terminators to prevent unnecessary lookahead (i.e. like `end namespace`, no need to continue)
|
|
@@ -196,18 +198,39 @@ class Parser {
|
|
|
196
198
|
this.synchronize();
|
|
197
199
|
}
|
|
198
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Try to get an identifier. If not found, add diagnostic and return undefined
|
|
203
|
+
*/
|
|
204
|
+
tryIdentifier(...additionalTokenKinds) {
|
|
205
|
+
const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...additionalTokenKinds);
|
|
206
|
+
if (identifier) {
|
|
207
|
+
// force the name into an identifier so the AST makes some sense
|
|
208
|
+
identifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
209
|
+
return identifier;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
199
212
|
identifier(...additionalTokenKinds) {
|
|
200
|
-
const identifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(),
|
|
213
|
+
const identifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...additionalTokenKinds);
|
|
201
214
|
// force the name into an identifier so the AST makes some sense
|
|
202
|
-
identifier.kind =
|
|
215
|
+
identifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
203
216
|
return identifier;
|
|
204
217
|
}
|
|
218
|
+
enumMemberStatement() {
|
|
219
|
+
const statement = new Statement_1.EnumMemberStatement({});
|
|
220
|
+
statement.tokens.name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
221
|
+
//look for `= SOME_EXPRESSION`
|
|
222
|
+
if (this.check(TokenKind_1.TokenKind.Equal)) {
|
|
223
|
+
statement.tokens.equal = this.advance();
|
|
224
|
+
statement.value = this.expression();
|
|
225
|
+
}
|
|
226
|
+
return statement;
|
|
227
|
+
}
|
|
205
228
|
/**
|
|
206
229
|
* Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration`
|
|
207
230
|
*/
|
|
208
231
|
interfaceFieldStatement() {
|
|
209
|
-
const name = this.identifier(...
|
|
210
|
-
let asToken = this.consumeToken(
|
|
232
|
+
const name = this.identifier(...TokenKind_1.AllowedProperties);
|
|
233
|
+
let asToken = this.consumeToken(TokenKind_1.TokenKind.As);
|
|
211
234
|
let typeToken = this.typeToken();
|
|
212
235
|
const type = util_1.util.tokenToBscType(typeToken);
|
|
213
236
|
if (!type) {
|
|
@@ -221,13 +244,13 @@ class Parser {
|
|
|
221
244
|
*/
|
|
222
245
|
interfaceMethodStatement() {
|
|
223
246
|
const functionType = this.advance();
|
|
224
|
-
const name = this.identifier(...
|
|
225
|
-
const leftParen = this.consumeToken(
|
|
247
|
+
const name = this.identifier(...TokenKind_1.AllowedProperties);
|
|
248
|
+
const leftParen = this.consumeToken(TokenKind_1.TokenKind.LeftParen);
|
|
226
249
|
const params = [];
|
|
227
|
-
const rightParen = this.consumeToken(
|
|
250
|
+
const rightParen = this.consumeToken(TokenKind_1.TokenKind.RightParen);
|
|
228
251
|
let asToken = null;
|
|
229
252
|
let returnTypeToken = null;
|
|
230
|
-
if (this.check(
|
|
253
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
231
254
|
asToken = this.advance();
|
|
232
255
|
returnTypeToken = this.typeToken();
|
|
233
256
|
const returnType = util_1.util.tokenToBscType(returnTypeToken);
|
|
@@ -241,7 +264,7 @@ class Parser {
|
|
|
241
264
|
interfaceDeclaration() {
|
|
242
265
|
this.warnIfNotBrighterScriptMode('interface declarations');
|
|
243
266
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
244
|
-
const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(
|
|
267
|
+
const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Interface), TokenKind_1.TokenKind.Interface);
|
|
245
268
|
const nameToken = this.identifier();
|
|
246
269
|
let extendsToken;
|
|
247
270
|
let parentInterfaceName;
|
|
@@ -252,23 +275,23 @@ class Parser {
|
|
|
252
275
|
this.consumeStatementSeparators();
|
|
253
276
|
//gather up all interface members (Fields, Methods)
|
|
254
277
|
let body = [];
|
|
255
|
-
while (this.checkAny(
|
|
278
|
+
while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
|
|
256
279
|
try {
|
|
257
280
|
let decl;
|
|
258
281
|
//collect leading annotations
|
|
259
|
-
if (this.check(
|
|
282
|
+
if (this.check(TokenKind_1.TokenKind.At)) {
|
|
260
283
|
this.annotationExpression();
|
|
261
284
|
}
|
|
262
285
|
//fields
|
|
263
|
-
if (this.checkAny(
|
|
286
|
+
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
264
287
|
decl = this.interfaceFieldStatement();
|
|
265
288
|
//methods (function/sub keyword followed by opening paren)
|
|
266
289
|
}
|
|
267
|
-
else if (this.checkAny(
|
|
290
|
+
else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
268
291
|
decl = this.interfaceMethodStatement();
|
|
269
292
|
//comments
|
|
270
293
|
}
|
|
271
|
-
else if (this.check(
|
|
294
|
+
else if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
272
295
|
decl = this.commentStatement();
|
|
273
296
|
}
|
|
274
297
|
if (decl) {
|
|
@@ -277,39 +300,87 @@ class Parser {
|
|
|
277
300
|
}
|
|
278
301
|
else {
|
|
279
302
|
//we didn't find a declaration...flag tokens until next line
|
|
280
|
-
this.flagUntil(
|
|
303
|
+
this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
281
304
|
}
|
|
282
305
|
}
|
|
283
306
|
catch (e) {
|
|
284
307
|
//throw out any failed members and move on to the next line
|
|
285
|
-
this.flagUntil(
|
|
308
|
+
this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
286
309
|
}
|
|
287
310
|
//ensure statement separator
|
|
288
311
|
this.consumeStatementSeparators();
|
|
289
312
|
//break out of this loop if we encountered the `EndInterface` token not followed by `as`
|
|
290
|
-
if (this.check(
|
|
313
|
+
if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
291
314
|
break;
|
|
292
315
|
}
|
|
293
316
|
}
|
|
294
317
|
//consume the final `end interface` token
|
|
295
|
-
const endInterfaceToken = this.consumeToken(
|
|
296
|
-
this.consumeStatementSeparators();
|
|
318
|
+
const endInterfaceToken = this.consumeToken(TokenKind_1.TokenKind.EndInterface);
|
|
297
319
|
const statement = new Statement_1.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endInterfaceToken, this.currentNamespaceName);
|
|
298
320
|
this._references.interfaceStatements.push(statement);
|
|
299
321
|
this.exitAnnotationBlock(parentAnnotations);
|
|
300
322
|
return statement;
|
|
301
323
|
}
|
|
324
|
+
enumDeclaration() {
|
|
325
|
+
const result = new Statement_1.EnumStatement({}, [], this.currentNamespaceName);
|
|
326
|
+
this.warnIfNotBrighterScriptMode('enum declarations');
|
|
327
|
+
const parentAnnotations = this.enterAnnotationBlock();
|
|
328
|
+
result.tokens.enum = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Enum), TokenKind_1.TokenKind.Enum);
|
|
329
|
+
result.tokens.name = this.tryIdentifier();
|
|
330
|
+
this.consumeStatementSeparators();
|
|
331
|
+
//gather up all members
|
|
332
|
+
while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
|
|
333
|
+
try {
|
|
334
|
+
let decl;
|
|
335
|
+
//collect leading annotations
|
|
336
|
+
if (this.check(TokenKind_1.TokenKind.At)) {
|
|
337
|
+
this.annotationExpression();
|
|
338
|
+
}
|
|
339
|
+
//members
|
|
340
|
+
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
341
|
+
decl = this.enumMemberStatement();
|
|
342
|
+
//comments
|
|
343
|
+
}
|
|
344
|
+
else if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
345
|
+
decl = this.commentStatement();
|
|
346
|
+
}
|
|
347
|
+
if (decl) {
|
|
348
|
+
this.consumePendingAnnotations(decl);
|
|
349
|
+
result.body.push(decl);
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
//we didn't find a declaration...flag tokens until next line
|
|
353
|
+
this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
catch (e) {
|
|
357
|
+
//throw out any failed members and move on to the next line
|
|
358
|
+
this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
359
|
+
}
|
|
360
|
+
//ensure statement separator
|
|
361
|
+
this.consumeStatementSeparators();
|
|
362
|
+
//break out of this loop if we encountered the `EndEnum` token
|
|
363
|
+
if (this.check(TokenKind_1.TokenKind.EndEnum)) {
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
//consume the final `end interface` token
|
|
368
|
+
result.tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
|
|
369
|
+
this._references.enumStatements.push(result);
|
|
370
|
+
this.exitAnnotationBlock(parentAnnotations);
|
|
371
|
+
return result;
|
|
372
|
+
}
|
|
302
373
|
/**
|
|
303
374
|
* A BrighterScript class declaration
|
|
304
375
|
*/
|
|
305
376
|
classDeclaration() {
|
|
306
377
|
this.warnIfNotBrighterScriptMode('class declarations');
|
|
307
378
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
308
|
-
let classKeyword = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(
|
|
379
|
+
let classKeyword = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Class), TokenKind_1.TokenKind.Class);
|
|
309
380
|
let extendsKeyword;
|
|
310
381
|
let parentClassName;
|
|
311
382
|
//get the class name
|
|
312
|
-
let className = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('class'),
|
|
383
|
+
let className = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('class'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
313
384
|
//see if the class inherits from parent
|
|
314
385
|
if (this.peek().text.toLowerCase() === 'extends') {
|
|
315
386
|
extendsKeyword = this.advance();
|
|
@@ -319,14 +390,14 @@ class Parser {
|
|
|
319
390
|
this.consumeStatementSeparators();
|
|
320
391
|
//gather up all class members (Fields, Methods)
|
|
321
392
|
let body = [];
|
|
322
|
-
while (this.checkAny(
|
|
393
|
+
while (this.checkAny(TokenKind_1.TokenKind.Public, TokenKind_1.TokenKind.Protected, TokenKind_1.TokenKind.Private, TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
|
|
323
394
|
try {
|
|
324
395
|
let decl;
|
|
325
396
|
let accessModifier;
|
|
326
|
-
if (this.check(
|
|
397
|
+
if (this.check(TokenKind_1.TokenKind.At)) {
|
|
327
398
|
this.annotationExpression();
|
|
328
399
|
}
|
|
329
|
-
if (this.checkAny(
|
|
400
|
+
if (this.checkAny(TokenKind_1.TokenKind.Public, TokenKind_1.TokenKind.Protected, TokenKind_1.TokenKind.Private)) {
|
|
330
401
|
//use actual access modifier
|
|
331
402
|
accessModifier = this.advance();
|
|
332
403
|
}
|
|
@@ -335,7 +406,7 @@ class Parser {
|
|
|
335
406
|
overrideKeyword = this.advance();
|
|
336
407
|
}
|
|
337
408
|
//methods (function/sub keyword OR identifier followed by opening paren)
|
|
338
|
-
if (this.checkAny(
|
|
409
|
+
if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) || (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.checkNext(TokenKind_1.TokenKind.LeftParen))) {
|
|
339
410
|
const funcDeclaration = this.functionDeclaration(false, false);
|
|
340
411
|
//remove this function from the lists because it's not a callable
|
|
341
412
|
const functionStatement = this._references.functionStatements.pop();
|
|
@@ -348,7 +419,7 @@ class Parser {
|
|
|
348
419
|
functionStatement.func.functionStatement = decl;
|
|
349
420
|
//fields
|
|
350
421
|
}
|
|
351
|
-
else if (this.checkAny(
|
|
422
|
+
else if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
352
423
|
decl = this.classFieldDeclaration(accessModifier);
|
|
353
424
|
//class fields cannot be overridden
|
|
354
425
|
if (overrideKeyword) {
|
|
@@ -356,7 +427,7 @@ class Parser {
|
|
|
356
427
|
}
|
|
357
428
|
//comments
|
|
358
429
|
}
|
|
359
|
-
else if (this.check(
|
|
430
|
+
else if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
360
431
|
decl = this.commentStatement();
|
|
361
432
|
}
|
|
362
433
|
if (decl) {
|
|
@@ -366,13 +437,13 @@ class Parser {
|
|
|
366
437
|
}
|
|
367
438
|
catch (e) {
|
|
368
439
|
//throw out any failed members and move on to the next line
|
|
369
|
-
this.flagUntil(
|
|
440
|
+
this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
370
441
|
}
|
|
371
442
|
//ensure statement separator
|
|
372
443
|
this.consumeStatementSeparators();
|
|
373
444
|
}
|
|
374
445
|
let endingKeyword = this.advance();
|
|
375
|
-
if (endingKeyword.kind !==
|
|
446
|
+
if (endingKeyword.kind !== TokenKind_1.TokenKind.EndClass) {
|
|
376
447
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('class')), { range: endingKeyword.range }));
|
|
377
448
|
}
|
|
378
449
|
const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName, this.currentNamespaceName);
|
|
@@ -381,11 +452,11 @@ class Parser {
|
|
|
381
452
|
return result;
|
|
382
453
|
}
|
|
383
454
|
classFieldDeclaration(accessModifier) {
|
|
384
|
-
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(),
|
|
455
|
+
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
385
456
|
let asToken;
|
|
386
457
|
let fieldType;
|
|
387
458
|
//look for `as SOME_TYPE`
|
|
388
|
-
if (this.check(
|
|
459
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
389
460
|
asToken = this.advance();
|
|
390
461
|
fieldType = this.typeToken();
|
|
391
462
|
//no field type specified
|
|
@@ -396,7 +467,7 @@ class Parser {
|
|
|
396
467
|
let initialValue;
|
|
397
468
|
let equal;
|
|
398
469
|
//if there is a field initializer
|
|
399
|
-
if (this.check(
|
|
470
|
+
if (this.check(TokenKind_1.TokenKind.Equal)) {
|
|
400
471
|
equal = this.advance();
|
|
401
472
|
initialValue = this.expression();
|
|
402
473
|
}
|
|
@@ -410,14 +481,14 @@ class Parser {
|
|
|
410
481
|
//track depth to help certain statements need to know if they are contained within a function body
|
|
411
482
|
this.namespaceAndFunctionDepth++;
|
|
412
483
|
let functionType;
|
|
413
|
-
if (this.checkAny(
|
|
484
|
+
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
414
485
|
functionType = this.advance();
|
|
415
486
|
}
|
|
416
487
|
else {
|
|
417
488
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingCallableKeyword()), { range: this.peek().range }));
|
|
418
489
|
functionType = {
|
|
419
490
|
isReserved: true,
|
|
420
|
-
kind:
|
|
491
|
+
kind: TokenKind_1.TokenKind.Function,
|
|
421
492
|
text: 'function',
|
|
422
493
|
//zero-length location means derived
|
|
423
494
|
range: {
|
|
@@ -427,16 +498,16 @@ class Parser {
|
|
|
427
498
|
leadingWhitespace: ''
|
|
428
499
|
};
|
|
429
500
|
}
|
|
430
|
-
let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) ===
|
|
501
|
+
let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) === TokenKind_1.TokenKind.Sub;
|
|
431
502
|
let functionTypeText = isSub ? 'sub' : 'function';
|
|
432
503
|
let name;
|
|
433
504
|
let leftParen;
|
|
434
505
|
if (isAnonymous) {
|
|
435
|
-
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText),
|
|
506
|
+
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText), TokenKind_1.TokenKind.LeftParen);
|
|
436
507
|
}
|
|
437
508
|
else {
|
|
438
|
-
name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionTypeText),
|
|
439
|
-
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionTypeText),
|
|
509
|
+
name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionTypeText), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
510
|
+
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionTypeText), TokenKind_1.TokenKind.LeftParen);
|
|
440
511
|
//prevent functions from ending with type designators
|
|
441
512
|
let lastChar = name.text[name.text.length - 1];
|
|
442
513
|
if (['$', '%', '!', '#', '&'].includes(lastChar)) {
|
|
@@ -444,23 +515,23 @@ class Parser {
|
|
|
444
515
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionNameCannotEndWithTypeDesignator(functionTypeText, name.text, lastChar)), { range: name.range }));
|
|
445
516
|
}
|
|
446
517
|
//flag functions with keywords for names (only for standard functions)
|
|
447
|
-
if (checkIdentifier &&
|
|
518
|
+
if (checkIdentifier && TokenKind_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
|
|
448
519
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
|
|
449
520
|
}
|
|
450
521
|
}
|
|
451
522
|
let params = [];
|
|
452
523
|
let asToken;
|
|
453
524
|
let typeToken;
|
|
454
|
-
if (!this.check(
|
|
525
|
+
if (!this.check(TokenKind_1.TokenKind.RightParen)) {
|
|
455
526
|
do {
|
|
456
527
|
if (params.length >= Expression_1.CallExpression.MaximumArguments) {
|
|
457
528
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(params.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
|
|
458
529
|
}
|
|
459
530
|
params.push(this.functionParameter());
|
|
460
|
-
} while (this.match(
|
|
531
|
+
} while (this.match(TokenKind_1.TokenKind.Comma));
|
|
461
532
|
}
|
|
462
533
|
let rightParen = this.advance();
|
|
463
|
-
if (this.check(
|
|
534
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
464
535
|
asToken = this.advance();
|
|
465
536
|
typeToken = this.typeToken();
|
|
466
537
|
if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript)) {
|
|
@@ -498,7 +569,7 @@ class Parser {
|
|
|
498
569
|
}
|
|
499
570
|
// consume 'end sub' or 'end function'
|
|
500
571
|
func.end = this.advance();
|
|
501
|
-
let expectedEndKind = isSub ?
|
|
572
|
+
let expectedEndKind = isSub ? TokenKind_1.TokenKind.EndSub : TokenKind_1.TokenKind.EndFunction;
|
|
502
573
|
//if `function` is ended with `end sub`, or `sub` is ended with `end function`, then
|
|
503
574
|
//add an error but don't hard-fail so the AST can continue more gracefully
|
|
504
575
|
if (func.end.kind !== expectedEndKind) {
|
|
@@ -522,22 +593,22 @@ class Parser {
|
|
|
522
593
|
}
|
|
523
594
|
}
|
|
524
595
|
functionParameter() {
|
|
525
|
-
if (!this.checkAny(
|
|
596
|
+
if (!this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
|
|
526
597
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedParameterNameButFound(this.peek().text)), { range: this.peek().range }));
|
|
527
598
|
throw this.lastDiagnosticAsError();
|
|
528
599
|
}
|
|
529
600
|
let name = this.advance();
|
|
530
601
|
// force the name into an identifier so the AST makes some sense
|
|
531
|
-
name.kind =
|
|
602
|
+
name.kind = TokenKind_1.TokenKind.Identifier;
|
|
532
603
|
let typeToken;
|
|
533
604
|
let defaultValue;
|
|
534
605
|
// parse argument default value
|
|
535
|
-
if (this.match(
|
|
606
|
+
if (this.match(TokenKind_1.TokenKind.Equal)) {
|
|
536
607
|
// it seems any expression is allowed here -- including ones that operate on other arguments!
|
|
537
608
|
defaultValue = this.expression();
|
|
538
609
|
}
|
|
539
610
|
let asToken = null;
|
|
540
|
-
if (this.check(
|
|
611
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
541
612
|
asToken = this.advance();
|
|
542
613
|
typeToken = this.typeToken();
|
|
543
614
|
if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript)) {
|
|
@@ -550,30 +621,33 @@ class Parser {
|
|
|
550
621
|
assignment() {
|
|
551
622
|
let name = this.advance();
|
|
552
623
|
//add diagnostic if name is a reserved word that cannot be used as an identifier
|
|
553
|
-
if (
|
|
624
|
+
if (TokenKind_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
|
|
554
625
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
|
|
555
626
|
}
|
|
556
|
-
let operator = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier(
|
|
627
|
+
let operator = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier(TokenKind_1.AssignmentOperators, name.text), ...TokenKind_1.AssignmentOperators);
|
|
557
628
|
let value = this.expression();
|
|
558
629
|
let result;
|
|
559
|
-
if (operator.kind ===
|
|
630
|
+
if (operator.kind === TokenKind_1.TokenKind.Equal) {
|
|
560
631
|
result = new Statement_1.AssignmentStatement(operator, name, value, this.currentFunctionExpression);
|
|
561
632
|
}
|
|
562
633
|
else {
|
|
563
634
|
result = new Statement_1.AssignmentStatement(operator, name, new Expression_1.BinaryExpression(new Expression_1.VariableExpression(name, this.currentNamespaceName), operator, value), this.currentFunctionExpression);
|
|
635
|
+
//remove the right-hand-side expression from this assignment operator, and replace with the full assignment expression
|
|
636
|
+
this._references.expressions.delete(value);
|
|
637
|
+
this._references.expressions.add(result);
|
|
564
638
|
}
|
|
565
639
|
this._references.assignmentStatements.push(result);
|
|
566
640
|
return result;
|
|
567
641
|
}
|
|
568
642
|
checkLibrary() {
|
|
569
|
-
let isLibraryToken = this.check(
|
|
643
|
+
let isLibraryToken = this.check(TokenKind_1.TokenKind.Library);
|
|
570
644
|
//if we are at the top level, any line that starts with "library" should be considered a library statement
|
|
571
645
|
if (this.isAtRootLevel() && isLibraryToken) {
|
|
572
646
|
return true;
|
|
573
647
|
//not at root level, library statements are all invalid here, but try to detect if the tokens look
|
|
574
648
|
//like a library statement (and let the libraryStatement function handle emitting the diagnostics)
|
|
575
649
|
}
|
|
576
|
-
else if (isLibraryToken && this.checkNext(
|
|
650
|
+
else if (isLibraryToken && this.checkNext(TokenKind_1.TokenKind.StringLiteral)) {
|
|
577
651
|
return true;
|
|
578
652
|
//definitely not a library statement
|
|
579
653
|
}
|
|
@@ -585,54 +659,54 @@ class Parser {
|
|
|
585
659
|
if (this.checkLibrary()) {
|
|
586
660
|
return this.libraryStatement();
|
|
587
661
|
}
|
|
588
|
-
if (this.check(
|
|
662
|
+
if (this.check(TokenKind_1.TokenKind.Import)) {
|
|
589
663
|
return this.importStatement();
|
|
590
664
|
}
|
|
591
|
-
if (this.check(
|
|
665
|
+
if (this.check(TokenKind_1.TokenKind.Stop)) {
|
|
592
666
|
return this.stopStatement();
|
|
593
667
|
}
|
|
594
|
-
if (this.check(
|
|
668
|
+
if (this.check(TokenKind_1.TokenKind.If)) {
|
|
595
669
|
return this.ifStatement();
|
|
596
670
|
}
|
|
597
671
|
//`try` must be followed by a block, otherwise it could be a local variable
|
|
598
|
-
if (this.check(
|
|
672
|
+
if (this.check(TokenKind_1.TokenKind.Try) && this.checkAnyNext(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
|
|
599
673
|
return this.tryCatchStatement();
|
|
600
674
|
}
|
|
601
|
-
if (this.check(
|
|
675
|
+
if (this.check(TokenKind_1.TokenKind.Throw)) {
|
|
602
676
|
return this.throwStatement();
|
|
603
677
|
}
|
|
604
|
-
if (this.checkAny(
|
|
678
|
+
if (this.checkAny(TokenKind_1.TokenKind.Print, TokenKind_1.TokenKind.Question)) {
|
|
605
679
|
return this.printStatement();
|
|
606
680
|
}
|
|
607
|
-
if (this.check(
|
|
681
|
+
if (this.check(TokenKind_1.TokenKind.Dim)) {
|
|
608
682
|
return this.dimStatement();
|
|
609
683
|
}
|
|
610
|
-
if (this.check(
|
|
684
|
+
if (this.check(TokenKind_1.TokenKind.While)) {
|
|
611
685
|
return this.whileStatement();
|
|
612
686
|
}
|
|
613
|
-
if (this.check(
|
|
687
|
+
if (this.check(TokenKind_1.TokenKind.ExitWhile)) {
|
|
614
688
|
return this.exitWhile();
|
|
615
689
|
}
|
|
616
|
-
if (this.check(
|
|
690
|
+
if (this.check(TokenKind_1.TokenKind.For)) {
|
|
617
691
|
return this.forStatement();
|
|
618
692
|
}
|
|
619
|
-
if (this.check(
|
|
693
|
+
if (this.check(TokenKind_1.TokenKind.ForEach)) {
|
|
620
694
|
return this.forEachStatement();
|
|
621
695
|
}
|
|
622
|
-
if (this.check(
|
|
696
|
+
if (this.check(TokenKind_1.TokenKind.ExitFor)) {
|
|
623
697
|
return this.exitFor();
|
|
624
698
|
}
|
|
625
|
-
if (this.check(
|
|
699
|
+
if (this.check(TokenKind_1.TokenKind.End)) {
|
|
626
700
|
return this.endStatement();
|
|
627
701
|
}
|
|
628
|
-
if (this.match(
|
|
702
|
+
if (this.match(TokenKind_1.TokenKind.Return)) {
|
|
629
703
|
return this.returnStatement();
|
|
630
704
|
}
|
|
631
|
-
if (this.check(
|
|
705
|
+
if (this.check(TokenKind_1.TokenKind.Goto)) {
|
|
632
706
|
return this.gotoStatement();
|
|
633
707
|
}
|
|
634
708
|
//does this line look like a label? (i.e. `someIdentifier:` )
|
|
635
|
-
if (this.check(
|
|
709
|
+
if (this.check(TokenKind_1.TokenKind.Identifier) && this.checkNext(TokenKind_1.TokenKind.Colon) && this.checkPrevious(TokenKind_1.TokenKind.Newline)) {
|
|
636
710
|
try {
|
|
637
711
|
return this.labelStatement();
|
|
638
712
|
}
|
|
@@ -646,20 +720,23 @@ class Parser {
|
|
|
646
720
|
// BrightScript is like python, in that variables can be declared without a `var`,
|
|
647
721
|
// `let`, (...) keyword. As such, we must check the token *after* an identifier to figure
|
|
648
722
|
// out what to do with it.
|
|
649
|
-
if (this.checkAny(
|
|
650
|
-
this.checkAnyNext(...
|
|
723
|
+
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers) &&
|
|
724
|
+
this.checkAnyNext(...TokenKind_1.AssignmentOperators)) {
|
|
651
725
|
return this.assignment();
|
|
652
726
|
}
|
|
653
727
|
//some BrighterScript keywords are allowed as a local identifiers, so we need to check for them AFTER the assignment check
|
|
654
|
-
if (this.check(
|
|
728
|
+
if (this.check(TokenKind_1.TokenKind.Interface)) {
|
|
655
729
|
return this.interfaceDeclaration();
|
|
656
730
|
}
|
|
657
|
-
if (this.check(
|
|
731
|
+
if (this.check(TokenKind_1.TokenKind.Class)) {
|
|
658
732
|
return this.classDeclaration();
|
|
659
733
|
}
|
|
660
|
-
if (this.check(
|
|
734
|
+
if (this.check(TokenKind_1.TokenKind.Namespace)) {
|
|
661
735
|
return this.namespaceStatement();
|
|
662
736
|
}
|
|
737
|
+
if (this.check(TokenKind_1.TokenKind.Enum)) {
|
|
738
|
+
return this.enumDeclaration();
|
|
739
|
+
}
|
|
663
740
|
// TODO: support multi-statements
|
|
664
741
|
return this.setStatement();
|
|
665
742
|
}
|
|
@@ -667,9 +744,9 @@ class Parser {
|
|
|
667
744
|
const whileKeyword = this.advance();
|
|
668
745
|
const condition = this.expression();
|
|
669
746
|
this.consumeStatementSeparators();
|
|
670
|
-
const whileBlock = this.block(
|
|
747
|
+
const whileBlock = this.block(TokenKind_1.TokenKind.EndWhile);
|
|
671
748
|
let endWhile;
|
|
672
|
-
if (!whileBlock || this.peek().kind !==
|
|
749
|
+
if (!whileBlock || this.peek().kind !== TokenKind_1.TokenKind.EndWhile) {
|
|
673
750
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('while')), { range: this.peek().range }));
|
|
674
751
|
if (!whileBlock) {
|
|
675
752
|
throw this.lastDiagnosticAsError();
|
|
@@ -692,7 +769,7 @@ class Parser {
|
|
|
692
769
|
const finalValue = this.expression();
|
|
693
770
|
let incrementExpression;
|
|
694
771
|
let stepToken;
|
|
695
|
-
if (this.check(
|
|
772
|
+
if (this.check(TokenKind_1.TokenKind.Step)) {
|
|
696
773
|
stepToken = this.advance();
|
|
697
774
|
incrementExpression = this.expression();
|
|
698
775
|
}
|
|
@@ -700,9 +777,9 @@ class Parser {
|
|
|
700
777
|
// BrightScript for/to/step loops default to a step of 1 if no `step` is provided
|
|
701
778
|
}
|
|
702
779
|
this.consumeStatementSeparators();
|
|
703
|
-
let body = this.block(
|
|
780
|
+
let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
|
|
704
781
|
let endForToken;
|
|
705
|
-
if (!body || !this.checkAny(
|
|
782
|
+
if (!body || !this.checkAny(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next)) {
|
|
706
783
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndForOrNextToTerminateForLoop()), { range: this.peek().range }));
|
|
707
784
|
if (!body) {
|
|
708
785
|
throw this.lastDiagnosticAsError();
|
|
@@ -719,7 +796,7 @@ class Parser {
|
|
|
719
796
|
let forEach = this.advance();
|
|
720
797
|
let name = this.advance();
|
|
721
798
|
let maybeIn = this.peek();
|
|
722
|
-
if (this.check(
|
|
799
|
+
if (this.check(TokenKind_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
|
|
723
800
|
this.advance();
|
|
724
801
|
}
|
|
725
802
|
else {
|
|
@@ -732,7 +809,7 @@ class Parser {
|
|
|
732
809
|
throw this.lastDiagnosticAsError();
|
|
733
810
|
}
|
|
734
811
|
this.consumeStatementSeparators();
|
|
735
|
-
let body = this.block(
|
|
812
|
+
let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
|
|
736
813
|
if (!body) {
|
|
737
814
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndForOrNextToTerminateForLoop()), { range: this.peek().range }));
|
|
738
815
|
throw this.lastDiagnosticAsError();
|
|
@@ -757,7 +834,7 @@ class Parser {
|
|
|
757
834
|
}
|
|
758
835
|
else {
|
|
759
836
|
let comments = [this.advance()];
|
|
760
|
-
while (this.check(
|
|
837
|
+
while (this.check(TokenKind_1.TokenKind.Newline) && this.checkNext(TokenKind_1.TokenKind.Comment)) {
|
|
761
838
|
this.advance();
|
|
762
839
|
comments.push(this.advance());
|
|
763
840
|
}
|
|
@@ -774,13 +851,13 @@ class Parser {
|
|
|
774
851
|
let name = this.getNamespacedVariableNameExpression();
|
|
775
852
|
//set the current namespace name
|
|
776
853
|
this.currentNamespaceName = name;
|
|
777
|
-
this.globalTerminators.push([
|
|
854
|
+
this.globalTerminators.push([TokenKind_1.TokenKind.EndNamespace]);
|
|
778
855
|
let body = this.body();
|
|
779
856
|
this.globalTerminators.pop();
|
|
780
857
|
//unset the current namespace name
|
|
781
858
|
this.currentNamespaceName = undefined;
|
|
782
859
|
let endKeyword;
|
|
783
|
-
if (this.check(
|
|
860
|
+
if (this.check(TokenKind_1.TokenKind.EndNamespace)) {
|
|
784
861
|
endKeyword = this.advance();
|
|
785
862
|
}
|
|
786
863
|
else {
|
|
@@ -796,24 +873,25 @@ class Parser {
|
|
|
796
873
|
* Get an expression with identifiers separated by periods. Useful for namespaces and class extends
|
|
797
874
|
*/
|
|
798
875
|
getNamespacedVariableNameExpression() {
|
|
799
|
-
let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text),
|
|
876
|
+
let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
800
877
|
let expr;
|
|
801
878
|
if (firstIdentifier) {
|
|
802
879
|
// force it into an identifier so the AST makes some sense
|
|
803
|
-
firstIdentifier.kind =
|
|
804
|
-
|
|
880
|
+
firstIdentifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
881
|
+
const varExpr = new Expression_1.VariableExpression(firstIdentifier, null);
|
|
882
|
+
expr = varExpr;
|
|
805
883
|
//consume multiple dot identifiers (i.e. `Name.Space.Can.Have.Many.Parts`)
|
|
806
|
-
while (this.check(
|
|
807
|
-
let dot = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text),
|
|
884
|
+
while (this.check(TokenKind_1.TokenKind.Dot)) {
|
|
885
|
+
let dot = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.Dot);
|
|
808
886
|
if (!dot) {
|
|
809
887
|
break;
|
|
810
888
|
}
|
|
811
|
-
let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(),
|
|
889
|
+
let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers, ...TokenKind_1.AllowedProperties);
|
|
812
890
|
if (!identifier) {
|
|
813
891
|
break;
|
|
814
892
|
}
|
|
815
893
|
// force it into an identifier so the AST makes some sense
|
|
816
|
-
identifier.kind =
|
|
894
|
+
identifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
817
895
|
expr = new Expression_1.DottedGetExpression(expr, identifier, dot);
|
|
818
896
|
}
|
|
819
897
|
}
|
|
@@ -845,7 +923,7 @@ class Parser {
|
|
|
845
923
|
let libStatement = new Statement_1.LibraryStatement({
|
|
846
924
|
library: this.advance(),
|
|
847
925
|
//grab the next token only if it's a string
|
|
848
|
-
filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'),
|
|
926
|
+
filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), TokenKind_1.TokenKind.StringLiteral)
|
|
849
927
|
});
|
|
850
928
|
this._references.libraryStatements.push(libStatement);
|
|
851
929
|
return libStatement;
|
|
@@ -854,20 +932,20 @@ class Parser {
|
|
|
854
932
|
this.warnIfNotBrighterScriptMode('import statements');
|
|
855
933
|
let importStatement = new Statement_1.ImportStatement(this.advance(),
|
|
856
934
|
//grab the next token only if it's a string
|
|
857
|
-
this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'),
|
|
935
|
+
this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), TokenKind_1.TokenKind.StringLiteral));
|
|
858
936
|
this._references.importStatements.push(importStatement);
|
|
859
937
|
return importStatement;
|
|
860
938
|
}
|
|
861
939
|
annotationExpression() {
|
|
862
940
|
const atToken = this.advance();
|
|
863
|
-
const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(),
|
|
941
|
+
const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
864
942
|
if (identifier) {
|
|
865
|
-
identifier.kind =
|
|
943
|
+
identifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
866
944
|
}
|
|
867
945
|
let annotation = new Expression_1.AnnotationExpression(atToken, identifier);
|
|
868
946
|
this.pendingAnnotations.push(annotation);
|
|
869
947
|
//optional arguments
|
|
870
|
-
if (this.check(
|
|
948
|
+
if (this.check(TokenKind_1.TokenKind.LeftParen)) {
|
|
871
949
|
let leftParen = this.advance();
|
|
872
950
|
annotation.call = this.finishCall(leftParen, annotation, false);
|
|
873
951
|
}
|
|
@@ -880,7 +958,7 @@ class Parser {
|
|
|
880
958
|
}
|
|
881
959
|
const questionMarkToken = this.advance();
|
|
882
960
|
//consume newlines or comments
|
|
883
|
-
while (this.checkAny(
|
|
961
|
+
while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
884
962
|
this.advance();
|
|
885
963
|
}
|
|
886
964
|
let consequent;
|
|
@@ -889,12 +967,12 @@ class Parser {
|
|
|
889
967
|
}
|
|
890
968
|
catch (_a) { }
|
|
891
969
|
//consume newlines or comments
|
|
892
|
-
while (this.checkAny(
|
|
970
|
+
while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
893
971
|
this.advance();
|
|
894
972
|
}
|
|
895
|
-
const colonToken = this.tryConsumeToken(
|
|
973
|
+
const colonToken = this.tryConsumeToken(TokenKind_1.TokenKind.Colon);
|
|
896
974
|
//consume newlines
|
|
897
|
-
while (this.checkAny(
|
|
975
|
+
while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
898
976
|
this.advance();
|
|
899
977
|
}
|
|
900
978
|
let alternate;
|
|
@@ -912,7 +990,7 @@ class Parser {
|
|
|
912
990
|
}
|
|
913
991
|
regexLiteralExpression() {
|
|
914
992
|
this.warnIfNotBrighterScriptMode('regular expression literal');
|
|
915
|
-
return new
|
|
993
|
+
return new Expression_1.RegexLiteralExpression({
|
|
916
994
|
regexLiteral: this.advance()
|
|
917
995
|
});
|
|
918
996
|
}
|
|
@@ -921,23 +999,23 @@ class Parser {
|
|
|
921
999
|
//get the tag name
|
|
922
1000
|
let tagName;
|
|
923
1001
|
if (isTagged) {
|
|
924
|
-
tagName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(),
|
|
1002
|
+
tagName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
925
1003
|
// force it into an identifier so the AST makes some sense
|
|
926
|
-
tagName.kind =
|
|
1004
|
+
tagName.kind = TokenKind_1.TokenKind.Identifier;
|
|
927
1005
|
}
|
|
928
1006
|
let quasis = [];
|
|
929
1007
|
let expressions = [];
|
|
930
1008
|
let openingBacktick = this.peek();
|
|
931
1009
|
this.advance();
|
|
932
1010
|
let currentQuasiExpressionParts = [];
|
|
933
|
-
while (!this.isAtEnd() && !this.check(
|
|
1011
|
+
while (!this.isAtEnd() && !this.check(TokenKind_1.TokenKind.BackTick)) {
|
|
934
1012
|
let next = this.peek();
|
|
935
|
-
if (next.kind ===
|
|
1013
|
+
if (next.kind === TokenKind_1.TokenKind.TemplateStringQuasi) {
|
|
936
1014
|
//a quasi can actually be made up of multiple quasis when it includes char literals
|
|
937
1015
|
currentQuasiExpressionParts.push(new Expression_1.LiteralExpression(next));
|
|
938
1016
|
this.advance();
|
|
939
1017
|
}
|
|
940
|
-
else if (next.kind ===
|
|
1018
|
+
else if (next.kind === TokenKind_1.TokenKind.EscapedCharCodeLiteral) {
|
|
941
1019
|
currentQuasiExpressionParts.push(new Expression_1.EscapedCharCodeLiteralExpression(next));
|
|
942
1020
|
this.advance();
|
|
943
1021
|
}
|
|
@@ -945,12 +1023,12 @@ class Parser {
|
|
|
945
1023
|
//finish up the current quasi
|
|
946
1024
|
quasis.push(new Expression_1.TemplateStringQuasiExpression(currentQuasiExpressionParts));
|
|
947
1025
|
currentQuasiExpressionParts = [];
|
|
948
|
-
if (next.kind ===
|
|
1026
|
+
if (next.kind === TokenKind_1.TokenKind.TemplateStringExpressionBegin) {
|
|
949
1027
|
this.advance();
|
|
950
1028
|
}
|
|
951
1029
|
//now keep this expression
|
|
952
1030
|
expressions.push(this.expression());
|
|
953
|
-
if (!this.isAtEnd() && this.check(
|
|
1031
|
+
if (!this.isAtEnd() && this.check(TokenKind_1.TokenKind.TemplateStringExpressionEnd)) {
|
|
954
1032
|
//TODO is it an error if this is not present?
|
|
955
1033
|
this.advance();
|
|
956
1034
|
}
|
|
@@ -982,12 +1060,12 @@ class Parser {
|
|
|
982
1060
|
const statement = new Statement_1.TryCatchStatement(tryToken);
|
|
983
1061
|
//ensure statement separator
|
|
984
1062
|
this.consumeStatementSeparators();
|
|
985
|
-
statement.tryBranch = this.block(
|
|
1063
|
+
statement.tryBranch = this.block(TokenKind_1.TokenKind.Catch, TokenKind_1.TokenKind.EndTry);
|
|
986
1064
|
const peek = this.peek();
|
|
987
|
-
if (peek.kind !==
|
|
1065
|
+
if (peek.kind !== TokenKind_1.TokenKind.Catch) {
|
|
988
1066
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedCatchBlockInTryCatch()), { range: this.peek().range }));
|
|
989
1067
|
//gracefully handle end-try
|
|
990
|
-
if (peek.kind ===
|
|
1068
|
+
if (peek.kind === TokenKind_1.TokenKind.EndTry) {
|
|
991
1069
|
statement.endTryToken = this.advance();
|
|
992
1070
|
}
|
|
993
1071
|
return statement;
|
|
@@ -995,16 +1073,16 @@ class Parser {
|
|
|
995
1073
|
else {
|
|
996
1074
|
statement.catchToken = this.advance();
|
|
997
1075
|
}
|
|
998
|
-
const exceptionVarToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingExceptionVarToFollowCatch(),
|
|
1076
|
+
const exceptionVarToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingExceptionVarToFollowCatch(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
999
1077
|
if (exceptionVarToken) {
|
|
1000
1078
|
// force it into an identifier so the AST makes some sense
|
|
1001
|
-
exceptionVarToken.kind =
|
|
1079
|
+
exceptionVarToken.kind = TokenKind_1.TokenKind.Identifier;
|
|
1002
1080
|
statement.exceptionVariable = exceptionVarToken;
|
|
1003
1081
|
}
|
|
1004
1082
|
//ensure statement sepatator
|
|
1005
1083
|
this.consumeStatementSeparators();
|
|
1006
|
-
statement.catchBranch = this.block(
|
|
1007
|
-
if (this.peek().kind !==
|
|
1084
|
+
statement.catchBranch = this.block(TokenKind_1.TokenKind.EndTry);
|
|
1085
|
+
if (this.peek().kind !== TokenKind_1.TokenKind.EndTry) {
|
|
1008
1086
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndTryToTerminateTryCatch()), { range: this.peek().range }));
|
|
1009
1087
|
}
|
|
1010
1088
|
else {
|
|
@@ -1015,7 +1093,7 @@ class Parser {
|
|
|
1015
1093
|
throwStatement() {
|
|
1016
1094
|
const throwToken = this.advance();
|
|
1017
1095
|
let expression;
|
|
1018
|
-
if (this.checkAny(
|
|
1096
|
+
if (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
|
|
1019
1097
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExceptionExpressionAfterThrowKeyword()), { range: throwToken.range }));
|
|
1020
1098
|
}
|
|
1021
1099
|
else {
|
|
@@ -1025,19 +1103,19 @@ class Parser {
|
|
|
1025
1103
|
}
|
|
1026
1104
|
dimStatement() {
|
|
1027
1105
|
const dim = this.advance();
|
|
1028
|
-
let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('dim'),
|
|
1106
|
+
let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('dim'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
1029
1107
|
// force to an identifier so the AST makes some sense
|
|
1030
1108
|
if (identifier) {
|
|
1031
|
-
identifier.kind =
|
|
1109
|
+
identifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
1032
1110
|
}
|
|
1033
|
-
let leftSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingLeftSquareBracketAfterDimIdentifier(),
|
|
1111
|
+
let leftSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingLeftSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.LeftSquareBracket);
|
|
1034
1112
|
let expressions = [];
|
|
1035
1113
|
let expression;
|
|
1036
1114
|
do {
|
|
1037
1115
|
try {
|
|
1038
1116
|
expression = this.expression();
|
|
1039
1117
|
expressions.push(expression);
|
|
1040
|
-
if (this.check(
|
|
1118
|
+
if (this.check(TokenKind_1.TokenKind.Comma)) {
|
|
1041
1119
|
this.advance();
|
|
1042
1120
|
}
|
|
1043
1121
|
else {
|
|
@@ -1051,15 +1129,15 @@ class Parser {
|
|
|
1051
1129
|
if (expressions.length === 0) {
|
|
1052
1130
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExpressionsInDimStatement()), { range: this.peek().range }));
|
|
1053
1131
|
}
|
|
1054
|
-
let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(),
|
|
1132
|
+
let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1055
1133
|
return new Statement_1.DimStatement(dim, identifier, leftSquareBracket, expressions, rightSquareBracket);
|
|
1056
1134
|
}
|
|
1057
1135
|
ifStatement() {
|
|
1058
1136
|
// colon before `if` is usually not allowed, unless it's after `then`
|
|
1059
1137
|
if (this.current > 0) {
|
|
1060
1138
|
const prev = this.previous();
|
|
1061
|
-
if (prev.kind ===
|
|
1062
|
-
if (this.current > 1 && this.tokens[this.current - 2].kind !==
|
|
1139
|
+
if (prev.kind === TokenKind_1.TokenKind.Colon) {
|
|
1140
|
+
if (this.current > 1 && this.tokens[this.current - 2].kind !== TokenKind_1.TokenKind.Then) {
|
|
1063
1141
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedColonBeforeIfStatement()), { range: prev.range }));
|
|
1064
1142
|
}
|
|
1065
1143
|
}
|
|
@@ -1073,14 +1151,14 @@ class Parser {
|
|
|
1073
1151
|
let endIfToken;
|
|
1074
1152
|
let elseToken;
|
|
1075
1153
|
//optional `then`
|
|
1076
|
-
if (this.check(
|
|
1154
|
+
if (this.check(TokenKind_1.TokenKind.Then)) {
|
|
1077
1155
|
thenToken = this.advance();
|
|
1078
1156
|
}
|
|
1079
1157
|
//is it inline or multi-line if?
|
|
1080
|
-
const isInlineIfThen = !this.checkAny(
|
|
1158
|
+
const isInlineIfThen = !this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment);
|
|
1081
1159
|
if (isInlineIfThen) {
|
|
1082
1160
|
/*** PARSE INLINE IF STATEMENT ***/
|
|
1083
|
-
thenBranch = this.inlineConditionalBranch(
|
|
1161
|
+
thenBranch = this.inlineConditionalBranch(TokenKind_1.TokenKind.Else, TokenKind_1.TokenKind.EndIf);
|
|
1084
1162
|
if (!thenBranch) {
|
|
1085
1163
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedStatementToFollowConditionalCondition(ifToken.text)), { range: this.peek().range }));
|
|
1086
1164
|
throw this.lastDiagnosticAsError();
|
|
@@ -1089,9 +1167,9 @@ class Parser {
|
|
|
1089
1167
|
this.ensureInline(thenBranch.statements);
|
|
1090
1168
|
}
|
|
1091
1169
|
//else branch
|
|
1092
|
-
if (this.check(
|
|
1170
|
+
if (this.check(TokenKind_1.TokenKind.Else)) {
|
|
1093
1171
|
elseToken = this.advance();
|
|
1094
|
-
if (this.check(
|
|
1172
|
+
if (this.check(TokenKind_1.TokenKind.If)) {
|
|
1095
1173
|
// recurse-read `else if`
|
|
1096
1174
|
elseBranch = this.ifStatement();
|
|
1097
1175
|
//no multi-line if chained with an inline if
|
|
@@ -1099,13 +1177,13 @@ class Parser {
|
|
|
1099
1177
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedInlineIfStatement()), { range: elseBranch.range }));
|
|
1100
1178
|
}
|
|
1101
1179
|
}
|
|
1102
|
-
else if (this.checkAny(
|
|
1180
|
+
else if (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
|
|
1103
1181
|
//expecting inline else branch
|
|
1104
1182
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedInlineIfStatement()), { range: this.peek().range }));
|
|
1105
1183
|
throw this.lastDiagnosticAsError();
|
|
1106
1184
|
}
|
|
1107
1185
|
else {
|
|
1108
|
-
elseBranch = this.inlineConditionalBranch(
|
|
1186
|
+
elseBranch = this.inlineConditionalBranch(TokenKind_1.TokenKind.Else, TokenKind_1.TokenKind.EndIf);
|
|
1109
1187
|
if (elseBranch) {
|
|
1110
1188
|
this.ensureInline(elseBranch.statements);
|
|
1111
1189
|
}
|
|
@@ -1119,9 +1197,9 @@ class Parser {
|
|
|
1119
1197
|
if (!elseBranch || !(0, reflection_1.isIfStatement)(elseBranch)) {
|
|
1120
1198
|
//enforce newline at the end of the inline if statement
|
|
1121
1199
|
const peek = this.peek();
|
|
1122
|
-
if (peek.kind !==
|
|
1200
|
+
if (peek.kind !== TokenKind_1.TokenKind.Newline && peek.kind !== TokenKind_1.TokenKind.Comment && !this.isAtEnd()) {
|
|
1123
1201
|
//ignore last error if it was about a colon
|
|
1124
|
-
if (this.previous().kind ===
|
|
1202
|
+
if (this.previous().kind === TokenKind_1.TokenKind.Colon) {
|
|
1125
1203
|
this.diagnostics.pop();
|
|
1126
1204
|
this.current--;
|
|
1127
1205
|
}
|
|
@@ -1136,9 +1214,9 @@ class Parser {
|
|
|
1136
1214
|
//ensure newline/colon before next keyword
|
|
1137
1215
|
this.ensureNewLineOrColon();
|
|
1138
1216
|
//else branch
|
|
1139
|
-
if (this.check(
|
|
1217
|
+
if (this.check(TokenKind_1.TokenKind.Else)) {
|
|
1140
1218
|
elseToken = this.advance();
|
|
1141
|
-
if (this.check(
|
|
1219
|
+
if (this.check(TokenKind_1.TokenKind.If)) {
|
|
1142
1220
|
// recurse-read `else if`
|
|
1143
1221
|
elseBranch = this.ifStatement();
|
|
1144
1222
|
}
|
|
@@ -1149,7 +1227,7 @@ class Parser {
|
|
|
1149
1227
|
}
|
|
1150
1228
|
}
|
|
1151
1229
|
if (!(0, reflection_1.isIfStatement)(elseBranch)) {
|
|
1152
|
-
if (this.check(
|
|
1230
|
+
if (this.check(TokenKind_1.TokenKind.EndIf)) {
|
|
1153
1231
|
endIfToken = this.advance();
|
|
1154
1232
|
}
|
|
1155
1233
|
else {
|
|
@@ -1172,7 +1250,7 @@ class Parser {
|
|
|
1172
1250
|
let diagnosticsLengthBeforeBlock = this.diagnostics.length;
|
|
1173
1251
|
// we're parsing a multi-line ("block") form of the BrightScript if/then and must find
|
|
1174
1252
|
// a trailing "end if" or "else if"
|
|
1175
|
-
let branch = this.block(
|
|
1253
|
+
let branch = this.block(TokenKind_1.TokenKind.EndIf, TokenKind_1.TokenKind.Else);
|
|
1176
1254
|
if (!branch) {
|
|
1177
1255
|
//throw out any new diagnostics created as a result of a `then` block parse failure.
|
|
1178
1256
|
//the block() function will discard the current line, so any discarded diagnostics will
|
|
@@ -1186,7 +1264,7 @@ class Parser {
|
|
|
1186
1264
|
}
|
|
1187
1265
|
ensureNewLineOrColon(silent = false) {
|
|
1188
1266
|
const prev = this.previous().kind;
|
|
1189
|
-
if (prev !==
|
|
1267
|
+
if (prev !== TokenKind_1.TokenKind.Newline && prev !== TokenKind_1.TokenKind.Colon) {
|
|
1190
1268
|
if (!silent) {
|
|
1191
1269
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedNewlineOrColon()), { range: this.peek().range }));
|
|
1192
1270
|
}
|
|
@@ -1215,12 +1293,12 @@ class Parser {
|
|
|
1215
1293
|
const startingRange = statement.range;
|
|
1216
1294
|
//look for colon statement separator
|
|
1217
1295
|
let foundColon = false;
|
|
1218
|
-
while (this.match(
|
|
1296
|
+
while (this.match(TokenKind_1.TokenKind.Colon)) {
|
|
1219
1297
|
foundColon = true;
|
|
1220
1298
|
}
|
|
1221
1299
|
//if a colon was found, add the next statement or err if unexpected
|
|
1222
1300
|
if (foundColon) {
|
|
1223
|
-
if (!this.checkAny(
|
|
1301
|
+
if (!this.checkAny(TokenKind_1.TokenKind.Newline, ...additionalTerminators)) {
|
|
1224
1302
|
//if not an ending keyword, add next statement
|
|
1225
1303
|
let extra = this.inlineConditionalBranch(...additionalTerminators);
|
|
1226
1304
|
if (!extra) {
|
|
@@ -1238,9 +1316,9 @@ class Parser {
|
|
|
1238
1316
|
}
|
|
1239
1317
|
expressionStatement(expr) {
|
|
1240
1318
|
let expressionStart = this.peek();
|
|
1241
|
-
if (this.checkAny(
|
|
1319
|
+
if (this.checkAny(TokenKind_1.TokenKind.PlusPlus, TokenKind_1.TokenKind.MinusMinus)) {
|
|
1242
1320
|
let operator = this.advance();
|
|
1243
|
-
if (this.checkAny(
|
|
1321
|
+
if (this.checkAny(TokenKind_1.TokenKind.PlusPlus, TokenKind_1.TokenKind.MinusMinus)) {
|
|
1244
1322
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.consecutiveIncrementDecrementOperatorsAreNotAllowed()), { range: this.peek().range }));
|
|
1245
1323
|
throw this.lastDiagnosticAsError();
|
|
1246
1324
|
}
|
|
@@ -1248,7 +1326,9 @@ class Parser {
|
|
|
1248
1326
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.incrementDecrementOperatorsAreNotAllowedAsResultOfFunctionCall()), { range: expressionStart.range }));
|
|
1249
1327
|
throw this.lastDiagnosticAsError();
|
|
1250
1328
|
}
|
|
1251
|
-
|
|
1329
|
+
const result = new Statement_1.IncrementStatement(expr, operator);
|
|
1330
|
+
this._references.expressions.add(result);
|
|
1331
|
+
return result;
|
|
1252
1332
|
}
|
|
1253
1333
|
if ((0, reflection_1.isCallExpression)(expr) || (0, reflection_1.isCallfuncExpression)(expr)) {
|
|
1254
1334
|
return new Statement_1.ExpressionStatement(expr);
|
|
@@ -1265,18 +1345,18 @@ class Parser {
|
|
|
1265
1345
|
* priority as standalone function calls though, so we can parse them in the same way.
|
|
1266
1346
|
*/
|
|
1267
1347
|
let expr = this.call();
|
|
1268
|
-
if (this.checkAny(...
|
|
1348
|
+
if (this.checkAny(...TokenKind_1.AssignmentOperators) && !((0, reflection_1.isCallExpression)(expr))) {
|
|
1269
1349
|
let left = expr;
|
|
1270
1350
|
let operator = this.advance();
|
|
1271
1351
|
let right = this.expression();
|
|
1272
1352
|
// Create a dotted or indexed "set" based on the left-hand side's type
|
|
1273
1353
|
if ((0, reflection_1.isIndexedGetExpression)(left)) {
|
|
1274
|
-
return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind ===
|
|
1354
|
+
return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === TokenKind_1.TokenKind.Equal
|
|
1275
1355
|
? right
|
|
1276
1356
|
: new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare);
|
|
1277
1357
|
}
|
|
1278
1358
|
else if ((0, reflection_1.isDottedGetExpression)(left)) {
|
|
1279
|
-
return new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind ===
|
|
1359
|
+
return new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === TokenKind_1.TokenKind.Equal
|
|
1280
1360
|
? right
|
|
1281
1361
|
: new Expression_1.BinaryExpression(left, operator, right));
|
|
1282
1362
|
}
|
|
@@ -1287,13 +1367,13 @@ class Parser {
|
|
|
1287
1367
|
let printKeyword = this.advance();
|
|
1288
1368
|
let values = [];
|
|
1289
1369
|
while (!this.checkEndOfStatement()) {
|
|
1290
|
-
if (this.check(
|
|
1370
|
+
if (this.check(TokenKind_1.TokenKind.Semicolon)) {
|
|
1291
1371
|
values.push(this.advance());
|
|
1292
1372
|
}
|
|
1293
|
-
else if (this.check(
|
|
1373
|
+
else if (this.check(TokenKind_1.TokenKind.Comma)) {
|
|
1294
1374
|
values.push(this.advance());
|
|
1295
1375
|
}
|
|
1296
|
-
else if (this.check(
|
|
1376
|
+
else if (this.check(TokenKind_1.TokenKind.Else)) {
|
|
1297
1377
|
break; // inline branch
|
|
1298
1378
|
}
|
|
1299
1379
|
else {
|
|
@@ -1306,7 +1386,7 @@ class Parser {
|
|
|
1306
1386
|
values.push(emptyStringLiteral);
|
|
1307
1387
|
}
|
|
1308
1388
|
let last = values[values.length - 1];
|
|
1309
|
-
if ((0,
|
|
1389
|
+
if ((0, Token_1.isToken)(last)) {
|
|
1310
1390
|
// TODO: error, expected value
|
|
1311
1391
|
}
|
|
1312
1392
|
return new Statement_1.PrintStatement({ print: printKeyword }, values);
|
|
@@ -1320,7 +1400,7 @@ class Parser {
|
|
|
1320
1400
|
if (this.checkEndOfStatement()) {
|
|
1321
1401
|
return new Statement_1.ReturnStatement(tokens);
|
|
1322
1402
|
}
|
|
1323
|
-
let toReturn = this.check(
|
|
1403
|
+
let toReturn = this.check(TokenKind_1.TokenKind.Else) ? undefined : this.expression();
|
|
1324
1404
|
return new Statement_1.ReturnStatement(tokens, toReturn);
|
|
1325
1405
|
}
|
|
1326
1406
|
/**
|
|
@@ -1333,7 +1413,7 @@ class Parser {
|
|
|
1333
1413
|
colon: this.advance()
|
|
1334
1414
|
};
|
|
1335
1415
|
//label must be alone on its line, this is probably not a label
|
|
1336
|
-
if (!this.checkAny(
|
|
1416
|
+
if (!this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
1337
1417
|
//rewind and cancel
|
|
1338
1418
|
this.current -= 2;
|
|
1339
1419
|
throw new CancelStatementError();
|
|
@@ -1347,7 +1427,7 @@ class Parser {
|
|
|
1347
1427
|
gotoStatement() {
|
|
1348
1428
|
let tokens = {
|
|
1349
1429
|
goto: this.advance(),
|
|
1350
|
-
label: this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLabelIdentifierAfterGotoKeyword(),
|
|
1430
|
+
label: this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLabelIdentifierAfterGotoKeyword(), TokenKind_1.TokenKind.Identifier)
|
|
1351
1431
|
};
|
|
1352
1432
|
return new Statement_1.GotoStatement(tokens);
|
|
1353
1433
|
}
|
|
@@ -1378,7 +1458,7 @@ class Parser {
|
|
|
1378
1458
|
this.consumeStatementSeparators(true);
|
|
1379
1459
|
let startingToken = this.peek();
|
|
1380
1460
|
const statements = [];
|
|
1381
|
-
while (!this.isAtEnd() && !this.checkAny(
|
|
1461
|
+
while (!this.isAtEnd() && !this.checkAny(TokenKind_1.TokenKind.EndSub, TokenKind_1.TokenKind.EndFunction, ...terminators)) {
|
|
1382
1462
|
//grab the location of the current token
|
|
1383
1463
|
let loopCurrent = this.current;
|
|
1384
1464
|
let dec = this.declaration();
|
|
@@ -1394,7 +1474,7 @@ class Parser {
|
|
|
1394
1474
|
//something went wrong. reset to the top of the loop
|
|
1395
1475
|
this.current = loopCurrent;
|
|
1396
1476
|
//scrap the entire line (hopefully whatever failed has added a diagnostic)
|
|
1397
|
-
this.consumeUntil(
|
|
1477
|
+
this.consumeUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
1398
1478
|
//trash the next token. this prevents an infinite loop. not exactly sure why we need this,
|
|
1399
1479
|
//but there's already an error in the file being parsed, so just leave this line here
|
|
1400
1480
|
this.advance();
|
|
@@ -1411,8 +1491,8 @@ class Parser {
|
|
|
1411
1491
|
//if so, we need to restore the statement separator
|
|
1412
1492
|
let prev = this.previous().kind;
|
|
1413
1493
|
let peek = this.peek().kind;
|
|
1414
|
-
if ((peek ===
|
|
1415
|
-
(prev ===
|
|
1494
|
+
if ((peek === TokenKind_1.TokenKind.EndSub || peek === TokenKind_1.TokenKind.EndFunction) &&
|
|
1495
|
+
(prev === TokenKind_1.TokenKind.Newline || prev === TokenKind_1.TokenKind.Colon)) {
|
|
1416
1496
|
this.current--;
|
|
1417
1497
|
}
|
|
1418
1498
|
}
|
|
@@ -1444,13 +1524,15 @@ class Parser {
|
|
|
1444
1524
|
this.pendingAnnotations = parentAnnotations;
|
|
1445
1525
|
}
|
|
1446
1526
|
expression() {
|
|
1447
|
-
|
|
1527
|
+
const expression = this.anonymousFunction();
|
|
1528
|
+
this._references.expressions.add(expression);
|
|
1529
|
+
return expression;
|
|
1448
1530
|
}
|
|
1449
1531
|
anonymousFunction() {
|
|
1450
|
-
if (this.checkAny(
|
|
1532
|
+
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
1451
1533
|
const func = this.functionDeclaration(true);
|
|
1452
1534
|
//if there's an open paren after this, this is an IIFE
|
|
1453
|
-
if (this.check(
|
|
1535
|
+
if (this.check(TokenKind_1.TokenKind.LeftParen)) {
|
|
1454
1536
|
return this.finishCall(this.advance(), func);
|
|
1455
1537
|
}
|
|
1456
1538
|
else {
|
|
@@ -1458,10 +1540,10 @@ class Parser {
|
|
|
1458
1540
|
}
|
|
1459
1541
|
}
|
|
1460
1542
|
let expr = this.boolean();
|
|
1461
|
-
if (this.check(
|
|
1543
|
+
if (this.check(TokenKind_1.TokenKind.Question)) {
|
|
1462
1544
|
return this.ternaryExpression(expr);
|
|
1463
1545
|
}
|
|
1464
|
-
else if (this.check(
|
|
1546
|
+
else if (this.check(TokenKind_1.TokenKind.QuestionQuestion)) {
|
|
1465
1547
|
return this.nullCoalescingExpression(expr);
|
|
1466
1548
|
}
|
|
1467
1549
|
else {
|
|
@@ -1470,7 +1552,7 @@ class Parser {
|
|
|
1470
1552
|
}
|
|
1471
1553
|
boolean() {
|
|
1472
1554
|
let expr = this.relational();
|
|
1473
|
-
while (this.matchAny(
|
|
1555
|
+
while (this.matchAny(TokenKind_1.TokenKind.And, TokenKind_1.TokenKind.Or)) {
|
|
1474
1556
|
let operator = this.previous();
|
|
1475
1557
|
let right = this.relational();
|
|
1476
1558
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
@@ -1479,7 +1561,7 @@ class Parser {
|
|
|
1479
1561
|
}
|
|
1480
1562
|
relational() {
|
|
1481
1563
|
let expr = this.additive();
|
|
1482
|
-
while (this.matchAny(
|
|
1564
|
+
while (this.matchAny(TokenKind_1.TokenKind.Equal, TokenKind_1.TokenKind.LessGreater, TokenKind_1.TokenKind.Greater, TokenKind_1.TokenKind.GreaterEqual, TokenKind_1.TokenKind.Less, TokenKind_1.TokenKind.LessEqual)) {
|
|
1483
1565
|
let operator = this.previous();
|
|
1484
1566
|
let right = this.additive();
|
|
1485
1567
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
@@ -1489,7 +1571,7 @@ class Parser {
|
|
|
1489
1571
|
// TODO: bitshift
|
|
1490
1572
|
additive() {
|
|
1491
1573
|
let expr = this.multiplicative();
|
|
1492
|
-
while (this.matchAny(
|
|
1574
|
+
while (this.matchAny(TokenKind_1.TokenKind.Plus, TokenKind_1.TokenKind.Minus)) {
|
|
1493
1575
|
let operator = this.previous();
|
|
1494
1576
|
let right = this.multiplicative();
|
|
1495
1577
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
@@ -1498,7 +1580,7 @@ class Parser {
|
|
|
1498
1580
|
}
|
|
1499
1581
|
multiplicative() {
|
|
1500
1582
|
let expr = this.exponential();
|
|
1501
|
-
while (this.matchAny(
|
|
1583
|
+
while (this.matchAny(TokenKind_1.TokenKind.Forwardslash, TokenKind_1.TokenKind.Backslash, TokenKind_1.TokenKind.Star, TokenKind_1.TokenKind.Mod, TokenKind_1.TokenKind.LeftShift, TokenKind_1.TokenKind.RightShift)) {
|
|
1502
1584
|
let operator = this.previous();
|
|
1503
1585
|
let right = this.exponential();
|
|
1504
1586
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
@@ -1507,7 +1589,7 @@ class Parser {
|
|
|
1507
1589
|
}
|
|
1508
1590
|
exponential() {
|
|
1509
1591
|
let expr = this.prefixUnary();
|
|
1510
|
-
while (this.match(
|
|
1592
|
+
while (this.match(TokenKind_1.TokenKind.Caret)) {
|
|
1511
1593
|
let operator = this.previous();
|
|
1512
1594
|
let right = this.prefixUnary();
|
|
1513
1595
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
@@ -1516,7 +1598,7 @@ class Parser {
|
|
|
1516
1598
|
}
|
|
1517
1599
|
prefixUnary() {
|
|
1518
1600
|
const nextKind = this.peek().kind;
|
|
1519
|
-
if (nextKind ===
|
|
1601
|
+
if (nextKind === TokenKind_1.TokenKind.Not || nextKind === TokenKind_1.TokenKind.Minus) {
|
|
1520
1602
|
this.current++; //advance
|
|
1521
1603
|
let operator = this.previous();
|
|
1522
1604
|
let right = this.prefixUnary();
|
|
@@ -1526,17 +1608,17 @@ class Parser {
|
|
|
1526
1608
|
}
|
|
1527
1609
|
indexedGet(expr) {
|
|
1528
1610
|
let openingSquare = this.previous();
|
|
1529
|
-
while (this.match(
|
|
1611
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1530
1612
|
let index = this.expression();
|
|
1531
|
-
while (this.match(
|
|
1532
|
-
let closingSquare = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(),
|
|
1613
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1614
|
+
let closingSquare = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1533
1615
|
return new Expression_1.IndexedGetExpression(expr, index, openingSquare, closingSquare);
|
|
1534
1616
|
}
|
|
1535
1617
|
newExpression() {
|
|
1536
1618
|
this.warnIfNotBrighterScriptMode(`using 'new' keyword to construct a class`);
|
|
1537
1619
|
let newToken = this.advance();
|
|
1538
1620
|
let nameExpr = this.getNamespacedVariableNameExpression();
|
|
1539
|
-
let leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text),
|
|
1621
|
+
let leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.LeftParen);
|
|
1540
1622
|
let call = this.finishCall(leftParen, nameExpr);
|
|
1541
1623
|
//pop the call from the callExpressions list because this is technically something else
|
|
1542
1624
|
this.callExpressions.pop();
|
|
@@ -1550,46 +1632,52 @@ class Parser {
|
|
|
1550
1632
|
callfunc(callee) {
|
|
1551
1633
|
this.warnIfNotBrighterScriptMode('callfunc operator');
|
|
1552
1634
|
let operator = this.previous();
|
|
1553
|
-
let methodName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(),
|
|
1635
|
+
let methodName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
1554
1636
|
// force it into an identifier so the AST makes some sense
|
|
1555
|
-
methodName.kind =
|
|
1556
|
-
let openParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOpenParenToFollowCallfuncIdentifier(),
|
|
1637
|
+
methodName.kind = TokenKind_1.TokenKind.Identifier;
|
|
1638
|
+
let openParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOpenParenToFollowCallfuncIdentifier(), TokenKind_1.TokenKind.LeftParen);
|
|
1557
1639
|
let call = this.finishCall(openParen, callee, false);
|
|
1558
1640
|
return new Expression_1.CallfuncExpression(callee, operator, methodName, openParen, call.args, call.closingParen);
|
|
1559
1641
|
}
|
|
1560
1642
|
call() {
|
|
1561
|
-
if (this.check(
|
|
1643
|
+
if (this.check(TokenKind_1.TokenKind.New) && this.checkAnyNext(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
|
|
1562
1644
|
return this.newExpression();
|
|
1563
1645
|
}
|
|
1564
1646
|
let expr = this.primary();
|
|
1647
|
+
//an expression to keep for _references
|
|
1648
|
+
let referenceCallExpression;
|
|
1565
1649
|
while (true) {
|
|
1566
|
-
if (this.match(
|
|
1650
|
+
if (this.match(TokenKind_1.TokenKind.LeftParen)) {
|
|
1567
1651
|
expr = this.finishCall(this.previous(), expr);
|
|
1652
|
+
//store this call expression in references
|
|
1653
|
+
referenceCallExpression = expr;
|
|
1568
1654
|
}
|
|
1569
|
-
else if (this.match(
|
|
1655
|
+
else if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
1570
1656
|
expr = this.indexedGet(expr);
|
|
1571
1657
|
}
|
|
1572
|
-
else if (this.match(
|
|
1658
|
+
else if (this.match(TokenKind_1.TokenKind.Callfunc)) {
|
|
1573
1659
|
expr = this.callfunc(expr);
|
|
1660
|
+
//store this callfunc expression in references
|
|
1661
|
+
referenceCallExpression = expr;
|
|
1574
1662
|
}
|
|
1575
|
-
else if (this.match(
|
|
1576
|
-
if (this.match(
|
|
1663
|
+
else if (this.match(TokenKind_1.TokenKind.Dot)) {
|
|
1664
|
+
if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
1577
1665
|
expr = this.indexedGet(expr);
|
|
1578
1666
|
}
|
|
1579
1667
|
else {
|
|
1580
1668
|
let dot = this.previous();
|
|
1581
|
-
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(),
|
|
1669
|
+
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
1582
1670
|
// force it into an identifier so the AST makes some sense
|
|
1583
|
-
name.kind =
|
|
1671
|
+
name.kind = TokenKind_1.TokenKind.Identifier;
|
|
1584
1672
|
expr = new Expression_1.DottedGetExpression(expr, name, dot);
|
|
1585
1673
|
this.addPropertyHints(name);
|
|
1586
1674
|
}
|
|
1587
1675
|
}
|
|
1588
|
-
else if (this.check(
|
|
1676
|
+
else if (this.check(TokenKind_1.TokenKind.At)) {
|
|
1589
1677
|
let dot = this.advance();
|
|
1590
|
-
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(),
|
|
1678
|
+
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
1591
1679
|
// force it into an identifier so the AST makes some sense
|
|
1592
|
-
name.kind =
|
|
1680
|
+
name.kind = TokenKind_1.TokenKind.Identifier;
|
|
1593
1681
|
expr = new Expression_1.XmlAttributeGetExpression(expr, name, dot);
|
|
1594
1682
|
//only allow a single `@` expression
|
|
1595
1683
|
break;
|
|
@@ -1598,24 +1686,28 @@ class Parser {
|
|
|
1598
1686
|
break;
|
|
1599
1687
|
}
|
|
1600
1688
|
}
|
|
1689
|
+
//if we found a callExpression, add it to `expressions` in references
|
|
1690
|
+
if (referenceCallExpression) {
|
|
1691
|
+
this._references.expressions.add(referenceCallExpression);
|
|
1692
|
+
}
|
|
1601
1693
|
return expr;
|
|
1602
1694
|
}
|
|
1603
1695
|
finishCall(openingParen, callee, addToCallExpressionList = true) {
|
|
1604
1696
|
let args = [];
|
|
1605
|
-
while (this.match(
|
|
1697
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1606
1698
|
}
|
|
1607
|
-
if (!this.check(
|
|
1699
|
+
if (!this.check(TokenKind_1.TokenKind.RightParen)) {
|
|
1608
1700
|
do {
|
|
1609
|
-
while (this.match(
|
|
1701
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1610
1702
|
if (args.length >= Expression_1.CallExpression.MaximumArguments) {
|
|
1611
1703
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableArguments(args.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
|
|
1612
1704
|
throw this.lastDiagnosticAsError();
|
|
1613
1705
|
}
|
|
1614
1706
|
args.push(this.expression());
|
|
1615
|
-
} while (this.match(
|
|
1707
|
+
} while (this.match(TokenKind_1.TokenKind.Comma));
|
|
1616
1708
|
}
|
|
1617
|
-
while (this.match(
|
|
1618
|
-
const closingParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(),
|
|
1709
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1710
|
+
const closingParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), TokenKind_1.TokenKind.RightParen);
|
|
1619
1711
|
if ((0, reflection_1.isVariableExpression)(callee)) {
|
|
1620
1712
|
callee.isCalled = true;
|
|
1621
1713
|
}
|
|
@@ -1632,7 +1724,7 @@ class Parser {
|
|
|
1632
1724
|
*/
|
|
1633
1725
|
typeToken() {
|
|
1634
1726
|
let typeToken;
|
|
1635
|
-
if (this.checkAny(...
|
|
1727
|
+
if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
|
|
1636
1728
|
// Token is a built in type
|
|
1637
1729
|
typeToken = this.advance();
|
|
1638
1730
|
}
|
|
@@ -1640,7 +1732,7 @@ class Parser {
|
|
|
1640
1732
|
try {
|
|
1641
1733
|
// see if we can get a namespaced identifer
|
|
1642
1734
|
const qualifiedType = this.getNamespacedVariableNameExpression();
|
|
1643
|
-
typeToken = (0, creators_1.createToken)(
|
|
1735
|
+
typeToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, qualifiedType.getName(this.options.mode), qualifiedType.range);
|
|
1644
1736
|
}
|
|
1645
1737
|
catch (_a) {
|
|
1646
1738
|
//could not get an identifier - just get whatever's next
|
|
@@ -1655,53 +1747,53 @@ class Parser {
|
|
|
1655
1747
|
}
|
|
1656
1748
|
primary() {
|
|
1657
1749
|
switch (true) {
|
|
1658
|
-
case this.matchAny(
|
|
1750
|
+
case this.matchAny(TokenKind_1.TokenKind.False, TokenKind_1.TokenKind.True, TokenKind_1.TokenKind.Invalid, TokenKind_1.TokenKind.IntegerLiteral, TokenKind_1.TokenKind.LongIntegerLiteral, TokenKind_1.TokenKind.FloatLiteral, TokenKind_1.TokenKind.DoubleLiteral, TokenKind_1.TokenKind.StringLiteral):
|
|
1659
1751
|
return new Expression_1.LiteralExpression(this.previous());
|
|
1660
1752
|
//capture source literals (LINE_NUM if brightscript, or a bunch of them if brighterscript)
|
|
1661
|
-
case this.matchAny(
|
|
1753
|
+
case this.matchAny(TokenKind_1.TokenKind.LineNumLiteral, ...(this.options.mode === ParseMode.BrightScript ? [] : TokenKind_1.BrighterScriptSourceLiterals)):
|
|
1662
1754
|
return new Expression_1.SourceLiteralExpression(this.previous());
|
|
1663
1755
|
//template string
|
|
1664
|
-
case this.check(
|
|
1756
|
+
case this.check(TokenKind_1.TokenKind.BackTick):
|
|
1665
1757
|
return this.templateString(false);
|
|
1666
1758
|
//tagged template string (currently we do not support spaces between the identifier and the backtick)
|
|
1667
|
-
case this.checkAny(
|
|
1759
|
+
case this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers) && this.checkNext(TokenKind_1.TokenKind.BackTick):
|
|
1668
1760
|
return this.templateString(true);
|
|
1669
|
-
case this.matchAny(
|
|
1761
|
+
case this.matchAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
|
|
1670
1762
|
return new Expression_1.VariableExpression(this.previous(), this.currentNamespaceName);
|
|
1671
|
-
case this.match(
|
|
1763
|
+
case this.match(TokenKind_1.TokenKind.LeftParen):
|
|
1672
1764
|
let left = this.previous();
|
|
1673
1765
|
let expr = this.expression();
|
|
1674
|
-
let right = this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftParenAfterExpression(),
|
|
1766
|
+
let right = this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftParenAfterExpression(), TokenKind_1.TokenKind.RightParen);
|
|
1675
1767
|
return new Expression_1.GroupingExpression({ left: left, right: right }, expr);
|
|
1676
|
-
case this.match(
|
|
1768
|
+
case this.match(TokenKind_1.TokenKind.LeftSquareBracket):
|
|
1677
1769
|
let elements = [];
|
|
1678
1770
|
let openingSquare = this.previous();
|
|
1679
1771
|
//add any comment found right after the opening square
|
|
1680
|
-
if (this.check(
|
|
1772
|
+
if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1681
1773
|
elements.push(new Statement_1.CommentStatement([this.advance()]));
|
|
1682
1774
|
}
|
|
1683
|
-
while (this.match(
|
|
1775
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1684
1776
|
}
|
|
1685
|
-
if (!this.match(
|
|
1777
|
+
if (!this.match(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1686
1778
|
elements.push(this.expression());
|
|
1687
|
-
while (this.matchAny(
|
|
1688
|
-
if (this.checkPrevious(
|
|
1689
|
-
let comment = this.check(
|
|
1779
|
+
while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
1780
|
+
if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1781
|
+
let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
|
|
1690
1782
|
elements.push(new Statement_1.CommentStatement([comment]));
|
|
1691
1783
|
}
|
|
1692
|
-
while (this.match(
|
|
1784
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1693
1785
|
}
|
|
1694
|
-
if (this.check(
|
|
1786
|
+
if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1695
1787
|
break;
|
|
1696
1788
|
}
|
|
1697
1789
|
elements.push(this.expression());
|
|
1698
1790
|
}
|
|
1699
|
-
this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(),
|
|
1791
|
+
this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1700
1792
|
}
|
|
1701
1793
|
let closingSquare = this.previous();
|
|
1702
1794
|
//this.consume("Expected newline or ':' after array literal", TokenKind.Newline, TokenKind.Colon, TokenKind.Eof);
|
|
1703
1795
|
return new Expression_1.ArrayLiteralExpression(elements, openingSquare, closingSquare);
|
|
1704
|
-
case this.match(
|
|
1796
|
+
case this.match(TokenKind_1.TokenKind.LeftCurlyBrace):
|
|
1705
1797
|
let openingBrace = this.previous();
|
|
1706
1798
|
let members = [];
|
|
1707
1799
|
let key = () => {
|
|
@@ -1710,25 +1802,25 @@ class Parser {
|
|
|
1710
1802
|
keyToken: null,
|
|
1711
1803
|
range: null
|
|
1712
1804
|
};
|
|
1713
|
-
if (this.checkAny(
|
|
1805
|
+
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
1714
1806
|
result.keyToken = this.advance();
|
|
1715
1807
|
}
|
|
1716
|
-
else if (this.check(
|
|
1808
|
+
else if (this.check(TokenKind_1.TokenKind.StringLiteral)) {
|
|
1717
1809
|
result.keyToken = this.advance();
|
|
1718
1810
|
}
|
|
1719
1811
|
else {
|
|
1720
1812
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedAAKey()), { range: this.peek().range }));
|
|
1721
1813
|
throw this.lastDiagnosticAsError();
|
|
1722
1814
|
}
|
|
1723
|
-
result.colonToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedColonBetweenAAKeyAndvalue(),
|
|
1815
|
+
result.colonToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedColonBetweenAAKeyAndvalue(), TokenKind_1.TokenKind.Colon);
|
|
1724
1816
|
result.range = util_1.util.getRange(result.keyToken, result.colonToken);
|
|
1725
1817
|
return result;
|
|
1726
1818
|
};
|
|
1727
|
-
while (this.match(
|
|
1819
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1728
1820
|
}
|
|
1729
|
-
if (!this.match(
|
|
1821
|
+
if (!this.match(TokenKind_1.TokenKind.RightCurlyBrace)) {
|
|
1730
1822
|
let lastAAMember;
|
|
1731
|
-
if (this.check(
|
|
1823
|
+
if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1732
1824
|
lastAAMember = null;
|
|
1733
1825
|
members.push(new Statement_1.CommentStatement([this.advance()]));
|
|
1734
1826
|
}
|
|
@@ -1738,26 +1830,26 @@ class Parser {
|
|
|
1738
1830
|
lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr);
|
|
1739
1831
|
members.push(lastAAMember);
|
|
1740
1832
|
}
|
|
1741
|
-
while (this.matchAny(
|
|
1833
|
+
while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
|
|
1742
1834
|
// collect comma at end of expression
|
|
1743
|
-
if (lastAAMember && this.checkPrevious(
|
|
1835
|
+
if (lastAAMember && this.checkPrevious(TokenKind_1.TokenKind.Comma)) {
|
|
1744
1836
|
lastAAMember.commaToken = this.previous();
|
|
1745
1837
|
}
|
|
1746
1838
|
//check for comment at the end of the current line
|
|
1747
|
-
if (this.check(
|
|
1748
|
-
let token = this.checkPrevious(
|
|
1839
|
+
if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
|
|
1840
|
+
let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
|
|
1749
1841
|
members.push(new Statement_1.CommentStatement([token]));
|
|
1750
1842
|
}
|
|
1751
1843
|
else {
|
|
1752
1844
|
this.consumeStatementSeparators(true);
|
|
1753
1845
|
//check for a comment on its own line
|
|
1754
|
-
if (this.check(
|
|
1755
|
-
let token = this.checkPrevious(
|
|
1846
|
+
if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
|
|
1847
|
+
let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
|
|
1756
1848
|
lastAAMember = null;
|
|
1757
1849
|
members.push(new Statement_1.CommentStatement([token]));
|
|
1758
1850
|
continue;
|
|
1759
1851
|
}
|
|
1760
|
-
if (this.check(
|
|
1852
|
+
if (this.check(TokenKind_1.TokenKind.RightCurlyBrace)) {
|
|
1761
1853
|
break;
|
|
1762
1854
|
}
|
|
1763
1855
|
let k = key();
|
|
@@ -1766,22 +1858,22 @@ class Parser {
|
|
|
1766
1858
|
members.push(lastAAMember);
|
|
1767
1859
|
}
|
|
1768
1860
|
}
|
|
1769
|
-
this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(),
|
|
1861
|
+
this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(), TokenKind_1.TokenKind.RightCurlyBrace);
|
|
1770
1862
|
}
|
|
1771
1863
|
let closingBrace = this.previous();
|
|
1772
1864
|
const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace);
|
|
1773
1865
|
this.addPropertyHints(aaExpr);
|
|
1774
1866
|
return aaExpr;
|
|
1775
|
-
case this.matchAny(
|
|
1867
|
+
case this.matchAny(TokenKind_1.TokenKind.Pos, TokenKind_1.TokenKind.Tab):
|
|
1776
1868
|
let token = Object.assign(this.previous(), {
|
|
1777
|
-
kind:
|
|
1869
|
+
kind: TokenKind_1.TokenKind.Identifier
|
|
1778
1870
|
});
|
|
1779
1871
|
return new Expression_1.VariableExpression(token, this.currentNamespaceName);
|
|
1780
|
-
case this.checkAny(
|
|
1872
|
+
case this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub):
|
|
1781
1873
|
return this.anonymousFunction();
|
|
1782
|
-
case this.check(
|
|
1874
|
+
case this.check(TokenKind_1.TokenKind.RegexLiteral):
|
|
1783
1875
|
return this.regexLiteralExpression();
|
|
1784
|
-
case this.check(
|
|
1876
|
+
case this.check(TokenKind_1.TokenKind.Comment):
|
|
1785
1877
|
return new Statement_1.CommentStatement([this.advance()]);
|
|
1786
1878
|
default:
|
|
1787
1879
|
//if we found an expected terminator, don't throw a diagnostic...just return undefined
|
|
@@ -1851,12 +1943,12 @@ class Parser {
|
|
|
1851
1943
|
}
|
|
1852
1944
|
consumeStatementSeparators(optional = false) {
|
|
1853
1945
|
//a comment or EOF mark the end of the statement
|
|
1854
|
-
if (this.isAtEnd() || this.check(
|
|
1946
|
+
if (this.isAtEnd() || this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1855
1947
|
return true;
|
|
1856
1948
|
}
|
|
1857
1949
|
let consumed = false;
|
|
1858
1950
|
//consume any newlines and colons
|
|
1859
|
-
while (this.matchAny(
|
|
1951
|
+
while (this.matchAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
|
|
1860
1952
|
consumed = true;
|
|
1861
1953
|
}
|
|
1862
1954
|
if (!optional && !consumed) {
|
|
@@ -1872,7 +1964,7 @@ class Parser {
|
|
|
1872
1964
|
}
|
|
1873
1965
|
checkEndOfStatement() {
|
|
1874
1966
|
const nextKind = this.peek().kind;
|
|
1875
|
-
return [
|
|
1967
|
+
return [TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Eof].includes(nextKind);
|
|
1876
1968
|
}
|
|
1877
1969
|
checkPrevious(tokenKind) {
|
|
1878
1970
|
var _a;
|
|
@@ -1880,14 +1972,14 @@ class Parser {
|
|
|
1880
1972
|
}
|
|
1881
1973
|
check(tokenKind) {
|
|
1882
1974
|
const nextKind = this.peek().kind;
|
|
1883
|
-
if (nextKind ===
|
|
1975
|
+
if (nextKind === TokenKind_1.TokenKind.Eof) {
|
|
1884
1976
|
return false;
|
|
1885
1977
|
}
|
|
1886
1978
|
return nextKind === tokenKind;
|
|
1887
1979
|
}
|
|
1888
1980
|
checkAny(...tokenKinds) {
|
|
1889
1981
|
const nextKind = this.peek().kind;
|
|
1890
|
-
if (nextKind ===
|
|
1982
|
+
if (nextKind === TokenKind_1.TokenKind.Eof) {
|
|
1891
1983
|
return false;
|
|
1892
1984
|
}
|
|
1893
1985
|
return tokenKinds.includes(nextKind);
|
|
@@ -1906,7 +1998,7 @@ class Parser {
|
|
|
1906
1998
|
return tokenKinds.includes(nextKind);
|
|
1907
1999
|
}
|
|
1908
2000
|
isAtEnd() {
|
|
1909
|
-
return this.peek().kind ===
|
|
2001
|
+
return this.peek().kind === TokenKind_1.TokenKind.Eof;
|
|
1910
2002
|
}
|
|
1911
2003
|
peekNext() {
|
|
1912
2004
|
if (this.isAtEnd()) {
|
|
@@ -1928,16 +2020,16 @@ class Parser {
|
|
|
1928
2020
|
return;
|
|
1929
2021
|
}
|
|
1930
2022
|
switch (this.peek().kind) { //eslint-disable-line @typescript-eslint/switch-exhaustiveness-check
|
|
1931
|
-
case
|
|
1932
|
-
case
|
|
1933
|
-
case
|
|
1934
|
-
case
|
|
1935
|
-
case
|
|
1936
|
-
case
|
|
1937
|
-
case
|
|
1938
|
-
case
|
|
1939
|
-
case
|
|
1940
|
-
case
|
|
2023
|
+
case TokenKind_1.TokenKind.Namespace:
|
|
2024
|
+
case TokenKind_1.TokenKind.Class:
|
|
2025
|
+
case TokenKind_1.TokenKind.Function:
|
|
2026
|
+
case TokenKind_1.TokenKind.Sub:
|
|
2027
|
+
case TokenKind_1.TokenKind.If:
|
|
2028
|
+
case TokenKind_1.TokenKind.For:
|
|
2029
|
+
case TokenKind_1.TokenKind.ForEach:
|
|
2030
|
+
case TokenKind_1.TokenKind.While:
|
|
2031
|
+
case TokenKind_1.TokenKind.Print:
|
|
2032
|
+
case TokenKind_1.TokenKind.Return:
|
|
1941
2033
|
// start parsing again from the next block starter or obvious
|
|
1942
2034
|
// expression start
|
|
1943
2035
|
return;
|
|
@@ -1952,13 +2044,55 @@ class Parser {
|
|
|
1952
2044
|
*/
|
|
1953
2045
|
findReferences() {
|
|
1954
2046
|
this._references = new References();
|
|
2047
|
+
const excludedExpressions = new Set();
|
|
2048
|
+
const visitCallExpression = (e) => {
|
|
2049
|
+
for (const p of e.args) {
|
|
2050
|
+
this._references.expressions.add(p);
|
|
2051
|
+
}
|
|
2052
|
+
//add calls that were not excluded (from loop below)
|
|
2053
|
+
if (!excludedExpressions.has(e)) {
|
|
2054
|
+
this._references.expressions.add(e);
|
|
2055
|
+
}
|
|
2056
|
+
//if this call is part of a longer expression that includes a call higher up, find that higher one and remove it
|
|
2057
|
+
if (e.callee) {
|
|
2058
|
+
let node = e.callee;
|
|
2059
|
+
while (node) {
|
|
2060
|
+
//the primary goal for this loop. If we found a parent call expression, remove it from `references`
|
|
2061
|
+
if ((0, reflection_1.isCallExpression)(node)) {
|
|
2062
|
+
this.references.expressions.delete(node);
|
|
2063
|
+
excludedExpressions.add(node);
|
|
2064
|
+
//stop here. even if there are multiple calls in the chain, each child will find and remove its closest parent, so that reduces excess walking.
|
|
2065
|
+
break;
|
|
2066
|
+
//when we hit a variable expression, we're definitely at the leftmost expression so stop
|
|
2067
|
+
}
|
|
2068
|
+
else if ((0, reflection_1.isVariableExpression)(node)) {
|
|
2069
|
+
break;
|
|
2070
|
+
//if
|
|
2071
|
+
}
|
|
2072
|
+
else if ((0, reflection_1.isDottedGetExpression)(node) || (0, reflection_1.isIndexedGetExpression)(node)) {
|
|
2073
|
+
node = node.obj;
|
|
2074
|
+
}
|
|
2075
|
+
else {
|
|
2076
|
+
//some expression we don't understand. log it and quit the loop
|
|
2077
|
+
this.logger.info('Encountered unknown expression while calculating function expression chain', node);
|
|
2078
|
+
break;
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
};
|
|
1955
2083
|
this.ast.walk((0, visitors_1.createVisitor)({
|
|
1956
2084
|
AssignmentStatement: s => {
|
|
1957
2085
|
this._references.assignmentStatements.push(s);
|
|
2086
|
+
this.references.expressions.add(s.value);
|
|
1958
2087
|
},
|
|
1959
2088
|
ClassStatement: s => {
|
|
1960
2089
|
this._references.classStatements.push(s);
|
|
1961
2090
|
},
|
|
2091
|
+
ClassFieldStatement: s => {
|
|
2092
|
+
if (s.initialValue) {
|
|
2093
|
+
this._references.expressions.add(s.initialValue);
|
|
2094
|
+
}
|
|
2095
|
+
},
|
|
1962
2096
|
NamespaceStatement: s => {
|
|
1963
2097
|
this._references.namespaceStatements.push(s);
|
|
1964
2098
|
},
|
|
@@ -1978,15 +2112,50 @@ class Parser {
|
|
|
1978
2112
|
},
|
|
1979
2113
|
NewExpression: e => {
|
|
1980
2114
|
this._references.newExpressions.push(e);
|
|
2115
|
+
for (const p of e.call.args) {
|
|
2116
|
+
this._references.expressions.add(p);
|
|
2117
|
+
}
|
|
2118
|
+
},
|
|
2119
|
+
ExpressionStatement: s => {
|
|
2120
|
+
this._references.expressions.add(s.expression);
|
|
2121
|
+
},
|
|
2122
|
+
CallfuncExpression: e => {
|
|
2123
|
+
visitCallExpression(e);
|
|
2124
|
+
},
|
|
2125
|
+
CallExpression: e => {
|
|
2126
|
+
visitCallExpression(e);
|
|
1981
2127
|
},
|
|
1982
2128
|
AALiteralExpression: e => {
|
|
1983
2129
|
this.addPropertyHints(e);
|
|
2130
|
+
this._references.expressions.add(e);
|
|
2131
|
+
for (const member of e.elements) {
|
|
2132
|
+
if ((0, reflection_1.isAAMemberExpression)(member)) {
|
|
2133
|
+
this._references.expressions.add(member.value);
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
},
|
|
2137
|
+
ArrayLiteralExpression: e => {
|
|
2138
|
+
for (const element of e.elements) {
|
|
2139
|
+
//keep everything except comments
|
|
2140
|
+
if (!(0, reflection_1.isCommentStatement)(element)) {
|
|
2141
|
+
this._references.expressions.add(element);
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
1984
2144
|
},
|
|
1985
2145
|
DottedGetExpression: e => {
|
|
1986
2146
|
this.addPropertyHints(e.name);
|
|
1987
2147
|
},
|
|
1988
2148
|
DottedSetStatement: e => {
|
|
1989
2149
|
this.addPropertyHints(e.name);
|
|
2150
|
+
},
|
|
2151
|
+
EnumStatement: e => {
|
|
2152
|
+
this._references.enumStatements.push(e);
|
|
2153
|
+
},
|
|
2154
|
+
UnaryExpression: e => {
|
|
2155
|
+
this._references.expressions.add(e);
|
|
2156
|
+
},
|
|
2157
|
+
IncrementStatement: e => {
|
|
2158
|
+
this._references.expressions.add(e);
|
|
1990
2159
|
}
|
|
1991
2160
|
}), {
|
|
1992
2161
|
walkMode: visitors_1.WalkMode.visitAllRecursive
|
|
@@ -2003,11 +2172,24 @@ var ParseMode;
|
|
|
2003
2172
|
})(ParseMode = exports.ParseMode || (exports.ParseMode = {}));
|
|
2004
2173
|
class References {
|
|
2005
2174
|
constructor() {
|
|
2175
|
+
this.cache = new Cache_1.Cache();
|
|
2006
2176
|
this.assignmentStatements = [];
|
|
2007
2177
|
this.classStatements = [];
|
|
2008
2178
|
this.functionExpressions = [];
|
|
2009
2179
|
this.functionStatements = [];
|
|
2010
2180
|
this.interfaceStatements = [];
|
|
2181
|
+
this.enumStatements = [];
|
|
2182
|
+
/**
|
|
2183
|
+
* A collection of full expressions. This excludes intermediary expressions.
|
|
2184
|
+
*
|
|
2185
|
+
* Example 1:
|
|
2186
|
+
* `a.b.c` is composed of `a` (variableExpression) `.b` (DottedGetExpression) `.c` (DottedGetExpression)
|
|
2187
|
+
* This will only contain the final `.c` DottedGetExpression because `.b` and `a` can both be derived by walking back from the `.c` DottedGetExpression.
|
|
2188
|
+
*
|
|
2189
|
+
* Example 2:
|
|
2190
|
+
* `name.space.doSomething(a.b.c)` will result in 2 entries in this list. the `CallExpression` for `doSomething`, and the `.c` DottedGetExpression.
|
|
2191
|
+
*/
|
|
2192
|
+
this.expressions = new Set();
|
|
2011
2193
|
this.importStatements = [];
|
|
2012
2194
|
this.libraryStatements = [];
|
|
2013
2195
|
this.namespaceStatements = [];
|
|
@@ -2044,6 +2226,15 @@ class References {
|
|
|
2044
2226
|
}
|
|
2045
2227
|
return this._interfaceStatementLookup;
|
|
2046
2228
|
}
|
|
2229
|
+
get enumStatementLookup() {
|
|
2230
|
+
return this.cache.getOrAdd('enums', () => {
|
|
2231
|
+
const result = new Map();
|
|
2232
|
+
for (const stmt of this.enumStatements) {
|
|
2233
|
+
result.set(stmt.fullName.toLowerCase(), stmt);
|
|
2234
|
+
}
|
|
2235
|
+
return result;
|
|
2236
|
+
});
|
|
2237
|
+
}
|
|
2047
2238
|
}
|
|
2048
2239
|
exports.References = References;
|
|
2049
2240
|
class CancelStatementError extends Error {
|