public Node parseForStatement(Node node) { Node init; bool forIn; List<Node> initSeq; Token initStartToken; Node test; Node update; Node left = null, right = null; string kind; List<Node> declarations; List<Node> body; bool oldInIteration; bool previousAllowIn = state.allowIn; init = test = update = null; forIn = true; expectKeyword("for"); expect("("); if (match(";")) { lex(); } else { if (matchKeyword("var")) { init = new Node(); lex(); state.allowIn = false; declarations = parseVariableDeclarationList(new Options() { inFor = true }); state.allowIn = previousAllowIn; if (declarations.Count == 1 && matchKeyword("in")) { init = init.finishVariableDeclaration(declarations); lex(); left = init; right = parseExpression(); init = null; } else if (declarations.Count == 1 && declarations[0].init == null && matchContextualKeyword("of")) { init = init.finishVariableDeclaration(declarations); lex(); left = init; right = parseAssignmentExpression(); init = null; forIn = false; } else { init = init.finishVariableDeclaration(declarations); expect(";"); } } else if (matchKeyword("const") || matchKeyword("let")) { init = new Node(); kind = lex().value; state.allowIn = false; declarations = parseBindingList(kind, new Options() { inFor = true }); state.allowIn = previousAllowIn; if (declarations.Count == 1 && declarations[0].init == null && matchKeyword("in")) { init = init.finishLexicalDeclaration(declarations, kind); lex(); left = init; right = parseExpression(); init = null; } else if (declarations.Count == 1 && declarations[0].init == null && matchContextualKeyword("of")) { init = init.finishLexicalDeclaration(declarations, kind); lex(); left = init; right = parseAssignmentExpression(); init = null; forIn = false; } else { consumeSemicolon(); init = init.finishLexicalDeclaration(declarations, kind); } } else { initStartToken = lookahead; state.allowIn = false; init = inheritCoverGrammar(parseAssignmentExpression); state.allowIn = previousAllowIn; if (matchKeyword("in")) { if (!isAssignmentTarget) { tolerateError(Messages.InvalidLHSInForIn); } lex(); reinterpretExpressionAsPattern(init); left = init; right = parseExpression(); init = null; } else if (matchContextualKeyword("of")) { if (!isAssignmentTarget) { tolerateError(Messages.InvalidLHSInForLoop); } lex(); reinterpretExpressionAsPattern(init); left = init; right = parseAssignmentExpression(); init = null; forIn = false; } else { if (match(",")) { initSeq = new List<Node>() { init }; while (match(",")) { lex(); initSeq.Add(isolateCoverGrammar(parseAssignmentExpression)); } init = new Node(initStartToken).finishSequenceExpression(initSeq); } expect(";"); } } } if (left != null) { if (!match(";")) { test = parseExpression(); } expect(";"); if (!match(")")) { update = parseExpression(); } } expect(")"); oldInIteration = state.inIteration; state.inIteration = true; body = new List<Node>() { isolateCoverGrammar(parseStatement) }; state.inIteration = oldInIteration; return (left == null) ? node.finishForStatement(init, test, update, body) : forIn ? node.finishForInStatement(left, right, body) : node.finishForOfStatement(left, right, body); }