@@ -7867,7 +7867,7 @@ class Parser {
78677867 ///
78687868 /// ```
78697869 /// listLiteral:
7870- /// 'const'? typeArguments? '[' (expressionList ','?)? ']'
7870+ /// 'const'? typeArguments? '[' (elementList ','?)? ']'
78717871 /// ;
78727872 /// ```
78737873 ///
@@ -7900,12 +7900,13 @@ class Parser {
79007900 break ;
79017901 }
79027902 int ifCount = 0 ;
7903- LiteralEntryInfo ? info = computeLiteralEntry (token);
7903+ LiteralEntryInfo ? info = _computeLiteralEntry (token);
79047904 while (info != null ) {
7905+ next = token.next! ;
79057906 if (info.hasEntry) {
7906- if (token. next! .isA (TokenType .QUESTION )) {
7907- Token nullAwareToken = token. next! ;
7908- token = token. next! ;
7907+ if (next.isA (TokenType .QUESTION )) {
7908+ Token nullAwareToken = next;
7909+ token = next;
79097910 token = parseExpression (token);
79107911 listener.handleNullAwareElement (nullAwareToken);
79117912 } else {
@@ -7915,7 +7916,7 @@ class Parser {
79157916 token = info.parse (token, this );
79167917 }
79177918 ifCount += info.ifConditionDelta;
7918- info = info. computeNext ( token);
7919+ info = _nextLiteralEntry (info, token);
79197920 }
79207921 next = token.next! ;
79217922 ++ count;
@@ -7983,7 +7984,7 @@ class Parser {
79837984
79847985 while (true ) {
79857986 int ifCount = 0 ;
7986- LiteralEntryInfo ? info = computeLiteralEntry (token);
7987+ LiteralEntryInfo ? info = _computeLiteralEntry (token);
79877988 if (info == simpleEntry) {
79887989 // TODO(danrubel): Remove this section and use the while loop below
79897990 // once hasSetEntry is no longer needed.
@@ -7992,77 +7993,66 @@ class Parser {
79927993 hasSetEntry ?? = ! isMapEntry;
79937994 if (isMapEntry) {
79947995 Token colon = token.next! ;
7995- Token next = colon.next! ;
7996- if (next.isA (TokenType .QUESTION )) {
7997- // Null-aware value. For example:
7998- // <int, String>{ x: ?y }
7999- token = parseExpression (next);
8000- listener.handleLiteralMapEntry (
8001- colon,
8002- token,
8003- nullAwareKeyToken: null ,
8004- nullAwareValueToken: next,
8005- );
8006- } else {
8007- // Non null-aware entry. For example:
8008- // <bool, num>{ x: y }
8009- token = parseExpression (colon);
8010- listener.handleLiteralMapEntry (colon, token.next! );
7996+ token = colon;
7997+ Token next = token.next! ;
7998+ Token ? nullAwareValueToken;
7999+ if (next.isA (TokenType .QUESTION_PERIOD )) {
8000+ token = nullAwareValueToken = _splitFollowingQuestionPeriod (token);
8001+ } else if (next.isA (TokenType .QUESTION )) {
8002+ token = nullAwareValueToken = next;
80118003 }
8004+
8005+ token = parseExpression (token);
8006+ listener.handleLiteralMapEntry (
8007+ colon,
8008+ token.next! ,
8009+ nullAwareValueToken: nullAwareValueToken,
8010+ );
80128011 }
80138012 } else {
80148013 while (info != null ) {
80158014 if (info.hasEntry) {
80168015 Token ? nullAwareKeyToken;
8017- if (token.next! .isA (TokenType .QUESTION )) {
8016+ Token next = token.next! ;
8017+ if (next.isA (TokenType .QUESTION )) {
80188018 // Null-aware key, for example:
80198019 // <double, Symbol>{ if (b) ?x: y }
80208020 // <double, Symbol>{ if (b) ?x: ?y }
8021- nullAwareKeyToken = token.next! ;
8022-
8023- // Parse the expression after '?'.
8021+ nullAwareKeyToken = next;
80248022 token = nullAwareKeyToken;
8025- token = parseExpression (token);
8026- } else {
8027- token = parseExpression (token);
80288023 }
8024+ token = parseExpression (token);
8025+
80298026 if (token.next! .isA (TokenType .COLON )) {
80308027 Token colon = token.next! ;
8031- Token next = colon.next! ;
8032- if (next.isA (TokenType .QUESTION )) {
8033- token = parseExpression (next);
8034- // Null-aware value. For example:
8035- // <double, Symbol>{ if (b) x: ?y }
8036- // <double, Symbol>{ if (b) ?x: ?y }
8037- listener.handleLiteralMapEntry (
8038- colon,
8039- token.next! ,
8040- nullAwareKeyToken: nullAwareKeyToken,
8041- nullAwareValueToken: next,
8042- );
8043- } else {
8044- // Non null-aware value. For example:
8045- // <String, int>{ if (b) x : y }
8046- // <String, int>{ if (b) ?x : y }
8047- token = parseExpression (colon);
8048- listener.handleLiteralMapEntry (
8049- colon,
8050- token.next! ,
8051- nullAwareKeyToken: nullAwareKeyToken,
8052- );
8053- }
8054- } else {
8055- if (nullAwareKeyToken != null ) {
8056- // Null-aware element. For example:
8057- // <String>{ if (b) ?x }
8058- listener.handleNullAwareElement (nullAwareKeyToken);
8028+ token = colon;
8029+
8030+ Token ? nullAwareValueToken;
8031+ Token next = token.next! ;
8032+ if (next.isA (TokenType .QUESTION_PERIOD )) {
8033+ token = nullAwareValueToken =
8034+ _splitFollowingQuestionPeriod (token);
8035+ } else if (next.isA (TokenType .QUESTION )) {
8036+ token = nullAwareValueToken = next;
80598037 }
8038+
8039+ token = parseExpression (token);
8040+ listener.handleLiteralMapEntry (
8041+ colon,
8042+ token.next! ,
8043+ nullAwareKeyToken: nullAwareKeyToken,
8044+ nullAwareValueToken: nullAwareValueToken,
8045+ );
8046+ } else if (nullAwareKeyToken != null ) {
8047+ // Null-aware element. For example:
8048+ // <String>{ if (b) ?x }
8049+ listener.handleNullAwareElement (nullAwareKeyToken);
80608050 }
80618051 } else {
80628052 token = info.parse (token, this );
80638053 }
80648054 ifCount += info.ifConditionDelta;
8065- info = info. computeNext ( token);
8055+ info = _nextLiteralEntry (info, token);
80668056 }
80678057 }
80688058 ++ count;
@@ -8121,6 +8111,35 @@ class Parser {
81218111 }
81228112 }
81238113
8114+ LiteralEntryInfo ? _computeLiteralEntry (Token token) {
8115+ if (token.next! .isA (TokenType .QUESTION_PERIOD )) {
8116+ _splitFollowingQuestionPeriod (token);
8117+ }
8118+ return computeLiteralEntry (token);
8119+ }
8120+
8121+ LiteralEntryInfo ? _nextLiteralEntry (LiteralEntryInfo info, Token token) {
8122+ if (token.next! .isA (TokenType .QUESTION_PERIOD )) {
8123+ _splitFollowingQuestionPeriod (token);
8124+ }
8125+ return info.computeNext (token);
8126+ }
8127+
8128+ Token _splitFollowingQuestionPeriod (Token token) {
8129+ Token next = token.next! ;
8130+ assert (next.isA (TokenType .QUESTION_PERIOD ));
8131+ int offset = next.charOffset;
8132+ Token newNext = rewriter.replaceTokenFollowing (
8133+ token,
8134+ new Token (TokenType .QUESTION , offset),
8135+ );
8136+ rewriter.insertToken (
8137+ newNext,
8138+ new Token (TokenType .PERIOD , offset + 1 ),
8139+ );
8140+ return newNext;
8141+ }
8142+
81248143 /// formalParameterList functionBody.
81258144 ///
81268145 /// This is a suffix parser because it is assumed that type arguments have
0 commit comments