private Node parseForEach() {
		if (!EAT(TokenType.OPEN)) {
			return null;
		}

		if (!EAT(TokenType.FOREACH)) {
			return null;
		}

		Node iterNode = parseIdent();
		if (iterNode == null) {
			throw new ParserError("No variable name after (FOR|FOREACH)", this);
		}

		if (!EAT(TokenType.IN)) {
			throw new ParserError("No 'IN' keyword after (FOR|FOREACH)", this);
		}

		Node expr = parseExpr();
		if (expr == null) {
			throw new ParserError("No expression after (FOR|FOREACH)", this);
		}

		if (!EAT(TokenType.CLOSE)) {
			throw new ParserError("Missing closing tag after (FOR|FOREACH)",
					this);
		}

		Node body = parseTemplateBody();
		if (body == null) {
			throw new ParserError("No template body after (FOR|FOREACH)", this);
		}

		if (!parseEnd()) {
			throw new ParserError("No `[% END %]` after (FOR|FOREACH)", this);
		}

		List<Node> children = new ArrayList<>();
		children.add(iterNode);
		children.add(expr);
		children.add(body);
		return new Node(NodeType.FOREACH, children, PREV_LINE_NUMBER());
	}