/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef frontend_TokenKind_h #define frontend_TokenKind_h #include #include "js/TypeDecls.h" // IF_RECORD_TUPLE /* * List of token kinds and their ranges. * * The format for each line is: * * MACRO(, ) * * or * * RANGE(, ) * * where ; * is a legal C identifier of the token, that will be used in * the JS engine source. * * is a string that describe about the token, and will be used in * error message. * * is a legal C identifier of the range that will be used to * JS engine source. It should end with `First` or `Last`. This is used to check * TokenKind by range-testing: * BinOpFirst <= tt && tt <= BinOpLast * * Second argument of `RANGE` is the actual value of the , * should be same as one of in other `MACRO`s. * * To use this macro, define two macros for `MACRO` and `RANGE`, and pass them * as arguments. * * #define EMIT_TOKEN(name, desc) ... * #define EMIT_RANGE(name, value) ... * FOR_EACH_TOKEN_KIND_WITH_RANGE(EMIT_TOKEN, EMIT_RANGE) * #undef EMIT_TOKEN * #undef EMIT_RANGE * * If you don't need range data, use FOR_EACH_TOKEN_KIND instead. * * #define EMIT_TOKEN(name, desc) ... * FOR_EACH_TOKEN_KIND(EMIT_TOKEN) * #undef EMIT_TOKEN * * Note that this list does not contain ERROR and LIMIT. */ #define FOR_EACH_TOKEN_KIND_WITH_RANGE(MACRO, RANGE) \ MACRO(Eof, "end of script") \ \ /* only returned by peekTokenSameLine() */ \ MACRO(Eol, "line terminator") \ \ MACRO(Semi, "';'") \ MACRO(Comma, "','") \ MACRO(Hook, "'?'") /* conditional */ \ MACRO(Colon, "':'") /* conditional */ \ MACRO(Inc, "'++'") /* increment */ \ MACRO(Dec, "'--'") /* decrement */ \ MACRO(Dot, "'.'") /* member operator */ \ MACRO(TripleDot, "'...'") /* rest arguments and spread operator */ \ MACRO(OptionalChain, "'?.'") \ MACRO(LeftBracket, "'['") \ IF_RECORD_TUPLE(MACRO(HashBracket, "'#['")) \ MACRO(RightBracket, "']'") \ MACRO(LeftCurly, "'{'") \ IF_RECORD_TUPLE(MACRO(HashCurly, "'#{'")) \ MACRO(RightCurly, "'}'") \ MACRO(LeftParen, "'('") \ MACRO(RightParen, "')'") \ MACRO(Name, "identifier") \ MACRO(PrivateName, "private identifier") \ MACRO(Number, "numeric literal") \ MACRO(String, "string literal") \ MACRO(BigInt, "bigint literal") \ IF_DECORATORS(MACRO(At, "'@'")) \ \ /* start of template literal with substitutions */ \ MACRO(TemplateHead, "'${'") \ /* template literal without substitutions */ \ MACRO(NoSubsTemplate, "template literal") \ \ MACRO(RegExp, "regular expression literal") \ MACRO(True, "boolean literal 'true'") \ RANGE(ReservedWordLiteralFirst, True) \ MACRO(False, "boolean literal 'false'") \ MACRO(Null, "null literal") \ RANGE(ReservedWordLiteralLast, Null) \ MACRO(This, "keyword 'this'") \ RANGE(KeywordFirst, This) \ MACRO(Function, "keyword 'function'") \ MACRO(If, "keyword 'if'") \ MACRO(Else, "keyword 'else'") \ MACRO(Switch, "keyword 'switch'") \ MACRO(Case, "keyword 'case'") \ MACRO(Default, "keyword 'default'") \ MACRO(While, "keyword 'while'") \ MACRO(Do, "keyword 'do'") \ MACRO(For, "keyword 'for'") \ MACRO(Break, "keyword 'break'") \ MACRO(Continue, "keyword 'continue'") \ MACRO(Var, "keyword 'var'") \ MACRO(Const, "keyword 'const'") \ MACRO(With, "keyword 'with'") \ MACRO(Return, "keyword 'return'") \ MACRO(New, "keyword 'new'") \ MACRO(Delete, "keyword 'delete'") \ MACRO(Try, "keyword 'try'") \ MACRO(Catch, "keyword 'catch'") \ MACRO(Finally, "keyword 'finally'") \ MACRO(Throw, "keyword 'throw'") \ MACRO(Debugger, "keyword 'debugger'") \ MACRO(Export, "keyword 'export'") \ MACRO(Import, "keyword 'import'") \ MACRO(Class, "keyword 'class'") \ MACRO(Extends, "keyword 'extends'") \ MACRO(Super, "keyword 'super'") \ RANGE(KeywordLast, Super) \ \ /* contextual keywords */ \ MACRO(As, "'as'") \ RANGE(ContextualKeywordFirst, As) \ /* TODO: Move to alphabetical order when IF_DECORATORS is removed */ \ IF_DECORATORS(MACRO(Accessor, "'accessor'")) \ MACRO(Assert, "'assert'") \ MACRO(Async, "'async'") \ MACRO(Await, "'await'") \ MACRO(Each, "'each'") \ MACRO(From, "'from'") \ MACRO(Get, "'get'") \ MACRO(Let, "'let'") \ MACRO(Meta, "'meta'") \ MACRO(Of, "'of'") \ MACRO(Set, "'set'") \ MACRO(Static, "'static'") \ MACRO(Target, "'target'") \ MACRO(Yield, "'yield'") \ RANGE(ContextualKeywordLast, Yield) \ \ /* future reserved words */ \ MACRO(Enum, "reserved word 'enum'") \ RANGE(FutureReservedKeywordFirst, Enum) \ RANGE(FutureReservedKeywordLast, Enum) \ \ /* reserved words in strict mode */ \ MACRO(Implements, "reserved word 'implements'") \ RANGE(StrictReservedKeywordFirst, Implements) \ MACRO(Interface, "reserved word 'interface'") \ MACRO(Package, "reserved word 'package'") \ MACRO(Private, "reserved word 'private'") \ MACRO(Protected, "reserved word 'protected'") \ MACRO(Public, "reserved word 'public'") \ RANGE(StrictReservedKeywordLast, Public) \ \ /* \ * The following token types occupy contiguous ranges to enable easy \ * range-testing. \ */ \ /* \ * Binary operators. \ * This list must be kept in the same order in several places: \ * - the binary operators in ParseNode.h \ * - the precedence list in Parser.cpp \ * - the JSOp code list in BytecodeEmitter.cpp \ */ \ MACRO(Coalesce, "'\?\?'") /* escapes to avoid trigraphs warning */ \ RANGE(BinOpFirst, Coalesce) \ MACRO(Or, "'||'") /* logical or */ \ MACRO(And, "'&&'") /* logical and */ \ MACRO(BitOr, "'|'") /* bitwise-or */ \ MACRO(BitXor, "'^'") /* bitwise-xor */ \ MACRO(BitAnd, "'&'") /* bitwise-and */ \ \ /* Equality operation tokens, per TokenKindIsEquality. */ \ MACRO(StrictEq, "'==='") \ RANGE(EqualityStart, StrictEq) \ MACRO(Eq, "'=='") \ MACRO(StrictNe, "'!=='") \ MACRO(Ne, "'!='") \ RANGE(EqualityLast, Ne) \ \ /* Relational ops, per TokenKindIsRelational. */ \ MACRO(Lt, "'<'") \ RANGE(RelOpStart, Lt) \ MACRO(Le, "'<='") \ MACRO(Gt, "'>'") \ MACRO(Ge, "'>='") \ RANGE(RelOpLast, Ge) \ \ MACRO(InstanceOf, "keyword 'instanceof'") \ RANGE(KeywordBinOpFirst, InstanceOf) \ MACRO(In, "keyword 'in'") \ MACRO(PrivateIn, "keyword 'in' (private)") \ RANGE(KeywordBinOpLast, PrivateIn) \ \ /* Shift ops, per TokenKindIsShift. */ \ MACRO(Lsh, "'<<'") \ RANGE(ShiftOpStart, Lsh) \ MACRO(Rsh, "'>>'") \ MACRO(Ursh, "'>>>'") \ RANGE(ShiftOpLast, Ursh) \ \ MACRO(Add, "'+'") \ MACRO(Sub, "'-'") \ MACRO(Mul, "'*'") \ MACRO(Div, "'/'") \ MACRO(Mod, "'%'") \ MACRO(Pow, "'**'") \ RANGE(BinOpLast, Pow) \ \ /* Unary operation tokens. */ \ MACRO(TypeOf, "keyword 'typeof'") \ RANGE(KeywordUnOpFirst, TypeOf) \ MACRO(Void, "keyword 'void'") \ RANGE(KeywordUnOpLast, Void) \ MACRO(Not, "'!'") \ MACRO(BitNot, "'~'") \ \ MACRO(Arrow, "'=>'") /* function arrow */ \ \ /* Assignment ops, per TokenKindIsAssignment */ \ MACRO(Assign, "'='") \ RANGE(AssignmentStart, Assign) \ MACRO(AddAssign, "'+='") \ MACRO(SubAssign, "'-='") \ MACRO(CoalesceAssign, "'\?\?='") /* avoid trigraphs warning */ \ MACRO(OrAssign, "'||='") \ MACRO(AndAssign, "'&&='") \ MACRO(BitOrAssign, "'|='") \ MACRO(BitXorAssign, "'^='") \ MACRO(BitAndAssign, "'&='") \ MACRO(LshAssign, "'<<='") \ MACRO(RshAssign, "'>>='") \ MACRO(UrshAssign, "'>>>='") \ MACRO(MulAssign, "'*='") \ MACRO(DivAssign, "'/='") \ MACRO(ModAssign, "'%='") \ MACRO(PowAssign, "'**='") \ RANGE(AssignmentLast, PowAssign) #define TOKEN_KIND_RANGE_EMIT_NONE(name, value) #define FOR_EACH_TOKEN_KIND(MACRO) \ FOR_EACH_TOKEN_KIND_WITH_RANGE(MACRO, TOKEN_KIND_RANGE_EMIT_NONE) namespace js { namespace frontend { // Values of this type are used to index into arrays such as isExprEnding[], // so the first value must be zero. enum class TokenKind : uint8_t { #define EMIT_ENUM(name, desc) name, #define EMIT_ENUM_RANGE(name, value) name = value, FOR_EACH_TOKEN_KIND_WITH_RANGE(EMIT_ENUM, EMIT_ENUM_RANGE) #undef EMIT_ENUM #undef EMIT_ENUM_RANGE Limit // domain size }; inline bool TokenKindIsBinaryOp(TokenKind tt) { return TokenKind::BinOpFirst <= tt && tt <= TokenKind::BinOpLast; } inline bool TokenKindIsEquality(TokenKind tt) { return TokenKind::EqualityStart <= tt && tt <= TokenKind::EqualityLast; } inline bool TokenKindIsRelational(TokenKind tt) { return TokenKind::RelOpStart <= tt && tt <= TokenKind::RelOpLast; } inline bool TokenKindIsShift(TokenKind tt) { return TokenKind::ShiftOpStart <= tt && tt <= TokenKind::ShiftOpLast; } inline bool TokenKindIsAssignment(TokenKind tt) { return TokenKind::AssignmentStart <= tt && tt <= TokenKind::AssignmentLast; } [[nodiscard]] inline bool TokenKindIsKeyword(TokenKind tt) { return (TokenKind::KeywordFirst <= tt && tt <= TokenKind::KeywordLast) || (TokenKind::KeywordBinOpFirst <= tt && tt <= TokenKind::KeywordBinOpLast) || (TokenKind::KeywordUnOpFirst <= tt && tt <= TokenKind::KeywordUnOpLast); } [[nodiscard]] inline bool TokenKindIsContextualKeyword(TokenKind tt) { return TokenKind::ContextualKeywordFirst <= tt && tt <= TokenKind::ContextualKeywordLast; } [[nodiscard]] inline bool TokenKindIsFutureReservedWord(TokenKind tt) { return TokenKind::FutureReservedKeywordFirst <= tt && tt <= TokenKind::FutureReservedKeywordLast; } [[nodiscard]] inline bool TokenKindIsStrictReservedWord(TokenKind tt) { return TokenKind::StrictReservedKeywordFirst <= tt && tt <= TokenKind::StrictReservedKeywordLast; } [[nodiscard]] inline bool TokenKindIsReservedWordLiteral(TokenKind tt) { return TokenKind::ReservedWordLiteralFirst <= tt && tt <= TokenKind::ReservedWordLiteralLast; } [[nodiscard]] inline bool TokenKindIsReservedWord(TokenKind tt) { return TokenKindIsKeyword(tt) || TokenKindIsFutureReservedWord(tt) || TokenKindIsReservedWordLiteral(tt); } [[nodiscard]] inline bool TokenKindIsPossibleIdentifier(TokenKind tt) { return tt == TokenKind::Name || TokenKindIsContextualKeyword(tt) || TokenKindIsStrictReservedWord(tt); } [[nodiscard]] inline bool TokenKindIsPossibleIdentifierName(TokenKind tt) { return TokenKindIsPossibleIdentifier(tt) || TokenKindIsReservedWord(tt); } } // namespace frontend } // namespace js #endif /* frontend_TokenKind_h */