Basic ES6 Arrow Expressions support.

Added Property type to ObjectExpression properties.
Reserved ES6 properties in Property type.
This commit is contained in:
Ingvar Stepanyan 2014-07-24 01:44:22 +03:00 committed by Marijn Haverbeke
parent 12ac95732d
commit 757545a612
2 changed files with 93 additions and 29 deletions

View File

@ -313,6 +313,7 @@
var _braceR = {type: "}"}, _parenL = {type: "(", beforeExpr: true}, _parenR = {type: ")"};
var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true};
var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _ellipsis = {type: "..."}, _question = {type: "?", beforeExpr: true};
var _arrow = {type: "=>", beforeExpr: true};
// Operators. These carry several kinds of properties to help the
// parser use them properly (the presence of these properties is
@ -667,9 +668,13 @@
return finishOp(_relational, size);
}
function readToken_eq_excl(code) { // '=!'
function readToken_eq_excl(code) { // '=!', '=>'
var next = input.charCodeAt(tokPos + 1);
if (next === 61) return finishOp(_equality, input.charCodeAt(tokPos + 2) === 61 ? 3 : 2);
if (code === 61 && next === 62 && options.ecmaVersion >= 6) { // '=>'
tokPos += 2;
return finishToken(_arrow);
}
return finishOp(code === 61 ? _eq : _prefix, 1);
}
@ -1134,8 +1139,8 @@
// Raise an unexpected token error.
function unexpected() {
raise(tokStart, "Unexpected token");
function unexpected(pos) {
raise(pos != null ? pos : tokStart, "Unexpected token");
}
// Verify that a node is an lval — something that can be assigned
@ -1656,8 +1661,14 @@
var node = startNode();
next();
return finishNode(node, "ThisExpression");
case _name:
return parseIdent();
var id = parseIdent();
if (eat(_arrow)) {
return parseArrowExpression(startNodeFrom(id), [id]);
}
return id;
case _num: case _string: case _regexp:
var node = startNode();
node.value = tokVal;
@ -1673,18 +1684,27 @@
return finishNode(node, "Literal");
case _parenL:
var tokStartLoc1 = tokStartLoc, tokStart1 = tokStart;
var node = startNode(), tokStartLoc1 = tokStartLoc, tokStart1 = tokStart, val;
next();
var val = parseExpression();
if (tokType !== _parenR) {
val = parseExpression();
}
expect(_parenR);
if (eat(_arrow)) {
val = parseArrowExpression(node, !val ? [] : val.type === "SequenceExpression" ? val.expressions : [val]);
} else
// disallow '()' before everything but error
if (!val) {
unexpected(tokPos - 1);
}
val.start = tokStart1;
val.end = tokEnd;
val.end = lastEnd;
if (options.locations) {
val.loc.start = tokStartLoc1;
val.loc.end = tokEndLoc;
val.loc.end = lastEndLoc;
}
if (options.ranges)
val.range = [tokStart1, tokEnd];
expect(_parenR);
val.range = [tokStart1, lastEnd];
return val;
case _bracketL:
@ -1734,7 +1754,8 @@
if (options.allowTrailingCommas && eat(_braceR)) break;
} else first = false;
var prop = {key: parsePropertyName()}, isGetSet = false, kind;
var prop = startNode(), isGetSet = false, kind;
prop.key = parsePropertyName();
if (eat(_colon)) {
prop.value = parseExpression(true);
kind = prop.kind = "init";
@ -1762,7 +1783,12 @@
}
}
}
node.properties.push(prop);
if (options.ecmaVersion >= 6) {
prop.method = false;
prop.shorthand = false;
prop.computed = false;
}
node.properties.push(finishNode(prop, "Property"));
}
return finishNode(node, "ObjectExpression");
}
@ -1835,6 +1861,43 @@
return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
}
// Parse arrow function expression with given parameters.
function parseArrowExpression(node, params) {
var defaults = [], hasDefaults = false;
for (var i = 0; i < params.length; i++) {
var param = params[i];
switch (param.type) {
case "Identifier":
defaults.push(null);
break;
case "AssignmentExpression":
defaults.push(param.right);
hasDefaults = true;
params[i] = param.left;
break;
default:
unexpected(param.start);
}
}
var isExpression = tokType !== _braceL;
var body = isExpression ? parseExpression() : parseBlock(true);
node.id = null;
node.params = params;
node.defaults = hasDefaults ? defaults : [];
node.rest = null;
node.body = body;
node.generator = false;
node.expression = isExpression;
return finishNode(node, "ArrowFunctionExpression");
}
// Parses a comma-separated list of expressions, and returns them as
// an array. `close` is the token type that ends the list, and
// `allowEmpty` can be turned on to allow subsequent commas with

View File

@ -35,7 +35,8 @@ if (typeof exports != "undefined") {
}
/*
Tests below are automatically converted from https://github.com/ariya/esprima/blob/2bb17ef9a45c88e82d72c2c61b7b7af93caef028/test/harmonytest.js.
Tests below were automatically converted from https://github.com/ariya/esprima/blob/2bb17ef9a45c88e82d72c2c61b7b7af93caef028/test/harmonytest.js.
Locations for parenthesized expressions and expression statements were manually fixed.
*/
// ES6 Unicode Code Point Escape Sequence
@ -1504,10 +1505,10 @@ test("e => ({ property: 42 })", {
end: {line: 1, column: 20}
}
}],
range: [6, 22],
range: [5, 23],
loc: {
start: {line: 1, column: 6},
end: {line: 1, column: 22}
start: {line: 1, column: 5},
end: {line: 1, column: 23}
}
},
rest: null,
@ -1578,16 +1579,16 @@ test("e => { label: 42 }", {
end: {line: 1, column: 16}
}
},
range: [14, 17],
range: [14, 16],
loc: {
start: {line: 1, column: 14},
end: {line: 1, column: 17}
end: {line: 1, column: 16}
}
},
range: [7, 17],
range: [7, 16],
loc: {
start: {line: 1, column: 7},
end: {line: 1, column: 17}
end: {line: 1, column: 16}
}
}],
range: [5, 18],
@ -2323,10 +2324,10 @@ test("(x => x)", {
rest: null,
generator: false,
expression: true,
range: [1, 7],
range: [0, 8],
loc: {
start: {line: 1, column: 1},
end: {line: 1, column: 7}
start: {line: 1, column: 0},
end: {line: 1, column: 8}
}
},
range: [0, 8],
@ -2493,19 +2494,19 @@ test("(x) => ((y, z) => (x, y, z))", {
}
}
],
range: [19, 26],
range: [18, 27],
loc: {
start: {line: 1, column: 19},
end: {line: 1, column: 26}
start: {line: 1, column: 18},
end: {line: 1, column: 27}
}
},
rest: null,
generator: false,
expression: true,
range: [8, 27],
range: [7, 28],
loc: {
start: {line: 1, column: 8},
end: {line: 1, column: 27}
start: {line: 1, column: 7},
end: {line: 1, column: 28}
}
},
rest: null,