brighterscript 1.0.0-alpha.25 → 1.0.0-alpha.26

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.
Files changed (120) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/bsconfig.schema.json +5 -0
  3. package/dist/AstValidationSegmenter.js +4 -4
  4. package/dist/AstValidationSegmenter.js.map +1 -1
  5. package/dist/BsConfig.d.ts +1 -0
  6. package/dist/Program.d.ts +1 -1
  7. package/dist/Program.js +18 -19
  8. package/dist/Program.js.map +1 -1
  9. package/dist/Scope.d.ts +0 -5
  10. package/dist/Scope.js +8 -14
  11. package/dist/Scope.js.map +1 -1
  12. package/dist/XmlScope.d.ts +0 -5
  13. package/dist/XmlScope.js +3 -21
  14. package/dist/XmlScope.js.map +1 -1
  15. package/dist/astUtils/CachedLookups.js +3 -3
  16. package/dist/astUtils/CachedLookups.js.map +1 -1
  17. package/dist/astUtils/Editor.spec.js +1 -1
  18. package/dist/astUtils/Editor.spec.js.map +1 -1
  19. package/dist/astUtils/creators.js +32 -12
  20. package/dist/astUtils/creators.js.map +1 -1
  21. package/dist/astUtils/creators.spec.js +4 -4
  22. package/dist/astUtils/creators.spec.js.map +1 -1
  23. package/dist/astUtils/reflection.d.ts +1 -1
  24. package/dist/astUtils/reflection.js +1 -1
  25. package/dist/astUtils/reflection.js.map +1 -1
  26. package/dist/astUtils/reflection.spec.js +59 -42
  27. package/dist/astUtils/reflection.spec.js.map +1 -1
  28. package/dist/astUtils/visitors.spec.js +30 -19
  29. package/dist/astUtils/visitors.spec.js.map +1 -1
  30. package/dist/bscPlugin/BscPlugin.d.ts +2 -1
  31. package/dist/bscPlugin/BscPlugin.js +7 -3
  32. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  33. package/dist/bscPlugin/CallExpressionInfo.js +7 -7
  34. package/dist/bscPlugin/CallExpressionInfo.js.map +1 -1
  35. package/dist/bscPlugin/SignatureHelpUtil.js +5 -4
  36. package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -1
  37. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +2 -2
  38. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  39. package/dist/bscPlugin/completions/CompletionsProcessor.js +3 -3
  40. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
  41. package/dist/bscPlugin/definition/DefinitionProvider.d.ts +13 -0
  42. package/dist/bscPlugin/definition/DefinitionProvider.js +210 -0
  43. package/dist/bscPlugin/definition/DefinitionProvider.js.map +1 -0
  44. package/dist/bscPlugin/definition/DefinitionProvider.spec.d.ts +1 -0
  45. package/dist/bscPlugin/definition/DefinitionProvider.spec.js +88 -0
  46. package/dist/bscPlugin/definition/DefinitionProvider.spec.js.map +1 -0
  47. package/dist/bscPlugin/hover/HoverProcessor.js +2 -2
  48. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -1
  49. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +0 -2
  50. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
  51. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +8 -6
  52. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -1
  53. package/dist/bscPlugin/validation/BrsFileValidator.js +28 -28
  54. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  55. package/dist/bscPlugin/validation/ScopeValidator.d.ts +4 -0
  56. package/dist/bscPlugin/validation/ScopeValidator.js +51 -20
  57. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
  58. package/dist/bscPlugin/validation/ScopeValidator.spec.js +73 -0
  59. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -1
  60. package/dist/files/BrsFile.Class.spec.js +3 -3
  61. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  62. package/dist/files/BrsFile.d.ts +4 -11
  63. package/dist/files/BrsFile.js +39 -206
  64. package/dist/files/BrsFile.js.map +1 -1
  65. package/dist/files/BrsFile.spec.js +56 -2
  66. package/dist/files/BrsFile.spec.js.map +1 -1
  67. package/dist/interfaces.d.ts +32 -1
  68. package/dist/interfaces.js.map +1 -1
  69. package/dist/parser/AstNode.spec.js +6 -6
  70. package/dist/parser/AstNode.spec.js.map +1 -1
  71. package/dist/parser/Expression.d.ts +288 -145
  72. package/dist/parser/Expression.js +310 -271
  73. package/dist/parser/Expression.js.map +1 -1
  74. package/dist/parser/Parser.Class.spec.js +11 -11
  75. package/dist/parser/Parser.Class.spec.js.map +1 -1
  76. package/dist/parser/Parser.d.ts +5 -0
  77. package/dist/parser/Parser.js +315 -120
  78. package/dist/parser/Parser.js.map +1 -1
  79. package/dist/parser/Parser.spec.js +42 -185
  80. package/dist/parser/Parser.spec.js.map +1 -1
  81. package/dist/parser/Statement.d.ts +332 -188
  82. package/dist/parser/Statement.js +475 -364
  83. package/dist/parser/Statement.js.map +1 -1
  84. package/dist/parser/Statement.spec.js +2 -2
  85. package/dist/parser/Statement.spec.js.map +1 -1
  86. package/dist/parser/tests/controlFlow/For.spec.js +1 -1
  87. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  88. package/dist/parser/tests/controlFlow/ForEach.spec.js +2 -2
  89. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  90. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +1 -1
  91. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  92. package/dist/parser/tests/expression/Call.spec.js +11 -11
  93. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  94. package/dist/parser/tests/expression/Indexing.spec.js +30 -5
  95. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  96. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +2 -2
  97. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  98. package/dist/parser/tests/expression/TernaryExpression.spec.js +2 -2
  99. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  100. package/dist/parser/tests/statement/ConstStatement.spec.js +1 -1
  101. package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -1
  102. package/dist/parser/tests/statement/Dim.spec.js +8 -8
  103. package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
  104. package/dist/parser/tests/statement/Enum.spec.js +2 -2
  105. package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
  106. package/dist/parser/tests/statement/LibraryStatement.spec.js +2 -2
  107. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  108. package/dist/parser/tests/statement/Misc.spec.js +2 -2
  109. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  110. package/dist/parser/tests/statement/PrintStatement.spec.js +1 -1
  111. package/dist/parser/tests/statement/TryCatch.spec.js +1 -1
  112. package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
  113. package/dist/types/BuiltInInterfaceAdder.js +11 -4
  114. package/dist/types/BuiltInInterfaceAdder.js.map +1 -1
  115. package/dist/util.d.ts +17 -8
  116. package/dist/util.js +96 -51
  117. package/dist/util.js.map +1 -1
  118. package/dist/validators/ClassValidator.js +6 -6
  119. package/dist/validators/ClassValidator.js.map +1 -1
  120. package/package.json +1 -1
