/**
  * Calculates the first set of the symbol $source and adds it's elements to $set
  *
  * @param \Helstern\Nomsky\Grammar\Symbol\SymbolSet $set
  * @param \Helstern\Nomsky\Grammar\Symbol\Symbol $source
  * @param \Helstern\Nomsky\GrammarAnalysis\ParseSets\ParseSets $firstSets
  *
  * @return boolean if the epsilon symbol was added to $set
  */
 public function processSymbol(SymbolSet $set, Symbol $source, ParseSets $firstSets)
 {
     $symbolIsEpsilon = SymbolIsEpsilon::singletonInstance();
     if ($symbolIsEpsilon->matchSymbol($source)) {
         $set->add(new EpsilonSymbol());
         return true;
     }
     $symbolsIsNonTerminal = SymbolTypeEquals::newInstanceMatchingNonTerminals();
     if ($symbolsIsNonTerminal->matchSymbol($source)) {
         $epsilonCounter = new MatchCountingInterceptor($symbolIsEpsilon);
         $acceptPredicate = Inverter::newInstance($epsilonCounter);
         $otherSet = $firstSets->filterTerminalSet($source, $acceptPredicate);
         $set->addAll($otherSet);
         if ($epsilonCounter->getMatchCount() > 0) {
             $set->add(new EpsilonSymbol());
             return true;
         }
         return false;
     }
     $set->add($source);
     return false;
 }