コード例 #1
0
 /**
  * @param $sentence
  * @param array|Symbol[][] $parseSets
  * @param array|Symbol[] $nonTerminals
  * @param array|Symbol[] $terminals
  *
  * @return ArraySet
  */
 private function buildFirstSet($sentence, array $parseSets, array $nonTerminals, array $terminals)
 {
     $firstSets = $this->buildFirstSets($nonTerminals, $parseSets);
     $sentenceList = $this->buildSentenceList($sentence, $nonTerminals, $terminals);
     $set = new ArraySet();
     $calculator = new FirstSetCalculator();
     $calculator->processSymbolList($set, $sentenceList, $firstSets);
     return $set;
 }
コード例 #2
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;
 }
コード例 #3
0
ファイル: SetsGenerator.php プロジェクト: helstern/nomsky-lib
 /**
  * @param array|NormalizedProduction[] $productions
  * @param ParseSets $firstSets
  * @param SymbolSet $emptySet
  *
  * @return SetsGenerator
  */
 public function generateFirstSets(array $productions, ParseSets $firstSets, SymbolSet $emptySet)
 {
     //add epsilon to the first sets of the non terminals which generate epsilon
     foreach ($productions as $production) {
         $lhs = $production->getLeftHandSide();
         if ($emptySet->contains($lhs)) {
             $firstSets->addEpsilon($lhs);
         }
     }
     //initialize the obvious first sets of productions which start with a terminal
     foreach ($productions as $production) {
         $symbol = $production->getFirstSymbol();
         if ($symbol->getType() == Symbol::TYPE_TERMINAL) {
             $firstSets->addTerminal($production->getLeftHandSide(), $symbol);
         }
     }
     //initialize first sets for productions which contain several non-terminals
     do {
         $changes = false;
         foreach ($productions as $production) {
             $updateSet = new ArraySet();
             $rhs = $production->getRightHandSide();
             $this->firstSetCalculator->processSymbolList($updateSet, $rhs, $firstSets);
             $nonTerminal = $production->getLeftHandSide();
             $changes |= $firstSets->addAllTerminals($nonTerminal, $updateSet);
         }
     } while ($changes);
     return $this;
 }
コード例 #4
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;
 }