コード例 #1
0
ファイル: Rules.php プロジェクト: bigwhoop/sentence-breaker
 /**
  * @param Rule $rule
  */
 public function addRule(Rule $rule)
 {
     if (array_key_exists($rule->getTokenName(), $this->rules)) {
         $this->rules[$rule->getTokenName()]->addPatterns($rule->getPatterns());
     } else {
         $this->rules[$rule->getTokenName()] = $rule;
     }
 }
コード例 #2
0
 /**
  * @inheritdoc
  */
 public function getRules()
 {
     $data = $this->data;
     $rules = new Rules();
     foreach ($data->rule as $ruleData) {
         $rule = new Rule((string) $ruleData->token);
         $patternIdx = 0;
         foreach ($ruleData->patterns->pattern as $patternData) {
             $patternName = "Pattern {$rule->getTokenName()}#{$patternIdx}";
             $hasStartToken = false;
             $potentialStartTokenIdxs = [];
             $tokens = [];
             foreach ($patternData->token as $tokenData) {
                 $tokenName = (string) $tokenData;
                 $isStartToken = (bool) $tokenData['is_start_token'];
                 $tokens[] = ['name' => $tokenName, 'is_start_token' => $isStartToken];
                 if ($isStartToken) {
                     if ($tokenName !== $rule->getTokenName()) {
                         throw new ConfigurationException("{$patternName}: Only {$rule->getTokenName()} tokens can have the 'is_start_token' attribute.");
                     }
                     if ($hasStartToken) {
                         throw new ConfigurationException("{$patternName}: Multiple {$rule->getTokenName()} tokens with 'is_start_token' attribute found. Only one is allowed.");
                     } else {
                         $hasStartToken = true;
                     }
                 }
                 if ($tokenName === $rule->getTokenName()) {
                     $potentialStartTokenIdxs[] = count($tokens) - 1;
                 }
             }
             if (!$hasStartToken) {
                 if (count($potentialStartTokenIdxs) === 0) {
                     throw new ConfigurationException("Pattern {$rule->getTokenName()}/#{$patternIdx} must have unambiguous start token. No {$rule->getTokenName()} token found.");
                 } elseif (count($potentialStartTokenIdxs) > 1) {
                     throw new ConfigurationException("Pattern {$rule->getTokenName()}/#{$patternIdx} must have unambiguous start token. Multiple {$rule->getTokenName()} tokens found.");
                 } else {
                     $potentialStartTokenIdx = $potentialStartTokenIdxs[0];
                     $tokens[$potentialStartTokenIdx]['is_start_token'] = true;
                 }
             }
             $pattern = new RulePattern((int) $patternData['probability']);
             foreach ($tokens as $token) {
                 $pattern->addToken(new RulePatternToken($token['name'], $token['is_start_token']));
             }
             $rule->addPattern($pattern);
             $patternIdx++;
         }
         $rules->addRule($rule);
     }
     return $rules;
 }
コード例 #3
0
ファイル: Parser.php プロジェクト: Bizkaitarra/pintxobot
 /**
  * Parse current rule.
  *
  * @param   \Hoa\Compiler\Llk\Rule  $zeRule    Current rule.
  * @param   int                     $next      Next rule index.
  * @return  bool
  */
 protected function _parse(Rule $zeRule, $next)
 {
     if ($zeRule instanceof Rule\Token) {
         $name = $this->getCurrentToken();
         if ($zeRule->getTokenName() !== $name) {
             return false;
         }
         $value = $this->getCurrentToken('value');
         if (0 <= ($unification = $zeRule->getUnificationIndex())) {
             for ($skip = 0, $i = count($this->_trace) - 1; $i >= 0; --$i) {
                 $trace = $this->_trace[$i];
                 if ($trace instanceof Rule\Entry) {
                     if (false === $trace->isTransitional()) {
                         if ($trace->getDepth() <= $this->_depth) {
                             break;
                         }
                         --$skip;
                     }
                 } elseif ($trace instanceof Rule\Ekzit && false === $trace->isTransitional()) {
                     $skip += $trace->getDepth() > $this->_depth;
                 }
                 if (0 < $skip) {
                     continue;
                 }
                 if ($trace instanceof Rule\Token && $unification === $trace->getUnificationIndex() && $value !== $trace->getValue()) {
                     return false;
                 }
             }
         }
         $namespace = $this->getCurrentToken('namespace');
         $zzeRule = clone $zeRule;
         $zzeRule->setValue($value);
         $zzeRule->setNamespace($namespace);
         if (isset($this->_tokens[$namespace][$name])) {
             $zzeRule->setRepresentation($this->_tokens[$namespace][$name]);
         } else {
             foreach ($this->_tokens[$namespace] as $_name => $regex) {
                 if (false === ($pos = strpos($_name, ':'))) {
                     continue;
                 }
                 $_name = substr($_name, 0, $pos);
                 if ($_name === $name) {
                     break;
                 }
             }
             $zzeRule->setRepresentation($regex);
         }
         array_pop($this->_todo);
         $this->_trace[] = $zzeRule;
         $this->_errorState = ++$this->_currentState;
         return true;
     } elseif ($zeRule instanceof Rule\Concatenation) {
         if (false === $zeRule->isTransitional()) {
             ++$this->_depth;
         }
         $this->_trace[] = new Rule\Entry($zeRule->getName(), 0, null, $this->_depth);
         $content = $zeRule->getContent();
         for ($i = count($content) - 1; $i >= 0; --$i) {
             $nextRule = $content[$i];
             $this->_todo[] = new Rule\Ekzit($nextRule, 0);
             $this->_todo[] = new Rule\Entry($nextRule, 0);
         }
         return true;
     } elseif ($zeRule instanceof Rule\Choice) {
         $content = $zeRule->getContent();
         if ($next >= count($content)) {
             return false;
         }
         if (false === $zeRule->isTransitional()) {
             ++$this->_depth;
         }
         $this->_trace[] = new Rule\Entry($zeRule->getName(), $next, $this->_todo, $this->_depth);
         $nextRule = $content[$next];
         $this->_todo[] = new Rule\Ekzit($nextRule, 0);
         $this->_todo[] = new Rule\Entry($nextRule, 0);
         return true;
     } elseif ($zeRule instanceof Rule\Repetition) {
         $nextRule = $zeRule->getContent();
         if (0 === $next) {
             $name = $zeRule->getName();
             $min = $zeRule->getMin();
             if (false === $zeRule->isTransitional()) {
                 ++$this->_depth;
             }
             $this->_trace[] = new Rule\Entry($name, $min, null, $this->_depth);
             array_pop($this->_todo);
             $this->_todo[] = new Rule\Ekzit($name, $min, $this->_todo);
             for ($i = 0; $i < $min; ++$i) {
                 $this->_todo[] = new Rule\Ekzit($nextRule, 0);
                 $this->_todo[] = new Rule\Entry($nextRule, 0);
             }
             return true;
         } else {
             $max = $zeRule->getMax();
             if (-1 != $max && $next > $max) {
                 return false;
             }
             $this->_todo[] = new Rule\Ekzit($zeRule->getName(), $next, $this->_todo);
             $this->_todo[] = new Rule\Ekzit($nextRule, 0);
             $this->_todo[] = new Rule\Entry($nextRule, 0);
             return true;
         }
     }
     return false;
 }