| // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'package:_fe_analyzer_shared/src/base/analyzer_public_api.dart'; | |
| /** | |
| * Defines the tokens that are produced by the scanner, used by the parser, and | |
| * referenced from the [AST structure](ast.dart). | |
| */ | |
| import 'dart:collection'; | |
| import '../base/syntactic_entity.dart'; | |
| import 'string_utilities.dart'; | |
| import 'token_constants.dart'; | |
| const int NO_PRECEDENCE = 0; | |
| const int ASSIGNMENT_PRECEDENCE = 1; | |
| const int CASCADE_PRECEDENCE = 2; | |
| const int CONDITIONAL_PRECEDENCE = 3; | |
| const int IF_NULL_PRECEDENCE = 4; | |
| const int LOGICAL_OR_PRECEDENCE = 5; | |
| const int LOGICAL_AND_PRECEDENCE = 6; | |
| const int EQUALITY_PRECEDENCE = 7; | |
| const int RELATIONAL_PRECEDENCE = 8; | |
| const int BITWISE_OR_PRECEDENCE = 9; | |
| const int BITWISE_XOR_PRECEDENCE = 10; | |
| const int BITWISE_AND_PRECEDENCE = 11; | |
| const int SHIFT_PRECEDENCE = 12; | |
| const int ADDITIVE_PRECEDENCE = 13; | |
| const int MULTIPLICATIVE_PRECEDENCE = 14; | |
| const int PREFIX_PRECEDENCE = 15; | |
| const int POSTFIX_PRECEDENCE = 16; | |
| const int SELECTOR_PRECEDENCE = 17; | |
| /** | |
| * The opening half of a grouping pair of tokens. This is used for curly | |
| * brackets ('{'), parentheses ('('), and square brackets ('['). | |
| */ | |
| class BeginToken extends SimpleToken { | |
| /** | |
| * The token that corresponds to this token. | |
| */ | |
| Token? endToken; | |
| /** | |
| * Initialize a newly created token to have the given [type] at the given | |
| * [offset]. | |
| */ | |
| @pragma('vm:prefer-inline') | |
| BeginToken(TokenType type, int offset, [CommentToken? precedingComment]) | |
| : super(type, offset, precedingComment) { | |
| assert( | |
| type == TokenType.LT || | |
| type == TokenType.OPEN_CURLY_BRACKET || | |
| type == TokenType.OPEN_PAREN || | |
| type == TokenType.OPEN_SQUARE_BRACKET || | |
| type == TokenType.STRING_INTERPOLATION_EXPRESSION, | |
| ); | |
| } | |
| @override | |
| Token? get endGroup => endToken; | |
| /** | |
| * Set the token that corresponds to this token. | |
| */ | |
| set endGroup(Token? token) { | |
| endToken = token; | |
| } | |
| } | |
| /** | |
| * A token representing a comment. | |
| */ | |
| @AnalyzerPublicApi(message: 'exported by package:analyzer/dart/ast/token.dart') | |
| class CommentToken extends StringToken { | |
| /** | |
| * The token that contains this comment. | |
| */ | |
| SimpleToken? parent; | |
| /** | |
| * Initialize a newly created token to represent a token of the given [type] | |
| * with the given [value] at the given [offset]. | |
| */ | |
| CommentToken(super.type, super.value, super.offset); | |
| } | |
| /** | |
| * A documentation comment token. | |
| */ | |
| class DocumentationCommentToken extends CommentToken { | |
| /** | |
| * Initialize a newly created token to represent a token of the given [type] | |
| * with the given [value] at the given [offset]. | |
| */ | |
| DocumentationCommentToken(super.type, super.value, super.offset); | |
| } | |
| @AnalyzerPublicApi(message: 'exposed by Keyword.keywordStyle') | |
| enum KeywordStyle { reserved, builtIn, pseudo } | |
| /** | |
| * The keywords in the Dart programming language. | |
| * | |
| * Clients may not extend, implement or mix-in this class. | |
| */ | |
| @AnalyzerPublicApi(message: 'exported by package:analyzer/dart/ast/token.dart') | |
| class Keyword extends TokenType { | |
| static const Keyword ABSTRACT = const Keyword( | |
| /* index = */ 82, | |
| "abstract", | |
| "ABSTRACT", | |
| KeywordStyle.builtIn, | |
| isModifier: true, | |
| ); | |
| static const Keyword AS = const Keyword( | |
| /* index = */ 83, | |
| "as", | |
| "AS", | |
| KeywordStyle.builtIn, | |
| precedence: RELATIONAL_PRECEDENCE, | |
| ); | |
| static const Keyword ASSERT = const Keyword( | |
| /* index = */ 84, | |
| "assert", | |
| "ASSERT", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword ASYNC = const Keyword( | |
| /* index = */ 85, | |
| "async", | |
| "ASYNC", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword AUGMENT = const Keyword( | |
| /* index = */ 86, | |
| "augment", | |
| "AUGMENT", | |
| KeywordStyle.builtIn, | |
| isModifier: true, | |
| ); | |
| static const Keyword AWAIT = const Keyword( | |
| /* index = */ 87, | |
| "await", | |
| "AWAIT", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword BASE = const Keyword( | |
| /* index = */ 88, | |
| "base", | |
| "BASE", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword BREAK = const Keyword( | |
| /* index = */ 89, | |
| "break", | |
| "BREAK", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword CASE = const Keyword( | |
| /* index = */ 90, | |
| "case", | |
| "CASE", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword CATCH = const Keyword( | |
| /* index = */ 91, | |
| "catch", | |
| "CATCH", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword CLASS = const Keyword( | |
| /* index = */ 92, | |
| "class", | |
| "CLASS", | |
| KeywordStyle.reserved, | |
| isTopLevelKeyword: true, | |
| ); | |
| static const Keyword CONST = const Keyword( | |
| /* index = */ 93, | |
| "const", | |
| "CONST", | |
| KeywordStyle.reserved, | |
| isModifier: true, | |
| ); | |
| static const Keyword CONTINUE = const Keyword( | |
| /* index = */ 94, | |
| "continue", | |
| "CONTINUE", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword COVARIANT = const Keyword( | |
| /* index = */ 95, | |
| "covariant", | |
| "COVARIANT", | |
| KeywordStyle.builtIn, | |
| isModifier: true, | |
| ); | |
| static const Keyword DEFAULT = const Keyword( | |
| /* index = */ 96, | |
| "default", | |
| "DEFAULT", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword DEFERRED = const Keyword( | |
| /* index = */ 97, | |
| "deferred", | |
| "DEFERRED", | |
| KeywordStyle.builtIn, | |
| ); | |
| static const Keyword DO = const Keyword( | |
| /* index = */ 98, | |
| "do", | |
| "DO", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword DYNAMIC = const Keyword( | |
| /* index = */ 99, | |
| "dynamic", | |
| "DYNAMIC", | |
| KeywordStyle.builtIn, | |
| ); | |
| static const Keyword ELSE = const Keyword( | |
| /* index = */ 100, | |
| "else", | |
| "ELSE", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword ENUM = const Keyword( | |
| /* index = */ 101, | |
| "enum", | |
| "ENUM", | |
| KeywordStyle.reserved, | |
| isTopLevelKeyword: true, | |
| ); | |
| static const Keyword EXPORT = const Keyword( | |
| /* index = */ 102, | |
| "export", | |
| "EXPORT", | |
| KeywordStyle.builtIn, | |
| isTopLevelKeyword: true, | |
| ); | |
| static const Keyword EXTENDS = const Keyword( | |
| /* index = */ 103, | |
| "extends", | |
| "EXTENDS", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword EXTENSION = const Keyword( | |
| /* index = */ 104, | |
| "extension", | |
| "EXTENSION", | |
| KeywordStyle.builtIn, | |
| isTopLevelKeyword: true, | |
| ); | |
| static const Keyword EXTERNAL = const Keyword( | |
| /* index = */ 105, | |
| "external", | |
| "EXTERNAL", | |
| KeywordStyle.builtIn, | |
| isModifier: true, | |
| ); | |
| static const Keyword FACTORY = const Keyword( | |
| /* index = */ 106, | |
| "factory", | |
| "FACTORY", | |
| KeywordStyle.builtIn, | |
| ); | |
| static const Keyword FALSE = const Keyword( | |
| /* index = */ 107, | |
| "false", | |
| "FALSE", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword FINAL = const Keyword( | |
| /* index = */ 108, | |
| "final", | |
| "FINAL", | |
| KeywordStyle.reserved, | |
| isModifier: true, | |
| ); | |
| static const Keyword FINALLY = const Keyword( | |
| /* index = */ 109, | |
| "finally", | |
| "FINALLY", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword FOR = const Keyword( | |
| /* index = */ 110, | |
| "for", | |
| "FOR", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword FUNCTION = const Keyword( | |
| /* index = */ 111, | |
| "Function", | |
| "FUNCTION", | |
| KeywordStyle.builtIn, | |
| ); | |
| static const Keyword GET = const Keyword( | |
| /* index = */ 112, | |
| "get", | |
| "GET", | |
| KeywordStyle.builtIn, | |
| ); | |
| static const Keyword HIDE = const Keyword( | |
| /* index = */ 113, | |
| "hide", | |
| "HIDE", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword IF = const Keyword( | |
| /* index = */ 114, | |
| "if", | |
| "IF", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword IMPLEMENTS = const Keyword( | |
| /* index = */ 115, | |
| "implements", | |
| "IMPLEMENTS", | |
| KeywordStyle.builtIn, | |
| ); | |
| static const Keyword IMPORT = const Keyword( | |
| /* index = */ 116, | |
| "import", | |
| "IMPORT", | |
| KeywordStyle.builtIn, | |
| isTopLevelKeyword: true, | |
| ); | |
| static const Keyword IN = const Keyword( | |
| /* index = */ 117, | |
| "in", | |
| "IN", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword INOUT = const Keyword( | |
| /* index = */ 118, | |
| "inout", | |
| "INOUT", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword INTERFACE = const Keyword( | |
| /* index = */ 119, | |
| "interface", | |
| "INTERFACE", | |
| KeywordStyle.builtIn, | |
| ); | |
| static const Keyword IS = const Keyword( | |
| /* index = */ 120, | |
| "is", | |
| "IS", | |
| KeywordStyle.reserved, | |
| precedence: RELATIONAL_PRECEDENCE, | |
| ); | |
| static const Keyword LATE = const Keyword( | |
| /* index = */ 121, | |
| "late", | |
| "LATE", | |
| KeywordStyle.builtIn, | |
| isModifier: true, | |
| ); | |
| static const Keyword LIBRARY = const Keyword( | |
| /* index = */ 122, | |
| "library", | |
| "LIBRARY", | |
| KeywordStyle.builtIn, | |
| isTopLevelKeyword: true, | |
| ); | |
| static const Keyword MIXIN = const Keyword( | |
| /* index = */ 123, | |
| "mixin", | |
| "MIXIN", | |
| KeywordStyle.builtIn, | |
| isTopLevelKeyword: true, | |
| ); | |
| static const Keyword NATIVE = const Keyword( | |
| /* index = */ 124, | |
| "native", | |
| "NATIVE", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword NEW = const Keyword( | |
| /* index = */ 125, | |
| "new", | |
| "NEW", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword NULL = const Keyword( | |
| /* index = */ 126, | |
| "null", | |
| "NULL", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword OF = const Keyword( | |
| /* index = */ 127, | |
| "of", | |
| "OF", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword ON = const Keyword( | |
| /* index = */ 128, | |
| "on", | |
| "ON", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword OPERATOR = const Keyword( | |
| /* index = */ 129, | |
| "operator", | |
| "OPERATOR", | |
| KeywordStyle.builtIn, | |
| ); | |
| static const Keyword OUT = const Keyword( | |
| /* index = */ 130, | |
| "out", | |
| "OUT", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword PART = const Keyword( | |
| /* index = */ 131, | |
| "part", | |
| "PART", | |
| KeywordStyle.builtIn, | |
| isTopLevelKeyword: true, | |
| ); | |
| static const Keyword PATCH = const Keyword( | |
| /* index = */ 132, | |
| "patch", | |
| "PATCH", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword REQUIRED = const Keyword( | |
| /* index = */ 133, | |
| "required", | |
| "REQUIRED", | |
| KeywordStyle.builtIn, | |
| isModifier: true, | |
| ); | |
| static const Keyword RETHROW = const Keyword( | |
| /* index = */ 134, | |
| "rethrow", | |
| "RETHROW", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword RETURN = const Keyword( | |
| /* index = */ 135, | |
| "return", | |
| "RETURN", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword SEALED = const Keyword( | |
| /* index = */ 136, | |
| "sealed", | |
| "SEALED", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword SET = const Keyword( | |
| /* index = */ 137, | |
| "set", | |
| "SET", | |
| KeywordStyle.builtIn, | |
| ); | |
| static const Keyword SHOW = const Keyword( | |
| /* index = */ 138, | |
| "show", | |
| "SHOW", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword SOURCE = const Keyword( | |
| /* index = */ 139, | |
| "source", | |
| "SOURCE", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword STATIC = const Keyword( | |
| /* index = */ 140, | |
| "static", | |
| "STATIC", | |
| KeywordStyle.builtIn, | |
| isModifier: true, | |
| ); | |
| static const Keyword SUPER = const Keyword( | |
| /* index = */ 141, | |
| "super", | |
| "SUPER", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword SWITCH = const Keyword( | |
| /* index = */ 142, | |
| "switch", | |
| "SWITCH", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword SYNC = const Keyword( | |
| /* index = */ 143, | |
| "sync", | |
| "SYNC", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword THIS = const Keyword( | |
| /* index = */ 144, | |
| "this", | |
| "THIS", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword THROW = const Keyword( | |
| /* index = */ 145, | |
| "throw", | |
| "THROW", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword TRUE = const Keyword( | |
| /* index = */ 146, | |
| "true", | |
| "TRUE", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword TRY = const Keyword( | |
| /* index = */ 147, | |
| "try", | |
| "TRY", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword TYPEDEF = const Keyword( | |
| /* index = */ 148, | |
| "typedef", | |
| "TYPEDEF", | |
| KeywordStyle.builtIn, | |
| isTopLevelKeyword: true, | |
| ); | |
| static const Keyword VAR = const Keyword( | |
| /* index = */ 149, | |
| "var", | |
| "VAR", | |
| KeywordStyle.reserved, | |
| isModifier: true, | |
| ); | |
| static const Keyword VOID = const Keyword( | |
| /* index = */ 150, | |
| "void", | |
| "VOID", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword WHEN = const Keyword( | |
| /* index = */ 151, | |
| "when", | |
| 'WHEN', | |
| KeywordStyle.pseudo, | |
| ); | |
| static const Keyword WHILE = const Keyword( | |
| /* index = */ 152, | |
| "while", | |
| "WHILE", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword WITH = const Keyword( | |
| /* index = */ 153, | |
| "with", | |
| "WITH", | |
| KeywordStyle.reserved, | |
| ); | |
| static const Keyword YIELD = const Keyword( | |
| /* index = */ 154, | |
| "yield", | |
| "YIELD", | |
| KeywordStyle.pseudo, | |
| ); | |
| static const List<Keyword> values = const <Keyword>[ | |
| ABSTRACT, | |
| AS, | |
| ASSERT, | |
| ASYNC, | |
| AUGMENT, | |
| AWAIT, | |
| BASE, | |
| BREAK, | |
| CASE, | |
| CATCH, | |
| CLASS, | |
| CONST, | |
| CONTINUE, | |
| COVARIANT, | |
| DEFAULT, | |
| DEFERRED, | |
| DO, | |
| DYNAMIC, | |
| ELSE, | |
| ENUM, | |
| EXPORT, | |
| EXTENDS, | |
| EXTENSION, | |
| EXTERNAL, | |
| FACTORY, | |
| FALSE, | |
| FINAL, | |
| FINALLY, | |
| FOR, | |
| FUNCTION, | |
| GET, | |
| HIDE, | |
| IF, | |
| IMPLEMENTS, | |
| IMPORT, | |
| IN, | |
| INOUT, | |
| INTERFACE, | |
| IS, | |
| LATE, | |
| LIBRARY, | |
| MIXIN, | |
| NATIVE, | |
| NEW, | |
| NULL, | |
| OF, | |
| ON, | |
| OPERATOR, | |
| OUT, | |
| PART, | |
| PATCH, | |
| REQUIRED, | |
| RETHROW, | |
| RETURN, | |
| SEALED, | |
| SET, | |
| SHOW, | |
| SOURCE, | |
| STATIC, | |
| SUPER, | |
| SWITCH, | |
| SYNC, | |
| THIS, | |
| THROW, | |
| TRUE, | |
| TRY, | |
| TYPEDEF, | |
| VAR, | |
| VOID, | |
| WHEN, | |
| WHILE, | |
| WITH, | |
| YIELD, | |
| ]; | |
| /** | |
| * A table mapping the lexemes of keywords to the corresponding keyword. | |
| */ | |
| static final Map<String, Keyword> keywords = _createKeywordMap(); | |
| final KeywordStyle keywordStyle; | |
| /** | |
| * Initialize a newly created keyword. | |
| */ | |
| const Keyword( | |
| int index, | |
| String lexeme, | |
| String name, | |
| this.keywordStyle, { | |
| bool isModifier = false, | |
| bool isTopLevelKeyword = false, | |
| int precedence = NO_PRECEDENCE, | |
| }) : super( | |
| index, | |
| lexeme, | |
| name, | |
| precedence, | |
| KEYWORD_TOKEN, | |
| isModifier: isModifier, | |
| isTopLevelKeyword: isTopLevelKeyword, | |
| ); | |
| @override | |
| bool get isBuiltIn => keywordStyle == KeywordStyle.builtIn; | |
| @override | |
| bool get isPseudo => keywordStyle == KeywordStyle.pseudo; | |
| bool get isBuiltInOrPseudo => isBuiltIn || isPseudo; | |
| @override | |
| bool get isReservedWord => keywordStyle == KeywordStyle.reserved; | |
| /** | |
| * The name of the keyword type. | |
| */ | |
| @override | |
| String get name => lexeme.toUpperCase(); | |
| @override | |
| String toString() => name; | |
| /** | |
| * Create a table mapping the lexemes of keywords to the corresponding keyword | |
| * and return the table that was created. | |
| */ | |
| static Map<String, Keyword> _createKeywordMap() { | |
| LinkedHashMap<String, Keyword> result = | |
| new LinkedHashMap<String, Keyword>(); | |
| for (Keyword keyword in values) { | |
| result[keyword.lexeme] = keyword; | |
| } | |
| return result; | |
| } | |
| } | |
| /** | |
| * A token representing a keyword in the language. | |
| */ | |
| class KeywordToken extends SimpleToken { | |
| @override | |
| Keyword get keyword => type as Keyword; | |
| /** | |
| * Initialize a newly created token to represent the given [keyword] at the | |
| * given [offset]. | |
| */ | |
| KeywordToken(super.keyword, super.offset, [super.precedingComment]); | |
| @override | |
| bool get isIdentifier => keyword.isPseudo || keyword.isBuiltIn; | |
| @override | |
| bool get isKeyword => true; | |
| @override | |
| bool get isKeywordOrIdentifier => true; | |
| @override | |
| Object value() => keyword; | |
| } | |
| /** | |
| * A specialized comment token representing a language version | |
| * (e.g. '// @dart = 2.1'). | |
| */ | |
| @AnalyzerPublicApi(message: 'exported by package:analyzer/dart/ast/token.dart') | |
| class LanguageVersionToken extends CommentToken { | |
| /** | |
| * The major language version. | |
| */ | |
| final int major; | |
| /** | |
| * The minor language version. | |
| */ | |
| final int minor; | |
| LanguageVersionToken.from(String text, int offset, this.major, this.minor) | |
| : super(TokenType.SINGLE_LINE_COMMENT, text, offset); | |
| } | |
| /** | |
| * A token that was scanned from the input. Each token knows which tokens | |
| * precede and follow it, acting as a link in a doubly linked list of tokens. | |
| */ | |
| @AnalyzerPublicApi( | |
| message: 'exposed by CommentToken.parent and StringToken (superclass)', | |
| ) | |
| class SimpleToken extends SyntacticEntity implements Token { | |
| /** | |
| * The type of the token. | |
| */ | |
| @override | |
| TokenType get type => _tokenTypesByIndex[_typeAndOffset & 0xff]; | |
| /** | |
| * The index of the type. | |
| */ | |
| @override | |
| int get typeIndex => _typeAndOffset & 0xff; | |
| /** | |
| * The offset from the beginning of the file to the first character in the | |
| * token. | |
| */ | |
| @override | |
| int get offset => (_typeAndOffset >> 8) - 1; | |
| /** | |
| * Set the offset from the beginning of the file to the first character in | |
| * the token to the given [offset]. | |
| */ | |
| @override | |
| void set offset(int value) { | |
| assert(_tokenTypesByIndex.length == 256); | |
| // See https://github.com/dart-lang/sdk/issues/50048 for details. | |
| assert(value >= -1); | |
| _typeAndOffset = ((value + 1) << 8) | (_typeAndOffset & 0xff); | |
| } | |
| /** | |
| * The previous token in the token stream. | |
| */ | |
| @override | |
| Token? previous; | |
| @override | |
| Token? next; | |
| /** | |
| * The first comment in the list of comments that precede this token. | |
| */ | |
| CommentToken? _precedingComment; | |
| /** | |
| * The combined encoding of token type and offset. | |
| */ | |
| int _typeAndOffset; | |
| /** | |
| * Initialize a newly created token to have the given [type] and [offset]. | |
| */ | |
| @pragma('vm:prefer-inline') | |
| SimpleToken(TokenType type, int offset, [this._precedingComment]) | |
| : _typeAndOffset = (((offset + 1) << 8) | type.index) { | |
| // See https://github.com/dart-lang/sdk/issues/50048 for details. | |
| assert(offset >= -1); | |
| // Assert the encoding of the [type] is fully reversible. | |
| assert(type.index < 256 && _tokenTypesByIndex.length == 256); | |
| assert(identical(offset, this.offset)); | |
| assert(identical(type, this.type), '$type != ${this.type}'); | |
| _setCommentParent(_precedingComment); | |
| } | |
| @override | |
| int get charCount => length; | |
| @override | |
| int get charOffset => offset; | |
| @override | |
| int get charEnd => end; | |
| @override | |
| Token? get beforeSynthetic => null; | |
| @override | |
| set beforeSynthetic(Token? previous) { | |
| // ignored | |
| } | |
| @override | |
| int get end => offset + length; | |
| @override | |
| Token? get endGroup => null; | |
| @override | |
| bool get isEof => type == TokenType.EOF; | |
| @override | |
| bool get isIdentifier => false; | |
| @override | |
| bool get isKeyword => false; | |
| @override | |
| bool get isKeywordOrIdentifier => isIdentifier; | |
| @override | |
| bool get isModifier => type.isModifier; | |
| @override | |
| bool get isOperator => type.isOperator; | |
| @override | |
| bool get isSynthetic => length == 0; | |
| @override | |
| bool get isTopLevelKeyword => type.isTopLevelKeyword; | |
| @override | |
| bool get isUserDefinableOperator => type.isUserDefinableOperator; | |
| @override | |
| Keyword? get keyword => null; | |
| @override | |
| int get kind => type.kind; | |
| @override | |
| int get length => lexeme.length; | |
| @override | |
| String get lexeme => type.lexeme; | |
| @override | |
| CommentToken? get precedingComments => _precedingComment; | |
| void set precedingComments(CommentToken? comment) { | |
| _precedingComment = comment; | |
| _setCommentParent(_precedingComment); | |
| } | |
| @override | |
| String? get stringValue => type.stringValue; | |
| @override | |
| bool matchesAny(List<TokenType> types) { | |
| // [type] is a getter that accesses [_tokenTypesByIndex]: | |
| TokenType type = this.type; | |
| for (TokenType t in types) { | |
| if (type == t) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| @override | |
| Token setNext(Token token) { | |
| next = token; | |
| token.previous = this; | |
| token.beforeSynthetic = this; | |
| return token; | |
| } | |
| @override | |
| Token? setNextWithoutSettingPrevious(Token? token) { | |
| next = token; | |
| return token; | |
| } | |
| @override | |
| String toString() => lexeme; | |
| @override | |
| Object value() => lexeme; | |
| /** | |
| * Sets the `parent` property to `this` for the given [comment] and all the | |
| * next tokens. | |
| */ | |
| @pragma("vm:prefer-inline") | |
| void _setCommentParent(CommentToken? comment) { | |
| while (comment != null) { | |
| comment.parent = this; | |
| comment = comment.next as CommentToken?; | |
| } | |
| } | |
| } | |
| /** | |
| * A token whose value is independent of it's type. | |
| */ | |
| @AnalyzerPublicApi(message: 'exposed by CommentToken (superclass)') | |
| class StringToken extends SimpleToken { | |
| /** | |
| * The lexeme represented by this token. | |
| */ | |
| final String _value; | |
| /** | |
| * Initialize a newly created token to represent a token of the given [type] | |
| * with the given [value] at the given [offset]. | |
| */ | |
| StringToken(super.type, String value, super.offset, [super.precedingComment]) | |
| : _value = StringUtilities.intern(value); | |
| @override | |
| bool get isIdentifier => kind == IDENTIFIER_TOKEN; | |
| @override | |
| String get lexeme => _value; | |
| @override | |
| String value() => _value; | |
| } | |
| /** | |
| * A synthetic begin token. | |
| */ | |
| class SyntheticBeginToken extends BeginToken { | |
| /** | |
| * Initialize a newly created token to have the given [type] at the given | |
| * [offset]. | |
| */ | |
| SyntheticBeginToken(super.type, super.offset, [super.precedingComment]); | |
| @override | |
| Token? beforeSynthetic; | |
| @override | |
| bool get isSynthetic => true; | |
| @override | |
| int get length => 0; | |
| } | |
| /** | |
| * A synthetic keyword token. | |
| */ | |
| class SyntheticKeywordToken extends KeywordToken { | |
| /** | |
| * Initialize a newly created token to represent the given [keyword] at the | |
| * given [offset]. | |
| */ | |
| SyntheticKeywordToken(super.keyword, super.offset); | |
| @override | |
| Token? beforeSynthetic; | |
| @override | |
| int get length => 0; | |
| } | |
| /** | |
| * A token whose value is independent of it's type. | |
| */ | |
| class SyntheticStringToken extends StringToken { | |
| final int? _length; | |
| /** | |
| * Initialize a newly created token to represent a token of the given [type] | |
| * with the given [value] at the given [offset]. If the [length] is | |
| * not specified, then it defaults to the length of [value]. | |
| */ | |
| SyntheticStringToken(super.type, super.value, super.offset, [this._length]); | |
| @override | |
| Token? beforeSynthetic; | |
| @override | |
| bool get isSynthetic => true; | |
| @override | |
| int get length => _length ?? super.length; | |
| } | |
| /** | |
| * A synthetic token. | |
| */ | |
| class SyntheticToken extends SimpleToken { | |
| SyntheticToken(super.type, super.offset); | |
| @override | |
| Token? beforeSynthetic; | |
| @override | |
| bool get isSynthetic => true; | |
| @override | |
| int get length => 0; | |
| } | |
| /// A token used to replace another token in the stream, while still keeping the | |
| /// old token around (in [replacedToken]). Automatically sets the offset and | |
| /// precedingComments from the data available on [replacedToken]. | |
| class ReplacementToken extends SyntheticToken { | |
| /// The token that this token replaces. This will normally be the token | |
| /// representing what the user actually wrote. | |
| final Token replacedToken; | |
| ReplacementToken(TokenType type, this.replacedToken) | |
| : super(type, replacedToken.offset) { | |
| precedingComments = replacedToken.precedingComments; | |
| } | |
| @override | |
| Token? beforeSynthetic; | |
| @override | |
| bool get isSynthetic => true; | |
| @override | |
| int get length => 0; | |
| } | |
| /** | |
| * A token that was scanned from the input. Each token knows which tokens | |
| * precede and follow it, acting as a link in a doubly linked list of tokens. | |
| * | |
| * Clients may not extend, implement or mix-in this class. | |
| */ | |
| @AnalyzerPublicApi(message: 'exported by package:analyzer/dart/ast/token.dart') | |
| abstract class Token implements SyntacticEntity { | |
| /** | |
| * Initialize a newly created token to have the given [type] and [offset]. | |
| */ | |
| factory Token(TokenType type, int offset, [CommentToken? precedingComment]) = | |
| SimpleToken; | |
| /** | |
| * Initialize a newly created end-of-file token to have the given [offset]. | |
| */ | |
| factory Token.eof(int offset, [CommentToken? precedingComments]) { | |
| Token eof = new SimpleToken(TokenType.EOF, offset, precedingComments); | |
| // EOF points to itself so there's always infinite look-ahead. | |
| eof.previous = eof; | |
| eof.next = eof; | |
| return eof; | |
| } | |
| /** | |
| * The number of characters parsed by this token. | |
| */ | |
| int get charCount; | |
| /** | |
| * The character offset of the start of this token within the source text. | |
| */ | |
| int get charOffset; | |
| /** | |
| * The character offset of the end of this token within the source text. | |
| */ | |
| int get charEnd; | |
| /** | |
| * The token before this synthetic token, | |
| * or `null` if this is not a synthetic `)`, `]`, `}`, or `>` token. | |
| */ | |
| Token? get beforeSynthetic; | |
| /** | |
| * Set token before this synthetic `)`, `]`, `}`, or `>` token, | |
| * and ignored otherwise. | |
| */ | |
| set beforeSynthetic(Token? previous); | |
| @override | |
| int get end; | |
| /** | |
| * The token that corresponds to this token, or `null` if this token is not | |
| * the first of a pair of matching tokens (such as parentheses). | |
| */ | |
| Token? get endGroup => null; | |
| /** | |
| * Return `true` if this token represents an end of file. | |
| */ | |
| bool get isEof; | |
| /** | |
| * True if this token is an identifier. Some keywords allowed as identifiers, | |
| * see implementation in [KeywordToken]. | |
| */ | |
| bool get isIdentifier; | |
| /** | |
| * True if this token is a keyword. Some keywords allowed as identifiers, | |
| * see implementation in [KeywordToken]. | |
| */ | |
| bool get isKeyword; | |
| /** | |
| * True if this token is a keyword or an identifier. | |
| */ | |
| bool get isKeywordOrIdentifier; | |
| /** | |
| * Return `true` if this token is a modifier such as `abstract` or `const`. | |
| */ | |
| bool get isModifier; | |
| /** | |
| * Return `true` if this token represents an operator. | |
| */ | |
| bool get isOperator; | |
| /** | |
| * Return `true` if this token is a synthetic token. A synthetic token is a | |
| * token that was introduced by the parser in order to recover from an error | |
| * in the code. | |
| */ | |
| bool get isSynthetic; | |
| /** | |
| * Return `true` if this token is a keyword starting a top level declaration | |
| * such as `class`, `enum`, `import`, etc. | |
| */ | |
| bool get isTopLevelKeyword; | |
| /** | |
| * Return `true` if this token represents an operator that can be defined by | |
| * users. | |
| */ | |
| bool get isUserDefinableOperator; | |
| /** | |
| * Return the keyword, if a keyword token, or `null` otherwise. | |
| */ | |
| Keyword? get keyword; | |
| /** | |
| * The kind enum of this token as determined by its [type]. | |
| */ | |
| int get kind; | |
| @override | |
| int get length; | |
| /** | |
| * Return the lexeme that represents this token. | |
| * | |
| * For [StringToken]s the [lexeme] includes the quotes, explicit escapes, etc. | |
| */ | |
| String get lexeme; | |
| /** | |
| * Return the next token in the token stream. | |
| */ | |
| Token? get next; | |
| /** | |
| * Return the next token in the token stream. | |
| */ | |
| void set next(Token? next); | |
| @override | |
| int get offset; | |
| /** | |
| * Set the offset from the beginning of the file to the first character in | |
| * the token to the given [offset]. | |
| */ | |
| void set offset(int offset); | |
| /** | |
| * Return the first comment in the list of comments that precede this token, | |
| * or `null` if there are no comments preceding this token. Additional | |
| * comments can be reached by following the token stream using [next] until | |
| * `null` is returned. | |
| * | |
| * For example, if the original contents were `/* one */ /* two */ id`, then | |
| * the first preceding comment token will have a lexeme of `/* one */` and | |
| * the next comment token will have a lexeme of `/* two */`. | |
| */ | |
| CommentToken? get precedingComments; | |
| /** | |
| * Return the previous token in the token stream. | |
| */ | |
| Token? get previous; | |
| /** | |
| * Set the previous token in the token stream to the given [token]. | |
| */ | |
| void set previous(Token? token); | |
| /** | |
| * For symbol and keyword tokens, returns the string value represented by this | |
| * token. For [StringToken]s this method returns [:null:]. | |
| * | |
| * For symbol [Token]s and [KeywordToken]s, the string value is a compile-time | |
| * constant originating in the [TokenType] or in the [Keyword] instance. | |
| * This allows testing for keywords and symbols using [:identical:], e.g., | |
| * [:identical('class', token.value):]. | |
| * | |
| * Note that returning [:null:] for string tokens is important to identify | |
| * symbols and keywords, we cannot use [lexeme] instead. The string literal | |
| * "$a($b" | |
| * produces ..., SymbolToken($), StringToken(a), StringToken((), ... | |
| * | |
| * After parsing the identifier 'a', the parser tests for a function | |
| * declaration using [:identical(next.stringValue, '('):], which (rightfully) | |
| * returns false because stringValue returns [:null:]. | |
| */ | |
| String? get stringValue; | |
| /** | |
| * Return the type of the token. | |
| */ | |
| TokenType get type; | |
| /** | |
| * Return the index of the type of the token. | |
| */ | |
| int get typeIndex; | |
| /** | |
| * Return `true` if this token has any one of the given [types]. | |
| */ | |
| bool matchesAny(List<TokenType> types); | |
| /** | |
| * Set the next token in the token stream to the given [token]. This has the | |
| * side-effect of setting this token to be the previous token for the given | |
| * token. Return the token that was passed in. | |
| */ | |
| Token setNext(Token token); | |
| /** | |
| * Set the next token in the token stream to the given token without changing | |
| * which token is the previous token for the given token. Return the token | |
| * that was passed in. | |
| */ | |
| Token? setNextWithoutSettingPrevious(Token? token); | |
| /** | |
| * Returns a textual representation of this token to be used for debugging | |
| * purposes. The resulting string might contain information about the | |
| * structure of the token, for example 'StringToken(foo)' for the identifier | |
| * token 'foo'. | |
| * | |
| * Use [lexeme] for the text actually parsed by the token. | |
| */ | |
| @override | |
| String toString(); | |
| /** | |
| * Return the value of this token. For keyword tokens, this is the keyword | |
| * associated with the token, for other tokens it is the lexeme associated | |
| * with the token. | |
| */ | |
| Object value(); | |
| /** | |
| * Compare the given tokens to find the token that appears first in the | |
| * source being parsed. That is, return the left-most of all of the tokens. | |
| * Return the token with the smallest offset, or `null` if all of the | |
| * tokens are `null`. | |
| */ | |
| static Token? lexicallyFirst([ | |
| Token? t1, | |
| Token? t2, | |
| Token? t3, | |
| Token? t4, | |
| Token? t5, | |
| ]) { | |
| Token? result = t1; | |
| if (result == null || t2 != null && t2.offset < result.offset) { | |
| result = t2; | |
| } | |
| if (result == null || t3 != null && t3.offset < result.offset) { | |
| result = t3; | |
| } | |
| if (result == null || t4 != null && t4.offset < result.offset) { | |
| result = t4; | |
| } | |
| if (result == null || t5 != null && t5.offset < result.offset) { | |
| result = t5; | |
| } | |
| return result; | |
| } | |
| } | |
| /** | |
| * The classes (or groups) of tokens with a similar use. | |
| */ | |
| class TokenClass { | |
| /** | |
| * A value used to indicate that the token type is not part of any specific | |
| * class of token. | |
| */ | |
| static const TokenClass NO_CLASS = const TokenClass('NO_CLASS'); | |
| /** | |
| * A value used to indicate that the token type is an additive operator. | |
| */ | |
| static const TokenClass ADDITIVE_OPERATOR = const TokenClass( | |
| 'ADDITIVE_OPERATOR', | |
| ADDITIVE_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is an assignment operator. | |
| */ | |
| static const TokenClass ASSIGNMENT_OPERATOR = const TokenClass( | |
| 'ASSIGNMENT_OPERATOR', | |
| ASSIGNMENT_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is a bitwise-and operator. | |
| */ | |
| static const TokenClass BITWISE_AND_OPERATOR = const TokenClass( | |
| 'BITWISE_AND_OPERATOR', | |
| BITWISE_AND_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is a bitwise-or operator. | |
| */ | |
| static const TokenClass BITWISE_OR_OPERATOR = const TokenClass( | |
| 'BITWISE_OR_OPERATOR', | |
| BITWISE_OR_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is a bitwise-xor operator. | |
| */ | |
| static const TokenClass BITWISE_XOR_OPERATOR = const TokenClass( | |
| 'BITWISE_XOR_OPERATOR', | |
| BITWISE_XOR_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is a cascade operator. | |
| */ | |
| static const TokenClass CASCADE_OPERATOR = const TokenClass( | |
| 'CASCADE_OPERATOR', | |
| CASCADE_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is a conditional operator. | |
| */ | |
| static const TokenClass CONDITIONAL_OPERATOR = const TokenClass( | |
| 'CONDITIONAL_OPERATOR', | |
| CONDITIONAL_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is an equality operator. | |
| */ | |
| static const TokenClass EQUALITY_OPERATOR = const TokenClass( | |
| 'EQUALITY_OPERATOR', | |
| EQUALITY_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is an if-null operator. | |
| */ | |
| static const TokenClass IF_NULL_OPERATOR = const TokenClass( | |
| 'IF_NULL_OPERATOR', | |
| IF_NULL_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is a logical-and operator. | |
| */ | |
| static const TokenClass LOGICAL_AND_OPERATOR = const TokenClass( | |
| 'LOGICAL_AND_OPERATOR', | |
| LOGICAL_AND_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is a logical-or operator. | |
| */ | |
| static const TokenClass LOGICAL_OR_OPERATOR = const TokenClass( | |
| 'LOGICAL_OR_OPERATOR', | |
| LOGICAL_OR_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is a multiplicative operator. | |
| */ | |
| static const TokenClass MULTIPLICATIVE_OPERATOR = const TokenClass( | |
| 'MULTIPLICATIVE_OPERATOR', | |
| MULTIPLICATIVE_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is a relational operator. | |
| */ | |
| static const TokenClass RELATIONAL_OPERATOR = const TokenClass( | |
| 'RELATIONAL_OPERATOR', | |
| RELATIONAL_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is a shift operator. | |
| */ | |
| static const TokenClass SHIFT_OPERATOR = const TokenClass( | |
| 'SHIFT_OPERATOR', | |
| SHIFT_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is a unary operator. | |
| */ | |
| static const TokenClass UNARY_POSTFIX_OPERATOR = const TokenClass( | |
| 'UNARY_POSTFIX_OPERATOR', | |
| POSTFIX_PRECEDENCE, | |
| ); | |
| /** | |
| * A value used to indicate that the token type is a unary operator. | |
| */ | |
| static const TokenClass UNARY_PREFIX_OPERATOR = const TokenClass( | |
| 'UNARY_PREFIX_OPERATOR', | |
| PREFIX_PRECEDENCE, | |
| ); | |
| /** | |
| * The name of the token class. | |
| */ | |
| final String name; | |
| /** | |
| * The precedence of tokens of this class, or `0` if the such tokens do not | |
| * represent an operator. | |
| */ | |
| final int precedence; | |
| /** | |
| * Initialize a newly created class of tokens to have the given [name] and | |
| * [precedence]. | |
| */ | |
| const TokenClass(this.name, [this.precedence = NO_PRECEDENCE]); | |
| @override | |
| String toString() => name; | |
| } | |
| /** | |
| * The types of tokens that can be returned by the scanner. | |
| * | |
| * Clients may not extend, implement or mix-in this class. | |
| */ | |
| @AnalyzerPublicApi(message: 'exported by package:analyzer/dart/ast/token.dart') | |
| class TokenType { | |
| static const TokenType UNUSED = const TokenType( | |
| /* index = */ 255, | |
| '', | |
| 'UNUSED', | |
| NO_PRECEDENCE, | |
| EOF_TOKEN, | |
| ); | |
| /** | |
| * The type of the token that marks the start or end of the input. | |
| */ | |
| static const TokenType EOF = const TokenType( | |
| /* index = */ 0, | |
| '', | |
| 'EOF', | |
| NO_PRECEDENCE, | |
| EOF_TOKEN, | |
| ); | |
| static const TokenType DOUBLE = const TokenType( | |
| /* index = */ 1, | |
| 'double', | |
| 'DOUBLE', | |
| NO_PRECEDENCE, | |
| DOUBLE_TOKEN, | |
| stringValueShouldBeNull: true, | |
| ); | |
| static const TokenType DOUBLE_WITH_SEPARATORS = const TokenType( | |
| /* index = */ 2, | |
| 'double', | |
| 'DOUBLE_WITH_SEPARATORS', | |
| NO_PRECEDENCE, | |
| DOUBLE_TOKEN, | |
| stringValueShouldBeNull: true, | |
| ); | |
| static const TokenType HEXADECIMAL = const TokenType( | |
| /* index = */ 3, | |
| 'hexadecimal', | |
| 'HEXADECIMAL', | |
| NO_PRECEDENCE, | |
| HEXADECIMAL_TOKEN, | |
| stringValueShouldBeNull: true, | |
| ); | |
| static const TokenType HEXADECIMAL_WITH_SEPARATORS = const TokenType( | |
| /* index = */ 4, | |
| 'hexadecimal', | |
| 'HEXADECIMAL_WITH_SEPARATORS', | |
| NO_PRECEDENCE, | |
| HEXADECIMAL_TOKEN, | |
| stringValueShouldBeNull: true, | |
| ); | |
| static const TokenType IDENTIFIER = const TokenType( | |
| /* index = */ 5, | |
| 'identifier', | |
| 'IDENTIFIER', | |
| NO_PRECEDENCE, | |
| IDENTIFIER_TOKEN, | |
| stringValueShouldBeNull: true, | |
| ); | |
| static const TokenType INT = const TokenType( | |
| /* index = */ 6, | |
| 'int', | |
| 'INT', | |
| NO_PRECEDENCE, | |
| INT_TOKEN, | |
| stringValueShouldBeNull: true, | |
| ); | |
| static const TokenType INT_WITH_SEPARATORS = const TokenType( | |
| /* index = */ 7, | |
| 'int', | |
| 'INT_WITH_SEPARATORS', | |
| NO_PRECEDENCE, | |
| INT_TOKEN, | |
| stringValueShouldBeNull: true, | |
| ); | |
| static const TokenType MULTI_LINE_COMMENT = const TokenType( | |
| /* index = */ 8, | |
| 'comment', | |
| 'MULTI_LINE_COMMENT', | |
| NO_PRECEDENCE, | |
| COMMENT_TOKEN, | |
| stringValueShouldBeNull: true, | |
| ); | |
| static const TokenType SCRIPT_TAG = const TokenType( | |
| /* index = */ 9, | |
| 'script', | |
| 'SCRIPT_TAG', | |
| NO_PRECEDENCE, | |
| SCRIPT_TOKEN, | |
| ); | |
| static const TokenType SINGLE_LINE_COMMENT = const TokenType( | |
| /* index = */ 10, | |
| 'comment', | |
| 'SINGLE_LINE_COMMENT', | |
| NO_PRECEDENCE, | |
| COMMENT_TOKEN, | |
| stringValueShouldBeNull: true, | |
| ); | |
| static const TokenType STRING = const TokenType( | |
| /* index = */ 11, | |
| 'string', | |
| 'STRING', | |
| NO_PRECEDENCE, | |
| STRING_TOKEN, | |
| stringValueShouldBeNull: true, | |
| ); | |
| static const TokenType AMPERSAND = const TokenType( | |
| /* index = */ 12, | |
| '&', | |
| 'AMPERSAND', | |
| BITWISE_AND_PRECEDENCE, | |
| AMPERSAND_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType AMPERSAND_AMPERSAND = const TokenType( | |
| /* index = */ 13, | |
| '&&', | |
| 'AMPERSAND_AMPERSAND', | |
| LOGICAL_AND_PRECEDENCE, | |
| AMPERSAND_AMPERSAND_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| ); | |
| // This is not yet part of the language and not supported by the scanner. | |
| static const TokenType AMPERSAND_AMPERSAND_EQ = const TokenType( | |
| /* index = */ 14, | |
| '&&=', | |
| 'AMPERSAND_AMPERSAND_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| AMPERSAND_AMPERSAND_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.AMPERSAND_AMPERSAND, | |
| isOperator: true, | |
| ); | |
| static const TokenType AMPERSAND_EQ = const TokenType( | |
| /* index = */ 15, | |
| '&=', | |
| 'AMPERSAND_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| AMPERSAND_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.AMPERSAND, | |
| isOperator: true, | |
| ); | |
| static const TokenType AT = const TokenType( | |
| /* index = */ 16, | |
| '@', | |
| 'AT', | |
| NO_PRECEDENCE, | |
| AT_TOKEN, | |
| ); | |
| static const TokenType BANG = const TokenType( | |
| /* index = */ 17, | |
| '!', | |
| 'BANG', | |
| PREFIX_PRECEDENCE, | |
| BANG_TOKEN, | |
| isOperator: true, | |
| ); | |
| static const TokenType BANG_EQ = const TokenType( | |
| /* index = */ 18, | |
| '!=', | |
| 'BANG_EQ', | |
| EQUALITY_PRECEDENCE, | |
| BANG_EQ_TOKEN, | |
| isOperator: true, | |
| ); | |
| static const TokenType BANG_EQ_EQ = const TokenType( | |
| /* index = */ 19, | |
| '!==', | |
| 'BANG_EQ_EQ', | |
| EQUALITY_PRECEDENCE, | |
| BANG_EQ_EQ_TOKEN, | |
| ); | |
| static const TokenType BAR = const TokenType( | |
| /* index = */ 20, | |
| '|', | |
| 'BAR', | |
| BITWISE_OR_PRECEDENCE, | |
| BAR_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType BAR_BAR = const TokenType( | |
| /* index = */ 21, | |
| '||', | |
| 'BAR_BAR', | |
| LOGICAL_OR_PRECEDENCE, | |
| BAR_BAR_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| ); | |
| // This is not yet part of the language and not supported by the scanner. | |
| static const TokenType BAR_BAR_EQ = const TokenType( | |
| /* index = */ 22, | |
| '||=', | |
| 'BAR_BAR_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| BAR_BAR_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.BAR_BAR, | |
| isOperator: true, | |
| ); | |
| static const TokenType BAR_EQ = const TokenType( | |
| /* index = */ 23, | |
| '|=', | |
| 'BAR_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| BAR_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.BAR, | |
| isOperator: true, | |
| ); | |
| static const TokenType COLON = const TokenType( | |
| /* index = */ 24, | |
| ':', | |
| 'COLON', | |
| NO_PRECEDENCE, | |
| COLON_TOKEN, | |
| ); | |
| static const TokenType COMMA = const TokenType( | |
| /* index = */ 25, | |
| ',', | |
| 'COMMA', | |
| NO_PRECEDENCE, | |
| COMMA_TOKEN, | |
| ); | |
| static const TokenType CARET = const TokenType( | |
| /* index = */ 26, | |
| '^', | |
| 'CARET', | |
| BITWISE_XOR_PRECEDENCE, | |
| CARET_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType CARET_EQ = const TokenType( | |
| /* index = */ 27, | |
| '^=', | |
| 'CARET_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| CARET_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.CARET, | |
| isOperator: true, | |
| ); | |
| static const TokenType CLOSE_CURLY_BRACKET = const TokenType( | |
| /* index = */ 28, | |
| '}', | |
| 'CLOSE_CURLY_BRACKET', | |
| NO_PRECEDENCE, | |
| CLOSE_CURLY_BRACKET_TOKEN, | |
| ); | |
| static const TokenType CLOSE_PAREN = const TokenType( | |
| /* index = */ 29, | |
| ')', | |
| 'CLOSE_PAREN', | |
| NO_PRECEDENCE, | |
| CLOSE_PAREN_TOKEN, | |
| ); | |
| static const TokenType CLOSE_SQUARE_BRACKET = const TokenType( | |
| /* index = */ 30, | |
| ']', | |
| 'CLOSE_SQUARE_BRACKET', | |
| NO_PRECEDENCE, | |
| CLOSE_SQUARE_BRACKET_TOKEN, | |
| ); | |
| static const TokenType EQ = const TokenType( | |
| /* index = */ 31, | |
| '=', | |
| 'EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| EQ_TOKEN, | |
| isOperator: true, | |
| ); | |
| static const TokenType EQ_EQ = const TokenType( | |
| /* index = */ 32, | |
| '==', | |
| 'EQ_EQ', | |
| EQUALITY_PRECEDENCE, | |
| EQ_EQ_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| /// The `===` operator is not supported in the Dart language | |
| /// but is parsed as such by the scanner to support better recovery | |
| /// when a JavaScript code snippet is pasted into a Dart file. | |
| static const TokenType EQ_EQ_EQ = const TokenType( | |
| /* index = */ 33, | |
| '===', | |
| 'EQ_EQ_EQ', | |
| EQUALITY_PRECEDENCE, | |
| EQ_EQ_EQ_TOKEN, | |
| ); | |
| static const TokenType FUNCTION = const TokenType( | |
| /* index = */ 34, | |
| '=>', | |
| 'FUNCTION', | |
| NO_PRECEDENCE, | |
| FUNCTION_TOKEN, | |
| ); | |
| static const TokenType GT = const TokenType( | |
| /* index = */ 35, | |
| '>', | |
| 'GT', | |
| RELATIONAL_PRECEDENCE, | |
| GT_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType GT_EQ = const TokenType( | |
| /* index = */ 36, | |
| '>=', | |
| 'GT_EQ', | |
| RELATIONAL_PRECEDENCE, | |
| GT_EQ_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType GT_GT = const TokenType( | |
| /* index = */ 37, | |
| '>>', | |
| 'GT_GT', | |
| SHIFT_PRECEDENCE, | |
| GT_GT_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType GT_GT_EQ = const TokenType( | |
| /* index = */ 38, | |
| '>>=', | |
| 'GT_GT_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| GT_GT_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.GT_GT, | |
| isOperator: true, | |
| ); | |
| static const TokenType GT_GT_GT = const TokenType( | |
| /* index = */ 39, | |
| '>>>', | |
| 'GT_GT_GT', | |
| SHIFT_PRECEDENCE, | |
| GT_GT_GT_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType GT_GT_GT_EQ = const TokenType( | |
| /* index = */ 40, | |
| '>>>=', | |
| 'GT_GT_GT_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| GT_GT_GT_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.GT_GT_GT, | |
| isOperator: true, | |
| ); | |
| static const TokenType HASH = const TokenType( | |
| /* index = */ 41, | |
| '#', | |
| 'HASH', | |
| NO_PRECEDENCE, | |
| HASH_TOKEN, | |
| ); | |
| static const TokenType INDEX = const TokenType( | |
| /* index = */ 42, | |
| '[]', | |
| 'INDEX', | |
| SELECTOR_PRECEDENCE, | |
| INDEX_TOKEN, | |
| isOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType INDEX_EQ = const TokenType( | |
| /* index = */ 43, | |
| '[]=', | |
| 'INDEX_EQ', | |
| NO_PRECEDENCE, | |
| INDEX_EQ_TOKEN, | |
| isOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType LT = const TokenType( | |
| /* index = */ 44, | |
| '<', | |
| 'LT', | |
| RELATIONAL_PRECEDENCE, | |
| LT_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType LT_EQ = const TokenType( | |
| /* index = */ 45, | |
| '<=', | |
| 'LT_EQ', | |
| RELATIONAL_PRECEDENCE, | |
| LT_EQ_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType LT_LT = const TokenType( | |
| /* index = */ 46, | |
| '<<', | |
| 'LT_LT', | |
| SHIFT_PRECEDENCE, | |
| LT_LT_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType LT_LT_EQ = const TokenType( | |
| /* index = */ 47, | |
| '<<=', | |
| 'LT_LT_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| LT_LT_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.LT_LT, | |
| isOperator: true, | |
| ); | |
| static const TokenType MINUS = const TokenType( | |
| /* index = */ 48, | |
| '-', | |
| 'MINUS', | |
| ADDITIVE_PRECEDENCE, | |
| MINUS_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType MINUS_EQ = const TokenType( | |
| /* index = */ 49, | |
| '-=', | |
| 'MINUS_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| MINUS_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.MINUS, | |
| isOperator: true, | |
| ); | |
| static const TokenType MINUS_MINUS = const TokenType( | |
| /* index = */ 50, | |
| '--', | |
| 'MINUS_MINUS', | |
| POSTFIX_PRECEDENCE, | |
| MINUS_MINUS_TOKEN, | |
| isOperator: true, | |
| ); | |
| static const TokenType OPEN_CURLY_BRACKET = const TokenType( | |
| /* index = */ 51, | |
| '{', | |
| 'OPEN_CURLY_BRACKET', | |
| NO_PRECEDENCE, | |
| OPEN_CURLY_BRACKET_TOKEN, | |
| ); | |
| static const TokenType OPEN_PAREN = const TokenType( | |
| /* index = */ 52, | |
| '(', | |
| 'OPEN_PAREN', | |
| SELECTOR_PRECEDENCE, | |
| OPEN_PAREN_TOKEN, | |
| ); | |
| static const TokenType OPEN_SQUARE_BRACKET = const TokenType( | |
| /* index = */ 53, | |
| '[', | |
| 'OPEN_SQUARE_BRACKET', | |
| SELECTOR_PRECEDENCE, | |
| OPEN_SQUARE_BRACKET_TOKEN, | |
| ); | |
| static const TokenType PERCENT = const TokenType( | |
| /* index = */ 54, | |
| '%', | |
| 'PERCENT', | |
| MULTIPLICATIVE_PRECEDENCE, | |
| PERCENT_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType PERCENT_EQ = const TokenType( | |
| /* index = */ 55, | |
| '%=', | |
| 'PERCENT_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| PERCENT_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.PERCENT, | |
| isOperator: true, | |
| ); | |
| static const TokenType PERIOD = const TokenType( | |
| /* index = */ 56, | |
| '.', | |
| 'PERIOD', | |
| SELECTOR_PRECEDENCE, | |
| PERIOD_TOKEN, | |
| ); | |
| static const TokenType PERIOD_PERIOD = const TokenType( | |
| /* index = */ 57, | |
| '..', | |
| 'PERIOD_PERIOD', | |
| CASCADE_PRECEDENCE, | |
| PERIOD_PERIOD_TOKEN, | |
| isOperator: true, | |
| ); | |
| static const TokenType PLUS = const TokenType( | |
| /* index = */ 58, | |
| '+', | |
| 'PLUS', | |
| ADDITIVE_PRECEDENCE, | |
| PLUS_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType PLUS_EQ = const TokenType( | |
| /* index = */ 59, | |
| '+=', | |
| 'PLUS_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| PLUS_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.PLUS, | |
| isOperator: true, | |
| ); | |
| static const TokenType PLUS_PLUS = const TokenType( | |
| /* index = */ 60, | |
| '++', | |
| 'PLUS_PLUS', | |
| POSTFIX_PRECEDENCE, | |
| PLUS_PLUS_TOKEN, | |
| isOperator: true, | |
| ); | |
| static const TokenType QUESTION = const TokenType( | |
| /* index = */ 61, | |
| '?', | |
| 'QUESTION', | |
| CONDITIONAL_PRECEDENCE, | |
| QUESTION_TOKEN, | |
| isOperator: true, | |
| ); | |
| static const TokenType QUESTION_PERIOD = const TokenType( | |
| /* index = */ 62, | |
| '?.', | |
| 'QUESTION_PERIOD', | |
| SELECTOR_PRECEDENCE, | |
| QUESTION_PERIOD_TOKEN, | |
| isOperator: true, | |
| ); | |
| static const TokenType QUESTION_QUESTION = const TokenType( | |
| /* index = */ 63, | |
| '??', | |
| 'QUESTION_QUESTION', | |
| IF_NULL_PRECEDENCE, | |
| QUESTION_QUESTION_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| ); | |
| static const TokenType QUESTION_QUESTION_EQ = const TokenType( | |
| /* index = */ 64, | |
| '??=', | |
| 'QUESTION_QUESTION_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| QUESTION_QUESTION_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.QUESTION_QUESTION, | |
| isOperator: true, | |
| ); | |
| static const TokenType SEMICOLON = const TokenType( | |
| /* index = */ 65, | |
| ';', | |
| 'SEMICOLON', | |
| NO_PRECEDENCE, | |
| SEMICOLON_TOKEN, | |
| ); | |
| static const TokenType SLASH = const TokenType( | |
| /* index = */ 66, | |
| '/', | |
| 'SLASH', | |
| MULTIPLICATIVE_PRECEDENCE, | |
| SLASH_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType SLASH_EQ = const TokenType( | |
| /* index = */ 67, | |
| '/=', | |
| 'SLASH_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| SLASH_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.SLASH, | |
| isOperator: true, | |
| ); | |
| static const TokenType STAR = const TokenType( | |
| /* index = */ 68, | |
| '*', | |
| 'STAR', | |
| MULTIPLICATIVE_PRECEDENCE, | |
| STAR_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType STAR_EQ = const TokenType( | |
| /* index = */ 69, | |
| '*=', | |
| 'STAR_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| STAR_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.STAR, | |
| isOperator: true, | |
| ); | |
| static const TokenType STRING_INTERPOLATION_EXPRESSION = const TokenType( | |
| /* index = */ 70, | |
| '\${', | |
| 'STRING_INTERPOLATION_EXPRESSION', | |
| NO_PRECEDENCE, | |
| STRING_INTERPOLATION_TOKEN, | |
| ); | |
| static const TokenType STRING_INTERPOLATION_IDENTIFIER = const TokenType( | |
| /* index = */ 71, | |
| '\$', | |
| 'STRING_INTERPOLATION_IDENTIFIER', | |
| NO_PRECEDENCE, | |
| STRING_INTERPOLATION_IDENTIFIER_TOKEN, | |
| ); | |
| static const TokenType TILDE = const TokenType( | |
| /* index = */ 72, | |
| '~', | |
| 'TILDE', | |
| PREFIX_PRECEDENCE, | |
| TILDE_TOKEN, | |
| isOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType TILDE_SLASH = const TokenType( | |
| /* index = */ 73, | |
| '~/', | |
| 'TILDE_SLASH', | |
| MULTIPLICATIVE_PRECEDENCE, | |
| TILDE_SLASH_TOKEN, | |
| isOperator: true, | |
| isBinaryOperator: true, | |
| isUserDefinableOperator: true, | |
| ); | |
| static const TokenType TILDE_SLASH_EQ = const TokenType( | |
| /* index = */ 74, | |
| '~/=', | |
| 'TILDE_SLASH_EQ', | |
| ASSIGNMENT_PRECEDENCE, | |
| TILDE_SLASH_EQ_TOKEN, | |
| binaryOperatorOfCompoundAssignment: TokenType.TILDE_SLASH, | |
| isOperator: true, | |
| ); | |
| static const TokenType BACKPING = const TokenType( | |
| /* index = */ 75, | |
| '`', | |
| 'BACKPING', | |
| NO_PRECEDENCE, | |
| BACKPING_TOKEN, | |
| ); | |
| static const TokenType BACKSLASH = const TokenType( | |
| /* index = */ 76, | |
| '\\', | |
| 'BACKSLASH', | |
| NO_PRECEDENCE, | |
| BACKSLASH_TOKEN, | |
| ); | |
| static const TokenType PERIOD_PERIOD_PERIOD = const TokenType( | |
| /* index = */ 77, | |
| '...', | |
| 'PERIOD_PERIOD_PERIOD', | |
| NO_PRECEDENCE, | |
| PERIOD_PERIOD_PERIOD_TOKEN, | |
| ); | |
| static const TokenType PERIOD_PERIOD_PERIOD_QUESTION = const TokenType( | |
| /* index = */ 78, | |
| '...?', | |
| 'PERIOD_PERIOD_PERIOD_QUESTION', | |
| NO_PRECEDENCE, | |
| PERIOD_PERIOD_PERIOD_QUESTION_TOKEN, | |
| ); | |
| static const TokenType QUESTION_PERIOD_PERIOD = const TokenType( | |
| /* index = */ 79, | |
| '?..', | |
| 'QUESTION_PERIOD_PERIOD', | |
| CASCADE_PRECEDENCE, | |
| QUESTION_PERIOD_PERIOD_TOKEN, | |
| ); | |
| static const TokenType AS = Keyword.AS; | |
| static const TokenType IS = Keyword.IS; | |
| /** | |
| * Token type used by error tokens. | |
| */ | |
| static const TokenType BAD_INPUT = const TokenType( | |
| /* index = */ 80, | |
| 'malformed input', | |
| 'BAD_INPUT', | |
| NO_PRECEDENCE, | |
| BAD_INPUT_TOKEN, | |
| stringValueShouldBeNull: true, | |
| ); | |
| /** | |
| * Token type used by synthetic tokens that are created during parser | |
| * recovery (non-analyzer use case). | |
| */ | |
| static const TokenType RECOVERY = const TokenType( | |
| /* index = */ 81, | |
| 'recovery', | |
| 'RECOVERY', | |
| NO_PRECEDENCE, | |
| RECOVERY_TOKEN, | |
| stringValueShouldBeNull: true, | |
| ); | |
| // TODO(danrubel): "all" is misleading | |
| // because this list does not include all TokenType instances. | |
| static const List<TokenType> all = const <TokenType>[ | |
| TokenType.EOF, | |
| TokenType.DOUBLE, | |
| TokenType.DOUBLE_WITH_SEPARATORS, | |
| TokenType.HEXADECIMAL, | |
| TokenType.HEXADECIMAL_WITH_SEPARATORS, | |
| TokenType.IDENTIFIER, | |
| TokenType.INT, | |
| TokenType.INT_WITH_SEPARATORS, | |
| TokenType.MULTI_LINE_COMMENT, | |
| TokenType.SCRIPT_TAG, | |
| TokenType.SINGLE_LINE_COMMENT, | |
| TokenType.STRING, | |
| TokenType.AMPERSAND, | |
| TokenType.AMPERSAND_AMPERSAND, | |
| TokenType.AMPERSAND_EQ, | |
| TokenType.AT, | |
| TokenType.BANG, | |
| TokenType.BANG_EQ, | |
| TokenType.BAR, | |
| TokenType.BAR_BAR, | |
| TokenType.BAR_EQ, | |
| TokenType.COLON, | |
| TokenType.COMMA, | |
| TokenType.CARET, | |
| TokenType.CARET_EQ, | |
| TokenType.CLOSE_CURLY_BRACKET, | |
| TokenType.CLOSE_PAREN, | |
| TokenType.CLOSE_SQUARE_BRACKET, | |
| TokenType.EQ, | |
| TokenType.EQ_EQ, | |
| TokenType.FUNCTION, | |
| TokenType.GT, | |
| TokenType.GT_EQ, | |
| TokenType.GT_GT, | |
| TokenType.GT_GT_EQ, | |
| TokenType.HASH, | |
| TokenType.INDEX, | |
| TokenType.INDEX_EQ, | |
| TokenType.LT, | |
| TokenType.LT_EQ, | |
| TokenType.LT_LT, | |
| TokenType.LT_LT_EQ, | |
| TokenType.MINUS, | |
| TokenType.MINUS_EQ, | |
| TokenType.MINUS_MINUS, | |
| TokenType.OPEN_CURLY_BRACKET, | |
| TokenType.OPEN_PAREN, | |
| TokenType.OPEN_SQUARE_BRACKET, | |
| TokenType.PERCENT, | |
| TokenType.PERCENT_EQ, | |
| TokenType.PERIOD, | |
| TokenType.PERIOD_PERIOD, | |
| TokenType.PLUS, | |
| TokenType.PLUS_EQ, | |
| TokenType.PLUS_PLUS, | |
| TokenType.QUESTION, | |
| TokenType.QUESTION_PERIOD, | |
| TokenType.QUESTION_QUESTION, | |
| TokenType.QUESTION_QUESTION_EQ, | |
| TokenType.SEMICOLON, | |
| TokenType.SLASH, | |
| TokenType.SLASH_EQ, | |
| TokenType.STAR, | |
| TokenType.STAR_EQ, | |
| TokenType.STRING_INTERPOLATION_EXPRESSION, | |
| TokenType.STRING_INTERPOLATION_IDENTIFIER, | |
| TokenType.TILDE, | |
| TokenType.TILDE_SLASH, | |
| TokenType.TILDE_SLASH_EQ, | |
| TokenType.BACKPING, | |
| TokenType.BACKSLASH, | |
| TokenType.PERIOD_PERIOD_PERIOD, | |
| TokenType.PERIOD_PERIOD_PERIOD_QUESTION, | |
| // TODO(danrubel): Should these be added to the "all" list? | |
| //TokenType.IS, | |
| //TokenType.AS, | |
| // These are not yet part of the language and not supported by the scanner: | |
| //TokenType.AMPERSAND_AMPERSAND_EQ, | |
| //TokenType.BAR_BAR_EQ, | |
| // Supported by the scanner but not part of the language | |
| //TokenType.BANG_EQ_EQ, | |
| //TokenType.EQ_EQ_EQ, | |
| // Used by synthetic tokens generated during recovery | |
| //TokenType.BAD_INPUT, | |
| //TokenType.RECOVERY, | |
| ]; | |
| /** | |
| * A unique index identifying this [TokenType]. | |
| */ | |
| final int index; | |
| /** | |
| * The binary operator that is invoked by this compound assignment operator, | |
| * or `null` otherwise. | |
| */ | |
| final TokenType? binaryOperatorOfCompoundAssignment; | |
| final int kind; | |
| /** | |
| * `true` if this token type represents a modifier | |
| * such as `abstract` or `const`. | |
| */ | |
| final bool isModifier; | |
| /** | |
| * `true` if this token type represents an operator. | |
| */ | |
| final bool isOperator; | |
| /** | |
| * `true` if this token type represents a binary operator. | |
| */ | |
| final bool isBinaryOperator; | |
| /** | |
| * `true` if this token type represents a keyword starting a top level | |
| * declaration such as `class`, `enum`, `import`, etc. | |
| */ | |
| final bool isTopLevelKeyword; | |
| /** | |
| * `true` if this token type represents an operator | |
| * that can be defined by users. | |
| */ | |
| final bool isUserDefinableOperator; | |
| /** | |
| * The lexeme that defines this type of token, | |
| * or `null` if there is more than one possible lexeme for this type of token. | |
| */ | |
| final String lexeme; | |
| /** | |
| * The name of the token type. | |
| */ | |
| final String name; | |
| /** | |
| * The precedence of this type of token, | |
| * or `0` if the token does not represent an operator. | |
| */ | |
| final int precedence; | |
| /** | |
| * See [Token.stringValue] for an explanation. | |
| */ | |
| final String? stringValue; | |
| const TokenType( | |
| this.index, | |
| this.lexeme, | |
| this.name, | |
| this.precedence, | |
| this.kind, { | |
| this.binaryOperatorOfCompoundAssignment, | |
| this.isBinaryOperator = false, | |
| this.isModifier = false, | |
| this.isOperator = false, | |
| this.isTopLevelKeyword = false, | |
| this.isUserDefinableOperator = false, | |
| bool stringValueShouldBeNull = false, | |
| }) : this.stringValue = stringValueShouldBeNull ? null : lexeme; | |
| /** | |
| * Return `true` if this type of token represents an additive operator. | |
| */ | |
| bool get isAdditiveOperator => precedence == ADDITIVE_PRECEDENCE; | |
| /** | |
| * Return `true` if this type of token represents an assignment operator. | |
| */ | |
| bool get isAssignmentOperator => precedence == ASSIGNMENT_PRECEDENCE; | |
| /** | |
| * Return `true` if this type of token represents an associative operator. An | |
| * associative operator is an operator for which the following equality is | |
| * true: `(a * b) * c == a * (b * c)`. In other words, if the result of | |
| * applying the operator to multiple operands does not depend on the order in | |
| * which those applications occur. | |
| * | |
| * Note: This method considers the logical-and and logical-or operators to be | |
| * associative, even though the order in which the application of those | |
| * operators can have an effect because evaluation of the right-hand operand | |
| * is conditional. | |
| */ | |
| bool get isAssociativeOperator => | |
| this == TokenType.AMPERSAND || | |
| this == TokenType.AMPERSAND_AMPERSAND || | |
| this == TokenType.BAR || | |
| this == TokenType.BAR_BAR || | |
| this == TokenType.CARET || | |
| this == TokenType.PLUS || | |
| this == TokenType.STAR; | |
| /** | |
| * A flag indicating whether the keyword is a "built-in" identifier. | |
| */ | |
| bool get isBuiltIn => false; | |
| /// A flag indicating whether the keyword is a "reserved word". | |
| bool get isReservedWord => false; | |
| /** | |
| * Return `true` if this type of token represents an equality operator. | |
| */ | |
| bool get isEqualityOperator => | |
| this == TokenType.BANG_EQ || this == TokenType.EQ_EQ; | |
| /** | |
| * Return `true` if this type of token represents an increment operator. | |
| */ | |
| bool get isIncrementOperator => | |
| this == TokenType.PLUS_PLUS || this == TokenType.MINUS_MINUS; | |
| /** | |
| * Return `true` if this type of token is a keyword. | |
| */ | |
| bool get isKeyword => kind == KEYWORD_TOKEN; | |
| /** | |
| * A flag indicating whether the keyword can be used as an identifier | |
| * in some situations. | |
| */ | |
| bool get isPseudo => false; | |
| /** | |
| * Return `true` if this type of token represents a multiplicative operator. | |
| */ | |
| bool get isMultiplicativeOperator => precedence == MULTIPLICATIVE_PRECEDENCE; | |
| /** | |
| * Return `true` if this type of token represents a relational operator. | |
| */ | |
| bool get isRelationalOperator => | |
| this == TokenType.LT || | |
| this == TokenType.LT_EQ || | |
| this == TokenType.GT || | |
| this == TokenType.GT_EQ; | |
| /** | |
| * Return `true` if this type of token represents a shift operator. | |
| */ | |
| bool get isShiftOperator => precedence == SHIFT_PRECEDENCE; | |
| /** | |
| * Return `true` if this type of token represents a unary postfix operator. | |
| */ | |
| bool get isUnaryPostfixOperator => precedence == POSTFIX_PRECEDENCE; | |
| /** | |
| * Return `true` if this type of token represents a unary prefix operator. | |
| */ | |
| bool get isUnaryPrefixOperator => | |
| precedence == PREFIX_PRECEDENCE || | |
| this == TokenType.MINUS || | |
| this == TokenType.PLUS_PLUS || | |
| this == TokenType.MINUS_MINUS; | |
| /** | |
| * Return `true` if this type of token represents a selector operator | |
| * (starting token of a selector). | |
| */ | |
| bool get isSelectorOperator => precedence == SELECTOR_PRECEDENCE; | |
| @override | |
| String toString() => name; | |
| } | |
| /// Constant list of [TokenType] and [Keyword] ordered by index. | |
| /// | |
| /// This list should always have length 256 to avoid bounds checks in | |
| /// SimpleToken.type: | |
| /// DartDocTest(_tokenTypesByIndex.length, 256) | |
| const List<TokenType> _tokenTypesByIndex = [ | |
| TokenType.EOF, | |
| TokenType.DOUBLE, | |
| TokenType.DOUBLE_WITH_SEPARATORS, | |
| TokenType.HEXADECIMAL, | |
| TokenType.HEXADECIMAL_WITH_SEPARATORS, | |
| TokenType.IDENTIFIER, | |
| TokenType.INT, | |
| TokenType.INT_WITH_SEPARATORS, | |
| TokenType.MULTI_LINE_COMMENT, | |
| TokenType.SCRIPT_TAG, | |
| TokenType.SINGLE_LINE_COMMENT, | |
| TokenType.STRING, | |
| TokenType.AMPERSAND, | |
| TokenType.AMPERSAND_AMPERSAND, | |
| TokenType.AMPERSAND_AMPERSAND_EQ, | |
| TokenType.AMPERSAND_EQ, | |
| TokenType.AT, | |
| TokenType.BANG, | |
| TokenType.BANG_EQ, | |
| TokenType.BANG_EQ_EQ, | |
| TokenType.BAR, | |
| TokenType.BAR_BAR, | |
| TokenType.BAR_BAR_EQ, | |
| TokenType.BAR_EQ, | |
| TokenType.COLON, | |
| TokenType.COMMA, | |
| TokenType.CARET, | |
| TokenType.CARET_EQ, | |
| TokenType.CLOSE_CURLY_BRACKET, | |
| TokenType.CLOSE_PAREN, | |
| TokenType.CLOSE_SQUARE_BRACKET, | |
| TokenType.EQ, | |
| TokenType.EQ_EQ, | |
| TokenType.EQ_EQ_EQ, | |
| TokenType.FUNCTION, | |
| TokenType.GT, | |
| TokenType.GT_EQ, | |
| TokenType.GT_GT, | |
| TokenType.GT_GT_EQ, | |
| TokenType.GT_GT_GT, | |
| TokenType.GT_GT_GT_EQ, | |
| TokenType.HASH, | |
| TokenType.INDEX, | |
| TokenType.INDEX_EQ, | |
| TokenType.LT, | |
| TokenType.LT_EQ, | |
| TokenType.LT_LT, | |
| TokenType.LT_LT_EQ, | |
| TokenType.MINUS, | |
| TokenType.MINUS_EQ, | |
| TokenType.MINUS_MINUS, | |
| TokenType.OPEN_CURLY_BRACKET, | |
| TokenType.OPEN_PAREN, | |
| TokenType.OPEN_SQUARE_BRACKET, | |
| TokenType.PERCENT, | |
| TokenType.PERCENT_EQ, | |
| TokenType.PERIOD, | |
| TokenType.PERIOD_PERIOD, | |
| TokenType.PLUS, | |
| TokenType.PLUS_EQ, | |
| TokenType.PLUS_PLUS, | |
| TokenType.QUESTION, | |
| TokenType.QUESTION_PERIOD, | |
| TokenType.QUESTION_QUESTION, | |
| TokenType.QUESTION_QUESTION_EQ, | |
| TokenType.SEMICOLON, | |
| TokenType.SLASH, | |
| TokenType.SLASH_EQ, | |
| TokenType.STAR, | |
| TokenType.STAR_EQ, | |
| TokenType.STRING_INTERPOLATION_EXPRESSION, | |
| TokenType.STRING_INTERPOLATION_IDENTIFIER, | |
| TokenType.TILDE, | |
| TokenType.TILDE_SLASH, | |
| TokenType.TILDE_SLASH_EQ, | |
| TokenType.BACKPING, | |
| TokenType.BACKSLASH, | |
| TokenType.PERIOD_PERIOD_PERIOD, | |
| TokenType.PERIOD_PERIOD_PERIOD_QUESTION, | |
| TokenType.QUESTION_PERIOD_PERIOD, | |
| TokenType.BAD_INPUT, | |
| TokenType.RECOVERY, | |
| Keyword.ABSTRACT, | |
| Keyword.AS, | |
| Keyword.ASSERT, | |
| Keyword.ASYNC, | |
| Keyword.AUGMENT, | |
| Keyword.AWAIT, | |
| Keyword.BASE, | |
| Keyword.BREAK, | |
| Keyword.CASE, | |
| Keyword.CATCH, | |
| Keyword.CLASS, | |
| Keyword.CONST, | |
| Keyword.CONTINUE, | |
| Keyword.COVARIANT, | |
| Keyword.DEFAULT, | |
| Keyword.DEFERRED, | |
| Keyword.DO, | |
| Keyword.DYNAMIC, | |
| Keyword.ELSE, | |
| Keyword.ENUM, | |
| Keyword.EXPORT, | |
| Keyword.EXTENDS, | |
| Keyword.EXTENSION, | |
| Keyword.EXTERNAL, | |
| Keyword.FACTORY, | |
| Keyword.FALSE, | |
| Keyword.FINAL, | |
| Keyword.FINALLY, | |
| Keyword.FOR, | |
| Keyword.FUNCTION, | |
| Keyword.GET, | |
| Keyword.HIDE, | |
| Keyword.IF, | |
| Keyword.IMPLEMENTS, | |
| Keyword.IMPORT, | |
| Keyword.IN, | |
| Keyword.INOUT, | |
| Keyword.INTERFACE, | |
| Keyword.IS, | |
| Keyword.LATE, | |
| Keyword.LIBRARY, | |
| Keyword.MIXIN, | |
| Keyword.NATIVE, | |
| Keyword.NEW, | |
| Keyword.NULL, | |
| Keyword.OF, | |
| Keyword.ON, | |
| Keyword.OPERATOR, | |
| Keyword.OUT, | |
| Keyword.PART, | |
| Keyword.PATCH, | |
| Keyword.REQUIRED, | |
| Keyword.RETHROW, | |
| Keyword.RETURN, | |
| Keyword.SEALED, | |
| Keyword.SET, | |
| Keyword.SHOW, | |
| Keyword.SOURCE, | |
| Keyword.STATIC, | |
| Keyword.SUPER, | |
| Keyword.SWITCH, | |
| Keyword.SYNC, | |
| Keyword.THIS, | |
| Keyword.THROW, | |
| Keyword.TRUE, | |
| Keyword.TRY, | |
| Keyword.TYPEDEF, | |
| Keyword.VAR, | |
| Keyword.VOID, | |
| Keyword.WHEN, | |
| Keyword.WHILE, | |
| Keyword.WITH, | |
| Keyword.YIELD, | |
| // Fill to length 256 to avoid bounds check in SimpleToken.type. | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| TokenType.UNUSED, | |
| ]; | |
| extension TokenIsAExtension on Token { | |
| /// Returns true if this has the token type [value]. | |
| @pragma("vm:prefer-inline") | |
| bool isA(TokenType value) { | |
| return value.index == typeIndex; | |
| } | |
| } | |
| extension TokenTypeIsAExtension on TokenType { | |
| /// Returns true if this is the token type [value]. | |
| @pragma("vm:prefer-inline") | |
| bool isA(TokenType value) { | |
| return identical(value, this); | |
| } | |
| } |