Beispiel #1
0
 /**
  * This method runs the machine using the specified sigma (i.e. the input alphabet/sequence).
  *
  * @access public
  * @param \Unicity\Common\IList $sigma                      the sigma to be processed
  * @param \Unicity\Common\Mutable\IList $path               the path through which the pattern
  *                                                          was found
  * @return boolean                                          whether the machine finished in
  *                                                          a goal state
  * @throws \Unicity\Throwable\InvalidArgument\Exception     indicates that no sigma has been
  *                                                          specified
  * @throws \Unicity\Throwable\Parse\Exception               indicates that the machine failed
  *                                                          to parse
  */
 public function run(Common\IList $sigma, Common\Mutable\IList $path = null)
 {
     if ($sigma === null || $sigma->isEmpty()) {
         throw new Throwable\InvalidArgument\Exception('No sigma has been defined.');
     }
     $count = $sigma->count();
     if ($this->initials === null || $this->initials->isEmpty()) {
         throw new Throwable\Parse\Exception('Machine failed. No initial state has been defined.');
     }
     $stack = new Common\Mutable\Stack($path);
     $states = $this->states->getValues($this->initials);
     usort($states, function (Core\IComparable $c0, Core\IComparable $c1) {
         return $c0->compareTo($c1);
     });
     $state = $states[0];
     $stack->push($state->getId());
     $this->onStart($this, $state);
     for ($i = 0; $i < $count; $i++) {
         $transitions = $this->transitions->getValues($state->getTransitions());
         usort($transitions, function (Core\IComparable $c0, Core\IComparable $c1) {
             return $c0->compareTo($c1);
         });
         $hasTransitioned = false;
         foreach ($transitions as $transition) {
             if ($transition->isTraversable($sigma, $i)) {
                 $this->onExit($this, $state);
                 $this->onTransition($this, $transition);
                 $targets = $this->states->getValues($transition->getTargets());
                 usort($targets, function (Core\IComparable $c0, Core\IComparable $c1) {
                     return $c0->compareTo($c1);
                 });
                 $state = $targets[0];
                 $stack->push($state->getId());
                 $this->onEntry($this, $state);
                 $hasTransitioned = true;
                 break;
             }
         }
         if (!$hasTransitioned) {
             $stack->clear();
             throw new Throwable\Parse\Exception('Machine failed. Unable to transition between states.');
         }
     }
     $this->onCompletion($this, $state);
     if (Automaton\StateType::goal()->__equals($state->getType())) {
         return true;
     }
     $stack->clear();
     return false;
 }
Beispiel #2
0
 /**
  * This method recursively traverses the machine.
  *
  * @access protected
  * @param \Unicity\Common\IList $sigma                      the sigma to be processed
  * @param integer $i                                        the index to the input symbol
  * @param \Unicity\Automaton\IState $state                  the current a set of target states
  * @param \Unicity\Common\Mutable\Stack $stack              the path through which the pattern
  *                                                          was found
  * @return boolean                                          whether the machine finished in
  *                                                          a goal state
  *                                                          a goal state
  * @throws \Unicity\Throwable\Parse\Exception               indicates that the machine failed
  *                                                          to parse
  */
 protected function traverse(Common\IList $sigma, $i, Automaton\IState $state, Common\Mutable\Stack $stack)
 {
     if ($i >= $sigma->count()) {
         return Automaton\StateType::goal()->__equals($state->getType());
     }
     $transitions = $this->transitions->getValues($state->getTransitions());
     usort($transitions, function (Core\IComparable $c0, Core\IComparable $c1) {
         return $c0->compareTo($c1);
     });
     $hasTransitioned = false;
     foreach ($transitions as $transition) {
         if ($transition->isTraversable($sigma, $i)) {
             $targets = $this->states->getValues($transition->getTargets());
             usort($targets, function (Core\IComparable $c0, Core\IComparable $c1) {
                 return $c0->compareTo($c1);
             });
             foreach ($targets as $target) {
                 $stack->push($target->getId());
                 if ($this->traverse($sigma, $i + 1, $target, $stack)) {
                     return true;
                 }
                 $stack->pop();
             }
             $hasTransitioned = true;
             break;
         }
     }
     if (!$hasTransitioned) {
         throw new Throwable\Parse\Exception('Machine failed. Unable to transition between states.');
     }
     return false;
 }
Beispiel #3
0
 /**
  * This method logs any changes between the source and target objects.
  *
  * @access protected
  * @param Common\IList $source                              the source object to be evaluated
  * @param Common\IList $target                              the target object to be evaluated
  * @param string $path                                      the current path
  * @param Common\Mutable\IList $log                         a reference to the log
  */
 protected function compareLists(Common\IList $source, Common\IList $target, $path, Common\Mutable\IList $log)
 {
     foreach ($source as $index => $source_value) {
         $new_path = static::buildPath($path, $index);
         if ($this->doLog($new_path)) {
             if ($target->hasIndex($index)) {
                 $target_value = $target->getValue($index);
                 if ($source_value instanceof Common\IList && $target_value instanceof Common\IList) {
                     $this->compareLists($source_value, $target_value, $new_path, $log);
                 } else {
                     if ($source_value instanceof Common\IMap && $target_value instanceof Common\IMap) {
                         $this->compareMaps($source_value, $target_value, $new_path, $log);
                     } else {
                         $this->compareValues($source_value, $target_value, $new_path, $log);
                     }
                 }
             } else {
                 $log->addValue(array('body' => strtr('Target index ":index" is missing in list.', array(':index' => $index)), 'level' => Log\Level::warning()->__name(), 'path' => $new_path, 'time' => date('c')));
             }
         }
     }
 }
Beispiel #4
0
 /**
  * This method removes an action from the transition.
  *
  * @access public
  * @param \Unicity\Automaton\IAction $action                the action to be removed
  */
 public function removeAction(Automaton\IAction $action)
 {
     if ($action !== null) {
         $this->actions->removeValue($action);
     }
 }