parseTemplateLiteral_(operand) {
    let start = operand ?
        operand.location.start : this.getTreeStartLocation_();

    let token = nextToken();
    let elements = [new TemplateLiteralPortion(token.location, token)];

    if (token.type === NO_SUBSTITUTION_TEMPLATE) {
      return new TemplateLiteralExpression(this.getTreeLocation_(start),
                                        operand, elements);
    }

    // `abc${
    let expression = this.parseExpression_(ALLOW_IN);
    elements.push(new TemplateSubstitution(expression.location, expression));

    while (expression.type !== SYNTAX_ERROR_TREE) {
      token = nextTemplateLiteralToken();
      if (token.type === ERROR || token.type === END_OF_FILE)
        break;

      elements.push(new TemplateLiteralPortion(token.location, token));
      if (token.type === TEMPLATE_TAIL)
        break;

      expression = this.parseExpression_(ALLOW_IN);
      elements.push(new TemplateSubstitution(expression.location, expression));
    }

    return new TemplateLiteralExpression(this.getTreeLocation_(start),
                                      operand, elements);
  }
Template Literals

Template ::
  FullTemplate
  TemplateHead

FullTemplate ::
  ` TemplateCharactersopt `

TemplateHead ::
  ` TemplateCharactersopt ${

TemplateSubstitutionTail ::
  TemplateMiddle
  TemplateTail

TemplateMiddle ::
  } TemplateCharactersopt ${

TemplateTail ::
  } TemplateCharactersopt `

TemplateCharacters ::
  TemplateCharacter TemplateCharactersopt

TemplateCharacter ::
  SourceCharacter but not one of ` or \ or $
  $ [lookahead not { ]
  \ EscapeSequence
  LineContinuation

@param {ParseTree} operand
@return {ParseTree}
@private