/** * Visit an element. * * @param \Hoa\Visitor\Element $element Element to visit. * @param mixed &$handle Handle (reference). * @param mixed $eldnah Handle (not reference). * @return string */ public function visit(Visitor\Element $element, &$handle = null, $eldnah = null) { $pre = null; $in = '> ' . str_repeat(' ', $this->_i) . $element->getValue() . "\n"; $post = null; $childs = $element->getChilds(); $i = 0; $max = floor(count($childs) / 2); ++$this->_i; foreach ($childs as $id => $child) { if ($i++ < $max) { $pre .= $child->accept($this, $handle, $eldnah); } else { $post .= $child->accept($this, $handle, $eldnah); } } --$this->_i; switch ($this->getOrder()) { case parent::IN_ORDER: return $in . $pre . $post; case parent::POST_ORDER: return $post . $in . $pre; default: return $pre . $in . $post; } }
/** * Visit an element. * * @param \Hoa\Visitor\Element $element Element to visit. * @param mixed &$handle Handle (reference). * @param mixed $eldnah Handle (not reference). * @return string */ public function visit(Visitor\Element $element, &$handle = null, $eldnah = null) { $ou = null; $t = null; if ($this->_i == 0) { $ou = 'digraph {' . "\n"; $t = '}' . "\n"; } $foo = $element->getValue(); $bar = null; ++$this->_i; if (null == $eldnah) { $eldnah = $foo; $ou .= ' "' . md5($foo) . '" [label = "' . $foo . '"];' . "\n"; } foreach ($element->getChilds() as $child) { $left = md5($eldnah); $right = md5($eldnah . '.' . $child->getValue()); $ou .= ' "' . $left . '" -> "' . $right . '";' . "\n" . ' "' . $right . '" [label = "' . str_replace('\\', '\\\\', $child->getValue()) . '"];' . "\n"; $bar .= $child->accept($this, $handle, $eldnah . '.' . $child->getValue()); } $ou .= $bar; --$this->_i; return $ou . $t; }
/** * 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; }
/** * 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(); } }
/** * 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; }
/** * 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); } }
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; }
/** * 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) { $out = null; // Hoa\Praspel. if ($element instanceof HoaPraspel\Model\Specification) { $oout = []; foreach ($element::getAllowedClauses() as $clause) { if (true === $element->clauseExists($clause)) { $oout[] = $element->getClause($clause)->accept($this, $handle, $eldnah); } } $out = implode("\n", $oout); } elseif ($element instanceof HoaPraspel\Model\Is) { $out = '@is ' . $element->getPropertyName() . ';'; } elseif ($element instanceof HoaPraspel\Model\Declaration) { $clause = $element->getName(); $out = '@' . $clause; $oout = []; foreach ($element->getLocalVariables() as $name => $var) { $oout[] = ' ' . $var->accept($this, $handle, $eldnah); } foreach ($element->getPredicates() as $predicate) { $oout[] = ' \\pred(\'' . $predicate . '\')'; } $out .= implode(' and', $oout) . ';'; } elseif ($element instanceof HoaPraspel\Model\Variable) { $name = $element->getName(); if (true === $element->isLocal()) { $out = 'let '; } $out .= $name; if (null === ($alias = $element->getAlias())) { $out .= ': ' . $element->getDomains()->accept($this, $handle, $eldnah); } else { $out .= ' domainof ' . $alias; } $constraints = $element->getConstraints(); if (isset($constraints['is'])) { $out .= ' and ' . $name . ' is ' . implode(', ', $constraints['is']); } if (isset($constraints['contains'])) { foreach ($constraints['contains'] as $contains) { $out .= ' and ' . $name . ' contains ' . $contains->accept($this, $handle, $eldnah); } } if (isset($constraints['key'])) { foreach ($constraints['key'] as $pairs) { $out .= ' and ' . $name . '[' . $pairs[0]->accept($this, $handle, $eldnah) . ']: ' . $pairs[1]->accept($this, $handle, $eldnah); } } } elseif ($element instanceof HoaPraspel\Model\Throwable) { $oout = []; foreach ($element as $identifier) { $exception = $element[$identifier]; if (true === $exception->isDisjointed()) { continue; } $line = ' ' . $exception->getInstanceName() . ' ' . $identifier; foreach ((array) $exception->getDisjunction() as $_identifier) { $_exception = $element[$_identifier]; $line .= ' or ' . $_exception->getInstanceName() . ' ' . $_identifier; } if (null !== ($with = $exception->getWith())) { $line .= ' with '; $liine = []; foreach ($with as $var) { $liine[] = $var->accept($this, $handle, $eldnah); } foreach ($with->getPredicates() as $predicate) { $liine[] = '\\pred(\'' . $predicate . '\')'; } $line .= implode(' and ', $liine); } $oout[] = $line; } $out = '@throwable' . implode(' or', $oout) . ';'; } elseif ($element instanceof HoaPraspel\Model\DefaultBehavior) { $out = '@default {' . "\n"; $oout = []; foreach ($element::getAllowedClauses() as $clause) { if (true === $element->clauseExists($clause)) { $oout[] = ' ' . str_replace("\n", "\n" . ' ', $element->getClause($clause)->accept($this, $handle, $eldnah)); } } $out .= implode("\n", $oout) . "\n" . '}'; } elseif ($element instanceof HoaPraspel\Model\Behavior) { $out = '@behavior ' . $element->getIdentifier() . ' {' . "\n"; $oout = []; foreach ($element::getAllowedClauses() as $clause) { if (true === $element->clauseExists($clause)) { $oout[] = ' ' . str_replace("\n", "\n" . ' ', $element->getClause($clause)->accept($this, $handle, $eldnah)); } } $out .= implode("\n", $oout) . "\n" . '}'; } elseif ($element instanceof HoaPraspel\Model\Description) { $oout = []; foreach ($element as $example) { $oout[] = '@description \'' . preg_replace('#(?<!\\\\)\'#', '\\\'', $example) . '\';'; } $out = implode("\n", $oout); } elseif ($element instanceof HoaPraspel\Model\Collection) { foreach ($element as $el) { $out .= $el->accept($this, $handle, $eldnah); } } elseif ($element instanceof Realdom\Disjunction) { $realdoms = $element->getUnflattenedRealdoms(); if (!empty($realdoms)) { $oout = []; foreach ($realdoms as $realdom) { $oout[] = $realdom->accept($this, $handle, $eldnah); } $out .= implode(' or ', $oout); } } elseif ($element instanceof Realdom) { if ($element instanceof Realdom\IRealdom\Constant) { $out .= $element->getConstantRepresentation(); } else { $oout = []; foreach ($element->getArguments() as $argument) { $oout[] = $argument->accept($this, $handle, $eldnah); } $out .= $element->getName() . '(' . implode(', ', $oout) . ')'; } } elseif ($element instanceof Realdom\Crate\Constant) { $praspel = $element->getPraspelRepresentation(); $out .= $praspel(); } elseif ($element instanceof Realdom\Crate\Variable) { $out .= $element->getVariable()->getName(); } else { throw new HoaPraspel\Exception\Compiler('%s is not yet implemented.', 0, get_class($element)); } return $out; }
/** * 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 "[D"; 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); } }
/** * 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; } }
/** * 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) { $out = null; $_ = str_repeat(' ', $this->_indentation); if ($element instanceof Ruler\Model) { $this->_indentation = 1; $out = '$model = new \\Hoa\\Ruler\\Model();' . "\n" . '$model->expression =' . "\n" . $element->getExpression()->accept($this, $handle, $eldnah) . ';'; } elseif ($element instanceof Ruler\Model\Operator) { $out = $_ . '$model->'; $name = $element->getName(); $_handle = []; if (false === $element->isFunction()) { if (true === Core\Consistency::isIdentifier($name)) { $out .= $name; } else { $out .= '{\'' . $name . '\'}'; } $out .= '(' . "\n"; } else { $out .= 'func(' . "\n" . $_ . ' '; $_handle[] = '\'' . $name . '\''; } ++$this->_indentation; foreach ($element->getArguments() as $argument) { $_handle[] = $argument->accept($this, $handle, $eldnah); } --$this->_indentation; $out .= implode(',' . "\n", $_handle) . "\n" . $_ . ')'; } elseif ($element instanceof Ruler\Model\Bag\Scalar) { $value = $element->getValue(); $out = $_; if (true === $value) { $out .= 'true'; } elseif (false === $value) { $out .= 'false'; } elseif (null === $value) { $out .= 'null'; } elseif (is_numeric($value)) { $out .= (string) $value; } else { $out .= '\'' . str_replace('\\', '\\\'', $value) . '\''; } } elseif ($element instanceof Ruler\Model\Bag\RulerArray) { $values = []; ++$this->_indentation; foreach ($element->getArray() as $value) { $values[] = $value->accept($this, $handle, $eldnah); } --$this->_indentation; $out = $_ . '[' . "\n" . implode(',' . "\n", $values) . "\n" . $_ . ']'; } elseif ($element instanceof Ruler\Model\Bag\Context) { $out = $_ . '$model->variable(\'' . $element->getId() . '\')'; $this->_indentation += 2; foreach ($element->getDimensions() as $dimension) { $value = $dimension[Ruler\Model\Bag\Context::ACCESS_VALUE]; $out .= "\n" . $_ . ' ->'; switch ($dimension[Ruler\Model\Bag\Context::ACCESS_TYPE]) { case Ruler\Model\Bag\Context::ARRAY_ACCESS: $out .= 'index(' . "\n" . $value->accept($this, $handle, $eldnah) . "\n" . $_ . ' )'; break; case Ruler\Model\Bag\Context::ATTRIBUTE_ACCESS: $out .= 'attribute(\'' . $value . '\')'; break; case Ruler\Model\Bag\Context::METHOD_ACCESS: $out .= 'call(' . "\n" . $value->accept($this, $handle, $eldnah) . "\n" . $_ . ' )'; break; } } $this->_indentation -= 2; } return $out; }
/** * 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) { $out = null; if ($element instanceof Ruler\Model) { $out .= $element->getExpression()->accept($this, $handle, $eldnah); } elseif ($element instanceof Ruler\Model\Operator) { $name = $element->getName(); $arguments = []; foreach ($element->getArguments() as $argument) { $arguments[] = $argument->accept($this, $handle, $eldnah); } if (true === $element->isFunction()) { $out .= $name . '(' . implode(', ', $arguments) . ')'; } else { if (!isset($arguments[1])) { $_out = $name . ' ' . $arguments[0]; } else { $_out = $arguments[0] . ' ' . $name . ' ' . $arguments[1]; } if (false === Ruler\Model\Operator::isToken($name)) { $_out = '(' . $_out . ')'; } $out .= $_out; } } elseif ($element instanceof Ruler\Model\Bag\Scalar) { $value = $element->getValue(); if (true === $value) { $out .= 'true'; } elseif (false === $value) { $out .= 'false'; } elseif (null === $value) { $out .= 'null'; } elseif (is_numeric($value)) { $out .= (string) $value; } else { $out .= '\'' . str_replace('\\', '\\\'', $value) . '\''; } } elseif ($element instanceof Ruler\Model\Bag\RulerArray) { $values = []; foreach ($element->getArray() as $value) { $values[] = $value->accept($this, $handle, $eldnah); } $out .= '[' . implode(', ', $values) . ']'; } elseif ($element instanceof Ruler\Model\Bag\Context) { $out .= $element->getId(); foreach ($element->getDimensions() as $dimension) { $value = $dimension[Ruler\Model\Bag\Context::ACCESS_VALUE]; switch ($dimension[Ruler\Model\Bag\Context::ACCESS_TYPE]) { case Ruler\Model\Bag\Context::ARRAY_ACCESS: $out .= '[' . $value->accept($this, $handle, $eldnah) . ']'; break; case Ruler\Model\Bag\Context::ATTRIBUTE_ACCESS: $out .= '.' . $value; break; case Ruler\Model\Bag\Context::METHOD_ACCESS: $out .= '.' . $value->accept($this, $handle, $eldnah); break; } } } return $out; }
/** * 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) { $out = null; // Hoa\Praspel. if ($element instanceof Praspel\Model\Specification) { $variable = '$' . $element->getId(); $out = $variable . ' = new \\Hoa\\Praspel\\Model\\Specification();' . "\n"; foreach ($element::getAllowedClauses() as $clause) { if (true === $element->clauseExists($clause)) { $out .= $element->getClause($clause)->accept($this, $handle, $eldnah); } } } elseif ($element instanceof Praspel\Model\Is) { $variable = '$' . $element->getParent()->getId(); $out = "\n" . $variable . '->getClause(\'is\')->setProperty(' . $element->getProperty() . ');' . "\n"; } elseif ($element instanceof Praspel\Model\Declaration) { $variable = '$' . ($eldnah ?: $element->getId()); $out = "\n" . $variable . ' = $' . $element->getParent()->getId() . '->getClause(\'' . $element->getName() . '\');' . "\n"; foreach ($element->getLocalVariables() as $var) { $out .= $var->accept($this, $handle, $eldnah); } foreach ($element->getPredicates() as $predicate) { $out .= $variable . '->predicate(\'' . $predicate . '\');' . "\n"; } } elseif ($element instanceof Praspel\Model\Variable) { $variable = '$' . ($eldnah ?: $element->getClause()->getId()); $name = $element->getName(); $start = $variable . '[\'' . $name . '\']'; if (true === $element->isLocal()) { $out .= $variable . '->let[\'' . $name . '\']'; } else { $out .= $start; } if (null !== ($alias = $element->getAlias())) { $out .= '->domainof(\'' . $alias . '\');' . "\n"; } else { $out .= '->in = ' . $element->getDomains()->accept($this, $handle, $eldnah) . ';' . "\n"; } $constraints = $element->getConstraints(); if (isset($constraints['is'])) { $out .= $start . '->is(\'' . implode('\', \'', $constraints['is']) . '\');' . "\n"; } if (isset($constraints['contains'])) { foreach ($constraints['contains'] as $contains) { $out .= $start . '->contains(' . $contains . ');' . "\n"; } } if (isset($constraints['key'])) { foreach ($constraints['key'] as $pairs) { $out .= $start . '->key(' . $pairs[0] . ')->in = ' . $pairs[1] . ';' . "\n"; } } } elseif ($element instanceof Praspel\Model\Throwable) { $parent = '$' . $element->getParent()->getId(); $_variable = $element->getId(); $variable = '$' . $_variable; $out = "\n" . $variable . ' = ' . $parent . '->getClause(\'throwable\');' . "\n"; foreach ($element as $identifier) { $exception = $element[$identifier]; $start = $variable . '[\'' . $identifier . '\']'; $out .= $start . ' = \'' . $exception->getInstanceName() . '\';' . "\n"; if (false === $element->isDisjointed()) { if (null !== ($with = $element->getWith())) { $temp = $_variable . '_' . $identifier . '_with'; $out .= '$' . $temp . ' = ' . $variable . '->newWith();' . "\n"; foreach ($with->getLocalVariables() as $var) { $out .= $var->accept($this, $handle, $temp); } foreach ($with->getPredicates() as $predicate) { $out .= '$' . $temp . '->predicate(\'' . $predicate . '\');' . "\n"; } $out .= $start . '->setWith($' . $temp . ');' . "\n"; } } else { $out .= $start . '->disjunctionWith(\'' . $exception->getDisjunction() . '\');' . "\n"; } } } elseif ($element instanceof Praspel\Model\DefaultBehavior) { $out = "\n" . '$' . $element->getId() . ' = $' . $element->getParent()->getId() . '->getClause(\'default\')' . "\n"; foreach ($element::getAllowedClauses() as $clause) { if (true === $element->clauseExists($clause)) { $out .= $element->getClause($clause)->accept($this, $handle, $eldnah); } } } elseif ($element instanceof Praspel\Model\Behavior) { $out = "\n" . '$' . $element->getId() . ' = $' . $element->getParent()->getId() . '->getClause(\'behavior\')' . '->get(\'' . $element->getIdentifier() . '\');' . "\n"; foreach ($element::getAllowedClauses() as $clause) { if (true === $element->clauseExists($clause)) { $out .= $element->getClause($clause)->accept($this, $handle, $eldnah); } } } elseif ($element instanceof Praspel\Model\Description) { $parent = '$' . $element->getParent()->getId(); $variable = '$' . $element->getId(); $out = "\n" . $variable . ' = ' . $parent . '->getClause(\'description\');' . "\n"; foreach ($element as $example) { $out .= $variable . '[] = \'' . preg_replace('#(?<!\\\\)\'#', '\\\'', $example) . '\';' . "\n"; } } elseif ($element instanceof Praspel\Model\Collection) { foreach ($element as $el) { $out .= $el->accept($this, $handle, $eldnah); } } elseif ($element instanceof Realdom\Disjunction) { $realdoms = $element->getUnflattenedRealdoms(); if (!empty($realdoms)) { $oout = []; foreach ($realdoms as $realdom) { if ($realdom instanceof Realdom\IRealdom\Constant) { $oout[] = 'const(' . $realdom->accept($this, $handle, $eldnah) . ')'; } else { $oout[] = $realdom->accept($this, $handle, $eldnah); } } $out .= 'realdom()->' . implode('->or->', $oout); } } elseif ($element instanceof Realdom) { if ($element instanceof Realdom\IRealdom\Constant) { if ($element instanceof Realdom\_Array) { $oout = []; foreach ($element['pairs'] as $pair) { $_oout = null; foreach ($pair as $_pair) { if (null !== $_oout) { $_oout .= ', '; } $_oout .= $_pair->accept($this, $handle, $eldnah); } $oout[] = 'array(' . $_oout . ')'; } $out .= 'array(' . implode(', ', $oout) . ')'; } else { $out .= $element->getConstantRepresentation(); } } else { $oout = []; foreach ($element->getArguments() as $argument) { $oout[] = $argument->accept($this, $handle, $eldnah); } $out .= $element->getName() . '(' . implode(', ', $oout) . ')'; } } elseif ($element instanceof Realdom\Crate\Constant) { $holder = $element->getHolder(); $praspel = $element->getPraspelRepresentation(); $out .= '$' . $element->getDeclaration()->getId() . '[\'' . $praspel() . '\']'; } elseif ($element instanceof Realdom\Crate\Variable) { $holder = $element->getVariable(); if ($holder instanceof Praspel\Model\Variable\Implicit) { $out .= 'variable($' . $holder->getClause()->getId() . '->getImplicitVariable(\'' . $holder->getName() . '\'))'; } else { $out .= 'variable($' . $holder->getClause()->getId() . '->getVariable(\'' . $holder->getName() . '\', true))'; } } else { throw new Praspel\Exception\Compiler('%s is not yet implemented.', 0, get_class($element)); } return $out; }
/** * 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(); }