Skip to content

Commit 8c5dce6

Browse files
jensjohaCommit Queue
authored andcommitted
[parser] Replace optional/optional2/isOneOf/isOneOfOrEof with extension method calls
The entire scanner/parser now no longer uses `optional` or `optional2`, the latter being completely removed. Furthermore, when compiling a fixed version of the CFE with the CFE this CL reduces the instructions used by ~13.6 mio. ``` page-faults:u: -0.3695% +/- 0.0676% (-384.20 +/- 70.23) instructions:u: -0.0645% +/- 0.0007% (-13671097.80 +/- 153289.78) ``` Change-Id: Ib93dd2983aa1b4df0610d099010ac10f55f357f8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388323 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Jens Johansen <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent fd2b247 commit 8c5dce6

19 files changed

+1337
-1164
lines changed

pkg/_fe_analyzer_shared/lib/src/parser/identifier_context.dart

Lines changed: 86 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@
55
import '../messages/codes.dart'
66
show Message, Template, templateExpectedIdentifier;
77

8-
import '../scanner/token.dart' show Token, TokenType;
8+
import '../scanner/token.dart'
9+
show Keyword, Token, TokenIsAExtension, TokenType;
910

1011
import 'identifier_context_impl.dart';
1112

1213
import 'parser_impl.dart' show Parser;
1314

14-
import 'util.dart' show isOneOfOrEof, optional;
15-
1615
/// Information about the parser state that is passed to the listener at the
1716
/// time an identifier is encountered. It is also used by the parser for error
1817
/// recovery when a recovery template is defined.
@@ -140,7 +139,12 @@ abstract class IdentifierContext {
140139
/// Identifier is a name being declared by a top level variable declaration.
141140
static const TopLevelDeclarationIdentifierContext
142141
topLevelVariableDeclaration = const TopLevelDeclarationIdentifierContext(
143-
'topLevelVariableDeclaration', const [';', '=', ',']);
142+
'topLevelVariableDeclaration', const [
143+
TokenType.SEMICOLON,
144+
TokenType.EQ,
145+
TokenType.COMMA,
146+
TokenType.EOF
147+
]);
144148

145149
/// Identifier is a name being declared by a field declaration.
146150
static const FieldDeclarationIdentifierContext fieldDeclaration =
@@ -149,8 +153,15 @@ abstract class IdentifierContext {
149153
/// Identifier is the name being declared by a top level function declaration.
150154
static const TopLevelDeclarationIdentifierContext
151155
topLevelFunctionDeclaration = const TopLevelDeclarationIdentifierContext(
152-
'topLevelFunctionDeclaration',
153-
const ['<', '(', '{', '=>', 'async', 'sync']);
156+
'topLevelFunctionDeclaration', const [
157+
TokenType.LT,
158+
TokenType.OPEN_PAREN,
159+
TokenType.OPEN_CURLY_BRACKET,
160+
TokenType.FUNCTION,
161+
Keyword.ASYNC,
162+
Keyword.SYNC,
163+
TokenType.EOF
164+
]);
154165

