/* -*- 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 <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 */