Merge 9715ef8544 into 6c8db6eae1
This commit is contained in:
commit
5f6d9d637a
23
lib/ast.js
23
lib/ast.js
|
|
@ -262,6 +262,22 @@ var AST_ForIn = DEFNODE("ForIn", "init name object", {
|
|||
}
|
||||
}, AST_IterationStatement);
|
||||
|
||||
var AST_ForOf = DEFNODE("ForOf", "init name object", {
|
||||
$documentation: "A `for ... of` statement",
|
||||
$propdoc: {
|
||||
init: "[AST_Node] the `for/of` initialization code",
|
||||
name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
|
||||
object: "[AST_Node] the object that we're looping through"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.init._walk(visitor);
|
||||
this.object._walk(visitor);
|
||||
this.body._walk(visitor);
|
||||
});
|
||||
}
|
||||
}, AST_IterationStatement);
|
||||
|
||||
var AST_With = DEFNODE("With", "expression", {
|
||||
$documentation: "A `with` statement",
|
||||
$propdoc: {
|
||||
|
|
@ -359,9 +375,10 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
|||
}
|
||||
}, AST_Scope);
|
||||
|
||||
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
|
||||
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments isgenerator", {
|
||||
$documentation: "Base class for functions",
|
||||
$propdoc: {
|
||||
isgenerator: "is generatorFn or not",
|
||||
name: "[AST_SymbolDeclaration?] the name of this function",
|
||||
argnames: "[AST_SymbolFunarg*] array of function arguments",
|
||||
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
|
||||
|
|
@ -546,6 +563,10 @@ var AST_Const = DEFNODE("Const", null, {
|
|||
$documentation: "A `const` statement"
|
||||
}, AST_Definitions);
|
||||
|
||||
var AST_Let = DEFNODE("Let", null, {
|
||||
$documentation: "A `let` statement"
|
||||
}, AST_Definitions);
|
||||
|
||||
var AST_VarDef = DEFNODE("VarDef", "name value", {
|
||||
$documentation: "A variable declaration; only appears in a AST_Definitions node",
|
||||
$propdoc: {
|
||||
|
|
|
|||
|
|
@ -227,6 +227,10 @@ function OutputStream(options) {
|
|||
might_need_space = true;
|
||||
};
|
||||
|
||||
var star = function(){
|
||||
print("*");
|
||||
}
|
||||
|
||||
var indent = options.beautify ? function(half) {
|
||||
if (options.beautify) {
|
||||
print(make_indent(half ? 0.5 : 0));
|
||||
|
|
@ -339,6 +343,7 @@ function OutputStream(options) {
|
|||
newline : newline,
|
||||
print : print,
|
||||
space : space,
|
||||
star : star,
|
||||
comma : comma,
|
||||
colon : colon,
|
||||
last : function() { return last },
|
||||
|
|
@ -723,6 +728,19 @@ function OutputStream(options) {
|
|||
output.space();
|
||||
self._do_print_body(output);
|
||||
});
|
||||
DEFPRINT(AST_ForOf, function(self, output){
|
||||
output.print("for");
|
||||
output.space();
|
||||
output.with_parens(function(){
|
||||
self.init.print(output);
|
||||
output.space();
|
||||
output.print("of");
|
||||
output.space();
|
||||
self.object.print(output);
|
||||
});
|
||||
output.space();
|
||||
self._do_print_body(output);
|
||||
});
|
||||
DEFPRINT(AST_With, function(self, output){
|
||||
output.print("with");
|
||||
output.space();
|
||||
|
|
@ -738,6 +756,8 @@ function OutputStream(options) {
|
|||
var self = this;
|
||||
if (!nokeyword) {
|
||||
output.print("function");
|
||||
if(this.isgenerator)
|
||||
output.star();
|
||||
}
|
||||
if (self.name) {
|
||||
output.space();
|
||||
|
|
@ -923,7 +943,7 @@ function OutputStream(options) {
|
|||
def.print(output);
|
||||
});
|
||||
var p = output.parent();
|
||||
var in_for = p instanceof AST_For || p instanceof AST_ForIn;
|
||||
var in_for = p instanceof AST_For || p instanceof AST_ForIn || p instanceof AST_ForOf;
|
||||
var avoid_semicolon = in_for && p.init === this;
|
||||
if (!avoid_semicolon)
|
||||
output.semicolon();
|
||||
|
|
@ -934,6 +954,9 @@ function OutputStream(options) {
|
|||
DEFPRINT(AST_Const, function(self, output){
|
||||
self._do_print(output, "const");
|
||||
});
|
||||
DEFPRINT(AST_Let, function(self, output){
|
||||
self._do_print(output, "let");
|
||||
});
|
||||
|
||||
function parenthesize_for_noin(node, output, noin) {
|
||||
if (!noin) node.print(output);
|
||||
|
|
@ -958,7 +981,7 @@ function OutputStream(options) {
|
|||
output.print("=");
|
||||
output.space();
|
||||
var p = output.parent(1);
|
||||
var noin = p instanceof AST_For || p instanceof AST_ForIn;
|
||||
var noin = p instanceof AST_For || p instanceof AST_ForIn || p instanceof AST_ForOf;
|
||||
parenthesize_for_noin(self.value, output, noin);
|
||||
}
|
||||
});
|
||||
|
|
@ -1038,7 +1061,10 @@ function OutputStream(options) {
|
|||
output.print(self.operator);
|
||||
});
|
||||
DEFPRINT(AST_Binary, function(self, output){
|
||||
var isYield = (self.left.operator == "yield" || self.left.operator === "yield*");
|
||||
isYield && output.print("(");
|
||||
self.left.print(output);
|
||||
isYield && output.print(")");
|
||||
output.space();
|
||||
output.print(self.operator);
|
||||
if (self.operator == "<"
|
||||
|
|
@ -1053,7 +1079,10 @@ function OutputStream(options) {
|
|||
// the space is optional depending on "beautify"
|
||||
output.space();
|
||||
}
|
||||
isYield = (self.right.operator == "yield" || self.right.operator === "yield*");
|
||||
isYield && output.print("(");
|
||||
self.right.print(output);
|
||||
isYield && output.print(")");
|
||||
});
|
||||
DEFPRINT(AST_Conditional, function(self, output){
|
||||
self.condition.print(output);
|
||||
|
|
|
|||
47
lib/parse.js
47
lib/parse.js
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with';
|
||||
var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return yield switch throw try typeof var let void while with';
|
||||
var KEYWORDS_ATOM = 'false null true';
|
||||
var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile yield'
|
||||
+ " " + KEYWORDS_ATOM + " " + KEYWORDS;
|
||||
|
|
@ -66,6 +66,7 @@ var OPERATORS = makePredicate([
|
|||
"instanceof",
|
||||
"typeof",
|
||||
"new",
|
||||
"yield",
|
||||
"void",
|
||||
"delete",
|
||||
"++",
|
||||
|
|
@ -586,6 +587,7 @@ var UNARY_PREFIX = makePredicate([
|
|||
"typeof",
|
||||
"void",
|
||||
"delete",
|
||||
"yield",
|
||||
"--",
|
||||
"++",
|
||||
"!",
|
||||
|
|
@ -851,6 +853,9 @@ function parse($TEXT, options) {
|
|||
case "var":
|
||||
return tmp = var_(), semicolon(), tmp;
|
||||
|
||||
case "let":
|
||||
return tmp = let_(), semicolon(), tmp;
|
||||
|
||||
case "const":
|
||||
return tmp = const_(), semicolon(), tmp;
|
||||
|
||||
|
|
@ -923,13 +928,21 @@ function parse($TEXT, options) {
|
|||
if (!is("punc", ";")) {
|
||||
init = is("keyword", "var")
|
||||
? (next(), var_(true))
|
||||
: expression(true, true);
|
||||
: is("keyword", "let")
|
||||
? (next(), let_(true))
|
||||
:expression(true, true);
|
||||
if (is("operator", "in")) {
|
||||
if (init instanceof AST_Var && init.definitions.length > 1)
|
||||
croak("Only one variable declaration allowed in for..in loop");
|
||||
next();
|
||||
return for_in(init);
|
||||
}
|
||||
if (is("name", "of")) {
|
||||
if (init instanceof AST_Var && init.definitions.length > 1)
|
||||
croak("Only one variable declaration allowed in for..of loop");
|
||||
next();
|
||||
return for_of(init);
|
||||
}
|
||||
}
|
||||
return regular_for(init);
|
||||
};
|
||||
|
|
@ -960,14 +973,30 @@ function parse($TEXT, options) {
|
|||
});
|
||||
};
|
||||
|
||||
function for_of(init){
|
||||
var lhs = init instanceof AST_Var ? init.definitions[0].name : null;
|
||||
var obj = expression(true);
|
||||
expect(")");
|
||||
return new AST_ForOf({
|
||||
init : init,
|
||||
name : lhs,
|
||||
object : obj,
|
||||
body : in_loop(statement)
|
||||
});
|
||||
}
|
||||
|
||||
var function_ = function(ctor) {
|
||||
var in_statement = ctor === AST_Defun;
|
||||
var isgenerator = is("operator", "*");
|
||||
if (isgenerator)
|
||||
next();
|
||||
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
|
||||
if (in_statement && !name)
|
||||
unexpected();
|
||||
expect("(");
|
||||
return new ctor({
|
||||
name: name,
|
||||
isgenerator: isgenerator,
|
||||
argnames: (function(first, a){
|
||||
while (!is("punc", ")")) {
|
||||
if (first) first = false; else expect(",");
|
||||
|
|
@ -1114,6 +1143,14 @@ function parse($TEXT, options) {
|
|||
});
|
||||
};
|
||||
|
||||
var let_ = function(no_in) {
|
||||
return new AST_Let({
|
||||
start : prev(),
|
||||
definitions : vardefs(no_in, false),
|
||||
end : prev()
|
||||
});
|
||||
};
|
||||
|
||||
var new_ = function() {
|
||||
var start = S.token;
|
||||
expect_token("operator", "new");
|
||||
|
|
@ -1358,6 +1395,10 @@ function parse($TEXT, options) {
|
|||
var start = S.token;
|
||||
if (is("operator") && UNARY_PREFIX(start.value)) {
|
||||
next();
|
||||
if(start.type === "operator" && start.value === "yield" && is("operator", "*")) {
|
||||
start.value = "yield*";
|
||||
next()
|
||||
}
|
||||
handle_regexp();
|
||||
var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls));
|
||||
ex.start = start;
|
||||
|
|
@ -1382,7 +1423,7 @@ function parse($TEXT, options) {
|
|||
|
||||
var expr_op = function(left, min_prec, no_in) {
|
||||
var op = is("operator") ? S.token.value : null;
|
||||
if (op == "in" && no_in) op = null;
|
||||
if (op == "in"&& no_in) op = null;
|
||||
var prec = op != null ? PRECEDENCE[op] : null;
|
||||
if (prec != null && prec > min_prec) {
|
||||
next();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user