in lib/Parser/JSParserImpl.cpp [2233:2447]
Optional<ESTree::Node *> JSParserImpl::parsePrimaryExpression() {
CHECK_RECURSION;
switch (tok_->getKind()) {
case TokenKind::rw_this: {
auto *res =
setLocation(tok_, tok_, new (context_) ESTree::ThisExpressionNode());
advance(JSLexer::AllowDiv);
return res;
}
case TokenKind::identifier: {
if (check(yieldIdent_)) {
// yield is only allowed as an IdentifierReference when ParamYield is
// false.
if (paramYield_) {
error(
tok_->getSourceRange(),
"Unexpected usage of 'yield' as an identifier reference");
}
}
if (check(asyncIdent_) && checkAsyncFunction()) {
auto func = parseFunctionExpression();
if (!func)
return None;
return func.getValue();
}
auto *res = setLocation(
tok_,
tok_,
new (context_)
ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
advance(JSLexer::AllowDiv);
return res;
}
case TokenKind::rw_null: {
auto *res =
setLocation(tok_, tok_, new (context_) ESTree::NullLiteralNode());
advance(JSLexer::AllowDiv);
return res;
}
case TokenKind::rw_true:
case TokenKind::rw_false: {
auto *res = setLocation(
tok_,
tok_,
new (context_) ESTree::BooleanLiteralNode(
tok_->getKind() == TokenKind::rw_true));
advance(JSLexer::AllowDiv);
return res;
}
case TokenKind::numeric_literal: {
auto *res = setLocation(
tok_,
tok_,
new (context_) ESTree::NumericLiteralNode(tok_->getNumericLiteral()));
advance(JSLexer::AllowDiv);
return res;
}
case TokenKind::bigint_literal: {
auto *res = setLocation(
tok_,
tok_,
new (context_) ESTree::BigIntLiteralNode(tok_->getBigIntLiteral()));
advance(JSLexer::AllowDiv);
return res;
}
case TokenKind::string_literal: {
auto *res = setLocation(
tok_,
tok_,
new (context_) ESTree::StringLiteralNode(tok_->getStringLiteral()));
advance(JSLexer::AllowDiv);
return res;
}
case TokenKind::regexp_literal: {
auto *res = setLocation(
tok_,
tok_,
new (context_) ESTree::RegExpLiteralNode(
tok_->getRegExpLiteral()->getBody(),
tok_->getRegExpLiteral()->getFlags()));
advance(JSLexer::AllowDiv);
return res;
}
case TokenKind::l_square: {
auto res = parseArrayLiteral();
if (!res)
return None;
return res.getValue();
}
case TokenKind::l_brace: {
auto res = parseObjectLiteral();
if (!res)
return None;
return res.getValue();
}
case TokenKind::l_paren: {
SMLoc startLoc = advance().Start;
// Cover "()".
if (check(TokenKind::r_paren)) {
SMLoc endLoc = advance().End;
return setLocation(
startLoc, endLoc, new (context_) ESTree::CoverEmptyArgsNode());
}
#if HERMES_PARSE_FLOW
SMLoc startLocAfterParen = tok_->getStartLoc();
#endif
ESTree::Node *expr;
if (check(TokenKind::dotdotdot)) {
auto optRest = parseBindingRestElement(ParamIn);
if (!optRest)
return None;
expr = setLocation(
*optRest,
*optRest,
new (context_) ESTree::CoverRestElementNode(*optRest));
} else {
auto optExpr = parseExpression(ParamIn, CoverTypedParameters::Yes);
if (!optExpr)
return None;
expr = *optExpr;
}
#if HERMES_PARSE_FLOW
if (context_.getParseFlow()) {
if (auto *cover = dyn_cast<ESTree::CoverTypedIdentifierNode>(expr)) {
if (cover->_right && !cover->_optional) {
expr = setLocation(
expr,
getPrevTokenEndLoc(),
new (context_) ESTree::TypeCastExpressionNode(
cover->_left, cover->_right));
}
} else if (check(TokenKind::colon)) {
SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
auto optType = parseTypeAnnotationFlow(annotStart);
if (!optType)
return None;
ESTree::Node *type = *optType;
expr = setLocation(
startLocAfterParen,
getPrevTokenEndLoc(),
new (context_) ESTree::TypeCastExpressionNode(expr, type));
}
}
#endif
if (!eat(
TokenKind::r_paren,
JSLexer::AllowDiv,
"at end of parenthesized expression",
"started here",
startLoc))
return None;
// Record the number of parens surrounding an expression.
expr->incParens();
return expr;
}
case TokenKind::rw_function: {
auto fExpr = parseFunctionExpression();
if (!fExpr)
return None;
return fExpr.getValue();
}
case TokenKind::rw_class: {
auto optClass = parseClassExpression();
if (!optClass)
return None;
return optClass.getValue();
}
case TokenKind::no_substitution_template:
case TokenKind::template_head: {
auto optTemplate = parseTemplateLiteral(Param{});
if (!optTemplate) {
return None;
}
return optTemplate.getValue();
}
#if HERMES_PARSE_JSX
case TokenKind::less:
if (context_.getParseJSX()) {
auto optJSX = parseJSX();
if (!optJSX)
return None;
return optJSX.getValue();
}
error(
tok_->getStartLoc(),
"invalid expression (possible JSX: pass -parse-jsx to parse)");
return None;
#endif
default:
error(tok_->getStartLoc(), "invalid expression");
return None;
}
}