Beispiel #1
0
/** 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;
            }
        }
    }
}
Beispiel #2
0
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;
            }
        }
    }
}
Beispiel #3
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;
 }