1049 /**
1050 * VariableStatement :
1051 * var VariableDeclarationList ;
1052 *
1053 * VariableDeclarationList :
1054 * VariableDeclaration
1055 * VariableDeclarationList , VariableDeclaration
1056 *
1057 * VariableDeclaration :
1058 * Identifier Initializer?
1059 *
1060 * Initializer :
1061 * = AssignmentExpression
1062 *
1063 * See 12.2
1064 *
1065 * Parse a VAR statement.
1066 * @param isStatement True if a statement (not used in a FOR.)
1067 */
1068 private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
1069 // VAR tested in caller.
1070 next();
1071
1072 final List<VarNode> vars = new ArrayList<>();
1073 int varFlags = 0;
1074 if (varType == LET) {
1075 varFlags |= VarNode.IS_LET;
1076 } else if (varType == CONST) {
1077 varFlags |= VarNode.IS_CONST;
1078 }
1079
1080 while (true) {
1081 // Get starting token.
1082 final int varLine = line;
1083 final long varToken = token;
1084 // Get name of var.
1085 final IdentNode name = getIdent();
1086 verifyStrictIdent(name, "variable name");
1087
1088 // Assume no init.
1089 Expression init = null;
1090
1091 // Look for initializer assignment.
1092 if (type == ASSIGN) {
1093 next();
1094
1095 // Get initializer expression. Suppress IN if not statement.
1096 defaultNames.push(name);
1097 try {
1098 init = assignmentExpression(!isStatement);
1099 } finally {
1100 defaultNames.pop();
1101 }
1102 } else if (varType == CONST) {
1103 throw error(AbstractParser.message("missing.const.assignment", name.getName()));
1104 }
1105
1106 // Allocate var node.
1107 final VarNode var = new VarNode(varLine, varToken, finish, name.setIsDeclaredHere(), init, varFlags);
1108 vars.add(var);
1109 appendStatement(var);
1110
1111 if (type != COMMARIGHT) {
1112 break;
1113 }
1114 next();
1115 }
1116
1117 // If is a statement then handle end of line.
1118 if (isStatement) {
1119 endOfLine();
1120 }
1121
1122 return vars;
1123 }
1124
1125 /**
1126 * EmptyStatement :
1127 * ;
1194 }
1195
1196 appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail));
1197 }
1198
1199 /**
1200 * ... IterationStatement:
1201 * ...
1202 * for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1203 * for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1204 * for ( LeftHandSideExpression in Expression ) Statement
1205 * for ( var VariableDeclaration[NoIn] in Expression ) Statement
1206 *
1207 * See 12.6
1208 *
1209 * Parse a FOR statement.
1210 */
1211 private void forStatement() {
1212 final long forToken = token;
1213 final int forLine = line;
1214 // When ES6 for-let is enabled we create a container block to capture the LET.
1215 final int startLine = start;
1216 final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
1217
1218 // Create FOR node, capturing FOR token.
1219 final ParserContextLoopNode forNode = new ParserContextLoopNode();
1220 lc.push(forNode);
1221 Block body = null;
1222 List<VarNode> vars = null;
1223 Expression init = null;
1224 JoinPredecessorExpression test = null;
1225 JoinPredecessorExpression modify = null;
1226
1227 int flags = 0;
1228
1229 try {
1230 // FOR tested in caller.
1231 next();
1232
1233 // Nashorn extension: for each expression.
1234 // iterate property values rather than property names.
1235 if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1236 flags |= ForNode.IS_FOR_EACH;
1237 next();
1238 }
1239
1240 expect(LPAREN);
1241
1242
1243 switch (type) {
1244 case VAR:
1245 // Var declaration captured in for outer block.
1246 vars = variableStatement(type, false);
1247 break;
1248 case SEMICOLON:
1249 break;
1250 default:
1251 if (useBlockScope() && (type == LET || type == CONST)) {
1252 if (type == LET) {
1253 flags |= ForNode.PER_ITERATION_SCOPE;
1254 }
1255 // LET/CONST declaration captured in container block created above.
1256 vars = variableStatement(type, false);
1257 break;
1258 }
1259 if (env._const_as_var && type == CONST) {
1260 // Var declaration captured in for outer block.
1261 vars = variableStatement(TokenType.VAR, false);
1262 break;
1263 }
1264
1265 init = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1266 break;
1267 }
1268
1269 switch (type) {
1270 case SEMICOLON:
1271 // for (init; test; modify)
1272
1273 // for each (init; test; modify) is invalid
1274 if ((flags & ForNode.IS_FOR_EACH) != 0) {
1275 throw error(AbstractParser.message("for.each.without.in"), token);
1276 }
1277
1278 expect(SEMICOLON);
1279 if (type != SEMICOLON) {
1280 test = joinPredecessorExpression();
1281 }
|
1049 /**
1050 * VariableStatement :
1051 * var VariableDeclarationList ;
1052 *
1053 * VariableDeclarationList :
1054 * VariableDeclaration
1055 * VariableDeclarationList , VariableDeclaration
1056 *
1057 * VariableDeclaration :
1058 * Identifier Initializer?
1059 *
1060 * Initializer :
1061 * = AssignmentExpression
1062 *
1063 * See 12.2
1064 *
1065 * Parse a VAR statement.
1066 * @param isStatement True if a statement (not used in a FOR.)
1067 */
1068 private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
1069 return variableStatement(varType, isStatement, -1);
1070 }
1071
1072 private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement, final int sourceOrder) {
1073 // VAR tested in caller.
1074 next();
1075
1076 final List<VarNode> vars = new ArrayList<>();
1077 int varFlags = 0;
1078 if (varType == LET) {
1079 varFlags |= VarNode.IS_LET;
1080 } else if (varType == CONST) {
1081 varFlags |= VarNode.IS_CONST;
1082 }
1083
1084 while (true) {
1085 // Get starting token.
1086 final int varLine = line;
1087 final long varToken = token;
1088 // Get name of var.
1089 final IdentNode name = getIdent();
1090 verifyStrictIdent(name, "variable name");
1091
1092 // Assume no init.
1093 Expression init = null;
1094
1095 // Look for initializer assignment.
1096 if (type == ASSIGN) {
1097 next();
1098
1099 // Get initializer expression. Suppress IN if not statement.
1100 defaultNames.push(name);
1101 try {
1102 init = assignmentExpression(!isStatement);
1103 } finally {
1104 defaultNames.pop();
1105 }
1106 } else if (varType == CONST) {
1107 throw error(AbstractParser.message("missing.const.assignment", name.getName()));
1108 }
1109
1110 // Allocate var node.
1111 final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, name.setIsDeclaredHere(), init, varFlags);
1112 vars.add(var);
1113 appendStatement(var);
1114
1115 if (type != COMMARIGHT) {
1116 break;
1117 }
1118 next();
1119 }
1120
1121 // If is a statement then handle end of line.
1122 if (isStatement) {
1123 endOfLine();
1124 }
1125
1126 return vars;
1127 }
1128
1129 /**
1130 * EmptyStatement :
1131 * ;
1198 }
1199
1200 appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail));
1201 }
1202
1203 /**
1204 * ... IterationStatement:
1205 * ...
1206 * for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1207 * for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1208 * for ( LeftHandSideExpression in Expression ) Statement
1209 * for ( var VariableDeclaration[NoIn] in Expression ) Statement
1210 *
1211 * See 12.6
1212 *
1213 * Parse a FOR statement.
1214 */
1215 private void forStatement() {
1216 final long forToken = token;
1217 final int forLine = line;
1218 // start position of this for statement. This is used
1219 // for sort order for variables declared in the initialzer
1220 // part of this 'for' statement (if any).
1221 final int forStart = Token.descPosition(forToken);
1222 // When ES6 for-let is enabled we create a container block to capture the LET.
1223 final int startLine = start;
1224 final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
1225
1226 // Create FOR node, capturing FOR token.
1227 final ParserContextLoopNode forNode = new ParserContextLoopNode();
1228 lc.push(forNode);
1229 Block body = null;
1230 List<VarNode> vars = null;
1231 Expression init = null;
1232 JoinPredecessorExpression test = null;
1233 JoinPredecessorExpression modify = null;
1234
1235 int flags = 0;
1236
1237 try {
1238 // FOR tested in caller.
1239 next();
1240
1241 // Nashorn extension: for each expression.
1242 // iterate property values rather than property names.
1243 if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1244 flags |= ForNode.IS_FOR_EACH;
1245 next();
1246 }
1247
1248 expect(LPAREN);
1249
1250
1251 switch (type) {
1252 case VAR:
1253 // Var declaration captured in for outer block.
1254 vars = variableStatement(type, false, forStart);
1255 break;
1256 case SEMICOLON:
1257 break;
1258 default:
1259 if (useBlockScope() && (type == LET || type == CONST)) {
1260 if (type == LET) {
1261 flags |= ForNode.PER_ITERATION_SCOPE;
1262 }
1263 // LET/CONST declaration captured in container block created above.
1264 vars = variableStatement(type, false, forStart);
1265 break;
1266 }
1267 if (env._const_as_var && type == CONST) {
1268 // Var declaration captured in for outer block.
1269 vars = variableStatement(TokenType.VAR, false, forStart);
1270 break;
1271 }
1272
1273 init = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1274 break;
1275 }
1276
1277 switch (type) {
1278 case SEMICOLON:
1279 // for (init; test; modify)
1280
1281 // for each (init; test; modify) is invalid
1282 if ((flags & ForNode.IS_FOR_EACH) != 0) {
1283 throw error(AbstractParser.message("for.each.without.in"), token);
1284 }
1285
1286 expect(SEMICOLON);
1287 if (type != SEMICOLON) {
1288 test = joinPredecessorExpression();
1289 }
|