Пример #1
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
  */
 public function visit(Visitor\Element $element, &$handle = null, $eldnah = null)
 {
     ++self::$_i;
     $out = str_repeat('>  ', self::$_i) . $element->getId();
     if (null !== ($value = $element->getValue())) {
         $out .= '(' . ('default' !== $value['namespace'] ? $value['namespace'] . ':' : '') . $value['token'] . ', ' . $value['value'] . ')';
     }
     $data = $element->getData();
     if (!empty($data)) {
         $out .= ' ' . $this->dumpData($data);
     }
     $out .= "\n";
     foreach ($element->getChildren() as $child) {
         $out .= $child->accept($this, $handle, $eldnah);
     }
     --self::$_i;
     return $out;
 }
Пример #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  float
  */
 public function visit(Visitor\Element $element, &$handle = null, $eldnah = null)
 {
     $type = $element->getId();
     $children = $element->getChildren();
     if (null === $handle) {
         $handle = function ($x) {
             return $x;
         };
     }
     $acc =& $handle;
     switch ($type) {
         case '#function':
             $name = array_shift($children)->accept($this, $_, $eldnah);
             $function = $this->getFunction($name);
             $arguments = [];
             foreach ($children as $child) {
                 $child->accept($this, $_, $eldnah);
                 $arguments[] = $_();
                 unset($_);
             }
             $acc = function () use($function, $arguments, $acc) {
                 return $acc($function->distributeArguments($arguments));
             };
             break;
         case '#negative':
             $children[0]->accept($this, $a, $eldnah);
             $acc = function () use($a, $acc) {
                 return $acc(-$a());
             };
             break;
         case '#addition':
             $children[0]->accept($this, $a, $eldnah);
             $acc = function ($b) use($a, $acc) {
                 return $acc($a() + $b);
             };
             $children[1]->accept($this, $acc, $eldnah);
             break;
         case '#substraction':
             $children[0]->accept($this, $a, $eldnah);
             $acc = function ($b) use($a, $acc) {
                 return $acc($a()) - $b;
             };
             $children[1]->accept($this, $acc, $eldnah);
             break;
         case '#multiplication':
             $children[0]->accept($this, $a, $eldnah);
             $acc = function ($b) use($a, $acc) {
                 return $acc($a() * $b);
             };
             $children[1]->accept($this, $acc, $eldnah);
             break;
         case '#division':
             $children[0]->accept($this, $a, $eldnah);
             $parent = $element->getParent();
             if (null === $parent || $type === $parent->getId()) {
                 $acc = function ($b) use($a, $acc) {
                     if (0 === $b) {
                         throw new \RuntimeException('Division by zero is not possible.');
                     }
                     return $acc($a()) / $b;
                 };
             } else {
                 if ('#fakegroup' !== $parent->getId()) {
                     $classname = get_class($element);
                     $group = new $classname('#fakegroup', null, [$element], $parent);
                     $element->setParent($group);
                     $this->visit($group, $acc, $eldnah);
                     break;
                 } else {
                     $acc = function ($b) use($a, $acc) {
                         if (0 === $b) {
                             throw new \RuntimeException('Division by zero is not possible.');
                         }
                         return $acc($a() / $b);
                     };
                 }
             }
             $children[1]->accept($this, $acc, $eldnah);
             break;
         case '#fakegroup':
         case '#group':
             $children[0]->accept($this, $a, $eldnah);
             $acc = function () use($a, $acc) {
                 return $acc($a());
             };
             break;
         case '#variable':
             $out = $this->getVariable($children[0]->getValueValue());
             $acc = function () use($out, $acc) {
                 return $acc($out);
             };
             break;
         case 'token':
             $value = $element->getValueValue();
             $out = null;
             if ('constant' === $element->getValueToken()) {
                 if (defined($value)) {
                     $out = constant($value);
                 } else {
                     $out = $this->getConstant($value);
                 }
             } elseif ('id' === $element->getValueToken()) {
                 return $value;
             } else {
                 $out = (double) $value;
             }
             $acc = function () use($out, $acc) {
                 return $acc($out);
             };
             break;
     }
     if (null === $element->getParent()) {
         return $acc();
     }
 }
Пример #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\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;
 }
Пример #4
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);
     }
 }
