Add list literal spread collection parsing support

Change-Id: I96098e35baf44660b3f7a49952fde64def9998c7
Reviewed-on: https://dart-review.googlesource.com/c/89680
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>
This commit is contained in:
Dan Rubel 2019-01-15 21:16:05 +00:00 committed by commit-bot@chromium.org
parent 4074ebd0a0
commit b55bc09f1f
7 changed files with 67 additions and 2 deletions

View file

@ -46,7 +46,8 @@ import 'package:front_end/src/fasta/messages.dart'
messageStaticConstructor,
messageTypedefNotFunction,
templateDuplicateLabelInSwitchStatement,
templateExpectedIdentifier;
templateExpectedIdentifier,
templateUnexpectedToken;
import 'package:front_end/src/fasta/quote.dart';
import 'package:front_end/src/fasta/scanner/token_constants.dart';
import 'package:front_end/src/fasta/source/stack_listener.dart'
@ -270,6 +271,13 @@ class AstBuilder extends StackListener {
scriptTag = ast.scriptTag(token);
}
@override
void handleSpreadExpression(Token spreadToken) {
// TODO(danrubel): generate new AST structure
handleRecoverableError(templateUnexpectedToken.withArguments(spreadToken),
spreadToken, spreadToken);
}
void handleStringJuxtaposition(int literalCount) {
debugEvent("StringJuxtaposition");

View file

@ -260,6 +260,30 @@ class ExpressionParserTest_Fasta extends FastaParserTestCase
super.test_parseUnaryExpression_decrement_super_withComment();
}
void test_listLiteral_spread() {
// TODO(danrubel): Revise this test once AST supports new syntax
ListLiteral list = parseExpression('[1, ...[2]]', errors: [
expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 4, 3),
]);
expect(list.elements, hasLength(2));
IntegerLiteral first = list.elements[0];
expect(first.value, 1);
ListLiteral second = list.elements[1];
expect(second.elements, hasLength(1));
}
void test_listLiteral_spreadQ() {
// TODO(danrubel): Revise this test once AST supports new syntax
ListLiteral list = parseExpression('[1, ...?[2]]', errors: [
expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 4, 4),
]);
expect(list.elements, hasLength(2));
IntegerLiteral first = list.elements[0];
expect(first.value, 1);
ListLiteral second = list.elements[1];
expect(second.elements, hasLength(1));
}
void test_mapLiteral() {
MapLiteral map = parseExpression('{3: 6}', parseSetLiterals: true);
expect(map.constKeyword, isNull);

View file

@ -3518,6 +3518,16 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
token.next, token.offset, Constness.explicitConst);
}
@override
void handleSpreadExpression(Token spreadToken) {
debugEvent("SpreadExpression");
// TODO(danrubel) implement spread expression support
handleRecoverableError(
fasta.templateUnexpectedToken.withArguments(spreadToken),
spreadToken,
spreadToken);
}
@override
void endTypeArguments(int count, Token beginToken, Token endToken) {
debugEvent("TypeArguments");

View file

@ -1307,6 +1307,11 @@ class ForwardingListener implements Listener {
listener?.handleSend(beginToken, endToken);
}
@override
void handleSpreadExpression(Token spreadToken) {
listener?.handleSpreadExpression(spreadToken);
}
@override
void handleStringJuxtaposition(int literalCount) {
listener?.handleStringJuxtaposition(literalCount);

View file

@ -1074,6 +1074,13 @@ class Listener implements UnescapeErrorListener {
logEvent("ConstExpression");
}
/// Called after the parser has parsed an expression that starts with
/// one of the spread collection tokens `...` or `...?`. Substructures:
/// - expression
void handleSpreadExpression(Token spreadToken) {
logEvent("SpreadExpression");
}
/// Handle the start of a function typed formal parameter. Substructures:
/// - type variables
void beginFunctionTypedFormalParameter(Token token) {}

View file

@ -4186,7 +4186,12 @@ class Parser {
token = next;
break;
}
token = parseExpression(token);
if (optional('...', next) || optional('...?', next)) {
token = parseExpression(token.next);
listener.handleSpreadExpression(next);
} else {
token = parseExpression(token);
}
next = token.next;
++count;
if (!optional(',', next)) {

View file

@ -376,6 +376,12 @@ class TypePromotionLookAheadListener extends Listener {
doConstuctorInvocation(token, true);
}
@override
void handleSpreadExpression(Token spreadToken) {
// TODO(danrubel) add support for spread collections
// but for now this is ignored and an error reported in the body builder
}
void doConstuctorInvocation(Token token, bool isConst) {
state.pop(); // Arguments.
state.popPushNull(token.lexeme, token); // Constructor reference.