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 ]----- */
|
||||
|
||||
var AST_Jump = DEFNODE("Jump", null, {
|
||||
|
||||
@@ -776,6 +776,20 @@ function OutputStream(options) {
|
||||
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){
|
||||
var self = this;
|
||||
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_CHARS = makePredicate(characters("[]{}(),;:"));
|
||||
var PUNC_CHARS = makePredicate(characters("[]{}(),;:`"));
|
||||
|
||||
var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
|
||||
|
||||
@@ -595,6 +595,9 @@ function tokenizer($TEXT, filename, html5_comments) {
|
||||
parse_error("Unexpected character '" + ch + "'");
|
||||
};
|
||||
|
||||
next_token.next = next;
|
||||
next_token.peek = peek;
|
||||
|
||||
next_token.context = function(nc) {
|
||||
if (nc) S = nc;
|
||||
return S;
|
||||
@@ -805,6 +808,7 @@ function parse($TEXT, options) {
|
||||
});
|
||||
case "[":
|
||||
case "(":
|
||||
case "`":
|
||||
return simple_statement();
|
||||
case ";":
|
||||
next();
|
||||
@@ -1336,6 +1340,8 @@ function parse($TEXT, options) {
|
||||
return subscripts(array_(), allow_calls);
|
||||
case "{":
|
||||
return subscripts(object_or_object_destructuring_(), allow_calls);
|
||||
case "`":
|
||||
return subscripts(template_string(), allow_calls);
|
||||
}
|
||||
unexpected();
|
||||
}
|
||||
@@ -1352,6 +1358,38 @@ function parse($TEXT, options) {
|
||||
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) {
|
||||
var first = true, a = [];
|
||||
while (!is("punc", closing)) {
|
||||
|
||||
@@ -46,6 +46,16 @@ typeof_arrow_functions: {
|
||||
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: {
|
||||
input: {
|
||||
(function ( a ) { });
|
||||
|
||||
Reference in New Issue
Block a user