Пример #5
0
 private function visitText(Element $element)
 {
     $nodes = array();
     // Walk childs and merge adjacent text nodes if needed
     $last = null;
     $last_index = -1;
     foreach ($element->getChildren() as $child) {
         $node = $child->accept($this);
         // Merge text nodes together
         if ($last instanceof AST\TextNode && $node instanceof AST\TextNode) {
             // Prevent merge once a context is set
             if ($last->hasContext()) {
                 throw new Exception('Unexpected text node after context');
             }
             $nodes[$last_index] = $last = AST\TextNode::merge($last, $node);
         } else {
             $nodes[] = $node;
             $last = $node;
             $last_index++;
         }
     }
     // Once nodes are merged, we just "AND" them all together.
     $root = null;
     foreach ($nodes as $index => $node) {
         if (!$root) {
             $root = $node;
             continue;
         }
         if ($node instanceof AST\Context) {
             if ($root instanceof AST\ContextAbleInterface) {
                 $root = $root->withContext($node);
             } else {
                 throw new Exception('Unexpected context after non-contextualizable node');
             }
         } elseif ($node instanceof AST\Node) {
             $root = new AST\Boolean\AndExpression($root, $node);
         } else {
             throw new Exception('Unexpected node type inside text node.');
         }
     }
     return $root;
 }
Пример #6
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);
     }
 }
Пример #7
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  mixed
  */
 public function visit(\Hoa\Visitor\Element $element, &$handle = null, $eldnah = null)
 {
     $graphic = null;
     $id = str_replace('#', '', $element->getId());
     #$graphicCreator = \Hoathis\GraphicTools\SvgCreator::getInstance();
     switch ($id) {
         case 'expression':
             $graphic = $this->graphicCreator->createExpression();
             break;
         case 'quantification':
             $graphic = $this->graphicCreator->createQuantification();
             break;
         case 'alternation':
             $graphic = $this->graphicCreator->createAlternation();
             break;
         case 'concatenation':
             $graphic = $this->graphicCreator->createConcatenation();
             break;
         case 'class':
             $graphic = $this->graphicCreator->createClass();
             break;
         case 'negativeclass':
             $graphic = $this->graphicCreator->createNegativeClass();
             break;
         case 'range':
             $graphic = $this->graphicCreator->createRange();
             break;
         case 'token':
             $value = $element->getValue();
             $graphic = $this->graphicCreator->createToken($value['token'], $value['value']);
             break;
         case 'lookahead':
             $graphic = $this->graphicCreator->createLookahead();
             break;
         case 'negativelookahead':
             $graphic = $this->graphicCreator->createNegativeLookahead();
             break;
         case 'lookbehind':
             $graphic = $this->graphicCreator->createLookbehind();
             break;
         case 'negativelookbehind':
             $graphic = $this->graphicCreator->createNegativeLookbehind();
             break;
         case 'absolutecondition':
             // Still under construction
             throw new \Exception(' \\Hoathis\\Regex\\Visitor\\Visualization exception : Unhandled element "#' . $id . '" ');
             //$graphic = $this->graphicCreator->createAbsoluteCondition();
             break;
         default:
             throw new \Exception(' \\Hoathis\\Regex\\Visitor\\Visualization exception : Unhandled element "#' . $id . '" ');
     }
     $graphic->setAttribute("class", $id);
     foreach ($element->getChildren() as $child) {
         $childGraphic = $child->accept($this, $handle, $eldnah);
         $graphic->addChild($childGraphic);
     }
     if ($id == 'expression') {
         return $graphic->build();
     } else {
         return $graphic;
     }
 }
