public function getEndPosition() {
        // TODO test invariant - start of next node is end of previous node
        for ($i = \count($childKeys = $this::CHILD_NAMES) - 1; $i >= 0; $i--) {
            $lastChildKey = $childKeys[$i];
            $lastChild = $this->$lastChildKey;

            if (\is_array($lastChild)) {
                $lastChild = \end($lastChild);
            }

            if ($lastChild instanceof Token) {
                return $lastChild->fullStart + $lastChild->length;
            } elseif ($lastChild instanceof Node) {
                return $lastChild->getEndPosition();
            }
        }

        throw new \Exception("Unhandled node type");
    }