155166
/// Identifier is the start of the name being declared by a method
156167
/// declaration.
@@ -333,25 +344,25 @@ abstract class IdentifierContext {
333344
bool looksLikeExpressionStart(Token next) =>
334345
next.isIdentifier ||
335346
next.isKeyword && !looksLikeStatementStart(next) ||
336-
next.type == TokenType.DOUBLE ||
337-
next.type == TokenType.DOUBLE_WITH_SEPARATORS ||
338-
next.type == TokenType.HASH ||
339-
next.type == TokenType.HEXADECIMAL ||
340-
next.type == TokenType.HEXADECIMAL_WITH_SEPARATORS ||
341-
next.type == TokenType.IDENTIFIER ||
342-
next.type == TokenType.INT ||
343-
next.type == TokenType.INT_WITH_SEPARATORS ||
344-
next.type == TokenType.STRING ||
345-
optional('{', next) ||
346-
optional('(', next) ||
347-
optional('[', next) ||
348-
optional('[]', next) ||
349-
optional('<', next) ||
350-
optional('!', next) ||
351-
optional('-', next) ||
352-
optional('~', next) ||
353-
optional('++', next) ||
354-
optional('--', next);
347+
next.isA2(TokenType.DOUBLE) ||
348+
next.isA2(TokenType.DOUBLE_WITH_SEPARATORS) ||
349+
next.isA2(TokenType.HASH) ||
350+
next.isA2(TokenType.HEXADECIMAL) ||
351+
next.isA2(TokenType.HEXADECIMAL_WITH_SEPARATORS) ||
352+
next.isA2(TokenType.IDENTIFIER) ||
353+
next.isA2(TokenType.INT) ||
354+
next.isA2(TokenType.INT_WITH_SEPARATORS) ||
355+
next.isA2(TokenType.STRING) ||
356+
next.isA2(TokenType.OPEN_CURLY_BRACKET) ||
357+
next.isA2(TokenType.OPEN_PAREN) ||
358+
next.isA2(TokenType.OPEN_SQUARE_BRACKET) ||
359+
next.isA2(TokenType.INDEX) ||
360+
next.isA2(TokenType.LT) ||
361+
next.isA2(TokenType.BANG) ||
362+
next.isA2(TokenType.MINUS) ||
363+
next.isA2(TokenType.TILDE) ||
364+
next.isA2(TokenType.PLUS_PLUS) ||
365+
next.isA2(TokenType.MINUS_MINUS);
355366

356367
/// Returns `true` if [next] should be treated like the start of a pattern for
357368
/// the purposes of recovery.
@@ -360,48 +371,59 @@ bool looksLikeExpressionStart(Token next) =>
360371
/// we mostly re-use [looksLikeExpressionStart].
361372
bool looksLikePatternStart(Token next) =>
362373
next.isIdentifier ||
363-
next.type == TokenType.DOUBLE ||
364-
next.type == TokenType.DOUBLE_WITH_SEPARATORS ||
365-
next.type == TokenType.HASH ||
366-
next.type == TokenType.HEXADECIMAL ||
367-
next.type == TokenType.HEXADECIMAL_WITH_SEPARATORS ||
368-
next.type == TokenType.IDENTIFIER ||
369-
next.type == TokenType.INT ||
370-
next.type == TokenType.INT_WITH_SEPARATORS ||
371-
next.type == TokenType.STRING ||
372-
optional('null', next) ||
373-
optional('false', next) ||
374-
optional('true', next) ||
375-
optional('{', next) ||
376-
optional('(', next) ||
377-
optional('[', next) ||
378-
optional('[]', next) ||
379-
optional('<', next) ||
380-
optional('<=', next) ||
381-
optional('>', next) ||
382-
optional('>=', next) ||
383-
optional('!=', next) ||
384-
optional('==', next) ||
385-
optional('var', next) ||
386-
optional('final', next) ||
387-
optional('const', next);
374+
next.isA2(TokenType.DOUBLE) ||
375+
next.isA2(TokenType.DOUBLE_WITH_SEPARATORS) ||
376+
next.isA2(TokenType.HASH) ||
377+
next.isA2(TokenType.HEXADECIMAL) ||
378+
next.isA2(TokenType.HEXADECIMAL_WITH_SEPARATORS) ||
379+
next.isA2(TokenType.IDENTIFIER) ||
380+
next.isA2(TokenType.INT) ||
381+
next.isA2(TokenType.INT_WITH_SEPARATORS) ||
382+
next.isA2(TokenType.STRING) ||
383+
next.isA2(Keyword.NULL) ||
384+
next.isA2(Keyword.FALSE) ||
385+
next.isA2(Keyword.TRUE) ||
386+
next.isA2(TokenType.OPEN_CURLY_BRACKET) ||
387+
next.isA2(TokenType.OPEN_PAREN) ||
388+
next.isA2(TokenType.OPEN_SQUARE_BRACKET) ||
389+
next.isA2(TokenType.INDEX) ||
390+
next.isA2(TokenType.LT) ||
391+
next.isA2(TokenType.LT_EQ) ||
392+
next.isA2(TokenType.GT) ||
393+
next.isA2(TokenType.GT_EQ) ||
394+
next.isA2(TokenType.BANG_EQ) ||
395+
next.isA2(TokenType.EQ_EQ) ||
396+
next.isA2(Keyword.VAR) ||
397+
next.isA2(Keyword.FINAL) ||
398+
next.isA2(Keyword.CONST);
388399

389400
/// Return `true` if the given [token] should be treated like the start of
390401
/// a new statement for the purposes of recovery.
391-
bool looksLikeStatementStart(Token token) => isOneOfOrEof(token, const [
392-
'@',
393-
'assert', 'break', 'continue', 'do', 'else', 'final', 'for', //
394-
'if', 'return', 'switch', 'try', 'var', 'void', 'while', //
395-
]);
402+
bool looksLikeStatementStart(Token token) =>
403+
token.isA2(TokenType.AT) ||
404+
token.isA2(Keyword.ASSERT) ||
405+
token.isA2(Keyword.BREAK) ||
406+
token.isA2(Keyword.CONTINUE) ||
407+
token.isA2(Keyword.DO) ||
408+
token.isA2(Keyword.ELSE) ||
409+
token.isA2(Keyword.FINAL) ||
410+
token.isA2(Keyword.FOR) ||
411+
token.isA2(Keyword.IF) ||
412+
token.isA2(Keyword.RETURN) ||
413+
token.isA2(Keyword.SWITCH) ||
414+
token.isA2(Keyword.TRY) ||
415+
token.isA2(Keyword.VAR) ||
416+
token.isA2(Keyword.VOID) ||
417+
token.isA2(Keyword.WHILE) ||
418+
token.isA2(TokenType.EOF);
419+
420+
bool isOkNextValueInFormalParameter(Token token) =>
421+
token.isA2(TokenType.EQ) ||
422+
token.isA2(TokenType.COLON) ||
423+
token.isA2(TokenType.COMMA) ||
424+
token.isA2(TokenType.CLOSE_PAREN) ||
425+
token.isA2(TokenType.CLOSE_SQUARE_BRACKET) ||
426+
token.isA2(TokenType.CLOSE_CURLY_BRACKET);
396427

397428
// TODO(ahe): Remove when analyzer supports generalized function syntax.
398429
typedef _MessageWithArgument<T> = Message Function(T);
399-
400-
const List<String> okNextValueInFormalParameter = const [
401-
'=',
402-
':',
403-
',',
404-
')',
405-
']',
406-
'}',
407-
];

0 commit comments

Comments
 (0)