/** * @return PaccSet<PaccLRItem> */ private function closure(PaccSet $items) { if ($items->getType() !== 'PaccLRItem') { throw new InvalidArgumentException('Bad type - expected PaccSet<LRItem>, given PaccSet<' . $items->getType() . '>.'); } do { $done = TRUE; $itemscopy = clone $items; foreach ($items as $item) { if (!(count($item->afterDot()) >= 1 && current($item->afterDot()) instanceof PaccNonterminal)) { continue; } $newitems = new PaccSet('PaccLRItem'); $beta_first = new PaccSet('integer'); if (count($item->afterDot()) > 1) { $beta_first->add(next($item->afterDot())->first); $beta_first->delete($this->grammar->epsilon->index); } if ($beta_first->isEmpty()) { $beta_first->add($item->terminalindex); } $B = current($item->afterDot()); foreach ($this->grammar->productions as $production) { if ($B->__eq($production->left)) { foreach ($beta_first as $terminalindex) { $newitems->add(new PaccLRItem($production, 0, $terminalindex)); } } } if (!$newitems->isEmpty() && !$itemscopy->contains($newitems)) { $itemscopy->add($newitems); $done = FALSE; } } $items = $itemscopy; } while (!$done); return $items; }