/**
  * @return Symbol[]
  */
 public function getTerminals()
 {
     $visitor = new SymbolCollectorVisitor(SymbolTypeEquals::newInstanceMatchingTerminals());
     $walks = Walks::singletonInstance();
     $productions = $this->getProductions();
     foreach ($productions as $production) {
         $expression = $production->getExpression();
         $walks->depthFirstWalk($expression, $visitor);
     }
     $terminals = $visitor->getCollected();
     return $terminals;
 }
 /**
  * @param \Helstern\Nomsky\Grammar\Symbol\SymbolSet $set
  * @param SymbolOccurrence $occurrence
  * @param \Helstern\Nomsky\GrammarAnalysis\ParseSets\ParseSets $followSets
  * @param \Helstern\Nomsky\GrammarAnalysis\ParseSets\ParseSets $firstSets
  *
  * @return bool
  */
 public function processOccurrence(SymbolSet $set, SymbolOccurrence $occurrence, ParseSets $followSets, ParseSets $firstSets)
 {
     $symbol = $occurrence->getSymbol();
     $isTerminal = SymbolTypeEquals::newInstanceMatchingTerminals();
     if ($isTerminal->matchSymbol($symbol)) {
         return false;
     }
     $following = $occurrence->getFollowing();
     $epsilonAdded = $this->firstSetCalculator->processSymbolList($set, $following, $firstSets);
     if ($epsilonAdded) {
         $set->remove(new EpsilonSymbol());
         $lhs = $occurrence->getProductionNonTerminal();
         $otherSet = $followSets->getTerminalSet($lhs);
         $set->addAll($otherSet);
     }
     return true;
 }