| Index: src/preparser.h
|
| diff --git a/src/preparser.h b/src/preparser.h
|
| index 7c9791fc9ca25223983afbfee8f4f666c709af24..96b7b985fc19bcaa53111580bc3ef84524d58f62 100644
|
| --- a/src/preparser.h
|
| +++ b/src/preparser.h
|
| @@ -102,6 +102,7 @@ class ParserBase : public Traits {
|
| bool allow_harmony_object_literals() const {
|
| return allow_harmony_object_literals_;
|
| }
|
| + bool allow_harmony_templates() const { return scanner()->HarmonyTemplates(); }
|
|
|
| // Setters that determine whether certain syntactical constructs are
|
| // allowed to be parsed by this instance of the parser.
|
| @@ -119,6 +120,9 @@ class ParserBase : public Traits {
|
| void set_allow_harmony_object_literals(bool allow) {
|
| allow_harmony_object_literals_ = allow;
|
| }
|
| + void set_allow_harmony_templates(bool allow) {
|
| + scanner()->SetHarmonyTemplates(allow);
|
| + }
|
|
|
| protected:
|
| enum AllowEvalOrArgumentsAsIdentifier {
|
| @@ -494,6 +498,8 @@ class ParserBase : public Traits {
|
| Scanner::Location function_name_location,
|
| bool name_is_strict_reserved, int pos,
|
| bool* ok);
|
| + ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok);
|
| + void AddTemplateExpression(ExpressionT);
|
|
|
| // Checks if the expression is a valid reference expression (e.g., on the
|
| // left-hand side of assignments). Although ruled out by ECMA as early errors,
|
| @@ -1385,6 +1391,20 @@ class PreParserTraits {
|
| return 0;
|
| }
|
|
|
| + struct TemplateLiteralState {};
|
| +
|
| + TemplateLiteralState OpenTemplateLiteral(int pos) {
|
| + return TemplateLiteralState();
|
| + }
|
| + void AddTemplateSpan(TemplateLiteralState*, bool) {}
|
| + void AddTemplateExpression(TemplateLiteralState*, PreParserExpression) {}
|
| + PreParserExpression CloseTemplateLiteral(TemplateLiteralState*, int,
|
| + PreParserExpression) {
|
| + return EmptyExpression();
|
| + }
|
| + PreParserExpression NoTemplateTag() {
|
| + return PreParserExpression::Default();
|
| + }
|
| static AstValueFactory* ast_value_factory() { return NULL; }
|
|
|
| void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {}
|
| @@ -1755,6 +1775,7 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
|
| // RegExpLiteral
|
| // ClassLiteral
|
| // '(' Expression ')'
|
| + // TemplateLiteral
|
|
|
| int pos = peek_position();
|
| ExpressionT result = this->EmptyExpression();
|
| @@ -1843,6 +1864,12 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
|
| break;
|
| }
|
|
|
| + case Token::TEMPLATE_SPAN:
|
| + case Token::TEMPLATE_TAIL:
|
| + result = this->ParseTemplateLiteral(Traits::NoTemplateTag(), pos,
|
| + CHECK_OK);
|
| + break;
|
| +
|
| case Token::MOD:
|
| if (allow_natives_syntax() || extension_ != NULL) {
|
| result = this->ParseV8Intrinsic(CHECK_OK);
|
| @@ -2466,6 +2493,23 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
|
| break;
|
| }
|
|
|
| + case Token::TEMPLATE_SPAN:
|
| + case Token::TEMPLATE_TAIL: {
|
| + int pos;
|
| + if (scanner()->current_token() == Token::IDENTIFIER) {
|
| + pos = position();
|
| + } else {
|
| + pos = peek_position();
|
| + if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
|
| + // If the tag function looks like an IIFE, set_parenthesized() to
|
| + // force eager compilation.
|
| + result->AsFunctionLiteral()->set_parenthesized();
|
| + }
|
| + }
|
| + result = ParseTemplateLiteral(result, pos, CHECK_OK);
|
| + break;
|
| + }
|
| +
|
| case Token::PERIOD: {
|
| Consume(Token::PERIOD);
|
| int pos = position();
|
| @@ -2811,6 +2855,72 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseClassLiteral(
|
|
|
| template <typename Traits>
|
| typename ParserBase<Traits>::ExpressionT
|
| +ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start, bool* ok) {
|
| + // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal
|
| + // text followed by a substitution expression), finalized by a single
|
| + // TEMPLATE_TAIL.
|
| + //
|
| + // In terms of draft language, TEMPLATE_SPAN may be either the TemplateHead or
|
| + // TemplateMiddle productions, while TEMPLATE_TAIL is either TemplateTail, or
|
| + // NoSubstitutionTemplate.
|
| + //
|
| + // When parsing a TemplateLiteral, we must have scanned either an initial
|
| + // TEMPLATE_SPAN, or a TEMPLATE_TAIL.
|
| + CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL);
|
| +
|
| + if (peek() == Token::TEMPLATE_SPAN) {
|
| + Consume(Token::TEMPLATE_SPAN);
|
| + int pos = position();
|
| + typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
|
| + Traits::AddTemplateSpan(&ts, false);
|
| + Token::Value next;
|
| +
|
| + // If we open with a TEMPLATE_SPAN, we must scan the subsequent expression,
|
| + // and repeat if the following token is a TEMPLATE_SPAN as well (in this
|
| + // case, representing a TemplateMiddle).
|
| + do {
|
| + next = peek();
|
| + if (next <= 0) {
|
| + ReportMessage("unterminated_template");
|
| + *ok = false;
|
| + return Traits::EmptyExpression();
|
| + }
|
| +
|
| + ExpressionT expression = this->ParseExpression(false, CHECK_OK);
|
| + Traits::AddTemplateExpression(&ts, expression);
|
| +
|
| + // If we didn't die parsing that expression, our next token should be a
|
| + // TEMPLATE_SPAN or TEMPLATE_TAIL.
|
| + next = scanner()->ScanTemplateSpan();
|
| + Next();
|
| +
|
| + if (next == Token::ILLEGAL || next <= 0) {
|
| + ReportMessage("unterminated_template");
|
| + *ok = false;
|
| + return Traits::EmptyExpression();
|
| + }
|
| +
|
| + Traits::AddTemplateSpan(&ts, next == Token::TEMPLATE_TAIL);
|
| + } while (next == Token::TEMPLATE_SPAN);
|
| +
|
| + DCHECK_EQ(next, Token::TEMPLATE_TAIL);
|
| + // Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral.
|
| + return Traits::CloseTemplateLiteral(&ts, start, tag);
|
| + }
|
| +
|
| + // If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate.
|
| + // In this case we may simply consume the token and build a template with a
|
| + // single TEMPLATE_SPAN and no expressions.
|
| + Consume(Token::TEMPLATE_TAIL);
|
| + int pos = position();
|
| + typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
|
| + Traits::AddTemplateSpan(&ts, true);
|
| + return Traits::CloseTemplateLiteral(&ts, start, tag);
|
| +}
|
| +
|
| +
|
| +template <typename Traits>
|
| +typename ParserBase<Traits>::ExpressionT
|
| ParserBase<Traits>::CheckAndRewriteReferenceExpression(
|
| ExpressionT expression,
|
| Scanner::Location location, const char* message, bool* ok) {
|
|
|