Example #1
0
 /**
  * Visit an element.
  *
  * @access  public
  * @param   \Hoa\Visitor\Element  $element    Element to visit.
  * @param   mixed                 &$handle    Handle (reference).
  * @param   mixed                 $eldnah     Handle (not reference).
  *
  * @return  \Hoa\Ruler\Model
  *
  * @throw   \Hoa\Ruler\Exception\Interpreter
  */
 public function visit(Visitor\Element $element, &$handle = null, $eldnah = null)
 {
     $id = $element->getId();
     $variable = false !== $eldnah;
     switch ($id) {
         case '#expression':
             $this->root = new Ruler\Model();
             $this->root->expression = $element->getChild(0)->accept($this, $handle, $eldnah);
             return $this->root;
         case '#operation':
             $children = $element->getChildren();
             $left = $children[0]->accept($this, $handle, $eldnah);
             $right = $children[2]->accept($this, $handle, $eldnah);
             $name = $children[1]->accept($this, $handle, false);
             return $this->root->_operator($name, [$left, $right], false);
         case '#variable_access':
             $children = $element->getChildren();
             $name = $children[0]->accept($this, $handle, $eldnah);
             array_shift($children);
             foreach ($children as $child) {
                 $_child = $child->accept($this, $handle, $eldnah);
                 switch ($child->getId()) {
                     case '#attribute_access':
                         $name->attribute($_child);
                         break;
                 }
             }
             return $name;
         case '#attribute_access':
             return $element->getChild(0)->accept($this, $handle, false);
         case '#array_declaration':
             $out = [];
             foreach ($element->getChildren() as $child) {
                 $out[] = $child->accept($this, $handle, $eldnah);
             }
             return $out;
         case '#function_call':
             $children = $element->getChildren();
             $name = $children[0]->accept($this, $handle, false);
             array_shift($children);
             $arguments = [];
             foreach ($children as $child) {
                 $arguments[] = $child->accept($this, $handle, $eldnah);
             }
             return $this->root->_operator($name, $arguments, true);
         case '#and':
         case '#or':
         case '#xor':
             $name = substr($id, 1);
             $children = $element->getChildren();
             $left = $children[0]->accept($this, $handle, $eldnah);
             $right = $children[1]->accept($this, $handle, $eldnah);
             return $this->root->operation($name, array($left, $right));
         case '#not':
             return $this->root->operation('not', array($element->getChild(0)->accept($this, $handle, $eldnah)));
         case 'token':
             $token = $element->getValueToken();
             $value = $element->getValueValue();
             switch ($token) {
                 case 'identifier':
                     return true === $variable ? $this->root->variable($value) : $value;
                 case 'named_parameter':
                     return new Parameter(substr($value, 1));
                 case 'positional_parameter':
                     $index = $this->nextParameterIndex++;
                     return new Parameter($index);
                 case 'true':
                     return true;
                 case 'false':
                     return false;
                 case 'null':
                     return null;
                 case 'float':
                     return floatval($value);
                 case 'integer':
                     return intval($value);
                 case 'string':
                     return str_replace('\\' . $value[0], $value[0], substr($value, 1, -1));
                 default:
                     throw new Ruler\Exception\Interpreter('Token %s is unknown.', 0, $token);
             }
         default:
             throw new Ruler\Exception\Interpreter('Element %s is unknown.', 1, $id);
     }
 }
