@@ -450,12 +450,16 @@ class MiniJsParser {
450
450
static const COLON = 14 ;
451
451
static const SEMICOLON = 15 ;
452
452
static const ARROW = 16 ;
453
- static const HASH = 17 ;
454
- static const WHITESPACE = 18 ;
455
- static const OTHER = 19 ;
453
+ static const ELLIPSIS = 17 ;
454
+ static const HASH = 18 ;
455
+ static const WHITESPACE = 19 ;
456
+ static const OTHER = 20 ;
456
457
457
458
// Make sure that ]] is two symbols.
458
- bool singleCharCategory (int category) => category >= DOT ;
459
+ // TODO(jmesserly): => and ... are not single char tokens, should we change
460
+ // their numbers? It shouldn't matter because this is only called on values
461
+ // from the [CATEGORIES] table.
462
+ bool singleCharCategory (int category) => category > DOT ;
459
463
460
464
static String categoryToString (int cat) {
461
465
switch (cat) {
@@ -477,6 +481,7 @@ class MiniJsParser {
477
481
case COLON : return "COLON" ;
478
482
case SEMICOLON : return "SEMICOLON" ;
479
483
case ARROW : return "ARROW" ;
484
+ case ELLIPSIS : return "ELLIPSIS" ;
480
485
case HASH : return "HASH" ;
481
486
case WHITESPACE : return "WHITESPACE" ;
482
487
case OTHER : return "OTHER" ;
@@ -528,6 +533,7 @@ class MiniJsParser {
528
533
.toSet ();
529
534
530
535
static final ARROW_TOKEN = '=>' ;
536
+ static final ELLIPSIS_TOKEN = '...' ;
531
537
532
538
static final OPERATORS_THAT_LOOK_LIKE_IDENTIFIERS =
533
539
['typeof' , 'void' , 'delete' , 'in' , 'instanceof' , 'await' ].toSet ();
@@ -642,6 +648,12 @@ class MiniJsParser {
642
648
double .parse (lastToken, (_) {
643
649
error ("Unparseable number" );
644
650
});
651
+ } else if (cat == DOT && lastToken.length > 1 ) {
652
+ if (lastToken == ELLIPSIS_TOKEN ) {
653
+ lastCategory = ELLIPSIS ;
654
+ } else {
655
+ error ("Unknown operator" );
656
+ }
645
657
} else if (cat == SYMBOL ) {
646
658
if (lastToken == ARROW_TOKEN ) {
647
659
lastCategory = ARROW ;
@@ -792,26 +804,42 @@ class MiniJsParser {
792
804
Expression parseExpressionOrArrowFunction () {
793
805
if (acceptCategory (RPAREN )) {
794
806
expectCategory (ARROW );
795
- return parseArrowFunctionBody (< Identifier > []);
807
+ return parseArrowFunctionBody (< Parameter > []);
808
+ }
809
+ if (acceptCategory (ELLIPSIS )) {
810
+ var params = < Parameter > [new RestParameter (parseParameter ())];
811
+ expectCategory (RPAREN );
812
+ expectCategory (ARROW );
813
+ return parseArrowFunctionBody (params);
814
+ }
815
+ Expression expression = parseAssignment ();
816
+ while (acceptCategory (COMMA )) {
817
+ if (acceptCategory (ELLIPSIS )) {
818
+ var params = < Parameter > [];
819
+ _expressionToParameterList (expression, params);
820
+ params.add (new RestParameter (parseParameter ()));
821
+ expectCategory (RPAREN );
822
+ expectCategory (ARROW );
823
+ return parseArrowFunctionBody (params);
824
+ }
825
+ Expression right = parseAssignment ();
826
+ expression = new Binary (',' , expression, right);
796
827
}
797
- Expression expression = parseExpression ();
798
828
expectCategory (RPAREN );
799
829
if (acceptCategory (ARROW )) {
800
- var params = < Identifier > [];
830
+ var params = < Parameter > [];
801
831
_expressionToParameterList (expression, params);
802
832
return parseArrowFunctionBody (params);
803
833
}
804
834
return expression;
805
-
806
835
}
807
836
808
837
/**
809
838
* Converts a parenthesized expression into a list of parameters, issuing an
810
839
* error if the conversion fails.
811
840
*/
812
- void _expressionToParameterList (Expression node, List <Identifier > params) {
841
+ void _expressionToParameterList (Expression node, List <Parameter > params) {
813
842
if (node is Identifier ) {
814
- // TODO(jmesserly): support default/rest parameters
815
843
params.add (node);
816
844
} else if (node is Binary && node.op == ',' ) {
817
845
// TODO(jmesserly): this will allow illegal parens, such as
@@ -827,7 +855,7 @@ class MiniJsParser {
827
855
}
828
856
}
829
857
830
- Expression parseArrowFunctionBody (List <Identifier > params) {
858
+ Expression parseArrowFunctionBody (List <Parameter > params) {
831
859
Node body;
832
860
if (acceptCategory (LBRACE )) {
833
861
body = parseBlock ();
@@ -848,25 +876,22 @@ class MiniJsParser {
848
876
}
849
877
850
878
Expression parseFun () {
851
- List <Identifier > params = < Identifier > [];
879
+ List <Parameter > params = < Parameter > [];
852
880
853
881
expectCategory (LPAREN );
854
882
if (! acceptCategory (RPAREN )) {
855
883
for (;;) {
856
- if (acceptCategory (HASH )) {
857
- var nameOrPosition = parseHash ( );
858
- InterpolatedParameter parameter =
859
- new InterpolatedParameter (nameOrPosition) ;
860
- interpolatedValues. add (parameter);
861
- params. add (parameter);
862
- } else {
863
- String argumentName = lastToken;
864
- expectCategory (ALPHA );
865
- params. add ( new Identifier (argumentName)) ;
884
+ if (acceptCategory (ELLIPSIS )) {
885
+ params. add ( new RestParameter ( parseParameter ()) );
886
+ expectCategory ( RPAREN );
887
+ break ;
888
+ }
889
+
890
+ params. add ( parseParameter ());
891
+ if ( ! acceptCategory ( COMMA )) {
892
+ expectCategory (RPAREN );
893
+ break ;
866
894
}
867
- if (acceptCategory (COMMA )) continue ;
868
- expectCategory (RPAREN );
869
- break ;
870
895
}
871
896
}
872
897
AsyncModifier asyncModifier;
@@ -887,6 +912,21 @@ class MiniJsParser {
887
912
return new Fun (params, block, asyncModifier: asyncModifier);
888
913
}
889
914
915
+ /** Parse parameter name or interpolated parameter. */
916
+ Identifier parseParameter () {
917
+ if (acceptCategory (HASH )) {
918
+ var nameOrPosition = parseHash ();
919
+ var parameter = new InterpolatedParameter (nameOrPosition);
920
+ interpolatedValues.add (parameter);
921
+ return parameter;
922
+ } else {
923
+ // TODO(jmesserly): validate this is not a keyword
924
+ String argumentName = lastToken;
925
+ expectCategory (ALPHA );
926
+ return new Identifier (argumentName);
927
+ }
928
+ }
929
+
890
930
Expression parseObjectInitializer () {
891
931
List <Property > properties = < Property > [];
892
932
for (;;) {
@@ -928,8 +968,12 @@ class MiniJsParser {
928
968
final arguments = < Expression > [];
929
969
if (! acceptCategory (RPAREN )) {
930
970
while (true ) {
931
- Expression argument = parseAssignment ();
932
- arguments.add (argument);
971
+ if (acceptCategory (ELLIPSIS )) {
972
+ arguments.add (new Spread (parseAssignment ()));
973
+ expectCategory (RPAREN );
974
+ break ;
975
+ }
976
+ arguments.add (parseAssignment ());
933
977
if (acceptCategory (RPAREN )) break ;
934
978
expectCategory (COMMA );
935
979
}
0 commit comments