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(); |