Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Distinguish yield as a keyword vs an identifier. #1222

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ with the help of [many contributors](https://github.com/jquery/esprima/contribut
- Full support for ECMAScript 5.1 ([ECMA-262](http://www.ecma-international.org/publications/standards/Ecma-262.htm))
- Sensible [syntax tree format](https://github.com/estree/estree/blob/master/spec.md) as standardized by [EStree project](https://github.com/estree/estree)
- Optional tracking of syntax node location (index-based and line-column)
- Heavily tested (~1000 [unit tests](https://github.com/jquery/esprima/tree/master/test/fixtures) with [full code coverage](https://travis-ci.org/jquery/esprima))
- Heavily tested (~1100 [unit tests](https://github.com/jquery/esprima/tree/master/test/fixtures) with [full code coverage](https://travis-ci.org/jquery/esprima))
- [Partial support](https://github.com/jquery/esprima/issues/1099) for ECMAScript 6

Esprima serves as a **building block** for some JavaScript
Expand Down
104 changes: 68 additions & 36 deletions esprima.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@
IllegalContinue: 'Illegal continue statement',
IllegalBreak: 'Illegal break statement',
IllegalReturn: 'Illegal return statement',
IllegalYield: 'Unexpected token yield',
StrictModeWith: 'Strict mode code may not include a with statement',
StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
StrictVarName: 'Variable name may not be eval or arguments in strict mode',
Expand Down Expand Up @@ -2679,25 +2678,24 @@
}

function parsePattern(params) {
var identifier;
if (lookahead.type === Token.Identifier) {
params.push(lookahead);
identifier = parseVariableIdentifier();
return identifier;
} else if (match('[')) {
if (match('[')) {
return parseArrayPattern(params);
} else if (match('{')) {
return parseObjectPattern(params);
}
throwUnexpectedToken(lookahead);
params.push(lookahead);
return parseVariableIdentifier();
}

function parsePatternWithDefault(params) {
var startToken = lookahead, pattern, right;
var startToken = lookahead, pattern, previousAllowYield, right;
pattern = parsePattern(params);
if (match('=')) {
lex();
previousAllowYield = state.allowYield;
state.allowYield = true;
right = isolateCoverGrammar(parseAssignmentExpression);
state.allowYield = previousAllowYield;
pattern = new WrappingNode(startToken).finishAssignmentPattern(pattern, right);
}
return pattern;
Expand Down Expand Up @@ -2887,11 +2885,11 @@
key = parseObjectPropertyKey();
methodNode = new Node();

state.allowYield = false;
state.allowYield = true;
params = parseParams();
state.allowYield = previousAllowYield;

state.allowYield = true;
state.allowYield = false;
value = parsePropertyFunction(methodNode, params, true);
state.allowYield = previousAllowYield;

Expand Down Expand Up @@ -3119,6 +3117,13 @@
expect(')');

if (match('=>')) {
if (expr.type === Syntax.Identifier && expr.name === 'yield') {
return {
type: PlaceHolders.ArrowParameterPlaceHolder,
params: [expr]
};
}

if (!isBindingElement) {
throwUnexpectedToken(lookahead);
}
Expand Down Expand Up @@ -3171,6 +3176,9 @@
}
expr = node.finishLiteral(lex());
} else if (type === Token.Keyword) {
if (!strict && state.allowYield && matchKeyword('yield')) {
return parseNonComputedProperty();
}
isAssignmentTarget = isBindingElement = false;
if (matchKeyword('function')) {
return parseFunctionExpression();
Expand Down Expand Up @@ -3635,6 +3643,8 @@
}
}
break;
case Syntax.YieldExpression:
break;
default:
assert(param.type === Syntax.ObjectPattern, 'Invalid type');
for (i = 0; i < param.properties.length; i++) {
Expand Down Expand Up @@ -3669,6 +3679,15 @@
switch (param.type) {
case Syntax.AssignmentPattern:
params[i] = param.left;
if (param.right.type === Syntax.YieldExpression) {
if (param.right.argument) {
throwUnexpectedToken(lookahead);
}
param.right.type = Syntax.Identifier;
param.right.name = 'yield';
delete param.right.argument;
delete param.right.delegate;
}
defaults.push(param.right);
++defaultCount;
checkPatternParam(options, param.left);
Expand All @@ -3681,6 +3700,15 @@
}
}

if (strict || !state.allowYield) {
for (i = 0, len = params.length; i < len; i += 1) {
param = params[i];
if (param.type === Syntax.YieldExpression) {
throwUnexpectedToken(lookahead);
}
}
}

if (options.message === Messages.StrictParamDupe) {
token = strict ? options.stricted : options.firstRestricted;
throwUnexpectedToken(token, options.message);
Expand All @@ -3700,13 +3728,16 @@
}

function parseArrowFunctionExpression(options, node) {
var previousStrict, body;
var previousStrict, previousAllowYield, body;

if (hasLineTerminator) {
tolerateUnexpectedToken(lookahead);
}
expect('=>');

previousStrict = strict;
previousAllowYield = state.allowYield;
state.allowYield = true;

body = parseConciseBody();

Expand All @@ -3718,33 +3749,33 @@
}

strict = previousStrict;
state.allowYield = previousAllowYield;

return node.finishArrowFunctionExpression(options.params, options.defaults, body, body.type !== Syntax.BlockStatement);
}

// [ES6] 14.4 Yield expression

function parseYieldExpression() {
var argument, expr, delegate;
var argument, expr, delegate, previousAllowYield;

expr = new Node();

if (!state.allowYield) {
tolerateUnexpectedToken(lookahead, Messages.IllegalYield);
}

expectKeyword('yield');

if (!hasLineTerminator) {
previousAllowYield = state.allowYield;
state.allowYield = false;
delegate = match('*');
if (delegate) {
lex();
argument = parseExpression();
} else {
if (!match(';') && !match('}') && lookahead.type !== Token.EOF) {
if (!match(';') && !match('}') && !match(')') && lookahead.type !== Token.EOF) {
argument = parseExpression();
}
}
state.allowYield = previousAllowYield;
}

return expr.finishYieldExpression(argument, delegate);
Expand All @@ -3758,7 +3789,7 @@
startToken = lookahead;
token = lookahead;

if (matchKeyword('yield')) {
if (!state.allowYield && matchKeyword('yield')) {
return parseYieldExpression();
}

Expand Down Expand Up @@ -3884,7 +3915,13 @@

token = lex();

if (token.type !== Token.Identifier) {
if (token.type === Token.Keyword && token.value === 'yield') {
if (strict) {
tolerateUnexpectedToken(token, Messages.StrictReservedWord);
} if (!state.allowYield) {
throwUnexpectedToken(token);
}
} else if (token.type !== Token.Identifier) {
if (strict && token.type === Token.Keyword && isStrictModeReservedWord(token.value)) {
tolerateUnexpectedToken(token, Messages.StrictReservedWord);
} else {
Expand Down Expand Up @@ -4777,6 +4814,8 @@
var id = null, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict,
isGenerator, previousAllowYield;

previousAllowYield = state.allowYield;

expectKeyword('function');

isGenerator = match('*');
Expand All @@ -4802,11 +4841,8 @@
}
}

previousAllowYield = state.allowYield;
state.allowYield = false;
state.allowYield = !isGenerator;
tmp = parseParams(firstRestricted);
state.allowYield = previousAllowYield;

params = tmp.params;
defaults = tmp.defaults;
stricted = tmp.stricted;
Expand All @@ -4815,16 +4851,16 @@
message = tmp.message;
}

previousAllowYield = state.allowYield;

previousStrict = strict;
state.allowYield = isGenerator;
body = parseFunctionSourceElements();
if (strict && firstRestricted) {
throwUnexpectedToken(firstRestricted, message);
}
if (strict && stricted) {
tolerateUnexpectedToken(stricted, message);
}

strict = previousStrict;
state.allowYield = previousAllowYield;

Expand All @@ -4836,16 +4872,19 @@
params = [], defaults = [], body, previousStrict, node = new Node(),
isGenerator, previousAllowYield;

previousAllowYield = state.allowYield;

expectKeyword('function');

isGenerator = match('*');
if (isGenerator) {
lex();
}

state.allowYield = !isGenerator;
if (!match('(')) {
token = lookahead;
id = parseVariableIdentifier();
id = (!strict && !isGenerator && matchKeyword('yield')) ? parseNonComputedProperty() : parseVariableIdentifier();
if (strict) {
if (isRestrictedWord(token.value)) {
tolerateUnexpectedToken(token, Messages.StrictFunctionName);
Expand All @@ -4861,11 +4900,7 @@
}
}

previousAllowYield = state.allowYield;
state.allowYield = false;
tmp = parseParams(firstRestricted);
state.allowYield = previousAllowYield;

params = tmp.params;
defaults = tmp.defaults;
stricted = tmp.stricted;
Expand All @@ -4875,10 +4910,7 @@
}

previousStrict = strict;
previousAllowYield = state.allowYield;
state.allowYield = isGenerator;
body = parseFunctionSourceElements();

if (strict && firstRestricted) {
throwUnexpectedToken(firstRestricted, message);
}
Expand Down Expand Up @@ -5347,7 +5379,7 @@
lookahead = null;
state = {
allowIn: true,
allowYield: false,
allowYield: true,
labelSet: {},
inFunctionBody: false,
inIteration: false,
Expand Down Expand Up @@ -5436,7 +5468,7 @@
lookahead = null;
state = {
allowIn: true,
allowYield: false,
allowYield: true,
labelSet: {},
inFunctionBody: false,
inIteration: false,
Expand Down
3 changes: 0 additions & 3 deletions test/fixtures/ES6/generator/generator-binding-property.js

This file was deleted.

Loading