Example #2
0
 /**
  * Visit an element.
  *
  * @param   \Hoa\Visitor\Element  $element    Element to visit.
  * @param   mixed                 &$handle    Handle (reference).
  * @param   mixed                 $eldnah     Handle (not reference).
  * @return  mixed
  * @throws  \Hoa\Regex\Exception
  */
 public function visit(Visitor\Element $element, &$handle = null, $eldnah = null)
 {
     switch ($element->getId()) {
         case '#expression':
         case '#capturing':
         case '#noncapturing':
         case '#namedcapturing':
             return $element->getChild(0)->accept($this, $handle, $eldnah);
         case '#alternation':
         case '#class':
             return $element->getChild($this->_sampler->getInteger(0, $element->getChildrenNumber() - 1))->accept($this, $handle, $eldnah);
         case '#concatenation':
             $out = null;
             foreach ($element->getChildren() as $child) {
                 $out .= $child->accept($this, $handle, $eldnah);
             }
             return $out;
         case '#quantification':
             $out = null;
             $xy = $element->getChild(1)->getValueValue();
             $x = 0;
             $y = 0;
             switch ($element->getChild(1)->getValueToken()) {
                 case 'zero_or_one':
                     $y = 1;
                     break;
                 case 'zero_or_more':
                     $y = mt_rand(5, 8);
                     // why not?
                     break;
                 case 'one_or_more':
                     $x = 1;
                     $y = mt_rand(5, 8);
                     // why not?
                     break;
                 case 'exactly_n':
                     $x = $y = (int) substr($xy, 1, -1);
                     break;
                 case 'n_to_m':
                     $xy = explode(',', substr($xy, 1, -1));
                     $x = (int) trim($xy[0]);
                     $y = (int) trim($xy[1]);
                     break;
                 case 'n_or_more':
                     $xy = explode(',', substr($xy, 1, -1));
                     $x = (int) trim($xy[0]);
                     $y = mt_rand($x + 5, $x + 8);
                     // why not?
                     break;
             }
             for ($i = 0, $max = $this->_sampler->getInteger($x, $y); $i < $max; ++$i) {
                 $out .= $element->getChild(0)->accept($this, $handle, $eldnah);
             }
             return $out;
         case '#negativeclass':
             $c = [];
             foreach ($element->getChildren() as $child) {
                 $c[Ustring::toCode($child->accept($this, $handle, $eldnah))] = true;
             }
             do {
                 // all printable ASCII.
                 $i = $this->_sampler->getInteger(32, 126);
             } while (isset($c[$i]));
             return Ustring::fromCode($i);
         case '#range':
             $out = null;
             $left = $element->getChild(0)->accept($this, $handle, $eldnah);
             $right = $element->getChild(1)->accept($this, $handle, $eldnah);
             return Ustring::fromCode($this->_sampler->getInteger(Ustring::toCode($left), Ustring::toCode($right)));
         case 'token':
             $value = $element->getValueValue();
             switch ($element->getValueToken()) {
                 case 'character':
                     $value = ltrim($value, '\\');
                     switch ($value) {
                         case 'a':
                             return "\\a";
                         case 'e':
                             return "";
                         case 'f':
                             return "\f";
                         case 'n':
                             return "\n";
                         case 'r':
                             return "\r";
                         case 't':
                             return "\t";
                         default:
                             return Ustring::fromCode(intval(substr($value, 1)));
                     }
                     break;
                 case 'dynamic_character':
                     $value = ltrim($value, '\\');
                     switch ($value[0]) {
                         case 'x':
                             $value = trim($value, 'x{}');
                             return Ustring::fromCode(hexdec($value));
                         default:
                             return Ustring::fromCode(octdec($value));
                     }
                     break;
                 case 'character_type':
                     $value = ltrim($value, '\\');
                     if ('s' === $value) {
                         $value = $this->_sampler->getInteger(0, 1) ? 'h' : 'v';
                     }
                     switch ($value) {
                         case 'C':
                             return $this->_sampler->getInteger(0, 127);
                         case 'd':
                             return $this->_sampler->getInteger(0, 9);
                         case 'h':
                             $h = [Ustring::fromCode(0x9), Ustring::fromCode(0x20), Ustring::fromCode(0xa0)];
                             return $h[$this->_sampler->getInteger(0, count($h) - 1)];
                         case 'v':
                             $v = [Ustring::fromCode(0xa), Ustring::fromCode(0xb), Ustring::fromCode(0xc), Ustring::fromCode(0xd)];
                             return $v[$this->_sampler->getInteger(0, count($v) - 1)];
                         case 'w':
                             $w = array_merge(range(0x41, 0x5a), range(0x61, 0x7a), [0x5f]);
                             return Ustring::fromCode($w[$this->_sampler->getInteger(0, count($w) - 1)]);
                         default:
                             return '?';
                     }
                     break;
                 case 'literal':
                     if ('.' === $value) {
                         $w = array_merge(range(0x41, 0x5a), range(0x61, 0x7a), [0x5f]);
                         return Ustring::fromCode($w[$this->_sampler->getInteger(0, count($w) - 1)]);
                     }
                     return str_replace('\\\\', '\\', preg_replace('#\\\\(?!\\\\)#', '', $value));
             }
             break;
         case '#internal_options':
             break;
         default:
             throw new Regex\Exception('Unsupported node: %s.', 0, $element->getId());
     }
     return;
 }
