예제 #1
0
 /**
  * @param \Helstern\Nomsky\Grammar\Symbol\SymbolSet $set
  * @param NormalizedProduction $production
  * @param \Helstern\Nomsky\GrammarAnalysis\ParseSets\ParseSets $followSets
  * @param \Helstern\Nomsky\GrammarAnalysis\ParseSets\ParseSets $firstSets
  *
  * @return bool
  */
 public function processProduction(SymbolSet $set, NormalizedProduction $production, ParseSets $followSets, ParseSets $firstSets)
 {
     $rhs = $production->getRightHandSide();
     $epsilonAdded = $this->firstSetCalculator->processSymbolList($set, $rhs, $firstSets);
     if ($epsilonAdded) {
         $lhs = $production->getLeftHandSide();
         $otherSet = $followSets->getTerminalSet($lhs);
         $set->addAll($otherSet);
     }
     return $epsilonAdded;
 }
예제 #2
0
 /**
  * @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;
 }
예제 #3
0
 /**
  * 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;
 }
예제 #4
0
 /**
  * @return ParseSets
  */
 public static function followSets()
 {
     $sets = new ParseSets([StandardSymbol::nonTerminal('S'), StandardSymbol::nonTerminal('B'), StandardSymbol::nonTerminal('C')]);
     $sets->addTerminal(StandardSymbol::nonTerminal('S'), StandardSymbol::terminal('e'));
     $sets->addTerminal(StandardSymbol::nonTerminal('S'), new EpsilonSymbol());
     $sets->addTerminal(StandardSymbol::nonTerminal('B'), StandardSymbol::terminal('e'));
     $sets->addTerminal(StandardSymbol::nonTerminal('B'), new EpsilonSymbol());
     $sets->addTerminal(StandardSymbol::nonTerminal('C'), StandardSymbol::terminal('e'));
     $sets->addTerminal(StandardSymbol::nonTerminal('C'), new EpsilonSymbol());
     return $sets;
 }
예제 #5
0
 /**
  * @param array|NormalizedProduction[] $productions
  * @param Symbol $startSymbol
  * @param ParseSets $followSets
  * @param ParseSets $firstSets
  *
  * @return \Helstern\Nomsky\GrammarAnalysis\ParseSets\SetsGenerator
  */
 public function generateFollowSets(array $productions, Symbol $startSymbol, ParseSets $followSets, ParseSets $firstSets)
 {
     $followSets->addEpsilon($startSymbol);
     $occurrences = new \ArrayObject();
     foreach ($productions as $production) {
         $symbol = $production->getLeftHandSide();
         $rhs = $production->getRightHandSide();
         $this->followSetCalculator->addNonTerminalOccurrences($occurrences, $symbol, $rhs);
     }
     do {
         $changes = false;
         /** @var SymbolOccurrence $occurrence */
         foreach ($occurrences as $occurrence) {
             $set = new ArraySet();
             if ($this->followSetCalculator->processOccurrence($set, $occurrence, $followSets, $firstSets)) {
                 $symbol = $occurrence->getSymbol();
                 $changes |= $followSets->addAllTerminals($symbol, $set);
             }
         }
     } while ($changes);
     return $this;
 }
 /**
  * @param array|Symbol[] $nonTerminals
  * @param array|Symbol[][] $parseSets
  *
  * @return \Helstern\Nomsky\GrammarAnalysis\ParseSets\ParseSets
  */
 private function buildFirstSets(array $nonTerminals, array $parseSets)
 {
     $firstSets = new ParseSets(array_values($nonTerminals));
     foreach ($parseSets as $nonTerminal => $listOfTerminals) {
         foreach ($listOfTerminals as $terminal) {
             $firstSets->addTerminal($nonTerminals[$nonTerminal], $terminal);
         }
     }
     return $firstSets;
 }