diff options
Diffstat (limited to 'lib/parse.js')
-rw-r--r-- | lib/parse.js | 72 |
1 files changed, 56 insertions, 16 deletions
diff --git a/lib/parse.js b/lib/parse.js index 872561ff..b3c3f977 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -47,7 +47,7 @@ var KEYWORDS = "break case catch const continue debugger default delete do else finally for function if in instanceof let new return switch throw try typeof var 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 let long native package private protected public short static super synchronized this throws transient volatile yield", + "await 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, ].join(" "); @@ -656,6 +656,7 @@ function parse($TEXT, options) { token : null, prev : null, peeked : null, + in_async : false, in_function : 0, in_directives : true, in_loop : 0, @@ -786,9 +787,20 @@ function parse($TEXT, options) { return simple_statement(); case "name": - return is_token(peek(), "punc", ":") - ? labeled_statement() - : simple_statement(); + switch (S.token.value) { + case "async": + if (is_token(peek(), "keyword", "function")) { + next(); + next(); + return function_(AST_AsyncDefun); + } + case "await": + if (S.in_async) return simple_statement(); + default: + return is_token(peek(), "punc", ":") + ? labeled_statement() + : simple_statement(); + } case "punc": switch (S.token.value) { @@ -1026,10 +1038,18 @@ function parse($TEXT, options) { } var function_ = function(ctor) { - var in_statement = ctor === AST_Defun; - var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null; - if (in_statement && !name) - expect_token("name"); + var was_async = S.in_async; + var name; + if (ctor === AST_AsyncDefun) { + name = as_symbol(AST_SymbolDefun); + S.in_async = true; + } else if (ctor === AST_Defun) { + name = as_symbol(AST_SymbolDefun); + S.in_async = false; + } else { + S.in_async = ctor === AST_AsyncFunction; + name = as_symbol(AST_SymbolLambda, true); + } if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration)) unexpected(prev()); expect("("); @@ -1055,6 +1075,7 @@ function parse($TEXT, options) { --S.in_function; S.in_loop = loop; S.labels = labels; + S.in_async = was_async; return new ctor({ name: name, argnames: argnames, @@ -1304,9 +1325,16 @@ function parse($TEXT, options) { } unexpected(); } - if (is("keyword", "function")) { + var ctor; + if (is("name", "async") && is_token(peek(), "keyword", "function")) { next(); - var func = function_(AST_Function); + ctor = AST_AsyncFunction; + } else if (is("keyword", "function")) { + ctor = AST_Function; + } + if (ctor) { + next(); + var func = function_(ctor); func.start = start; func.end = prev(); return subscripts(func, allow_calls); @@ -1451,6 +1479,7 @@ function parse($TEXT, options) { function _make_symbol(type, token) { var name = token.value; + if (name === "await" && S.in_async) unexpected(token); return new (name === "this" ? AST_This : type)({ name: "" + name, start: token, @@ -1573,17 +1602,17 @@ function parse($TEXT, options) { return expr; }; - var maybe_unary = function(allow_calls) { + function maybe_unary() { var start = S.token; if (is("operator") && UNARY_PREFIX[start.value]) { next(); handle_regexp(); - var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(allow_calls)); + var ex = make_unary(AST_UnaryPrefix, start, maybe_await()); ex.start = start; ex.end = prev(); return ex; } - var val = expr_atom(allow_calls); + var val = expr_atom(true); while (is("operator") && UNARY_POSTFIX[S.token.value] && !has_newline_before(S.token)) { val = make_unary(AST_UnaryPostfix, S.token, val); val.start = start; @@ -1591,7 +1620,7 @@ function parse($TEXT, options) { next(); } return val; - }; + } function make_unary(ctor, token, expr) { var op = token.value; @@ -1609,13 +1638,24 @@ function parse($TEXT, options) { return new ctor({ operator: op, expression: expr }); } + function maybe_await() { + var start = S.token; + if (!(S.in_async && is("name", "await"))) return maybe_unary(); + next(); + return new AST_Await({ + start: start, + expression: maybe_await(), + end: prev(), + }); + } + var expr_op = function(left, min_prec, no_in) { var op = is("operator") ? S.token.value : null; if (op == "in" && no_in) op = null; var prec = op != null ? PRECEDENCE[op] : null; if (prec != null && prec > min_prec) { next(); - var right = expr_op(maybe_unary(true), prec, no_in); + var right = expr_op(maybe_await(), prec, no_in); return expr_op(new AST_Binary({ start : left.start, left : left, @@ -1628,7 +1668,7 @@ function parse($TEXT, options) { }; function expr_ops(no_in) { - return expr_op(maybe_unary(true), 0, no_in); + return expr_op(maybe_await(), 0, no_in); } var maybe_conditional = function(no_in) { |