Как пройти PHP исходный код с условием If - PullRequest
0 голосов
/ 11 марта 2020

Я использую PHP -Parser для оценки условий, используемых для обхода оператора if. Я просто хочу знать, какие условия используются при обходе кода. Например:

test

<?php 
$val = true;
if ($val == true){
   $result = true;
} else {
   $result  = false;
}

Я уже нашел AST тестового кода, который выглядит следующим образом

AST

array( 0: Stmt_Expression( expr: Expr_Assign( var: Expr_Variable( name: val ) expr: Expr_ConstFetch( name: Name( parts: array( 0: true ) ) ) ) ) 1: Stmt_If( cond: Expr_BinaryOp_Equal( left: Expr_Variable( name: val ) right: Expr_ConstFetch( name: Name( parts: array( 0: true ) ) ) ) stmts: array( 0: Stmt_Expression( expr: Expr_Assign( var: Expr_Variable( name: result ) expr: Expr_ConstFetch( name: Name( parts: array( 0: true ) ) ) ) ) ) elseifs: array( ) else: Stmt_Else( stmts: array( 0: Stmt_Expression( expr: Expr_Assign( var: Expr_Variable( name: result ) expr: Expr_ConstFetch( name: Name( parts: array( 0: false ) ) ) ) ) ) ) ) )

Что Я пытаюсь понять, какое условие использовалось в тестовом коде во время обхода. Ожидается, что оно будет примерно таким:

Ожидаемый результат

Conditions: (operator: Equal true:bool,true:bool,)

// OR 

Condition: (operator: NOT (operator: Equal true:bool,true:bool,),)

Так что я просто интересно, как получить условия, проходящие во время траверса.

1 Ответ

1 голос
/ 11 марта 2020

Единственное, что я скажу, это то, что вы не обязательно можете получить значения обоих операторов, так как это выполняется во время выполнения, а не при разборе. Таким образом, вместо

Conditions: (operator: Equal true:bool,true:bool,)

Вы можете получить что-то вроде ...

Conditions: (operator: Equal left -> $val, right -> true,)

Это что-то основанное на предыдущем вопросе / ответе на Как использовать PHP - Парсер, чтобы получить имя глобальной переменной и изменить его .

Таким образом, текущий код ...

$code = <<<'CODE'
<?php 
$val = true;
if ($val == true){
   $result = true;
} else {
   $result  = false;
}
CODE;


$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
try {
    $ast = $parser->parse($code);
} catch (Error $error) {
    echo "Parse error: {$error->getMessage()}\n";
    return;
}

$traverser = new NodeTraverser;
$traverser->addVisitor(new class extends NodeVisitorAbstract {
    public function leaveNode(Node $node){
        if ($node instanceof PhpParser\Node\Stmt\If_ ) {
            $prettyPrinter = new PhpParser\PrettyPrinter\Standard;
            echo "left=".$prettyPrinter->prettyPrintExpr($node->cond->left).
                " ".get_class($node->cond).
                " right=".$prettyPrinter->prettyPrintExpr($node->cond->right).PHP_EOL;

            echo "expression is `".$prettyPrinter->prettyPrintExpr($node->cond)."`".PHP_EOL;
        }
    }

});

$traverser->traverse($ast);

, который даст ...

left=$val PhpParser\Node\Expr\BinaryOp\Equal right=true
expression is `$val == true`
...