1<?php
2
3declare(strict_types=1);
4
5/*
6 * This file is part of the league/commonmark package.
7 *
8 * (c) Colin O'Dell <colinodell@gmail.com>
9 *
10 * For the full copyright and license information, please view the LICENSE
11 * file that was distributed with this source code.
12 */
13
14namespace League\CommonMark\Node;
15
16use League\CommonMark\Node\Block\AbstractBlock;
17
18/**
19 * @implements \IteratorAggregate<int, Node>
20 */
21final class NodeIterator implements \IteratorAggregate
22{
23    public const FLAG_BLOCKS_ONLY = 1;
24
25    private Node $node;
26    private bool $blocksOnly;
27
28    public function __construct(Node $node, int $flags = 0)
29    {
30        $this->node       = $node;
31        $this->blocksOnly = ($flags & self::FLAG_BLOCKS_ONLY) === self::FLAG_BLOCKS_ONLY;
32    }
33
34    /**
35     * @return \Generator<int, Node>
36     */
37    public function getIterator(): \Generator
38    {
39        $stack = [$this->node];
40        $index = 0;
41
42        while ($stack) {
43            $node = \array_pop($stack);
44
45            yield $index++ => $node;
46
47            // Push all children onto the stack in reverse order
48            $child = $node->lastChild();
49            while ($child !== null) {
50                if (! $this->blocksOnly || $child instanceof AbstractBlock) {
51                    $stack[] = $child;
52                }
53
54                $child = $child->previous();
55            }
56        }
57    }
58}
59