/** * The bounded-exhaustive algorithm. * * @param \Hoa\Compiler\Llk\Rule $rule Rule to cover. * @param int $next Next rule. * @return bool */ protected function boundedExhaustive(Compiler\Llk\Rule $rule, $next) { $content = $rule->getContent(); if ($rule instanceof Compiler\Llk\Rule\Repetition) { if (0 === $next) { $this->_trace[] = new Compiler\Llk\Rule\Entry($rule->getName(), $rule->getMin()); array_pop($this->_todo); $this->_todo[] = new Compiler\Llk\Rule\Ekzit($rule->getName(), $rule->getMin(), $this->_todo); for ($i = 0, $min = $rule->getMin(); $i < $min; ++$i) { $this->_todo[] = new Compiler\Llk\Rule\Ekzit($content, 0); $this->_todo[] = new Compiler\Llk\Rule\Entry($content, 0); } } else { $nbToken = 0; foreach ($this->_trace as $trace) { if ($trace instanceof Compiler\Llk\Rule\Token) { ++$nbToken; } } $max = $rule->getMax(); if (-1 != $max && $next > $max) { return false; } $this->_todo[] = new Compiler\Llk\Rule\Ekzit($rule->getName(), $next, $this->_todo); $this->_todo[] = new Compiler\Llk\Rule\Ekzit($content, 0); $this->_todo[] = new Compiler\Llk\Rule\Entry($content, 0); } return true; } elseif ($rule instanceof Compiler\Llk\Rule\Choice) { if (count($content) <= $next) { return false; } $this->_trace[] = new Compiler\Llk\Rule\Entry($rule->getName(), $next, $this->_todo); $nextRule = $content[$next]; $this->_todo[] = new Compiler\Llk\Rule\Ekzit($nextRule, 0); $this->_todo[] = new Compiler\Llk\Rule\Entry($nextRule, 0); return true; } elseif ($rule instanceof Compiler\Llk\Rule\Concatenation) { $this->_trace[] = new Compiler\Llk\Rule\Entry($rule->getName(), $next); for ($i = count($content) - 1; $i >= 0; --$i) { $nextRule = $content[$i]; $this->_todo[] = new Compiler\Llk\Rule\Ekzit($nextRule, 0); $this->_todo[] = new Compiler\Llk\Rule\Entry($nextRule, 0); } return true; } elseif ($rule instanceof Compiler\Llk\Rule\Token) { $nbToken = 0; foreach ($this->_trace as $trace) { if ($trace instanceof Compiler\Llk\Rule\Token) { ++$nbToken; } } if ($nbToken >= $this->getLength()) { return false; } $this->_trace[] = $rule; array_pop($this->_todo); return true; } return false; }