Source code
Revision control
Copy as Markdown
Other Tools
/* -*- 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
#ifndef frontend_TokenKind_h
#define frontend_TokenKind_h
#include <stdint.h>
#include "js/TypeDecls.h" // IF_RECORD_TUPLE
/*
* List of token kinds and their ranges.
*
* The format for each line is:
*
* MACRO(<TOKEN_KIND_NAME>, <DESCRIPTION>)
*
* or
*
* RANGE(<TOKEN_RANGE_NAME>, <TOKEN_KIND_NAME>)
*
* where ;
* <TOKEN_KIND_NAME> is a legal C identifier of the token, that will be used in
* the JS engine source.
*
* <DESCRIPTION> is a string that describe about the token, and will be used in
* error message.
*
* <TOKEN_RANGE_NAME> 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 <TOKEN_RANGE_NAME>,
* should be same as one of <TOKEN_KIND_NAME> 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 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'") \
IF_EXPLICIT_RESOURCE_MANAGEMENT(MACRO(Using, "'using'")) \
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 */