Пример #8
0
 /**
  * Evaluate given AST as CollectiveAccess expression
  *
  * @param Visitor\Element $po_element
  * @param Hoa\Core\Consistency\Xcallable $f_handle
  * @param Hoa\Core\Consistency\Xcallable $f_eldnah
  * @return mixed
  */
 public function visit(Visitor\Element $po_element, &$f_handle = null, $f_eldnah = null)
 {
     $vs_type = $po_element->getId();
     $va_children = $po_element->getChildren();
     // if no handle passed, use identity
     if ($f_handle === null) {
         $f_handle = function ($x) {
             return $x;
         };
     }
     $f_acc =& $f_handle;
     switch ($vs_type) {
         case '#function':
             $vs_name = array_shift($va_children)->accept($this, $_, $f_eldnah);
             $f_function = $this->getFunction($vs_name);
             $va_args = array();
             foreach ($va_children as $o_child) {
                 $o_child->accept($this, $_, $f_eldnah);
                 $va_args[] = $_();
                 unset($_);
             }
             $f_acc = function () use($f_function, $va_args, $f_acc) {
                 return $f_acc($f_function->distributeArguments($va_args));
             };
             break;
         case '#bool_and':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc($a() && $b);
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#bool_or':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc($a() || $b);
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#regex_match':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc((bool) @preg_match($b, $a()));
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#regex_nomatch':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc(!(bool) @preg_match($b, $a()));
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#comp_gt':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc($a() > $b);
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#comp_gte':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc($a() >= $b);
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#comp_lt':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc($a() < $b);
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#comp_lte':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc($a() <= $b);
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#comp_neq':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc($a() != $b);
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#comp_eq':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc($a() == $b);
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#in_op':
             $vs_needle = array_shift($va_children)->accept($this, $in, $f_eldnah);
             $va_haystack = array();
             $in = $f_handle;
             $o_op = array_shift($va_children);
             if ($o_op->getValueToken() !== 'in_op') {
                 throw new Exception('invalid syntax');
             }
             foreach ($va_children as $o_child) {
                 $o_child->accept($this, $in, $f_eldnah);
                 $va_haystack[] = $in();
                 unset($in);
             }
             $f_acc = function () use($vs_needle, $va_haystack, $f_acc) {
                 return $f_acc(in_array($vs_needle, $va_haystack));
             };
             break;
         case '#notin_op':
             $vs_needle = array_shift($va_children)->accept($this, $in, $f_eldnah);
             $va_haystack = array();
             $in = $f_handle;
             $o_op = array_shift($va_children);
             if ($o_op->getValueToken() !== 'notin_op') {
                 throw new Exception('invalid syntax');
             }
             foreach ($va_children as $o_child) {
                 $o_child->accept($this, $in, $f_eldnah);
                 $va_haystack[] = $in();
                 unset($in);
             }
             $f_acc = function () use($vs_needle, $va_haystack, $f_acc) {
                 return $f_acc(!in_array($vs_needle, $va_haystack));
             };
             break;
         case '#stradd':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc($a() . $b);
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#negative':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function () use($a, $f_acc) {
                 return $f_acc(-$a());
             };
             break;
         case '#addition':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc($a() + $b);
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#substraction':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc($a()) - $b;
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#multiplication':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function ($b) use($a, $f_acc) {
                 return $f_acc($a() * $b);
             };
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#division':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $parent = $po_element->getParent();
             if (null === $parent || $type === $parent->getId()) {
                 $f_acc = function ($b) use($a, $f_acc) {
                     if (0 === $b) {
                         throw new \RuntimeException('Division by zero is not possible.');
                     }
                     return $f_acc($a()) / $b;
                 };
             } else {
                 if ('#fakegroup' !== $parent->getId()) {
                     $classname = get_class($po_element);
                     $group = new $classname('#fakegroup', null, [$po_element], $parent);
                     $po_element->setParent($group);
                     $this->visit($group, $f_acc, $f_eldnah);
                     break;
                 } else {
                     $f_acc = function ($b) use($a, $f_acc) {
                         if (0 === $b) {
                             throw new \RuntimeException('Division by zero is not possible.');
                         }
                         return $f_acc($a() / $b);
                     };
                 }
             }
             $va_children[1]->accept($this, $f_acc, $f_eldnah);
             break;
         case '#fakegroup':
         case '#group':
             $va_children[0]->accept($this, $a, $f_eldnah);
             $f_acc = function () use($a, $f_acc) {
                 return $f_acc($a());
             };
             break;
         case 'token':
             $value = $po_element->getValueValue();
             $token = $po_element->getValueToken();
             $out = null;
             switch ($token) {
                 case 'id':
                     return $value;
                 case 'string':
                     $out = preg_replace('/(^"|"$)/', '', $value);
                     break;
                 case 'regex':
                     // @todo maybe mangle regex?
                     $out = (string) $value;
                     break;
                 case 'variable':
                     $vs_var = mb_substr((string) $value, 1);
                     // get rid of caret ^
                     $out = $this->getVariable($vs_var);
                     if (is_array($out)) {
                         $out = join("", $out);
                     }
                     // we need to join multiple values
                     break;
                 default:
                     $out = (double) $value;
                     break;
             }
             $f_acc = function () use($out, $f_acc) {
                 return $f_acc($out);
             };
             break;
     }
     return $f_acc();
 }