Parse and output ES6 template strings. Yikes!
This commit is contained in:
16
lib/ast.js
16
lib/ast.js
@@ -501,6 +501,22 @@ var AST_Destructuring = DEFNODE("Destructuring", "names is_array", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var AST_TemplateString = DEFNODE("TemplateString", "segments", {
|
||||||
|
$documentation: "A template string literal",
|
||||||
|
$propdoc: {
|
||||||
|
segments: "[string|AST_Expression]* One or more segments. They can be the parts that are evaluated, or the raw string parts."
|
||||||
|
},
|
||||||
|
_walk: function(visitor) {
|
||||||
|
return visitor._visit(this, function(){
|
||||||
|
this.segments.forEach(function(seg, i){
|
||||||
|
if (i % 2 !== 0) {
|
||||||
|
seg._walk(visitor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/* -----[ JUMPS ]----- */
|
/* -----[ JUMPS ]----- */
|
||||||
|
|
||||||
var AST_Jump = DEFNODE("Jump", null, {
|
var AST_Jump = DEFNODE("Jump", null, {
|
||||||
|
|||||||
@@ -776,6 +776,20 @@ function OutputStream(options) {
|
|||||||
self._do_print(output);
|
self._do_print(output);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
DEFPRINT(AST_TemplateString, function(self, output) {
|
||||||
|
output.print("`");
|
||||||
|
for (var i = 0; i < self.segments.length; i++) {
|
||||||
|
if (typeof self.segments[i] !== "string") {
|
||||||
|
output.print("${");
|
||||||
|
self.segments[i].print(output);
|
||||||
|
output.print("}");
|
||||||
|
} else {
|
||||||
|
output.print(self.segments[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output.print("`");
|
||||||
|
});
|
||||||
|
|
||||||
AST_Arrow.DEFMETHOD("_do_print", function(output){
|
AST_Arrow.DEFMETHOD("_do_print", function(output){
|
||||||
var self = this;
|
var self = this;
|
||||||
var parent = output.parent();
|
var parent = output.parent();
|
||||||
|
|||||||
40
lib/parse.js
40
lib/parse.js
@@ -114,7 +114,7 @@ var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u18
|
|||||||
|
|
||||||
var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
|
var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
|
||||||
|
|
||||||
var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
|
var PUNC_CHARS = makePredicate(characters("[]{}(),;:`"));
|
||||||
|
|
||||||
var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
|
var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
|
||||||
|
|
||||||
@@ -595,6 +595,9 @@ function tokenizer($TEXT, filename, html5_comments) {
|
|||||||
parse_error("Unexpected character '" + ch + "'");
|
parse_error("Unexpected character '" + ch + "'");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
next_token.next = next;
|
||||||
|
next_token.peek = peek;
|
||||||
|
|
||||||
next_token.context = function(nc) {
|
next_token.context = function(nc) {
|
||||||
if (nc) S = nc;
|
if (nc) S = nc;
|
||||||
return S;
|
return S;
|
||||||
@@ -805,6 +808,7 @@ function parse($TEXT, options) {
|
|||||||
});
|
});
|
||||||
case "[":
|
case "[":
|
||||||
case "(":
|
case "(":
|
||||||
|
case "`":
|
||||||
return simple_statement();
|
return simple_statement();
|
||||||
case ";":
|
case ";":
|
||||||
next();
|
next();
|
||||||
@@ -1336,6 +1340,8 @@ function parse($TEXT, options) {
|
|||||||
return subscripts(array_(), allow_calls);
|
return subscripts(array_(), allow_calls);
|
||||||
case "{":
|
case "{":
|
||||||
return subscripts(object_or_object_destructuring_(), allow_calls);
|
return subscripts(object_or_object_destructuring_(), allow_calls);
|
||||||
|
case "`":
|
||||||
|
return subscripts(template_string(), allow_calls);
|
||||||
}
|
}
|
||||||
unexpected();
|
unexpected();
|
||||||
}
|
}
|
||||||
@@ -1352,6 +1358,38 @@ function parse($TEXT, options) {
|
|||||||
unexpected();
|
unexpected();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function template_string() {
|
||||||
|
var tokenizer_S = S.input, start = S.token, segments = [], segment = "", ch;
|
||||||
|
|
||||||
|
while ((ch = tokenizer_S.next()) !== "`") {
|
||||||
|
if (ch === "$" && tokenizer_S.peek() === "{") {
|
||||||
|
segments.push(segment); segment = "";
|
||||||
|
tokenizer_S.next();
|
||||||
|
next();
|
||||||
|
segments.push(expression());
|
||||||
|
expect("}");
|
||||||
|
if (is("punc", "`")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
segment += ch;
|
||||||
|
if (ch === "\\") {
|
||||||
|
segment += tokenizer_S.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
segments.push(segment);
|
||||||
|
|
||||||
|
next();
|
||||||
|
|
||||||
|
return new AST_TemplateString({
|
||||||
|
start: start,
|
||||||
|
segments: segments,
|
||||||
|
end: S.token
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function expr_list(closing, allow_trailing_comma, allow_empty) {
|
function expr_list(closing, allow_trailing_comma, allow_empty) {
|
||||||
var first = true, a = [];
|
var first = true, a = [];
|
||||||
while (!is("punc", closing)) {
|
while (!is("punc", closing)) {
|
||||||
|
|||||||
@@ -46,6 +46,16 @@ typeof_arrow_functions: {
|
|||||||
expect_exact: "\"function\";"
|
expect_exact: "\"function\";"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template_strings: {
|
||||||
|
input: {
|
||||||
|
``;
|
||||||
|
`xx\`x`;
|
||||||
|
`${ foo + 2 }`;
|
||||||
|
` foo ${ bar + `baz ${ qux }` }`;
|
||||||
|
}
|
||||||
|
expect_exact: "``;`xx\\`x`;`${foo+2}`;` foo ${bar+`baz ${qux}`}`;";
|
||||||
|
}
|
||||||
|
|
||||||
destructuring_arguments: {
|
destructuring_arguments: {
|
||||||
input: {
|
input: {
|
||||||
(function ( a ) { });
|
(function ( a ) { });
|
||||||
|
|||||||
Reference in New Issue
Block a user