Example #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  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;
     }
 }
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  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;
 }
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
  */
 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;
 }
Example #4
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();
     }
 }
Example #5
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 #6
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 #7
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;
 }
Example #8
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)
 {
     $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;
 }
Example #9
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);
     }
 }
Example #10
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;
     }
 }
Example #11
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)
 {
     $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;
 }
Example #12
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)
 {
     $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;
 }
Example #13
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)
 {
     $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();
 }