コード例 #1
0
ファイル: util.php プロジェクト: einheitlix/php-ast
/** Dumps abstract syntax tree */
function ast_dump($ast, int $options = 0) : string
{
    if ($ast instanceof ast\Node) {
        $result = ast\get_kind_name($ast->kind);
        if ($options & AST_DUMP_LINENOS) {
            $result .= " @ {$ast->lineno}";
            if (isset($ast->endLineno)) {
                $result .= "-{$ast->endLineno}";
            }
        }
        if (ast\kind_uses_flags($ast->kind)) {
            $result .= "\n    flags: " . format_flags($ast->kind, $ast->flags);
        }
        if (isset($ast->name)) {
            $result .= "\n    name: {$ast->name}";
        }
        if (isset($ast->docComment)) {
            $result .= "\n    docComment: {$ast->docComment}";
        }
        foreach ($ast->children as $i => $child) {
            $result .= "\n    {$i}: " . str_replace("\n", "\n    ", ast_dump($child, $options));
        }
        return $result;
    } else {
        if ($ast === null) {
            return 'null';
        } else {
            if (is_string($ast)) {
                return "\"{$ast}\"";
            } else {
                return (string) $ast;
            }
        }
    }
}
コード例 #2
0
ファイル: AST.php プロジェクト: tmli3b3rm4n/phan
 /**
  * ast_node_type() is for places where an actual type
  * name appears. This returns that type name. Use node_type()
  * instead to figure out the type of a node
  *
  * @param Context $context
  * @param null|string|Node $node
  *
  * @see \Phan\Deprecated\AST::ast_node_type
  */
 public static function unionTypeFromSimpleNode(Context $context, $node) : UnionType
 {
     $type_string = null;
     if ($node instanceof \ast\Node) {
         switch ($node->kind) {
             case \ast\AST_NAME:
                 $type_string = self::qualifiedName($context, $node);
                 break;
             case \ast\AST_TYPE:
                 if ($node->flags == \ast\flags\TYPE_CALLABLE) {
                     $type_string = 'callable';
                 } else {
                     if ($node->flags == \ast\flags\TYPE_ARRAY) {
                         $type_string = 'array';
                     } else {
                         assert(false, "Unknown type: {$node->flags}");
                     }
                 }
                 break;
             default:
                 Log::err(Log::EFATAL, "ast_node_type: unknown node type: " . \ast\get_kind_name($node->kind));
                 break;
         }
     } else {
         $type_string = (string) $node;
     }
     return UnionType::fromStringInContext($type_string, $context);
 }
コード例 #3
0
ファイル: ast_util.php プロジェクト: bateller/phan
function ast_dump($ast, $children = true)
{
    if ($ast instanceof \ast\Node) {
        $result = \ast\get_kind_name($ast->kind);
        $result .= " @ {$ast->lineno}";
        if (isset($ast->endLineno)) {
            $result .= "-{$ast->endLineno}";
        }
        if (\ast\kind_uses_flags($ast->kind)) {
            $result .= "\n    flags: {$ast->flags}";
        }
        if (isset($ast->name)) {
            $result .= "\n    name: {$ast->name}";
        }
        if (isset($ast->docComment)) {
            $result .= "\n    docComment: {$ast->docComment}";
        }
        if ($children) {
            foreach ($ast->children as $i => $child) {
                $result .= "\n    {$i}: " . str_replace("\n", "\n    ", ast_dump($child));
            }
        }
        return $result;
    } else {
        if ($ast === null) {
            return 'null';
        } else {
            if (is_string($ast)) {
                return "\"{$ast}\"";
            } else {
                return (string) $ast;
            }
        }
    }
}
コード例 #4
0
ファイル: Debug.php プロジェクト: tmli3b3rm4n/phan
 /**
  * @param string|Node|null $node
  * An AST node
  *
  * @param int $indent
  * The indentation level for the string
  *
  * @return string
  * A string representation of an AST node
  */
 public static function nodeToString($node, $name = null, int $indent = 0) : string
 {
     $string = str_repeat("\t", $indent);
     if ($name !== null) {
         $string .= "{$name} => ";
     }
     if (is_string($node)) {
         return $string . $node . "\n";
     }
     if (!$node) {
         return $string . 'null' . "\n";
     }
     if (!is_object($node)) {
         return $string . $node . "\n";
     }
     $string .= \ast\get_kind_name($node->kind);
     $string .= ' [' . self::astFlagDescription($node->flags ?? 0) . ']';
     if (isset($node->lineno)) {
         $string .= ' #' . $node->lineno;
     }
     if (isset($node->endLineno)) {
         $string .= ':' . $node->endLineno;
     }
     if (isset($node->name)) {
         $string .= ' name:' . $node->name;
     }
     $string .= "\n";
     foreach ($node->children ?? [] as $name => $child_node) {
         $string .= self::nodeToString($child_node, $name, $indent + 1);
     }
     return $string;
 }
