11import { isAssignable } from "../interpreter.js" ;
22import { ASTType } from "../ast-type.js" ;
3- import { hasOwn , minErr } from "../../../shared/utils.js" ;
3+ import { hasOwn , isDefined , minErr } from "../../../shared/utils.js" ;
44
55/**
66 * @typedef {import("./ast-node.ts").ASTNode } ASTNode
@@ -9,6 +9,7 @@ import { hasOwn, minErr } from "../../../shared/utils.js";
99
1010const $parseMinErr = minErr ( "$parse" ) ;
1111
12+ /** @type {Record<string, any> } */
1213const literals = {
1314 true : true ,
1415 false : false ,
@@ -26,6 +27,7 @@ export class AST {
2627 constructor ( lexer ) {
2728 /** @type {import('../lexer/lexer.js').Lexer } */
2829 this . _lexer = lexer ;
30+ /** @type {Record<string, any> } */
2931 this . _selfReferential = {
3032 this : { type : ASTType . _ThisExpression } ,
3133 $locals : { type : ASTType . _LocalsExpression } ,
@@ -61,7 +63,11 @@ export class AST {
6163 let hasMore = true ;
6264
6365 while ( hasMore ) {
64- if ( this . _tokens . length > this . _index && ! this . _peek ( "}" , ")" , ";" , "]" ) )
66+ if (
67+ this . _tokens &&
68+ this . _tokens . length > this . _index &&
69+ ! this . _peek ( "}" , ")" , ";" , "]" )
70+ )
6571 body . push ( this . _expressionStatement ( ) ) ;
6672
6773 if ( ! this . _expect ( ";" ) ) {
@@ -364,7 +370,7 @@ export class AST {
364370 computed : false ,
365371 } ;
366372 } else {
367- this . _throwError ( "IMPOSSIBLE" ) ;
373+ throw new Error ( "IMPOSSIBLE" ) ;
368374 }
369375 }
370376
@@ -475,10 +481,7 @@ export class AST {
475481 }
476482 property = { type : ASTType . _Property , kind : "init" } ;
477483
478- if (
479- /** @type {import("../lexer/lexer.js").Token } */ ( this . _peek ( ) )
480- . constant
481- ) {
484+ if ( /** @type {Token } */ ( this . _peek ( ) ) . constant ) {
482485 property . key = this . _constant ( ) ;
483486 property . computed = false ;
484487 this . _consume ( ":" ) ;
@@ -520,7 +523,7 @@ export class AST {
520523 /**
521524 * Throws a syntax error.
522525 * @param {string } msg - The error message.
523- * @param {import("../lexer/lexer.js").Token } [ token] - The token that caused the error.
526+ * @param {import("../lexer/lexer.js").Token } token - The token that caused the error.
524527 */
525528 _throwError ( msg , token ) {
526529 throw $parseMinErr (
@@ -530,7 +533,7 @@ export class AST {
530533 msg ,
531534 token . index + 1 ,
532535 this . _text ,
533- this . _text . substring ( token . index ) ,
536+ this . _text ? .substring ( token . index ) ,
534537 ) ;
535538 }
536539
@@ -540,58 +543,62 @@ export class AST {
540543 * @returns {import("../lexer/lexer.js").Token } The consumed token.
541544 */
542545 _consume ( e1 ) {
543- if ( this . _tokens . length === this . _index ) {
546+ if ( this . _tokens && this . _tokens . length === this . _index ) {
544547 throw $parseMinErr (
545548 "ueoe" ,
546549 "Unexpected end of expression: {0}" ,
547550 this . _text ,
548551 ) ;
549552 }
550553
551- const token = this . _expect ( e1 ) ;
554+ const token = isDefined ( e1 ) ? this . _expect ( e1 ) : this . _expect ( ) ;
552555
553556 if ( ! token ) {
554557 this . _throwError (
555558 `is unexpected, expecting [${ e1 } ]` ,
556559 /** @type {import("../lexer/lexer.js").Token } */ ( this . _peek ( ) ) ,
557560 ) ;
561+
562+ return /** @type {never } */ ( undefined ) ;
558563 } else {
559564 return /** @type {import("../lexer/lexer.js").Token } */ ( token ) ;
560565 }
561-
562- return undefined ;
563566 }
564567
565568 /**
566569 * Returns the next token without consuming it.
567570 * @returns {import("../lexer/lexer.js").Token } The next token.
568571 */
569572 _peekToken ( ) {
570- if ( this . _tokens . length === this . _index ) {
573+ if ( ! this . _tokens || this . _tokens . length === this . _index ) {
571574 throw $parseMinErr (
572575 "ueoe" ,
573576 "Unexpected end of expression: {0}" ,
574577 this . _text ,
575578 ) ;
579+ } else {
580+ return this . _tokens [ this . _index ] ;
576581 }
577-
578- return this . _tokens [ this . _index ] ;
579582 }
580583
581584 /**
582585 * Checks if the next token matches any of the expected types.
583- * @param {...string } [ expected] - The expected token types.
586+ * @param {...string } expected - The expected token types.
584587 * @returns {import('../lexer/lexer.js').Token|boolean } The next token if it matches, otherwise false.
585588 */
586589 _peek ( ...expected ) {
587- const token = this . _tokens [ this . _index ] ;
590+ const token = this . _tokens && this . _tokens [ this . _index ] ;
591+
592+ if ( ! token ) return false ;
588593
589594 const j = expected . length ;
590595
591- if ( ! token || ! j ) return token ;
596+ if ( ! j ) return token ;
592597
593598 const txt = token . text ;
594599
600+ if ( expected . length === 1 ) return expected [ 0 ] === txt ? token : false ;
601+
595602 for ( let i = 0 ; i < j ; i ++ ) {
596603 if ( expected [ i ] === txt || ! expected [ i ] ) return token ;
597604 }
@@ -601,7 +608,7 @@ export class AST {
601608
602609 /**
603610 * Consumes the next token if it matches any of the expected types.
604- * @param {...string } [ expected] - The expected token types.
611+ * @param {...string } expected - The expected token types.
605612 * @returns {import("../lexer/lexer.js").Token|boolean } The consumed token if it matches, otherwise false.
606613 */
607614 _expect ( ...expected ) {
0 commit comments