< prev index next >
src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java
Print this page
@@ -890,11 +890,11 @@
switch (type) {
case LBRACE:
block();
break;
case VAR:
- variableStatement(type, true);
+ variableStatement(type);
break;
case SEMICOLON:
emptyStatement();
break;
case IF:
@@ -944,15 +944,15 @@
default:
if (useBlockScope() && (type == LET || type == CONST)) {
if (singleStatement) {
throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
}
- variableStatement(type, true);
+ variableStatement(type);
break;
}
if (env._const_as_var && type == CONST) {
- variableStatement(TokenType.VAR, true);
+ variableStatement(TokenType.VAR);
break;
}
if (type == IDENT || isNonStrictModeIdent()) {
if (T(k + 1) == COLON) {
@@ -1045,11 +1045,11 @@
throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
}
}
}
- /**
+ /*
* VariableStatement :
* var VariableDeclarationList ;
*
* VariableDeclarationList :
* VariableDeclaration
@@ -1064,12 +1064,12 @@
* See 12.2
*
* Parse a VAR statement.
* @param isStatement True if a statement (not used in a FOR.)
*/
- private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
- return variableStatement(varType, isStatement, -1);
+ private List<VarNode> variableStatement(final TokenType varType) {
+ return variableStatement(varType, true, -1);
}
private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement, final int sourceOrder) {
// VAR tested in caller.
next();
@@ -1213,10 +1213,11 @@
*
* See 12.6
*
* Parse a FOR statement.
*/
+ @SuppressWarnings("fallthrough")
private void forStatement() {
final long forToken = token;
final int forLine = line;
// start position of this for statement. This is used
// for sort order for variables declared in the initializer
@@ -1233,10 +1234,11 @@
Expression init = null;
JoinPredecessorExpression test = null;
JoinPredecessorExpression modify = null;
int flags = 0;
+ boolean isForOf = false;
try {
// FOR tested in caller.
next();
@@ -1290,45 +1292,53 @@
if (type != RPAREN) {
modify = joinPredecessorExpression();
}
break;
+ case IDENT:
+ if (env._es6 && "of".equals(getValue())) {
+ isForOf = true;
+ // fall through
+ } else {
+ expect(SEMICOLON); // fail with expected message
+ break;
+ }
case IN:
- flags |= ForNode.IS_FOR_IN;
+
+ flags |= isForOf ? ForNode.IS_FOR_OF : ForNode.IS_FOR_IN;
test = new JoinPredecessorExpression();
if (vars != null) {
// for (var i in obj)
if (vars.size() == 1) {
init = new IdentNode(vars.get(0).getName());
} else {
// for (var i, j in obj) is invalid
- throw error(AbstractParser.message("many.vars.in.for.in.loop"), vars.get(1).getToken());
+ throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), vars.get(1).getToken());
}
-
} else {
// for (expr in obj)
- assert init != null : "for..in init expression can not be null here";
+ assert init != null : "for..in/of init expression can not be null here";
// check if initial expression is a valid L-value
if (!(init instanceof AccessNode ||
init instanceof IndexNode ||
init instanceof IdentNode)) {
- throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
+ throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
}
if (init instanceof IdentNode) {
if (!checkIdentLValue((IdentNode)init)) {
- throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
+ throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
}
- verifyStrictIdent((IdentNode)init, "for-in iterator");
+ verifyStrictIdent((IdentNode)init, isForOf ? "for-of iterator" : "for-in iterator");
}
}
next();
- // Get the collection expression.
- modify = joinPredecessorExpression();
+ // For-of only allows AssignmentExpression.
+ modify = isForOf ? new JoinPredecessorExpression(assignmentExpression(false)) : joinPredecessorExpression();
break;
default:
expect(SEMICOLON);
break;
< prev index next >