@@ -21,7 +21,7 @@ class Parser {
21
21
  /**
22
22
  * The list of statements for the parsed file
23
23
  */
24
- this.ast = new Statement_1.Body([]);
24
+ this.ast = new Statement_1.Body({ statements: [] });
25
25
  this.globalTerminators = [];
26
26
  /**
27
27
  * An array of CallExpression for the current function body
@@ -83,7 +83,7 @@ class Parser {
83
83
  }
84
84
  body() {
85
85
  const parentAnnotations = this.enterAnnotationBlock();
86
- let body = new Statement_1.Body([]);
86
+ let body = new Statement_1.Body({ statements: [] });
87
87
  if (this.tokens.length > 0) {
88
88
  this.consumeStatementSeparators(true);
89
89
  try {
@@ -194,7 +194,7 @@ class Parser {
194
194
  statement.tokens.name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
195
195
  //look for `= SOME_EXPRESSION`
196
196
  if (this.check(TokenKind_1.TokenKind.Equal)) {
197
- statement.tokens.equal = this.advance();
197
+ statement.tokens.equals = this.advance();
198
198
  statement.value = this.expression();
199
199
  }
200
200
  return statement;
@@ -209,20 +209,24 @@ class Parser {
209
209
  if (this.check(TokenKind_1.TokenKind.As)) {
210
210
  [asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
211
211
  }
212
- return new Statement_1.InterfaceFieldStatement(name, asToken, typeExpression, optionalKeyword);
212
+ return new Statement_1.InterfaceFieldStatement({ name: name, as: asToken, typeExpression: typeExpression, optional: optionalKeyword });
213
213
  }
214
- consumeAsTokenAndTypeExpression() {
214
+ consumeAsTokenAndTypeExpression(ignoreDiagnostics = false) {
215
215
  let asToken = this.consumeToken(TokenKind_1.TokenKind.As);
216
216
  let typeExpression;
217
217
  if (asToken) {
218
218
  //if there's nothing after the `as`, add a diagnostic and continue
219
219
  if (this.checkEndOfStatement()) {
220
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(asToken.text)), { range: asToken.range }));
220
+ if (!ignoreDiagnostics) {
221
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(asToken.text)), { range: asToken.range }));
222
+ }
221
223
  //consume the statement separator
222
224
  this.consumeStatementSeparators();
223
225
  }
224
226
  else if (this.peek().kind !== TokenKind_1.TokenKind.Identifier && !this.checkAny(...TokenKind_1.DeclarableTypes, ...TokenKind_1.AllowedTypeIdentifiers)) {
225
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(asToken.text)), { range: asToken.range }));
227
+ if (!ignoreDiagnostics) {
228
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(asToken.text)), { range: asToken.range }));
229
+ }
226
230
  }
227
231
  else {
228
232
  typeExpression = this.typeExpression();
@@ -254,7 +258,16 @@ class Parser {
254
258
  if (this.check(TokenKind_1.TokenKind.As)) {
255
259
  [asToken, returnTypeExpression] = this.consumeAsTokenAndTypeExpression();
256
260
  }
257
- return new Statement_1.InterfaceMethodStatement(functionType, name, leftParen, params, rightParen, asToken, returnTypeExpression, optionalKeyword);
261
+ return new Statement_1.InterfaceMethodStatement({
262
+ functionType: functionType,
263
+ name: name,
264
+ leftParen: leftParen,
265
+ params: params,
266
+ rightParen: rightParen,
267
+ as: asToken,
268
+ returnTypeExpression: returnTypeExpression,
269
+ optional: optionalKeyword
270
+ });
258
271
  }
259
272
  interfaceDeclaration() {
260
273
  this.warnIfNotBrighterScriptMode('interface declarations');
@@ -323,12 +336,19 @@ class Parser {
323
336
  }
324
337
  //consume the final `end interface` token
325
338
  const endInterfaceToken = this.consumeToken(TokenKind_1.TokenKind.EndInterface);
326
- const statement = new Statement_1.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endInterfaceToken);
339
+ const statement = new Statement_1.InterfaceStatement({
340
+ interface: interfaceToken,
341
+ name: nameToken,
342
+ extends: extendsToken,
343
+ parentInterfaceName: parentInterfaceName,
344
+ body: body,
345
+ endInterface: endInterfaceToken
346
+ });
327
347
  this.exitAnnotationBlock(parentAnnotations);
328
348
  return statement;
329
349
  }
330
350
  enumDeclaration() {
331
- const result = new Statement_1.EnumStatement({}, []);
351
+ const result = new Statement_1.EnumStatement({ name: {}, body: [] });
332
352
  this.warnIfNotBrighterScriptMode('enum declarations');
333
353
  const parentAnnotations = this.enterAnnotationBlock();
334
354
  result.tokens.enum = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Enum), TokenKind_1.TokenKind.Enum);
@@ -419,10 +439,15 @@ class Parser {
419
439
  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))) {
420
440
  const funcDeclaration = this.functionDeclaration(false, false);
421
441
  //if we have an overrides keyword AND this method is called 'new', that's not allowed
422
- if (overrideKeyword && funcDeclaration.name.text.toLowerCase() === 'new') {
442
+ if (overrideKeyword && funcDeclaration.tokens.name.text.toLowerCase() === 'new') {
423
443
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseOverrideKeywordOnConstructorFunction()), { range: overrideKeyword.range }));
424
444
  }
425
- decl = new Statement_1.MethodStatement(accessModifier, funcDeclaration.name, funcDeclaration.func, overrideKeyword);
445
+ decl = new Statement_1.MethodStatement({
446
+ modifiers: accessModifier,
447
+ name: funcDeclaration.tokens.name,
448
+ func: funcDeclaration.func,
449
+ override: overrideKeyword
450
+ });
426
451
  //refer to this statement as parent of the expression
427
452
  funcDeclaration.func.functionStatement = decl;
428
453
  //fields
@@ -454,7 +479,14 @@ class Parser {
454
479
  if (endingKeyword.kind !== TokenKind_1.TokenKind.EndClass) {
455
480
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('class')), { range: endingKeyword.range }));
456
481
  }
457
- const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName);
482
+ const result = new Statement_1.ClassStatement({
483
+ class: classKeyword,
484
+ name: className,
485
+ body: body,
486
+ endClass: endingKeyword,
487
+ extends: extendsKeyword,
488
+ parentClassName: parentClassName
489
+ });
458
490
  this.exitAnnotationBlock(parentAnnotations);
459
491
  return result;
460
492
  }
@@ -499,7 +531,15 @@ class Parser {
499
531
  equal = this.advance();
500
532
  initialValue = this.expression();
501
533
  }
502
- return new Statement_1.FieldStatement(accessModifier, name, asToken, fieldTypeExpression, equal, initialValue, optionalKeyword);
534
+ return new Statement_1.FieldStatement({
535
+ accessModifier: accessModifier,
536
+ name: name,
537
+ as: asToken,
538
+ typeExpression: fieldTypeExpression,
539
+ equals: equal,
540
+ initialValue: initialValue,
541
+ optional: optionalKeyword
542
+ });
503
543
  }
504
544
  functionDeclaration(isAnonymous, checkIdentifier = true, onlyCallableAsMember = false) {
505
545
  var _a;
@@ -565,19 +605,29 @@ class Parser {
565
605
  }
566
606
  params.reduce((haveFoundOptional, param) => {
567
607
  if (haveFoundOptional && !param.defaultValue) {
568
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.requiredParameterMayNotFollowOptionalParameter(param.name.text)), { range: param.range }));
608
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.requiredParameterMayNotFollowOptionalParameter(param.tokens.name.text)), { range: param.range }));
569
609
  }
570
610
  return haveFoundOptional || !!param.defaultValue;
571
611
  }, false);
572
612
  this.consumeStatementSeparators(true);
573
- let func = new Expression_1.FunctionExpression(params, undefined, //body
574
- functionType, undefined, //ending keyword
575
- leftParen, rightParen, asToken, typeExpression);
613
+ let func = new Expression_1.FunctionExpression({
614
+ parameters: params,
615
+ body: undefined,
616
+ functionType: functionType,
617
+ endFunctionType: undefined,
618
+ leftParen: leftParen,
619
+ rightParen: rightParen,
620
+ as: asToken,
621
+ returnTypeExpression: typeExpression
622
+ });
576
623
  //support ending the function with `end sub` OR `end function`
577
624
  func.body = this.block();
578
625
  //if the parser was unable to produce a block, make an empty one so the AST makes some sense...
579
626
  if (!func.body) {
580
- func.body = new Statement_1.Block([], util_1.util.createRangeFromPositions(func.range.start, func.range.start));
627
+ func.body = new Statement_1.Block({
628
+ statements: [],
629
+ startingRange: util_1.util.createRangeFromPositions(func.range.start, func.range.start)
630
+ });
581
631
  }
582
632
  func.body.symbolTable = new SymbolTable_1.SymbolTable(`Block: Function '${(_a = name === null || name === void 0 ? void 0 : name.text) !== null && _a !== void 0 ? _a : ''}'`, () => func.getSymbolTable());
583
633
  if (!func.body) {
@@ -585,19 +635,19 @@ class Parser {
585
635
  throw this.lastDiagnosticAsError();
586
636
  }
587
637
  // consume 'end sub' or 'end function'
588
- func.end = this.advance();
638
+ func.tokens.endFunctionType = this.advance();
589
639
  let expectedEndKind = isSub ? TokenKind_1.TokenKind.EndSub : TokenKind_1.TokenKind.EndFunction;
590
640
  //if `function` is ended with `end sub`, or `sub` is ended with `end function`, then
591
641
  //add an error but don't hard-fail so the AST can continue more gracefully
592
- if (func.end.kind !== expectedEndKind) {
593
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword(functionTypeText, func.end.text)), { range: func.end.range }));
642
+ if (func.tokens.endFunctionType.kind !== expectedEndKind) {
643
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword(functionTypeText, func.tokens.endFunctionType.text)), { range: func.tokens.endFunctionType.range }));
594
644
  }
595
645
  func.callExpressions = this.callExpressions;
596
646
  if (isAnonymous) {
597
647
  return func;
598
648
  }
599
649
  else {
600
- let result = new Statement_1.FunctionStatement(name, func);
650
+ let result = new Statement_1.FunctionStatement({ name: name, func: func });
601
651
  func.symbolTable.name += `: '${name === null || name === void 0 ? void 0 : name.text}'`;
602
652
  func.functionStatement = result;
603
653
  return result;
@@ -629,7 +679,13 @@ class Parser {
629
679
  if (this.check(TokenKind_1.TokenKind.As)) {
630
680
  [asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
631
681
  }
632
- return new Expression_1.FunctionParameterExpression(name, equalToken, defaultValue, asToken, typeExpression);
682
+ return new Expression_1.FunctionParameterExpression({
683
+ name: name,
684
+ equals: equalToken,
685
+ defaultValue: defaultValue,
686
+ as: asToken,
687
+ typeExpression: typeExpression
688
+ });
633
689
  }
634
690
  assignment() {
635
691
  let name = this.advance();
@@ -637,15 +693,32 @@ class Parser {
637
693
  if (TokenKind_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
638
694
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
639
695
  }
696
+ let asToken;
697
+ let typeExpression;
698
+ //look for `as SOME_TYPE`
699
+ if (this.check(TokenKind_1.TokenKind.As)) {
700
+ this.warnIfNotBrighterScriptMode('typed assignment');
701
+ [asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
702
+ }
640
703
  let operator = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier(TokenKind_1.AssignmentOperators, name.text), ...TokenKind_1.AssignmentOperators);
641
704
  let value = this.expression();
642
705
  let result;
643
706
  if (operator.kind === TokenKind_1.TokenKind.Equal) {
644
- result = new Statement_1.AssignmentStatement(operator, name, value);
707
+ result = new Statement_1.AssignmentStatement({ equals: operator, name: name, value: value, as: asToken, typeExpression: typeExpression });
645
708
  }
646
709
  else {
647
- const nameExpression = new Expression_1.VariableExpression(name);
648
- result = new Statement_1.AssignmentStatement(operator, name, new Expression_1.BinaryExpression(nameExpression, operator, value));
710
+ const nameExpression = new Expression_1.VariableExpression({ name: name });
711
+ result = new Statement_1.AssignmentStatement({
712
+ equals: operator,
713
+ name: name,
714
+ value: new Expression_1.BinaryExpression({
715
+ left: nameExpression,
716
+ operator: operator,
717
+ right: value
718
+ }),
719
+ as: asToken,
720
+ typeExpression: typeExpression
721
+ });
649
722
  }
650
723
  return result;
651
724
  }
@@ -734,9 +807,31 @@ class Parser {
734
807
  // BrightScript is like python, in that variables can be declared without a `var`,
735
808
  // `let`, (...) keyword. As such, we must check the token *after* an identifier to figure
736
809
  // out what to do with it.
737
- if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers) &&
738
- this.checkAnyNext(...TokenKind_1.AssignmentOperators)) {
739
- return this.assignment();
810
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
811
+ if (this.checkAnyNext(...TokenKind_1.AssignmentOperators)) {
812
+ return this.assignment();
813
+ }
814
+ else if (this.checkNext(TokenKind_1.TokenKind.As)) {
815
+ // may be a typed assignment
816
+ const backtrack = this.current;
817
+ let validTypeExpression = false;
818
+ try {
819
+ // skip the identifier, and check for valid type expression
820
+ this.advance();
821
+ const parts = this.consumeAsTokenAndTypeExpression(true);
822
+ validTypeExpression = !!((parts === null || parts === void 0 ? void 0 : parts[0]) && (parts === null || parts === void 0 ? void 0 : parts[1]));
823
+ }
824
+ catch (e) {
825
+ // ignore any errors
826
+ }
827
+ finally {
828
+ this.current = backtrack;
829
+ }
830
+ if (validTypeExpression) {
831
+ // there is a valid 'as' and type expression
832
+ return this.assignment();
833
+ }
834
+ }
740
835
  }
741
836
  //some BrighterScript keywords are allowed as a local identifiers, so we need to check for them AFTER the assignment check
742
837
  if (this.check(TokenKind_1.TokenKind.Interface)) {
@@ -769,7 +864,12 @@ class Parser {
769
864
  else {
770
865
  endWhile = this.advance();
771
866
  }
772
- return new Statement_1.WhileStatement({ while: whileKeyword, endWhile: endWhile }, condition, whileBlock);
867
+ return new Statement_1.WhileStatement({
868
+ while: whileKeyword,
869
+ endWhile: endWhile,
870
+ condition: condition,
871
+ body: whileBlock
872
+ });
773
873
  }
774
874
  exitWhile() {
775
875
  let keyword = this.advance();
@@ -804,7 +904,16 @@ class Parser {
804
904
  }
805
905
  // WARNING: BrightScript doesn't delete the loop initial value after a for/to loop! It just
806
906
  // stays around in scope with whatever value it was when the loop exited.
807
- return new Statement_1.ForStatement(forToken, initializer, toToken, finalValue, body, endForToken, stepToken, incrementExpression);
907
+ return new Statement_1.ForStatement({
908
+ for: forToken,
909
+ counterDeclaration: initializer,
910
+ to: toToken,
911
+ finalValue: finalValue,
912
+ body: body,
913
+ endFor: endForToken,
914
+ step: stepToken,
915
+ increment: incrementExpression
916
+ });
808
917
  }
809
918
  forEachStatement() {
810
919
  let forEach = this.advance();
@@ -832,8 +941,11 @@ class Parser {
832
941
  return new Statement_1.ForEachStatement({
833
942
  forEach: forEach,
834
943
  in: maybeIn,
835
- endFor: endFor
836
- }, name, target, body);
944
+ endFor: endFor,
945
+ item: name,
946
+ target: target,
947
+ body: body
948
+ });
837
949
  }
838
950
  exitFor() {
839
951
  let keyword = this.advance();
@@ -844,7 +956,7 @@ class Parser {
844
956
  //then this comment should be treated as a single-line comment
845
957
  let prev = this.previous();
846
958
  if ((prev === null || prev === void 0 ? void 0 : prev.range.end.line) === this.peek().range.start.line) {
847
- return new Statement_1.CommentStatement([this.advance()]);
959
+ return new Statement_1.CommentStatement({ comments: [this.advance()] });
848
960
  }
849
961
  else {
850
962
  let comments = [this.advance()];
@@ -852,7 +964,7 @@ class Parser {
852
964
  this.advance();
853
965
  comments.push(this.advance());
854
966
  }
855
- return new Statement_1.CommentStatement(comments);
967
+ return new Statement_1.CommentStatement({ comments: comments });
856
968
  }
857
969
  }
858
970
  namespaceStatement() {
@@ -861,7 +973,7 @@ class Parser {
861
973
  this.namespaceAndFunctionDepth++;
862
974
  let name = this.identifyingExpression();
863
975
  //set the current namespace name
864
- let result = new Statement_1.NamespaceStatement(keyword, name, null, null);
976
+ let result = new Statement_1.NamespaceStatement({ namespace: keyword, nameExpression: name, body: null });
865
977
  this.globalTerminators.push([TokenKind_1.TokenKind.EndNamespace]);
866
978
  let body = this.body();
867
979
  this.globalTerminators.pop();
@@ -875,7 +987,7 @@ class Parser {
875
987
  }
876
988
  this.namespaceAndFunctionDepth--;
877
989
  result.body = body;
878
- result.endKeyword = endKeyword;
990
+ result.tokens.endNamespace = endKeyword;
879
991
  //cache the range property so that plugins can't affect it
880
992
  result.cacheRange();
881
993
  result.body.symbolTable.name += `: namespace '${result.name}'`;
@@ -891,7 +1003,7 @@ class Parser {
891
1003
  if (firstIdentifier) {
892
1004
  // force it into an identifier so the AST makes some sense
893
1005
  firstIdentifier.kind = TokenKind_1.TokenKind.Identifier;
894
- const varExpr = new Expression_1.VariableExpression(firstIdentifier);
1006
+ const varExpr = new Expression_1.VariableExpression({ name: firstIdentifier });
895
1007
  expr = varExpr;
896
1008
  //consume multiple dot identifiers (i.e. `Name.Space.Can.Have.Many.Parts`)
897
1009
  while (this.check(TokenKind_1.TokenKind.Dot)) {
@@ -905,7 +1017,7 @@ class Parser {
905
1017
  }
906
1018
  // force it into an identifier so the AST makes some sense
907
1019
  identifier.kind = TokenKind_1.TokenKind.Identifier;
908
- expr = new Expression_1.DottedGetExpression(expr, identifier, dot);
1020
+ expr = new Expression_1.DottedGetExpression({ obj: expr, name: identifier, dot: dot });
909
1021
  }
910
1022
  }
911
1023
  return expr;
@@ -941,8 +1053,9 @@ class Parser {
941
1053
  const statement = new Statement_1.ConstStatement({
942
1054
  const: constToken,
943
1055
  name: nameToken,
944
- equals: equalToken
945
- }, expression);
1056
+ equals: equalToken,
1057
+ value: expression
1058
+ });
946
1059
  return statement;
947
1060
  }
948
1061
  libraryStatement() {
@@ -955,9 +1068,11 @@ class Parser {
955
1068
  }
956
1069
  importStatement() {
957
1070
  this.warnIfNotBrighterScriptMode('import statements');
958
- let importStatement = new Statement_1.ImportStatement(this.advance(),
959
- //grab the next token only if it's a string
960
- this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), TokenKind_1.TokenKind.StringLiteral));
1071
+ let importStatement = new Statement_1.ImportStatement({
1072
+ import: this.advance(),
1073
+ //grab the next token only if it's a string
1074
+ filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), TokenKind_1.TokenKind.StringLiteral)
1075
+ });
961
1076
  return importStatement;
962
1077
  }
963
1078
  annotationExpression() {
@@ -966,7 +1081,7 @@ class Parser {
966
1081
  if (identifier) {
967
1082
  identifier.kind = TokenKind_1.TokenKind.Identifier;
968
1083
  }
969
- let annotation = new Expression_1.AnnotationExpression(atToken, identifier);
1084
+ let annotation = new Expression_1.AnnotationExpression({ at: atToken, name: identifier });
970
1085
  this.pendingAnnotations.push(annotation);
971
1086
  //optional arguments
972
1087
  if (this.check(TokenKind_1.TokenKind.LeftParen)) {
@@ -1004,13 +1119,23 @@ class Parser {
1004
1119
  alternate = this.expression();
1005
1120
  }
1006
1121
  catch (_b) { }
1007
- return new Expression_1.TernaryExpression(test, questionMarkToken, consequent, colonToken, alternate);
1122
+ return new Expression_1.TernaryExpression({
1123
+ test: test,
1124
+ questionMark: questionMarkToken,
1125
+ consequent: consequent,
1126
+ colon: colonToken,
1127
+ alternate: alternate
1128
+ });
1008
1129
  }
1009
1130
  nullCoalescingExpression(test) {
1010
1131
  this.warnIfNotBrighterScriptMode('null coalescing operator');
1011
1132
  const questionQuestionToken = this.advance();
1012
1133
  const alternate = this.expression();
1013
- return new Expression_1.NullCoalescingExpression(test, questionQuestionToken, alternate);
1134
+ return new Expression_1.NullCoalescingExpression({
1135
+ consequent: test,
1136
+ questionQuestion: questionQuestionToken,
1137
+ alternate: alternate
1138
+ });
1014
1139
  }
1015
1140
  regexLiteralExpression() {
1016
1141
  this.warnIfNotBrighterScriptMode('regular expression literal');
@@ -1036,16 +1161,16 @@ class Parser {
1036
1161
  let next = this.peek();
1037
1162
  if (next.kind === TokenKind_1.TokenKind.TemplateStringQuasi) {
1038
1163
  //a quasi can actually be made up of multiple quasis when it includes char literals
1039
- currentQuasiExpressionParts.push(new Expression_1.LiteralExpression(next));
1164
+ currentQuasiExpressionParts.push(new Expression_1.LiteralExpression({ value: next }));
1040
1165
  this.advance();
1041
1166
  }
1042
1167
  else if (next.kind === TokenKind_1.TokenKind.EscapedCharCodeLiteral) {
1043
- currentQuasiExpressionParts.push(new Expression_1.EscapedCharCodeLiteralExpression(next));
1168
+ currentQuasiExpressionParts.push(new Expression_1.EscapedCharCodeLiteralExpression({ value: next }));
1044
1169
  this.advance();
1045
1170
  }
1046
1171
  else {
1047
1172
  //finish up the current quasi
1048
- quasis.push(new Expression_1.TemplateStringQuasiExpression(currentQuasiExpressionParts));
1173
+ quasis.push(new Expression_1.TemplateStringQuasiExpression({ expressions: currentQuasiExpressionParts }));
1049
1174
  currentQuasiExpressionParts = [];
1050
1175
  if (next.kind === TokenKind_1.TokenKind.TemplateStringExpressionBegin) {
1051
1176
  this.advance();
@@ -1063,7 +1188,7 @@ class Parser {
1063
1188
  }
1064
1189
  }
1065
1190
  //store the final set of quasis
1066
- quasis.push(new Expression_1.TemplateStringQuasiExpression(currentQuasiExpressionParts));
1191
+ quasis.push(new Expression_1.TemplateStringQuasiExpression({ expressions: currentQuasiExpressionParts }));
1067
1192
  if (this.isAtEnd()) {
1068
1193
  //error - missing backtick
1069
1194
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unterminatedTemplateStringAtEndOfFile()), { range: util_1.util.getRange(openingBacktick, this.peek()) }));
@@ -1072,10 +1197,21 @@ class Parser {
1072
1197
  else {
1073
1198
  let closingBacktick = this.advance();
1074
1199
  if (isTagged) {
1075
- return new Expression_1.TaggedTemplateStringExpression(tagName, openingBacktick, quasis, expressions, closingBacktick);
1200
+ return new Expression_1.TaggedTemplateStringExpression({
1201
+ tagName: tagName,
1202
+ openingBacktick: openingBacktick,
1203
+ quasis: quasis,
1204
+ expressions: expressions,
1205
+ closingBacktick: closingBacktick
1206
+ });
1076
1207
  }
1077
1208
  else {
1078
- return new Expression_1.TemplateStringExpression(openingBacktick, quasis, expressions, closingBacktick);
1209
+ return new Expression_1.TemplateStringExpression({
1210
+ openingBacktick: openingBacktick,
1211
+ quasis: quasis,
1212
+ expressions: expressions,
1213
+ closingBacktick: closingBacktick
1214
+ });
1079
1215
  }
1080
1216
  }
1081
1217
  }
@@ -1100,7 +1236,7 @@ class Parser {
1100
1236
  if (exceptionVarToken) {
1101
1237
  // force it into an identifier so the AST makes some sense
1102
1238
  exceptionVarToken.kind = TokenKind_1.TokenKind.Identifier;
1103
- catchStmt.exceptionVariable = exceptionVarToken;
1239
+ catchStmt.tokens.exceptionVariable = exceptionVarToken;
1104
1240
  }
1105
1241
  //ensure statement sepatator
1106
1242
  this.consumeStatementSeparators();
@@ -1122,7 +1258,7 @@ class Parser {
1122
1258
  else {
1123
1259
  expression = this.expression();
1124
1260
  }
1125
- return new Statement_1.ThrowStatement(throwToken, expression);
1261
+ return new Statement_1.ThrowStatement({ throw: throwToken, expression: expression });
1126
1262
  }
1127
1263
  dimStatement() {
1128
1264
  const dim = this.advance();
@@ -1153,7 +1289,13 @@ class Parser {
1153
1289
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExpressionsInDimStatement()), { range: this.peek().range }));
1154
1290
  }
1155
1291
  let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.RightSquareBracket);
1156
- return new Statement_1.DimStatement(dim, identifier, leftSquareBracket, expressions, rightSquareBracket);
1292
+ return new Statement_1.DimStatement({
1293
+ dim: dim,
1294
+ name: identifier,
1295
+ openingSquare: leftSquareBracket,
1296
+ dimensions: expressions,
1297
+ closingSquare: rightSquareBracket
1298
+ });
1157
1299
  }
1158
1300
  ifStatement() {
1159
1301
  // colon before `if` is usually not allowed, unless it's after `then`
@@ -1263,8 +1405,12 @@ class Parser {
1263
1405
  if: ifToken,
1264
1406
  then: thenToken,
1265
1407
  endIf: endIfToken,
1266
- else: elseToken
1267
- }, condition, thenBranch, elseBranch, isInlineIfThen);
1408
+ else: elseToken,
1409
+ condition: condition,
1410
+ thenBranch: thenBranch,
1411
+ elseBranch: elseBranch,
1412
+ isInline: isInlineIfThen
1413
+ });
1268
1414
  }
1269
1415
  //consume a `then` or `else` branch block of an `if` statement
1270
1416
  blockConditionalBranch(ifToken) {
@@ -1335,7 +1481,7 @@ class Parser {
1335
1481
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(colon.text)), { range: colon.range }));
1336
1482
  }
1337
1483
  }
1338
- return new Statement_1.Block(statements, startingRange);
1484
+ return new Statement_1.Block({ statements: statements, startingRange: startingRange });
1339
1485
  }
1340
1486
  expressionStatement(expr) {
1341
1487
  let expressionStart = this.peek();
@@ -1349,15 +1495,15 @@ class Parser {
1349
1495
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.incrementDecrementOperatorsAreNotAllowedAsResultOfFunctionCall()), { range: expressionStart.range }));
1350
1496
  throw this.lastDiagnosticAsError();
1351
1497
  }
1352
- const result = new Statement_1.IncrementStatement(expr, operator);
1498
+ const result = new Statement_1.IncrementStatement({ value: expr, operator: operator });
1353
1499
  return result;
1354
1500
  }
1355
1501
  if ((0, reflection_1.isCallExpression)(expr) || (0, reflection_1.isCallfuncExpression)(expr)) {
1356
- return new Statement_1.ExpressionStatement(expr);
1502
+ return new Statement_1.ExpressionStatement({ expression: expr });
1357
1503
  }
1358
1504
  //at this point, it's probably an error. However, we recover a little more gracefully by creating an inclosing ExpressionStatement
1359
1505
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression()), { range: expressionStart.range }));
1360
- return new Statement_1.ExpressionStatement(expr);
1506
+ return new Statement_1.ExpressionStatement({ expression: expr });
1361
1507
  }
1362
1508
  setStatement() {
1363
1509
  /**
@@ -1373,14 +1519,25 @@ class Parser {
1373
1519
  let right = this.expression();
1374
1520
  // Create a dotted or indexed "set" based on the left-hand side's type
1375
1521
  if ((0, reflection_1.isIndexedGetExpression)(left)) {
1376
- return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === TokenKind_1.TokenKind.Equal
1377
- ? right
1378
- : new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare);
1522
+ return new Statement_1.IndexedSetStatement({
1523
+ obj: left.obj,
1524
+ indexes: left.indexes,
1525
+ value: operator.kind === TokenKind_1.TokenKind.Equal
1526
+ ? right
1527
+ : new Expression_1.BinaryExpression({ left: left, operator: operator, right: right }),
1528
+ openingSquare: left.tokens.openingSquare,
1529
+ closingSquare: left.tokens.closingSquare
1530
+ });
1379
1531
  }
1380
1532
  else if ((0, reflection_1.isDottedGetExpression)(left)) {
1381
- return new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === TokenKind_1.TokenKind.Equal
1382
- ? right
1383
- : new Expression_1.BinaryExpression(left, operator, right), left.dot);
1533
+ return new Statement_1.DottedSetStatement({
1534
+ obj: left.obj,
1535
+ name: left.tokens.name,
1536
+ value: operator.kind === TokenKind_1.TokenKind.Equal
1537
+ ? right
1538
+ : new Expression_1.BinaryExpression({ left: left, operator: operator, right: right }),
1539
+ dot: left.tokens.dot
1540
+ });
1384
1541
  }
1385
1542
  }
1386
1543
  return this.expressionStatement(expr);
@@ -1413,27 +1570,27 @@ class Parser {
1413
1570
  if ((0, Token_1.isToken)(last)) {
1414
1571
  // TODO: error, expected value
1415
1572
  }
1416
- return new Statement_1.PrintStatement({ print: printKeyword }, values);
1573
+ return new Statement_1.PrintStatement({ print: printKeyword, expressions: values });
1417
1574
  }
1418
1575
  /**
1419
1576
  * Parses a return statement with an optional return value.
1420
1577
  * @returns an AST representation of a return statement.
1421
1578
  */
1422
1579
  returnStatement() {
1423
- let tokens = { return: this.previous() };
1580
+ let options = { return: this.previous() };
1424
1581
  if (this.checkEndOfStatement()) {
1425
- return new Statement_1.ReturnStatement(tokens);
1582
+ return new Statement_1.ReturnStatement(options);
1426
1583
  }
1427
1584
  let toReturn = this.check(TokenKind_1.TokenKind.Else) ? undefined : this.expression();
1428
- return new Statement_1.ReturnStatement(tokens, toReturn);
1585
+ return new Statement_1.ReturnStatement(Object.assign(Object.assign({}, options), { value: toReturn }));
1429
1586
  }
1430
1587
  /**
1431
1588
  * Parses a `label` statement
1432
1589
  * @returns an AST representation of an `label` statement.
1433
1590
  */
1434
1591
  labelStatement() {
1435
- let tokens = {
1436
- identifier: this.advance(),
1592
+ let options = {
1593
+ name: this.advance(),
1437
1594
  colon: this.advance()
1438
1595
  };
1439
1596
  //label must be alone on its line, this is probably not a label
@@ -1442,7 +1599,7 @@ class Parser {
1442
1599
  this.current -= 2;
1443
1600
  throw new CancelStatementError();
1444
1601
  }
1445
- return new Statement_1.LabelStatement(tokens);
1602
+ return new Statement_1.LabelStatement(options);
1446
1603
  }
1447
1604
  /**
1448
1605
  * Parses a `continue` statement
@@ -1469,16 +1626,16 @@ class Parser {
1469
1626
  * @returns an AST representation of an `end` statement.
1470
1627
  */
1471
1628
  endStatement() {
1472
- let endTokens = { end: this.advance() };
1473
- return new Statement_1.EndStatement(endTokens);
1629
+ let options = { end: this.advance() };
1630
+ return new Statement_1.EndStatement(options);
1474
1631
  }
1475
1632
  /**
1476
1633
  * Parses a `stop` statement
1477
1634
  * @returns an AST representation of a `stop` statement
1478
1635
  */
1479
1636
  stopStatement() {
1480
- let tokens = { stop: this.advance() };
1481
- return new Statement_1.StopStatement(tokens);
1637
+ let options = { stop: this.advance() };
1638
+ return new Statement_1.StopStatement(options);
1482
1639
  }
1483
1640
  /**
1484
1641
  * Parses a block, looking for a specific terminating TokenKind to denote completion.
@@ -1530,7 +1687,7 @@ class Parser {
1530
1687
  }
1531
1688
  }
1532
1689
  this.exitAnnotationBlock(parentAnnotations);
1533
- return new Statement_1.Block(statements, startingToken.range);
1690
+ return new Statement_1.Block({ statements: statements, startingRange: startingToken.range });
1534
1691
  }
1535
1692
  /**
1536
1693
  * Attach pending annotations to the provided statement,
@@ -1569,7 +1726,7 @@ class Parser {
1569
1726
  // myVal = foo() as dynamic as string
1570
1727
  [asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
1571
1728
  if (asToken && typeExpression) {
1572
- expression = new Expression_1.TypeCastExpression(expression, asToken, typeExpression);
1729
+ expression = new Expression_1.TypeCastExpression({ obj: expression, as: asToken, typeExpression: typeExpression });
1573
1730
  }
1574
1731
  }
1575
1732
  else {
@@ -1606,7 +1763,7 @@ class Parser {
1606
1763
  while (this.matchAny(TokenKind_1.TokenKind.And, TokenKind_1.TokenKind.Or)) {
1607
1764
  let operator = this.previous();
1608
1765
  let right = this.relational();
1609
- expr = new Expression_1.BinaryExpression(expr, operator, right);
1766
+ expr = new Expression_1.BinaryExpression({ left: expr, operator: operator, right: right });
1610
1767
  }
1611
1768
  return expr;
1612
1769
  }
@@ -1615,7 +1772,7 @@ class Parser {
1615
1772
  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)) {
1616
1773
  let operator = this.previous();
1617
1774
  let right = this.additive();
1618
- expr = new Expression_1.BinaryExpression(expr, operator, right);
1775
+ expr = new Expression_1.BinaryExpression({ left: expr, operator: operator, right: right });
1619
1776
  }
1620
1777
  return expr;
1621
1778
  }
@@ -1625,7 +1782,7 @@ class Parser {
1625
1782
  while (this.matchAny(TokenKind_1.TokenKind.Plus, TokenKind_1.TokenKind.Minus)) {
1626
1783
  let operator = this.previous();
1627
1784
  let right = this.multiplicative();
1628
- expr = new Expression_1.BinaryExpression(expr, operator, right);
1785
+ expr = new Expression_1.BinaryExpression({ left: expr, operator: operator, right: right });
1629
1786
  }
1630
1787
  return expr;
1631
1788
  }
@@ -1634,7 +1791,7 @@ class Parser {
1634
1791
  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)) {
1635
1792
  let operator = this.previous();
1636
1793
  let right = this.exponential();
1637
- expr = new Expression_1.BinaryExpression(expr, operator, right);
1794
+ expr = new Expression_1.BinaryExpression({ left: expr, operator: operator, right: right });
1638
1795
  }
1639
1796
  return expr;
1640
1797
  }
@@ -1643,7 +1800,7 @@ class Parser {
1643
1800
  while (this.match(TokenKind_1.TokenKind.Caret)) {
1644
1801
  let operator = this.previous();
1645
1802
  let right = this.prefixUnary();
1646
- expr = new Expression_1.BinaryExpression(expr, operator, right);
1803
+ expr = new Expression_1.BinaryExpression({ left: expr, operator: operator, right: right });
1647
1804
  }
1648
1805
  return expr;
1649
1806
  }
@@ -1653,7 +1810,7 @@ class Parser {
1653
1810
  this.current++; //advance
1654
1811
  let operator = this.previous();
1655
1812
  let right = this.relational();
1656
- return new Expression_1.UnaryExpression(operator, right);
1813
+ return new Expression_1.UnaryExpression({ operator: operator, right: right });
1657
1814
  }
1658
1815
  else if (nextKind === TokenKind_1.TokenKind.Minus || nextKind === TokenKind_1.TokenKind.Plus) {
1659
1816
  this.current++; //advance
@@ -1661,25 +1818,38 @@ class Parser {
1661
1818
  let right = nextKind === TokenKind_1.TokenKind.Not
1662
1819
  ? this.boolean()
1663
1820
  : this.prefixUnary();
1664
- return new Expression_1.UnaryExpression(operator, right);
1821
+ return new Expression_1.UnaryExpression({ operator: operator, right: right });
1665
1822
  }
1666
1823
  return this.call();
1667
1824
  }
1668
1825
  indexedGet(expr) {
1669
1826
  let openingSquare = this.previous();
1670
1827
  let questionDotToken = this.getMatchingTokenAtOffset(-2, TokenKind_1.TokenKind.QuestionDot);
1671
- let index;
1672
- let closingSquare;
1828
+ let indexes = [];
1829
+ //consume leading newlines
1673
1830
  while (this.match(TokenKind_1.TokenKind.Newline)) { }
1674
1831
  try {
1675
- index = this.expression();
1832
+ indexes.push(this.expression());
1833
+ //consume additional indexes separated by commas
1834
+ while (this.check(TokenKind_1.TokenKind.Comma)) {
1835
+ //discard the comma
1836
+ this.advance();
1837
+ indexes.push(this.expression());
1838
+ }
1676
1839
  }
1677
1840
  catch (error) {
1678
1841
  this.rethrowNonDiagnosticError(error);
1679
1842
  }
1843
+ //consume trailing newlines
1680
1844
  while (this.match(TokenKind_1.TokenKind.Newline)) { }
1681
- closingSquare = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
1682
- return new Expression_1.IndexedGetExpression(expr, index, openingSquare, closingSquare, questionDotToken);
1845
+ const closingSquare = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
1846
+ return new Expression_1.IndexedGetExpression({
1847
+ obj: expr,
1848
+ indexes: indexes,
1849
+ openingSquare: openingSquare,
1850
+ closingSquare: closingSquare,
1851
+ questionDot: questionDotToken
1852
+ });
1683
1853
  }
1684
1854
  newExpression() {
1685
1855
  var _a;
@@ -1692,12 +1862,12 @@ class Parser {
1692
1862
  // wrap the name in an expression
1693
1863
  const endOfStatementRange = util_1.util.createRangeFromPositions(newToken.range.end, (_a = this.peek()) === null || _a === void 0 ? void 0 : _a.range.end);
1694
1864
  const exprStmt = nameExpr !== null && nameExpr !== void 0 ? nameExpr : (0, creators_1.createStringLiteral)('', endOfStatementRange);
1695
- return new Statement_1.ExpressionStatement(exprStmt);
1865
+ return new Statement_1.ExpressionStatement({ expression: exprStmt });
1696
1866
  }
1697
1867
  let call = this.finishCall(leftParen, nameExpr);
1698
1868
  //pop the call from the callExpressions list because this is technically something else
1699
1869
  this.callExpressions.pop();
1700
- let result = new Expression_1.NewExpression(newToken, call);
1870
+ let result = new Expression_1.NewExpression({ new: newToken, call: call });
1701
1871
  return result;
1702
1872
  }
1703
1873
  /**
@@ -1711,7 +1881,14 @@ class Parser {
1711
1881
  methodName.kind = TokenKind_1.TokenKind.Identifier;
1712
1882
  let openParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOpenParenToFollowCallfuncIdentifier(), TokenKind_1.TokenKind.LeftParen);
1713
1883
  let call = this.finishCall(openParen, callee, false);
1714
- return new Expression_1.CallfuncExpression(callee, operator, methodName, openParen, call.args, call.closingParen);
1884
+ return new Expression_1.CallfuncExpression({
1885
+ callee: callee,
1886
+ operator: operator,
1887
+ methodName: methodName,
1888
+ openingParen: openParen,
1889
+ args: call.args,
1890
+ closingParen: call.tokens.closingParen
1891
+ });
1715
1892
  }
1716
1893
  call() {
1717
1894
  if (this.check(TokenKind_1.TokenKind.New) && this.checkAnyNext(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
@@ -1740,7 +1917,7 @@ class Parser {
1740
1917
  }
1741
1918
  // force it into an identifier so the AST makes some sense
1742
1919
  name.kind = TokenKind_1.TokenKind.Identifier;
1743
- expr = new Expression_1.DottedGetExpression(expr, name, dot);
1920
+ expr = new Expression_1.DottedGetExpression({ obj: expr, name: name, dot: dot });
1744
1921
  }
1745
1922
  }
1746
1923
  else if (this.checkAny(TokenKind_1.TokenKind.At, TokenKind_1.TokenKind.QuestionAt)) {
@@ -1751,7 +1928,7 @@ class Parser {
1751
1928
  if (!name) {
1752
1929
  break;
1753
1930
  }
1754
- expr = new Expression_1.XmlAttributeGetExpression(expr, name, dot);
1931
+ expr = new Expression_1.XmlAttributeGetExpression({ obj: expr, name: name, at: dot });
1755
1932
  //only allow a single `@` expression
1756
1933
  break;
1757
1934
  }
@@ -1783,7 +1960,12 @@ class Parser {
1783
1960
  }
1784
1961
  while (this.match(TokenKind_1.TokenKind.Newline)) { }
1785
1962
  const closingParen = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), TokenKind_1.TokenKind.RightParen);
1786
- let expression = new Expression_1.CallExpression(callee, openingParen, closingParen, args);
1963
+ let expression = new Expression_1.CallExpression({
1964
+ callee: callee,
1965
+ openingParen: openingParen,
1966
+ args: args,
1967
+ closingParen: closingParen
1968
+ });
1787
1969
  if (addToCallExpressionList) {
1788
1970
  this.callExpressions.push(expression);
1789
1971
  }
@@ -1802,14 +1984,14 @@ class Parser {
1802
1984
  let operator = this.previous();
1803
1985
  let right = this.getTypeExpressionPart(changedTokens);
1804
1986
  if (right) {
1805
- expr = new Expression_1.BinaryExpression(expr, operator, right);
1987
+ expr = new Expression_1.BinaryExpression({ left: expr, operator: operator, right: right });
1806
1988
  }
1807
1989
  else {
1808
1990
  break;
1809
1991
  }
1810
1992
  }
1811
1993
  if (expr) {
1812
- return new Expression_1.TypeExpression(expr);
1994
+ return new Expression_1.TypeExpression({ expression: expr });
1813
1995
  }
1814
1996
  }
1815
1997
  catch (error) {
@@ -1831,7 +2013,7 @@ class Parser {
1831
2013
  let expr;
1832
2014
  if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
1833
2015
  // if this is just a type, just use directly
1834
- expr = new Expression_1.VariableExpression(this.advance());
2016
+ expr = new Expression_1.VariableExpression({ name: this.advance() });
1835
2017
  }
1836
2018
  else {
1837
2019
  if (this.checkAny(...TokenKind_1.AllowedTypeIdentifiers)) {
@@ -1856,7 +2038,7 @@ class Parser {
1856
2038
  const leftBracket = this.advance();
1857
2039
  if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
1858
2040
  const rightBracket = this.advance();
1859
- expr = new Expression_1.TypedArrayExpression(expr, leftBracket, rightBracket);
2041
+ expr = new Expression_1.TypedArrayExpression({ innerType: expr, leftBracket: leftBracket, rightBracket: rightBracket });
1860
2042
  }
1861
2043
  }
1862
2044
  }
@@ -1865,10 +2047,10 @@ class Parser {
1865
2047
  primary() {
1866
2048
  switch (true) {
1867
2049
  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):
1868
- return new Expression_1.LiteralExpression(this.previous());
2050
+ return new Expression_1.LiteralExpression({ value: this.previous() });
1869
2051
  //capture source literals (LINE_NUM if brightscript, or a bunch of them if brighterscript)
1870
2052
  case this.matchAny(TokenKind_1.TokenKind.LineNumLiteral, ...(this.options.mode === ParseMode.BrightScript ? [] : TokenKind_1.BrighterScriptSourceLiterals)):
1871
- return new Expression_1.SourceLiteralExpression(this.previous());
2053
+ return new Expression_1.SourceLiteralExpression({ value: this.previous() });
1872
2054
  //template string
1873
2055
  case this.check(TokenKind_1.TokenKind.BackTick):
1874
2056
  return this.templateString(false);
@@ -1876,12 +2058,12 @@ class Parser {
1876
2058
  case this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers) && this.checkNext(TokenKind_1.TokenKind.BackTick):
1877
2059
  return this.templateString(true);
1878
2060
  case this.matchAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
1879
- return new Expression_1.VariableExpression(this.previous());
2061
+ return new Expression_1.VariableExpression({ name: this.previous() });
1880
2062
  case this.match(TokenKind_1.TokenKind.LeftParen):
1881
2063
  let left = this.previous();
1882
2064
  let expr = this.expression();
1883
2065
  let right = this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftParenAfterExpression(), TokenKind_1.TokenKind.RightParen);
1884
- return new Expression_1.GroupingExpression({ left: left, right: right }, expr);
2066
+ return new Expression_1.GroupingExpression({ leftParen: left, rightParen: right, expression: expr });
1885
2067
  case this.matchAny(TokenKind_1.TokenKind.LeftSquareBracket):
1886
2068
  return this.arrayLiteral();
1887
2069
  case this.match(TokenKind_1.TokenKind.LeftCurlyBrace):
@@ -1890,13 +2072,13 @@ class Parser {
1890
2072
  let token = Object.assign(this.previous(), {
1891
2073
  kind: TokenKind_1.TokenKind.Identifier
1892
2074
  });
1893
- return new Expression_1.VariableExpression(token);
2075
+ return new Expression_1.VariableExpression({ name: token });
1894
2076
  case this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub):
1895
2077
  return this.anonymousFunction();
1896
2078
  case this.check(TokenKind_1.TokenKind.RegexLiteral):
1897
2079
  return this.regexLiteralExpression();
1898
2080
  case this.check(TokenKind_1.TokenKind.Comment):
1899
- return new Statement_1.CommentStatement([this.advance()]);
2081
+ return new Statement_1.CommentStatement({ comments: [this.advance()] });
1900
2082
  default:
1901
2083
  //if we found an expected terminator, don't throw a diagnostic...just return undefined
1902
2084
  if (this.checkAny(...this.peekGlobalTerminators())) {
@@ -1914,7 +2096,7 @@ class Parser {
1914
2096
  let openingSquare = this.previous();
1915
2097
  //add any comment found right after the opening square
1916
2098
  if (this.check(TokenKind_1.TokenKind.Comment)) {
1917
- elements.push(new Statement_1.CommentStatement([this.advance()]));
2099
+ elements.push(new Statement_1.CommentStatement({ comments: [this.advance()] }));
1918
2100
  }
1919
2101
  while (this.match(TokenKind_1.TokenKind.Newline)) {
1920
2102
  }
@@ -1925,7 +2107,7 @@ class Parser {
1925
2107
  while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
1926
2108
  if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
1927
2109
  let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
1928
- elements.push(new Statement_1.CommentStatement([comment]));
2110
+ elements.push(new Statement_1.CommentStatement({ comments: [comment] }));
1929
2111
  }
1930
2112
  while (this.match(TokenKind_1.TokenKind.Newline)) {
1931
2113
  }
@@ -1944,7 +2126,7 @@ class Parser {
1944
2126
  closingSquare = this.previous();
1945
2127
  }
1946
2128
  //this.consume("Expected newline or ':' after array literal", TokenKind.Newline, TokenKind.Colon, TokenKind.Eof);
1947
- return new Expression_1.ArrayLiteralExpression(elements, openingSquare, closingSquare);
2129
+ return new Expression_1.ArrayLiteralExpression({ elements: elements, open: openingSquare, close: closingSquare });
1948
2130
  }
1949
2131
  aaLiteral() {
1950
2132
  let openingBrace = this.previous();
@@ -1976,23 +2158,27 @@ class Parser {
1976
2158
  try {
1977
2159
  if (this.check(TokenKind_1.TokenKind.Comment)) {
1978
2160
  lastAAMember = null;
1979
- members.push(new Statement_1.CommentStatement([this.advance()]));
2161
+ members.push(new Statement_1.CommentStatement({ comments: [this.advance()] }));
1980
2162
  }
1981
2163
  else {
1982
2164
  let k = key();
1983
2165
  let expr = this.expression();
1984
- lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr);
2166
+ lastAAMember = new Expression_1.AAMemberExpression({
2167
+ key: k.keyToken,
2168
+ colon: k.colonToken,
2169
+ value: expr
2170
+ });
1985
2171
  members.push(lastAAMember);
1986
2172
  }
1987
2173
  while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
1988
2174
  // collect comma at end of expression
1989
2175
  if (lastAAMember && this.checkPrevious(TokenKind_1.TokenKind.Comma)) {
1990
- lastAAMember.commaToken = this.previous();
2176
+ lastAAMember.tokens.comma = this.previous();
1991
2177
  }
1992
2178
  //check for comment at the end of the current line
1993
2179
  if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
1994
2180
  let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
1995
- members.push(new Statement_1.CommentStatement([token]));
2181
+ members.push(new Statement_1.CommentStatement({ comments: [token] }));
1996
2182
  }
1997
2183
  else {
1998
2184
  this.consumeStatementSeparators(true);
@@ -2000,7 +2186,7 @@ class Parser {
2000
2186
  if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
2001
2187
  let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
2002
2188
  lastAAMember = null;
2003
- members.push(new Statement_1.CommentStatement([token]));
2189
+ members.push(new Statement_1.CommentStatement({ comments: [token] }));
2004
2190
  continue;
2005
2191
  }
2006
2192
  if (this.check(TokenKind_1.TokenKind.RightCurlyBrace)) {
@@ -2008,7 +2194,11 @@ class Parser {
2008
2194
  }
2009
2195
  let k = key();
2010
2196
  let expr = this.expression();
2011
- lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr);
2197
+ lastAAMember = new Expression_1.AAMemberExpression({
2198
+ key: k.keyToken,
2199
+ colon: k.colonToken,
2200
+ value: expr
2201
+ });
2012
2202
  members.push(lastAAMember);
2013
2203
  }
2014
2204
  }
@@ -2021,7 +2211,7 @@ class Parser {
2021
2211
  else {
2022
2212
  closingBrace = this.previous();
2023
2213
  }
2024
- const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace);
2214
+ const aaExpr = new Expression_1.AALiteralExpression({ elements: members, open: openingBrace, close: closingBrace });
2025
2215
  return aaExpr;
2026
2216
  }
2027
2217
  /**
@@ -2130,6 +2320,11 @@ class Parser {
2130
2320
  var _a;
2131
2321
  return ((_a = this.previous()) === null || _a === void 0 ? void 0 : _a.kind) === tokenKind;
2132
2322
  }
2323
+ /**
2324
+ * Check that the next token kind is the expected kind
2325
+ * @param tokenKind the expected next kind
2326
+ * @returns true if the next tokenKind is the expected value
2327
+ */
2133
2328
  check(tokenKind) {
2134
2329
  const nextKind = this.peek().kind;
2135
2330
  if (nextKind === TokenKind_1.TokenKind.Eof) {