Example #1
0
 /**
  * @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;
 }
 /**
  * Calculates the first set of $list and adds it's elements to $set
  *
  * @param \Helstern\Nomsky\Grammar\Symbol\SymbolSet $newFirstSet
  * @param array|NormalizedProduction[] $list
  * @param \Helstern\Nomsky\GrammarAnalysis\ParseSets\ParseSets $firstSets
  *
  * @return bool if the epsilon symbol was added to $set
  */
 public function processSymbolList(SymbolSet $newFirstSet, array $list, ParseSets $firstSets)
 {
     if (0 == count($list)) {
         $newFirstSet->add(new EpsilonSymbol());
         return true;
     }
     if (1 == count($list)) {
         /** @var Symbol $symbol */
         $symbol = $list[0];
         return $this->processSymbol($newFirstSet, $symbol, $firstSets);
     }
     $symbolIsEpsilon = SymbolIsEpsilon::singletonInstance();
     $symbolsIsNonTerminal = SymbolTypeEquals::newInstanceMatchingNonTerminals();
     /** @var SymbolSet $lastSet */
     $lastSet = null;
     $epsilonCounter = new MatchCountingInterceptor($symbolIsEpsilon);
     $acceptor = Inverter::newInstance($epsilonCounter);
     //we assume there is no epsilon symbol in the $list list
     $previousSymbol = reset($list);
     //add the first non-terminal and continue past this one later on
     if ($symbolsIsNonTerminal->matchSymbol($previousSymbol)) {
         $lastSet = $firstSets->filterTerminalSet($previousSymbol, $acceptor);
         $newFirstSet->addAll($lastSet);
     } else {
         $newFirstSet->add($previousSymbol);
     }
     //as long as the previous symbol was a non-terminal, process the next symbol
     for (next($list); !is_null(key($list)) && $symbolsIsNonTerminal->matchSymbol($previousSymbol) && $epsilonCounter->getMatchCount() > 0; next($list)) {
         $previousSymbol = current($list);
         $epsilonCounter = new MatchCountingInterceptor($symbolIsEpsilon);
         $acceptor = Inverter::newInstance($epsilonCounter);
         if ($symbolsIsNonTerminal->matchSymbol($previousSymbol)) {
             $lastSet = $firstSets->filterTerminalSet($previousSymbol, $acceptor);
             $newFirstSet->addAll($lastSet);
         } else {
             $newFirstSet->add($previousSymbol);
         }
     }
     if (is_null(key($list)) && $symbolsIsNonTerminal->matchSymbol($previousSymbol) && $epsilonCounter->getMatchCount() > 0) {
         $newFirstSet->add(new EpsilonSymbol());
         return true;
     }
     return false;
 }
 public function findAllNonTerminals()
 {
     $predicate = SymbolTypeEquals::newInstance(Symbol::TYPE_NON_TERMINAL);
     return $this->findMax($predicate, PHP_INT_MAX);
 }