如何在 AST 中获取变量名和值

我正在使用PHP-PARser来查找 PHP 程序的 AST。例如:

代码


<?php

use PhpParser\Error;

use PhpParser\NodeDumper;

use PhpParser\ParserFactory;


$code = <<<'CODE'

<?php

$variable = $_POST['first'];

$new = $nonexist; 

CODE;


$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);

try {

    $ast = $parser->parse($code);

} catch (Error $error) {

    echo "Parse error: {$error->getMessage()}\n";

    return;

}


$dumper = new NodeDumper;

echo $dumper->dump($ast) . "\n";

上面例子的AST结果如下:


array( 0: Stmt_Expression( expr: Expr_Assign( var: Expr_Variable( name: variable ) expr: Expr_ArrayDimFetch( var: Expr_Variable( name: _POST_first_symbol ) dim: Scalar_String( value: first ) ) ) ) 1: Stmt_Expression( expr: Expr_Assign( var: Expr_Variable( name: new ) expr: Expr_Variable( name: nonexist ) ) ) )


我要查找的是variable = _POSTANDnew = nonexist 我使用leavenode函数来达到_POSTand variable。我要查找的代码_POST如下variable:


public function leaveNode(Node $node)

    {

        $collect_to_print= array();


        if ($node instanceof ArrayDimFetch

            && $node->var instanceof Variable

            && $node->var->name === '_POST')

        {

            $variableName = (string) $node->var->name;

            $collect_to_print[$node->dim->value] = $node->var->name; // will store the variables in array in a way to print them all later such as variable => _POST , how to get the name `variable` in this case

            return $node;

        }

        else

            if ($node instanceof Variable

        && !($node->var->name === '_POST' ))

        {

            $collect_to_print[$node->name] = 'Empty' ;

        }


    }

到目前为止,我的结果在单独的行中显示每个变量,如下所示:


variable => 

first => _POST  // This _POST should be the value of variable (above)

new => Empty

nonexist => Empty

但是,我希望结果是:


variable => _POST

new => Empty

nonexist => Empty

请帮忙


茅侃侃
浏览 149回答 1
1回答

慕丝7291255

这比您提出的其他问题要复杂得多,但是了解如何编写它很有趣。我已经在代码中添加了注释,但基本上它会分析代码并查找分配(PhpParser\Node\Expr\Assign节点实例)。然后它将它分成左右两部分,并递归地提取两部分中的任何变量。该代码允许在表达式的任一侧嵌套变量,我更改了示例代码以提供一些更广泛的示例。代码中的注释(假定了解解析器如何与节点等一起工作)...$traverser = new NodeTraverser;class ExtractVars extends NodeVisitorAbstract {&nbsp; &nbsp; private $prettyPrinter = null;&nbsp; &nbsp; private $variables = [];&nbsp; &nbsp; private $expressions = [];&nbsp; &nbsp; public function __construct() {&nbsp; &nbsp; &nbsp; &nbsp; $this->prettyPrinter = new PhpParser\PrettyPrinter\Standard;&nbsp; &nbsp; }&nbsp; &nbsp; public function leaveNode(Node $node) {&nbsp; &nbsp; &nbsp; &nbsp; if ( $node instanceof PhpParser\Node\Expr\Assign&nbsp; ) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $assignVars = $this->extractVarRefs ( $node->var );&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Get string of what assigned to actually is&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $assign = $this->prettyPrinter->prettyPrintExpr($node->var);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Store the variables associated with the left hand side&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $this->expressions[$assign]["to"] = $assignVars;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Store variables from right&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $this->expressions[$assign][] = $this->extractVarRefs ( $node->expr );&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}&nbsp; &nbsp; }&nbsp; &nbsp; private function extractVarRefs ( Node $node ) : array&nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; $variableList = [];&nbsp; &nbsp; &nbsp; &nbsp; // If it's a variable, store the name&nbsp; &nbsp; &nbsp; &nbsp; if ( $node instanceof PhpParser\Node\Expr\Variable )&nbsp; &nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $variable = $this->prettyPrinter->prettyPrintExpr($node);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $this->variables[] = $variable;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $variableList[] = $variable;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // Look for any further variables in the node&nbsp; &nbsp; &nbsp; &nbsp; foreach ( $node->getSubNodeNames() as $newNodeName )&nbsp; &nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $newNode = $node->$newNodeName;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ( $newNode instanceof Node && $newNode->getSubNodeNames())&nbsp; &nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Recursive call to extract variables&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $toAdd = $this->extractVarRefs ( $newNode );&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Add new list to current list&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $variableList = array_merge($variableList, $toAdd);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return $variableList;&nbsp; &nbsp; }&nbsp; &nbsp; public function getVariables() : array&nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return array_unique($this->variables);&nbsp; &nbsp; }&nbsp; &nbsp; public function getExpressions() : array&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return $this->expressions;&nbsp; &nbsp; }}$varExtract = new ExtractVars();$traverser->addVisitor ($varExtract);$traverser->traverse($ast);print_r($varExtract->getVariables());print_r($varExtract->getExpressions());其中给出了变量列表...Array(&nbsp; &nbsp; [0] => $_POST&nbsp; &nbsp; [1] => $b&nbsp; &nbsp; [3] => $new&nbsp; &nbsp; [4] => $nonexist)表达式列表为Array(&nbsp; &nbsp; [$_POST[$b]] => Array&nbsp; &nbsp; &nbsp; &nbsp; (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [to] => Array&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [0] => $_POST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [1] => $b&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [0] => Array&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [0] => $_POST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; [$new] => Array&nbsp; &nbsp; &nbsp; &nbsp; (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [to] => Array&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [0] => $new&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [0] => Array&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [0] => $nonexist&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [1] => Array&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [0] => $_POST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [1] => $b&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; ))请注意,[to]数组的元素包含 . 左侧涉及的所有变量=。
打开App,查看更多内容
随时随地看视频慕课网APP