| Index: src/preparser.h
|
| diff --git a/src/preparser.h b/src/preparser.h
|
| index a53abfe4ff3af732cd2cd46ac79db8c35264f698..eb57d410f9d3f7b04aa6bf3b288228d0402d2c8a 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 {
|
| @@ -281,7 +285,7 @@ class ParserBase : public Traits {
|
| return scanner()->peek();
|
| }
|
|
|
| - INLINE(Token::Value Next()) {
|
| + INLINE(Token::Value Next(Scanner::Mode mode = Scanner::None)) {
|
| if (stack_overflow_) return Token::ILLEGAL;
|
| {
|
| if (GetCurrentStackPosition() < stack_limit_) {
|
| @@ -291,7 +295,7 @@ class ParserBase : public Traits {
|
| stack_overflow_ = true;
|
| }
|
| }
|
| - return scanner()->Next();
|
| + return scanner()->Next(mode);
|
| }
|
|
|
| void Consume(Token::Value token) {
|
| @@ -496,6 +500,9 @@ class ParserBase : public Traits {
|
| bool name_is_strict_reserved, int pos,
|
| bool* ok);
|
|
|
| + void AddTemplateSpan();
|
| + 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,
|
| // we allow calls for web compatibility and rewrite them to a runtime throw.
|
| @@ -1376,6 +1383,22 @@ class PreParserTraits {
|
| return 0;
|
| }
|
|
|
| + struct TemplateLiteralState {};
|
| +
|
| + TemplateLiteralState OpenTemplateLiteral() { return TemplateLiteralState(); }
|
| + void AddTemplateSpan(TemplateLiteralState* state) { USE(state); }
|
| + void AddTemplateExpression(TemplateLiteralState* state,
|
| + PreParserExpression expression) {
|
| + USE(state);
|
| + USE(expression);
|
| + }
|
| + PreParserExpression CloseTemplateLiteral(TemplateLiteralState* state,
|
| + int pos) {
|
| + USE(state);
|
| + USE(pos);
|
| + return EmptyExpression();
|
| + }
|
| +
|
| static AstValueFactory* ast_value_factory() { return NULL; }
|
|
|
| void CheckConflictingVarDeclarations(PreParserScope scope, bool* ok) {}
|
| @@ -1745,6 +1768,7 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
|
| // RegExpLiteral
|
| // ClassLiteral
|
| // '(' Expression ')'
|
| + // TemplateLiteral
|
|
|
| int pos = peek_position();
|
| ExpressionT result = this->EmptyExpression();
|
| @@ -1840,6 +1864,54 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
|
| // If we're not allowing special syntax we fall-through to the
|
| // default case.
|
|
|
| + case Token::TEMPLATE_SPAN: {
|
| + typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral();
|
| + // Add TV / TRV
|
| + Consume(Token::TEMPLATE_SPAN);
|
| + int pos = position();
|
| + Traits::AddTemplateSpan(&ts);
|
| +
|
| + for (;;) {
|
| + Token::Value next = peek();
|
| + if (next < 0) {
|
| + ReportMessage("unterminated_template");
|
| + *ok = false;
|
| + return Traits::EmptyExpression();
|
| + }
|
| +
|
| + // Parse an Expression
|
| + 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 = Next(Scanner::TemplateLiteral);
|
| + if (next == Token::ILLEGAL || next < 0) {
|
| + ReportMessage("unterminated_template");
|
| + *ok = false;
|
| + return Traits::EmptyExpression();
|
| + }
|
| +
|
| + CHECK(next == Token::TEMPLATE_SPAN || next == Token::TEMPLATE_TAIL);
|
| + Traits::AddTemplateSpan(&ts);
|
| +
|
| + if (next == Token::TEMPLATE_TAIL) {
|
| + break;
|
| + }
|
| + }
|
| + result = Traits::CloseTemplateLiteral(&ts, pos);
|
| + } break;
|
| +
|
| + case Token::TEMPLATE_TAIL: {
|
| + // Close TemplateLiteral
|
| + typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral();
|
| + Consume(Token::TEMPLATE_TAIL);
|
| + int pos = position();
|
| + Traits::AddTemplateSpan(&ts);
|
| + result = Traits::CloseTemplateLiteral(&ts, pos);
|
| + } break;
|
| +
|
| default: {
|
| Next();
|
| ReportUnexpectedToken(token);
|
| @@ -2443,6 +2515,14 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
|
| break;
|
| }
|
|
|
| + case Token::TEMPLATE_SPAN:
|
| + case Token::TEMPLATE_TAIL: {
|
| + ExpressionT templateLiteral = ParsePrimaryExpression(CHECK_OK);
|
| + USE(templateLiteral);
|
| + // TODO: Make sure we can invoke the tag with the expected parameters.
|
| + break;
|
| + }
|
| +
|
| case Token::PERIOD: {
|
| Consume(Token::PERIOD);
|
| int pos = position();
|
|
|