コード例 #5
0
 /**
  * Exports a syntax tree into two CSV files as
  * described in https://github.com/jexp/batch-import/
  *
  * @param $ast      The AST to export.
  * @param $nodeline Indicates the nodeline of the parent node. This
  *                  is necessary when $ast is a plain value, since
  *                  we cannot get back from a plain value to the
  *                  parent node to learn the line number.
  * @param $childnum Indicates that this node is the $childnum'th
  *                  child of its parent node (starting at 0).
  * @param $funcid   If the AST to be exported is part of a function,
  *                  the node id of that function.
  * 
  * @return The root node index of the exported AST (i.e., the value
  *         of $this->nodecount at the point in time where this
  *         function was called.)
  */
 public function export($ast, $nodeline = 0, $childnum = 0, $funcid = null) : int
 {
     // (1) if $ast is an AST node, print info and recurse
     // An instance of ast\Node declares:
     // $kind (integer, name can be retrieved using ast\get_kind_name())
     // $flags (integer, corresponding to a set of flags for the current node)
     // $lineno (integer, starting line number)
     // $children (array of child nodes)
     // Additionally, an instance of the subclass ast\Node\Decl declares:
     // $endLineno (integer, end line number of the declaration)
     // $name (string, the name of the declared function/class)
     // $docComment (string, the preceding doc comment)
     if ($ast instanceof ast\Node) {
         $nodetype = ast\get_kind_name($ast->kind);
         $nodeline = $ast->lineno;
         $nodeflags = "";
         if (ast\kind_uses_flags($ast->kind)) {
             $nodeflags = $this->csv_format_flags($ast->kind, $ast->flags);
         }
         // for decl nodes:
         if (isset($ast->endLineno)) {
             $nodeendline = $ast->endLineno;
         }
         if (isset($ast->name)) {
             $nodename = $ast->name;
         }
         if (isset($ast->docComment)) {
             $nodedoccomment = $this->quote_and_escape($ast->docComment);
         }
         // store node, export all children and store the relationships
         $rootnode = $this->store_node($nodetype, $nodeflags, $nodeline, null, $childnum, $funcid, $nodeendline, $nodename, $nodedoccomment);
         // If this node is a function/method/closure declaration, set $funcid.
         // Note that in particular, the decl node *itself* does not have $funcid set to its own id;
         // this is intentional. The *declaration* of a function/method/closure itself is part of the
         // control flow of the outer scope: e.g., a closure declaration is part of the control flow
         // of the function it is declared in, or a function/method declaration is part of the control flow
         // of the pseudo-function representing the top-level code it is declared in.
         if ($ast->kind === ast\AST_FUNC_DECL || $ast->kind === ast\AST_METHOD || $ast->kind === ast\AST_CLOSURE) {
             $funcid = $rootnode;
         }
         foreach ($ast->children as $i => $child) {
             $childnode = $this->export($child, $nodeline, $i, $funcid);
             $this->store_rel($rootnode, $childnode, "PARENT_OF");
         }
     } else {
         if (is_string($ast)) {
             $nodetype = gettype($ast);
             // should be string
             $rootnode = $this->store_node($nodetype, null, $nodeline, $this->quote_and_escape($ast), $childnum, $funcid);
         } else {
             if ($ast === null) {
                 $nodetype = gettype($ast);
                 // should be the string "NULL"
                 $rootnode = $this->store_node($nodetype, null, $nodeline, null, $childnum, $funcid);
             } else {
                 $nodetype = gettype($ast);
                 $nodecode = (string) $ast;
                 $rootnode = $this->store_node($nodetype, null, $nodeline, $nodecode, $childnum, $funcid);
             }
         }
     }
     return $rootnode;
 }
