| Index: lib/compiler/implementation/scanner/parser.dart
|
| diff --git a/lib/compiler/implementation/scanner/parser.dart b/lib/compiler/implementation/scanner/parser.dart
|
| index db3da46975f8984bce763df3da39552172d67443..e18389ea55cd06a2b9e9a77b59edeb7a0b393c4b 100644
|
| --- a/lib/compiler/implementation/scanner/parser.dart
|
| +++ b/lib/compiler/implementation/scanner/parser.dart
|
| @@ -150,7 +150,7 @@ class Parser {
|
| String value = token.stringValue;
|
| if (value === 'var') return parseType(token);
|
| if (value !== 'this') {
|
| - Token peek = peekAfterType(token);
|
| + Token peek = peekAfterExpectedType(token);
|
| if (isIdentifier(peek) || optional('this', peek)) {
|
| return parseType(token);
|
| }
|
| @@ -351,7 +351,7 @@ class Parser {
|
| token = parseModifiers(token);
|
| Token getOrSet = findGetOrSet(token);
|
| if (token === getOrSet) token = token.next;
|
| - Token peek = peekAfterType(token);
|
| + Token peek = peekAfterExpectedType(token);
|
| if (isIdentifier(peek)) {
|
| // Skip type.
|
| token = peek;
|
| @@ -463,13 +463,18 @@ class Parser {
|
| return expect(';', token);
|
| }
|
|
|
| + bool isModifier(Token token) {
|
| + final String value = token.stringValue;
|
| + return ('final' === value) ||
|
| + ('var' === value) ||
|
| + ('const' === value) ||
|
| + ('abstract' === value) ||
|
| + ('static' === value) ||
|
| + ('external' === value);
|
| + }
|
| +
|
| Token parseModifier(Token token) {
|
| - assert(('final' === token.stringValue) ||
|
| - ('var' === token.stringValue) ||
|
| - ('const' === token.stringValue) ||
|
| - ('abstract' === token.stringValue) ||
|
| - ('static' === token.stringValue) ||
|
| - ('external' === token.stringValue));
|
| + assert(isModifier(token));
|
| listener.handleModifier(token);
|
| return token.next;
|
| }
|
| @@ -477,13 +482,7 @@ class Parser {
|
| Token parseModifiers(Token token) {
|
| int count = 0;
|
| while (token.kind === KEYWORD_TOKEN) {
|
| - final String value = token.stringValue;
|
| - if (('final' !== value) &&
|
| - ('var' !== value) &&
|
| - ('const' !== value) &&
|
| - ('abstract' !== value) &&
|
| - ('static' !== value) &&
|
| - ('external' !== value))
|
| + if (!isModifier(token))
|
| break;
|
| token = parseModifier(token);
|
| count++;
|
| @@ -494,9 +493,6 @@ class Parser {
|
|
|
| Token peekAfterType(Token token) {
|
| // TODO(ahe): Also handle var?
|
| - if ('void' !== token.stringValue && !isIdentifier(token)) {
|
| - listener.unexpected(token);
|
| - }
|
| // We are looking at "identifier ...".
|
| Token peek = token.next;
|
| if (peek.kind === PERIOD_TOKEN) {
|
| @@ -519,6 +515,17 @@ class Parser {
|
| return peek;
|
| }
|
|
|
| + /**
|
| + * Returns the token after the type which is expected to begin at [token].
|
| + * If [token] is not the start of a type, [Listener.unexpectedType] is called.
|
| + */
|
| + Token peekAfterExpectedType(Token token) {
|
| + if ('void' !== token.stringValue && !isIdentifier(token)) {
|
| + return listener.expectedType(token);
|
| + }
|
| + return peekAfterType(token);
|
| + }
|
| +
|
| Token parseClassBody(Token token) {
|
| Token begin = token;
|
| listener.beginClassBody(token);
|
| @@ -544,7 +551,7 @@ class Parser {
|
| if (isGetOrSet(token)) {
|
| if (optional('<', token.next)) {
|
| // For example: get<T> ...
|
| - final Token peek = peekAfterType(token);
|
| + final Token peek = peekAfterExpectedType(token);
|
| if (isGetOrSet(peek) && isIdentifier(peek.next)) {
|
| // For example: get<T> get identifier
|
| return peek;
|
| @@ -560,7 +567,7 @@ class Parser {
|
| }
|
| }
|
| } else if (token.stringValue !== 'operator') {
|
| - final Token peek = peekAfterType(token);
|
| + final Token peek = peekAfterExpectedType(token);
|
| if (isGetOrSet(peek) && isIdentifier(peek.next)) {
|
| // type? get identifier
|
| return peek;
|
| @@ -580,7 +587,7 @@ class Parser {
|
| token = parseModifiers(token);
|
| Token getOrSet = findGetOrSet(token);
|
| if (token === getOrSet) token = token.next;
|
| - Token peek = peekAfterType(token);
|
| + Token peek = peekAfterExpectedType(token);
|
| if (isIdentifier(peek) && token.stringValue !== 'operator') {
|
| // Skip type.
|
| token = peek;
|
| @@ -791,6 +798,8 @@ class Parser {
|
| return parseContinueStatement(token);
|
| } else if (value === ';') {
|
| return parseEmptyStatement(token);
|
| + } else if (value === 'const') {
|
| + return parseExpressionStatementOrConstDeclaration(token);
|
| } else if (isIdentifier(token)) {
|
| return parseExpressionStatementOrDeclaration(token);
|
| } else {
|
| @@ -822,6 +831,19 @@ class Parser {
|
| }
|
| }
|
|
|
| + Token peekIdentifierAfterOptionalType(Token token) {
|
| + Token peek = peekIdentifierAfterType(token);
|
| + if (peek !== null) {
|
| + // We are looking at "type identifier".
|
| + return peek;
|
| + } else if (isIdentifier(token)) {
|
| + // We are looking at "identifier".
|
| + return token;
|
| + } else {
|
| + return null;
|
| + }
|
| + }
|
| +
|
| Token parseExpressionStatementOrDeclaration(Token token) {
|
| assert(isIdentifier(token) || token.stringValue === 'void');
|
| Token identifier = peekIdentifierAfterType(token);
|
| @@ -860,6 +882,28 @@ class Parser {
|
| return parseExpressionStatement(token);
|
| }
|
|
|
| + Token parseExpressionStatementOrConstDeclaration(Token token) {
|
| + assert(token.stringValue === 'const');
|
| + if (isModifier(token.next)) {
|
| + return parseVariablesDeclaration(token);
|
| + }
|
| + Token identifier = peekIdentifierAfterOptionalType(token.next);
|
| + if (identifier !== null) {
|
| + assert(isIdentifier(identifier));
|
| + Token afterId = identifier.next;
|
| + int afterIdKind = afterId.kind;
|
| + if (afterIdKind === EQ_TOKEN ||
|
| + afterIdKind === SEMICOLON_TOKEN ||
|
| + afterIdKind === COMMA_TOKEN) {
|
| + // We are looking at "const type identifier" followed by '=', ';', or
|
| + // ','.
|
| + return parseVariablesDeclaration(token);
|
| + }
|
| + // Fall-through to expression statement.
|
| + }
|
| + return parseExpressionStatement(token);
|
| + }
|
| +
|
| Token parseLabel(Token token) {
|
| token = parseIdentifier(token);
|
| Token colon = token;
|
| @@ -1213,7 +1257,7 @@ class Parser {
|
|
|
| Token parseSendOrFunctionLiteral(Token token) {
|
| if (!mayParseFunctionExpressions) return parseSend(token);
|
| - Token peek = peekAfterType(token);
|
| + Token peek = peekAfterExpectedType(token);
|
| if (peek.kind === IDENTIFIER_TOKEN && isFunctionDeclaration(peek.next)) {
|
| return parseFunctionExpression(token);
|
| } else if (isFunctionDeclaration(token.next)) {
|
|
|