Skip to content

Commit

Permalink
Change member expression parsing.
Browse files Browse the repository at this point in the history
Because of the nature of brackets like [] and (), we can't use run-time
patching to capture the position before and after some member expression
parsing routines. The solution is to create a specialized version when
we need to track the syntax node location.

Coverage regression is expected (temporarily) until variation in the
parsing options when running the test suite gets implemented.

http://code.google.com/p/esprima/issues/detail?id=324
http://code.google.com/p/esprima/issues/detail?id=343
  • Loading branch information
ariya committed Sep 19, 2012
1 parent 1f72370 commit 8f3fdb9
Show file tree
Hide file tree
Showing 2 changed files with 225 additions and 72 deletions.
215 changes: 144 additions & 71 deletions esprima.js
Expand Up @@ -1590,36 +1590,22 @@ parseStatement: true, parseSourceElement: true */
};
}

function parseNonComputedMember(object) {
return {
type: Syntax.MemberExpression,
computed: false,
object: object,
property: parseNonComputedProperty()
};
function parseNonComputedMember() {
expect('.');

return parseNonComputedProperty();
}

function parseComputedMember(object) {
var property, expr;
function parseComputedMember() {
var expr;

expect('[');
property = parseExpression();
expr = {
type: Syntax.MemberExpression,
computed: true,
object: object,
property: property
};

expr = parseExpression();

expect(']');
return expr;
}

function parseCallMember(object) {
return {
type: Syntax.CallExpression,
callee: object,
'arguments': parseArguments()
};
return expr;
}

function parseNewExpression() {
Expand All @@ -1641,41 +1627,58 @@ parseStatement: true, parseSourceElement: true */
}

function parseLeftHandSideExpressionAllowCall() {
var useNew, expr;
var expr;

useNew = matchKeyword('new');
expr = useNew ? parseNewExpression() : parsePrimaryExpression();
expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();

while (index < length) {
if (match('.')) {
lex();
expr = parseNonComputedMember(expr);
while (match('.') || match('[') || match('(')) {
if (match('(')) {
expr = {
type: Syntax.CallExpression,
callee: expr,
'arguments': parseArguments()
};
} else if (match('[')) {
expr = parseComputedMember(expr);
} else if (match('(')) {
expr = parseCallMember(expr);
expr = {
type: Syntax.MemberExpression,
computed: true,
object: expr,
property: parseComputedMember()
};
} else {
break;
expr = {
type: Syntax.MemberExpression,
computed: false,
object: expr,
property: parseNonComputedMember()
};
}
}

return expr;
}


function parseLeftHandSideExpression() {
var useNew, expr;
var expr;

useNew = matchKeyword('new');
expr = useNew ? parseNewExpression() : parsePrimaryExpression();
expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();

while (index < length) {
if (match('.')) {
lex();
expr = parseNonComputedMember(expr);
} else if (match('[')) {
expr = parseComputedMember(expr);
while (match('.') || match('[')) {
if (match('[')) {
expr = {
type: Syntax.MemberExpression,
computed: true,
object: expr,
property: parseComputedMember()
};
} else {
break;
expr = {
type: Syntax.MemberExpression,
computed: false,
object: expr,
property: parseNonComputedMember()
};
}
}

Expand Down Expand Up @@ -3378,16 +3381,99 @@ parseStatement: true, parseSourceElement: true */

marker.apply = function (node) {
if (extra.range) {
node.range = this.range;
node.range = [this.range[0], this.range[1]];
}
if (extra.loc) {
node.loc = this.loc;
node.loc = {
start: {
line: this.loc.start.line,
column: this.loc.start.column
},
end: {
line: this.loc.end.line,
column: this.loc.end.column
}
};
}
};

return marker;
}

function trackLeftHandSideExpression() {
var marker, expr;

skipComment();
marker = createLocationMarker();

expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();

while (match('.') || match('[')) {
if (match('[')) {
expr = {
type: Syntax.MemberExpression,
computed: true,
object: expr,
property: parseComputedMember()
};
marker.end();
marker.apply(expr);
} else {
expr = {
type: Syntax.MemberExpression,
computed: false,
object: expr,
property: parseNonComputedMember()
};
marker.end();
marker.apply(expr);
}
}

return expr;
}

function trackLeftHandSideExpressionAllowCall() {
var marker, expr;

skipComment();
marker = createLocationMarker();

expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();

while (match('.') || match('[') || match('(')) {
if (match('(')) {
expr = {
type: Syntax.CallExpression,
callee: expr,
'arguments': parseArguments()
};
marker.end();
marker.apply(expr);
} else if (match('[')) {
expr = {
type: Syntax.MemberExpression,
computed: true,
object: expr,
property: parseComputedMember()
};
marker.end();
marker.apply(expr);
} else {
expr = {
type: Syntax.MemberExpression,
computed: false,
object: expr,
property: parseNonComputedMember()
};
marker.end();
marker.apply(expr);
}
}

return expr;
}

function wrapTrackingFunction(range, loc) {

return function (parseFunction) {
Expand Down Expand Up @@ -3437,24 +3523,6 @@ parseStatement: true, parseSourceElement: true */
visit(node);
}

if (node.type === Syntax.MemberExpression) {
if (typeof node.object.range !== 'undefined') {
node.range[0] = node.object.range[0];
}
if (typeof node.object.loc !== 'undefined') {
node.loc.start = node.object.loc.start;
}
}

if (node.type === Syntax.CallExpression) {
if (typeof node.callee.range !== 'undefined') {
node.range[0] = node.callee.range[0];
}
if (typeof node.callee.loc !== 'undefined') {
node.loc.start = node.callee.loc.start;
}
}

return node;
};
};
Expand All @@ -3476,6 +3544,11 @@ parseStatement: true, parseSourceElement: true */

if (extra.range || extra.loc) {

extra.parseLeftHandSideExpression = parseLeftHandSideExpression;
extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall;
parseLeftHandSideExpression = trackLeftHandSideExpression;
parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall;

wrapTracking = wrapTrackingFunction(extra.range, extra.loc);

extra.parseAdditiveExpression = parseAdditiveExpression;
Expand All @@ -3485,7 +3558,6 @@ parseStatement: true, parseSourceElement: true */
extra.parseBitwiseXORExpression = parseBitwiseXORExpression;
extra.parseBlock = parseBlock;
extra.parseFunctionSourceElements = parseFunctionSourceElements;
extra.parseCallMember = parseCallMember;
extra.parseCatchClause = parseCatchClause;
extra.parseComputedMember = parseComputedMember;
extra.parseConditionalExpression = parseConditionalExpression;
Expand All @@ -3495,11 +3567,12 @@ parseStatement: true, parseSourceElement: true */
extra.parseForVariableDeclaration = parseForVariableDeclaration;
extra.parseFunctionDeclaration = parseFunctionDeclaration;
extra.parseFunctionExpression = parseFunctionExpression;
extra.parseLeftHandSideExpression = parseLeftHandSideExpression;
extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall;
extra.parseLogicalANDExpression = parseLogicalANDExpression;
extra.parseLogicalORExpression = parseLogicalORExpression;
extra.parseMultiplicativeExpression = parseMultiplicativeExpression;
extra.parseNewExpression = parseNewExpression;
extra.parseNonComputedMember = parseNonComputedMember;
extra.parseNonComputedProperty = parseNonComputedProperty;
extra.parseObjectProperty = parseObjectProperty;
extra.parseObjectPropertyKey = parseObjectPropertyKey;
Expand All @@ -3522,7 +3595,6 @@ parseStatement: true, parseSourceElement: true */
parseBitwiseXORExpression = wrapTracking(extra.parseBitwiseXORExpression);
parseBlock = wrapTracking(extra.parseBlock);
parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements);
parseCallMember = wrapTracking(extra.parseCallMember);
parseCatchClause = wrapTracking(extra.parseCatchClause);
parseComputedMember = wrapTracking(extra.parseComputedMember);
parseConditionalExpression = wrapTracking(extra.parseConditionalExpression);
Expand All @@ -3532,11 +3604,12 @@ parseStatement: true, parseSourceElement: true */
parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration);
parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration);
parseFunctionExpression = wrapTracking(extra.parseFunctionExpression);
parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression);
parseLeftHandSideExpressionAllowCall = wrapTracking(parseLeftHandSideExpressionAllowCall);
parseLogicalANDExpression = wrapTracking(extra.parseLogicalANDExpression);
parseLogicalORExpression = wrapTracking(extra.parseLogicalORExpression);
parseMultiplicativeExpression = wrapTracking(extra.parseMultiplicativeExpression);
parseNewExpression = wrapTracking(extra.parseNewExpression);
parseNonComputedMember = wrapTracking(extra.parseNonComputedMember);
parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty);
parseObjectProperty = wrapTracking(extra.parseObjectProperty);
parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey);
Expand Down Expand Up @@ -3579,7 +3652,6 @@ parseStatement: true, parseSourceElement: true */
parseBitwiseXORExpression = extra.parseBitwiseXORExpression;
parseBlock = extra.parseBlock;
parseFunctionSourceElements = extra.parseFunctionSourceElements;
parseCallMember = extra.parseCallMember;
parseCatchClause = extra.parseCatchClause;
parseComputedMember = extra.parseComputedMember;
parseConditionalExpression = extra.parseConditionalExpression;
Expand All @@ -3589,11 +3661,12 @@ parseStatement: true, parseSourceElement: true */
parseForVariableDeclaration = extra.parseForVariableDeclaration;
parseFunctionDeclaration = extra.parseFunctionDeclaration;
parseFunctionExpression = extra.parseFunctionExpression;
parseLeftHandSideExpression = extra.parseLeftHandSideExpression;
parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall;
parseLogicalANDExpression = extra.parseLogicalANDExpression;
parseLogicalORExpression = extra.parseLogicalORExpression;
parseMultiplicativeExpression = extra.parseMultiplicativeExpression;
parseNewExpression = extra.parseNewExpression;
parseNonComputedMember = extra.parseNonComputedMember;
parseNonComputedProperty = extra.parseNonComputedProperty;
parseObjectProperty = extra.parseObjectProperty;
parseObjectPropertyKey = extra.parseObjectPropertyKey;
Expand Down

0 comments on commit 8f3fdb9

Please sign in to comment.