コード例 #6
0
 private function revertAST($node) : string
 {
     if (!$node instanceof Node) {
         switch (gettype($node)) {
             case 'integer':
             case 'double':
             case 'boolean':
                 return $node;
             case 'string':
                 return '"' . $this->sanitiseString($node) . '"';
             default:
                 // an array, null, etc, should never come through here
                 assert(false, 'Unknown type (' . gettype($node) . ') found.');
         }
     }
     switch ($node->kind) {
         case \ast\AST_ARG_LIST:
             return $this->argList($node);
         case \ast\AST_ARRAY:
             return $this->array($node);
         case \ast\AST_ARRAY_ELEM:
             return $this->arrayElem($node);
         case \ast\AST_ASSIGN:
             return $this->assign($node);
         case \ast\AST_ASSIGN_OP:
             return $this->assignOp($node);
         case \ast\AST_ASSIGN_REF:
             return $this->assignRef($node);
         case \ast\AST_BINARY_OP:
             return $this->binaryOp($node);
         case \ast\AST_BREAK:
             return $this->break($node);
         case \ast\AST_CALL:
             return $this->call($node);
         case \ast\AST_CAST:
             return $this->cast($node);
         case \ast\AST_CATCH:
             return $this->catch($node);
         case \ast\AST_CATCH_LIST:
             return $this->catchList($node);
         case \ast\AST_CLASS:
             return $this->class($node);
         case \ast\AST_CLASS_CONST:
             return $this->classConst($node);
         case \ast\AST_CLASS_CONST_DECL:
             return $this->classConstDecl($node);
         case \ast\AST_CLONE:
             return $this->clone($node);
         case \ast\AST_CLOSURE:
             return $this->closure($node);
         case \ast\AST_CLOSURE_VAR:
             return $this->closureVar($node);
         case \ast\AST_COALESCE:
             return $this->coalesce($node);
         case \ast\AST_CONDITIONAL:
             return $this->conditional($node);
         case \ast\AST_CONST:
             return $this->const($node);
         case \ast\AST_CONST_DECL:
             return $this->constDecl($node);
         case \ast\AST_CONST_ELEM:
             return $this->constElem($node);
         case \ast\AST_CONTINUE:
             return $this->continue($node);
         case \ast\AST_DECLARE:
             return $this->declare($node);
         case \ast\AST_DIM:
             return $this->dim($node);
         case \ast\AST_DO_WHILE:
             return $this->doWhile($node);
         case \ast\AST_ECHO:
             return $this->echo($node);
         case \ast\AST_EMPTY:
             return $this->empty($node);
         case \ast\AST_ENCAPS_LIST:
             return $this->encapsList($node);
         case \ast\AST_EXIT:
             return $this->exit($node);
         case \ast\AST_EXPR_LIST:
             return $this->exprList($node);
         case \ast\AST_FOR:
             return $this->for($node);
         case \ast\AST_FOREACH:
             return $this->foreach($node);
         case \ast\AST_FUNC_DECL:
             return $this->funcDecl($node);
         case \ast\AST_GLOBAL:
             return $this->global($node);
         case \ast\AST_GOTO:
             return $this->goto($node);
         case \ast\AST_GROUP_USE:
             return $this->groupUse($node);
         case \ast\AST_HALT_COMPILER:
             return $this->haltCompiler($node);
         case \ast\AST_IF:
             return $this->if($node);
         case \ast\AST_IF_ELEM:
             return $this->ifElem($node);
         case \ast\AST_INCLUDE_OR_EVAL:
             return $this->includeOrEval($node);
         case \ast\AST_INSTANCEOF:
             return $this->instanceof($node);
         case \ast\AST_ISSET:
             return $this->isset($node);
         case \ast\AST_LABEL:
             return $this->label($node);
         case \ast\AST_LIST:
             return $this->list($node);
         case \ast\AST_MAGIC_CONST:
             return $this->magicConst($node);
         case \ast\AST_METHOD:
             return $this->method($node);
         case \ast\AST_METHOD_CALL:
             return $this->methodCall($node);
         case \ast\AST_METHOD_REFERENCE:
             return $this->methodReference($node);
         case \ast\AST_NAME:
             return $this->name($node);
         case \ast\AST_NAMESPACE:
             return $this->namespace($node);
         case \ast\AST_NAME_LIST:
             return $this->nameList($node);
         case \ast\AST_NEW:
             return $this->new($node);
         case \ast\AST_PARAM:
             return $this->param($node);
         case \ast\AST_PARAM_LIST:
             return $this->paramList($node);
         case \ast\AST_POST_DEC:
             return $this->postDec($node);
         case \ast\AST_POST_INC:
             return $this->postInc($node);
         case \ast\AST_PRE_DEC:
             return $this->preDec($node);
         case \ast\AST_PRE_INC:
             return $this->preInc($node);
         case \ast\AST_PRINT:
             return $this->print($node);
         case \ast\AST_PROP:
             return $this->prop($node);
         case \ast\AST_PROP_DECL:
             return $this->propDecl($node);
         case \ast\AST_PROP_ELEM:
             return $this->propElem($node);
         case \ast\AST_REF:
             return $this->ref($node);
         case \ast\AST_RETURN:
             return $this->return($node);
         case \ast\AST_SHELL_EXEC:
             return $this->shellExec($node);
         case \ast\AST_STATIC:
             return $this->static($node);
         case \ast\AST_STATIC_CALL:
             return $this->staticCall($node);
         case \ast\AST_STATIC_PROP:
             return $this->staticProp($node);
         case \ast\AST_STMT_LIST:
             return $this->stmtList($node);
         case \ast\AST_SWITCH:
             return $this->switch($node);
         case \ast\AST_SWITCH_CASE:
             return $this->switchCase($node);
         case \ast\AST_SWITCH_LIST:
             return $this->switchList($node);
         case \ast\AST_THROW:
             return $this->throw($node);
         case \ast\AST_TRAIT_ADAPTATIONS:
             return $this->traitAdaptations($node);
         case \ast\AST_TRAIT_ALIAS:
             return $this->traitAlias($node);
         case \ast\AST_TRAIT_PRECEDENCE:
             return $this->traitPrecedence($node);
         case \ast\AST_TRY:
             return $this->try($node);
         case \ast\AST_TYPE:
             return $this->type($node);
         case \ast\AST_UNARY_OP:
             return $this->unaryOp($node);
         case \ast\AST_UNPACK:
             return $this->unpack($node);
         case \ast\AST_UNSET:
             return $this->unset($node);
         case \ast\AST_USE:
             return $this->use($node);
         case \ast\AST_USE_ELEM:
             return $this->useElem($node);
         case \ast\AST_USE_TRAIT:
             return $this->useTrait($node);
         case \ast\AST_VAR:
             return $this->var($node);
         case \ast\AST_WHILE:
             return $this->while($node);
         case \ast\AST_YIELD:
             return $this->yield($node);
         case \ast\AST_YIELD_FROM:
             return $this->yieldFrom($node);
         default:
             assert(false, 'Unknown AST kind (' . \ast\get_kind_name($node->kind) . ') found.');
     }
 }