public function advance($parser) { if ($this->pos >= 0) { $type = $this->tokens[$this->pos][0]; switch ($type) { case T_FOR: case T_FOREACH: $this->start_loop(); break; case T_DO: $this->ignoreNextWhile = true; $this->start_loop(); break; case T_WHILE: if (!$this->ignoreNextWhile) { $this->start_loop(); } $this->ignoreNextWhile = false; break; case T_SWITCH: case T_TRY: $this->start_cond(); break; case T_IF: if (!$this->lastWasElse) { $this->start_cond(); } else { // count the number of "T_ELSE T_IF" because for each of those we get another call // to end_cond() $this->vars->set_elseif(); } break; case T_ELSEIF: $this->start_cond(true, false); break; case T_ELSE: $this->start_cond(true, true); break; } $this->lastWasElse = $type == T_ELSE; } $res = parent::advance($parser); if ($this->lastComment && $this->lastComment != $this->lastCheckComment) { // it was a comment, so lets see if it contains a "@var $<name> <type>" that gives us a // hint what type a variable has. $matches = array(); if (preg_match('/\\@var\\s+\\$([a-z0-9_]+)\\s+(\\S+)/i', $this->lastComment, $matches)) { // do we know that variable? $scopename = $this->scope->get_name(); if ($this->vars->exists($scopename, $matches[1])) { // ok, determine type and set it $type = PC_Obj_MultiType::get_type_by_name($matches[2]); $var = $this->vars->get($scopename, $matches[1]); $var->set_type($type); } } $this->lastCheckComment = $this->lastComment; } return $res; }
/** * Changes the variable with given name in the current scope * * @param string $file the current file * @param int $line the current line * @param PC_Engine_Scope $scope the current scope * @param array $layer the current layer * @param string $name the var-name * @param PC_Obj_Variable $backup the backup (0 if not present before the layer) * @param bool $present whether its present in all blocks in this layer */ private function change_var($file, $line, $scope, $layer, $name, $backup, $present) { $scopename = $scope->get_name(); // if its present in all blocks, merge the types if ($present) { // start with the type in scope; thats the one from the last block $mtype = $this->vars[$scopename][$name]->get_type(); // don't include the first block since thats the backup from the previous layer for ($i = 1; $i <= $layer['blockno']; $i++) { $mtype->merge($layer['vars'][$i][$name]->get_type()); } // note that this may discard the old value, if the variable was present $this->vars[$scopename][$name] = new PC_Obj_Variable($file, $line, $name, $mtype, $scope->get_name_of(T_FUNC_C), $scope->get_name_of(T_CLASS_C)); } else { if ($backup !== 0) { $mtype = $this->vars[$scopename][$name]->get_type(); for ($i = 0; $i <= $layer['blockno']; $i++) { if (isset($layer['vars'][$i][$name])) { $mtype->merge($layer['vars'][$i][$name]->get_type()); } } } else { if (!isset($this->vars[$scopename][$name])) { $this->vars[$scopename][$name] = new PC_Obj_Variable($file, $line, $name, new PC_Obj_MultiType(), $scope->get_name_of(T_FUNC_C), $scope->get_name_of(T_CLASS_C)); } else { $this->vars[$scopename][$name]->set_type(new PC_Obj_MultiType()); } } } // if there is a previous layer and the var is not known there in the last block, put // the first backup from this block in it. because this is the previous value for the previous // block, if it hasn't been assigned there if (count($this->layers) > 0) { $prevlayer =& $this->layers[count($this->layers) - 1]; if (!isset($prevlayer['vars'][$prevlayer['blockno']][$name])) { $prevlayer['vars'][$prevlayer['blockno']][$name] = $backup; } } }