Example #3
0
 /**
  * Visit an element.
  *
  * @param   \Hoa\Visitor\Element  $element    Element to visit.
  * @param   mixed                 &$handle    Handle (reference).
  * @param   mixed                 $eldnah     Handle (not reference).
  * @return  mixed
  * @throws  \Hoa\Praspel\Exception\Interpreter
  */
 public function visit(Visitor\Element $element, &$handle = null, $eldnah = null)
 {
     $id = $element->getId();
     switch ($id) {
         case '#specification':
             $this->_clause = $this->_current = $this->_root = new Praspel\Model\Specification();
             if (null !== ($classname = $this->getBindedClass())) {
                 $this->_root->bindToClass($classname);
             }
             foreach ($element->getChildren() as $child) {
                 $child->accept($this, $handle, $eldnah);
             }
             return $this->_root;
         case '#is':
             $this->_clause = $this->_root->getClause('is');
             foreach ($element->getChildren() as $child) {
                 $this->_clause->addProperty($this->_clause->getPropertyValue($child->accept($this, $handle, $eldnah)));
             }
             break;
         case '#requires':
         case '#ensures':
         case '#invariant':
             $this->_clause = $this->_current->getClause(substr($id, 1));
             foreach ($element->getChildren() as $child) {
                 $child->accept($this, $handle, $eldnah);
             }
             break;
         case '#behavior':
             $children = $element->getChildren();
             $child0 = array_shift($children);
             $identifier = $child0->accept($this, $handle, false);
             $previous = $this->_current;
             $this->_clause = $this->_current = $this->_current->getClause('behavior')->get($identifier);
             foreach ($children as $child) {
                 $child->accept($this, $handle, $eldnah);
             }
             $this->_current = $previous;
             break;
         case '#default':
             $children = $element->getChildren();
             $previous = $this->_current;
             $this->_clause = $this->_current = $this->_current->getClause('default');
             foreach ($children as $child) {
                 $child->accept($this, $handle, $eldnah);
             }
             $this->_current = $previous;
             break;
         case '#throwable':
             $this->_clause = $this->_current->getClause('throwable');
             $identifier = null;
             foreach ($element->getChildren() as $child) {
                 switch ($child->getId()) {
                     case '#exception_identifier':
                         $_identifier = $child->getChild(1)->accept($this, $handle, false);
                         $_instanceof = $child->getChild(0)->accept($this, $handle, false);
                         $this->_clause[$_identifier] = $_instanceof;
                         if (null === $identifier) {
                             $identifier = $_identifier;
                         } else {
                             $this->_clause[$_identifier]->disjunctionWith($identifier);
                         }
                         break;
                     case '#exception_with':
                         $old = $this->_clause;
                         $this->_clause = $old->newWith();
                         foreach ($child->getChildren() as $_child) {
                             $_child->accept($this, $handle, $eldnah);
                         }
                         $old[$identifier]->setWith($this->_clause);
                         $this->_clause = $old;
                         break;
                 }
             }
             break;
         case '#description':
             $this->_clause = $this->_root->getClause('description');
             $this->_clause[] = $element->getChild(0)->accept($this, $handle, $eldnah);
             break;
         case '#declaration':
             $left = $element->getChild(0)->accept($this, $handle, false);
             $right = $element->getChild(1)->accept($this, $handle, $eldnah);
             $variable = $left;
             if ($right instanceof Praspel\Model\Variable) {
                 $right = realdom()->variable($right);
             }
             $this->_clause[$variable]->in = $right;
             break;
         case '#local_declaration':
             $left = $element->getChild(0)->accept($this, $handle, false);
             $right = $element->getChild(1)->accept($this, $handle, $eldnah);
             $variable = $left;
             if ($right instanceof Praspel\Model\Variable) {
                 $right = realdom()->variable($right);
             }
             $this->_clause->let[$variable]->in = $right;
             break;
         case '#qualification':
             $children = $element->getChildren();
             $variable = $this->_clause[array_shift($children)->accept($this, $handle, false)];
             foreach ($children as $child) {
                 $variable->is($child->accept($this, $handle, false));
             }
             break;
         case '#contains':
             $variable = $element->getChild(0)->accept($this, $handle, false);
             $value = $element->getChild(1)->accept($this, $handle, false);
             $this->_clause[$variable]->contains($value);
             break;
         case '#domainof':
             $left = $element->getChild(0)->accept($this, $handle, false);
             $right = $element->getChild(1)->accept($this, $handle, false);
             $this->_clause[$left]->domainof($right);
             break;
         case '#predicate':
             $this->_clause->predicate($element->getChild(0)->accept($this, $handle, $eldnah));
             break;
         case '#disjunction':
             $disjunction = realdom();
             foreach ($element->getChildren() as $child) {
                 $value = $child->accept($this, $handle, $eldnah);
                 if ($value instanceof Realdom\Disjunction) {
                     $disjunction[] = $value;
                 } elseif ($value instanceof Praspel\Model\Variable) {
                     $disjunction->variable($value);
                 } else {
                     $disjunction->const($value);
                 }
             }
             return $disjunction;
         case '#realdom':
             $children = $element->getChildren();
             $child0 = array_shift($children);
             $name = $child0->accept($this, $handle, false);
             $arguments = [];
             foreach ($children as $child) {
                 $argument = $child->accept($this, $handle, $eldnah);
                 if ($argument instanceof Realdom\Disjunction) {
                     $realdoms = $argument->getRealdoms();
                     $argument = $realdoms[0];
                 }
                 $arguments[] = $argument;
             }
             return realdom()->_call($name, $arguments);
         case '#concatenation':
             $string = null;
             foreach ($element->getChildren() as $child) {
                 $string .= $child->accept($this, $handle, $eldnah);
             }
             return $string;
         case '#array':
             $array = [];
             foreach ($element->getChildren() as $child) {
                 if ('#pair' === $child->getId()) {
                     $key = $child->getChild(0)->accept($this, $handle, $eldnah);
                     $value = $child->getChild(1)->accept($this, $handle, $eldnah);
                     $array[] = [$key, $value];
                     continue;
                 }
                 $key = realdom()->natural(0, 1);
                 $value = $child->accept($this, $handle, $eldnah);
                 $array[] = [$key, $value];
             }
             return $array;
         case '#range':
             $left = $element->getChild(0)->accept($this, $handle, $eldnah);
             $right = $element->getChild(1)->accept($this, $handle, $eldnah);
             if (is_float($left) || is_float($right)) {
                 return realdom()->boundfloat(floatval($left), floatval($right));
             }
             return realdom()->boundinteger(intval($left), intval($right));
         case '#left_range':
             $left = $element->getChild(0)->accept($this, $handle, $eldnah);
             if (is_float($left)) {
                 return realdom()->boundfloat($left);
             }
             return realdom()->boundinteger($left);
         case '#right_range':
             $right = $element->getChild(0)->accept($this, $handle, $eldnah);
             if (is_float($right)) {
                 return realdom()->boundfloat(null, $right);
             }
             return realdom()->boundinteger(null, $right);
         case '#arrayaccessbykey':
             $variable = $element->getChild(0)->accept($this, $handle, $eldnah);
             $key = $element->getChild(1)->accept($this, $handle, $eldnah);
             $this->_clause[$variable]->key($key);
             return $variable;
         case '#dynamic_resolution':
             $value = null;
             foreach ($element->getChildren() as $child) {
                 if (null !== $value) {
                     $value .= '->';
                 }
                 $value .= $child->accept($this, $handle, false);
             }
             if (false !== $eldnah) {
                 return $this->_clause->getVariable($value, true);
             }
             return $value;
         case '#self_identifier':
         case '#static_identifier':
         case '#parent_identifier':
             $identifier = substr($id, 1, strpos($id, '_', 1) - 1);
             foreach ($element->getChildren() as $child) {
                 $identifier .= '::' . $child->accept($this, $handle, $eldnah);
             }
             return $identifier;
         case '#old':
             $value = '\\old(' . $element->getChild(0)->accept($this, $handle, false) . ')';
             if (false !== $eldnah) {
                 return $this->_clause->getVariable($value);
             }
             return $value;
         case '#result':
             return '\\result';
         case '#classname':
             $classname = [];
             foreach ($element->getChildren() as $child) {
                 $classname[] = $child->accept($this, $handle, $eldnah);
             }
             return implode('\\', $classname);
         case '#nowdoc':
         case '#heredoc':
             return $element->getChild(1)->accept($this, $handle, $eldnah);
         case '#regex':
             $regex = $element->getChild(0)->accept($this, $handle, $eldnah);
             if (true === $element->childExists(1)) {
                 $length = $element->getChild(1)->accept($this, $handle, $eldnah);
             }
             return realdom()->regex($regex);
         case '#class':
             $classname = $element->getChild(0)->accept($this, $handle, false);
             return realdom()->class($classname);
         case 'token':
             $tId = $element->getValueToken();
             $value = $element->getValueValue();
             switch ($tId) {
                 case 'identifier':
                     if (false !== $eldnah) {
                         return $this->getIdentifier($value);
                     }
                     return $value;
                 case 'this':
                     if (false !== $eldnah) {
                         return $this->_root->getImplicitVariable($value);
                     }
                     return $value;
                 case 'content':
                 case 'pure':
                 case 'result':
                     return $value;
                 case 'default':
                     return …;
                 case 'null':
                     return null;
                 case 'true':
                     return true;
                 case 'false':
                     return false;
                 case 'binary':
                     $int = intval(substr($value, strpos($value, 'b') + 1), 2);
                     if ('-' === $value[0]) {
                         return -$int;
                     }
                     return $int;
                 case 'octal':
                     $int = intval(substr($value, strpos($value, '0') + 1), 8);
                     if ('-' === $value[0]) {
                         return -$int;
                     }
                     return $int;
                 case 'hexa':
                     $value = strtolower($value);
                     $int = intval(substr($value, strpos($value, 'x') + 1), 16);
                     if ('-' === $value[0]) {
                         return -$int;
                     }
                     return $int;
                 case 'decimal':
                     if (true === ctype_digit(ltrim($value, '+-'))) {
                         return intval($value);
                     }
                     return floatval($value);
                 case 'escaped':
                     switch ($value[1]) {
                         case 'n':
                             return "\n";
                         case 'r':
                             return "\r";
                         case 't':
                             return "\t";
                         case 'v':
                             return "\v";
                         case 'e':
                             return "";
                         case 'f':
                             return "\f";
                         case 'b':
                             return "";
                         case 'x':
                             return Ustring::fromCode(hexdec($value));
                         case '\\':
                             return $value[1];
                         default:
                             return Ustring::fromCode(octdec($value));
                     }
                 case 'accepted':
                 case 'string':
                 case 'regex':
                     return $value;
                 default:
                     throw new Praspel\Exception\Interpreter('Token %s is not yet implemented.', 1, $tId);
             }
             break;
         default:
             throw new Praspel\Exception\Interpreter('Element %s is unknown.', 2, $id);
     }
 }