mirror of
https://github.com/danog/PHP-Parser.git
synced 2024-11-26 20:04:48 +01:00
Further work on PrettyPrinter. Add possibility to test PrettyPrinter correctness
This commit is contained in:
parent
685171ddc5
commit
3c13dce680
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
|
||||
class Node_Expr extends NodeAbstract
|
||||
abstract class Node_Expr extends NodeAbstract
|
||||
{
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property Node_Variable $var Variable reference is assigned to
|
||||
* @property Node_Variable $refVar Variable which is referenced
|
||||
*/
|
||||
class Node_Expr_AssignRef extends Node_Expr
|
||||
{
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property null|Node_Expr $expr Expression
|
||||
*/
|
||||
class Node_Expr_Exit extends Node_Expr
|
||||
{
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property array $assignList List of variables to assign to
|
||||
* @property Node_Expr $expr Expression
|
||||
*/
|
||||
class Node_Expr_List extends Node_Expr
|
||||
{
|
||||
}
|
@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property Node_Name|Node_Variable $class Class name
|
||||
* @property string|Node_Variable $func Method name
|
||||
* @property array $args Arguments
|
||||
*/
|
||||
class Node_Expr_StaticCall extends Node_Expr
|
||||
{
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
|
||||
class Node_Scalar extends NodeAbstract
|
||||
abstract class Node_Scalar extends NodeAbstract
|
||||
{
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
|
||||
class Node_Stmt extends NodeAbstract
|
||||
abstract class Node_Stmt extends NodeAbstract
|
||||
{
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property null|Node_Expr $cond Condition (null for default)
|
||||
* @property array $stmts Statements
|
||||
*/
|
||||
class Node_Stmt_Case extends Node_Stmt
|
||||
{
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property array $consts Constant declarations
|
||||
*/
|
||||
class Node_Stmt_Const extends Node_Stmt
|
||||
{
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property string $name Name
|
||||
* @property Node_Expr $value Value
|
||||
*/
|
||||
class Node_Stmt_ConstConst extends Node_Stmt
|
||||
{
|
||||
}
|
@ -1,5 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property array $init Init expression
|
||||
* @property array $cond Loop condition
|
||||
* @property array $loop Loop expression
|
||||
* @property array $stmts Statements
|
||||
*/
|
||||
class Node_Stmt_For extends Node_Stmt
|
||||
{
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property Node_Expr $cond Condition
|
||||
* @property array $caseList Case list
|
||||
*/
|
||||
class Node_Stmt_Switch extends Node_Stmt
|
||||
{
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property Node_Expr $expr Expression
|
||||
*/
|
||||
class Node_Stmt_Throw extends Node_Stmt
|
||||
{
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property Node_Expr $cond Condition
|
||||
* @property array $stmts Statements
|
||||
*/
|
||||
class Node_Stmt_While extends Node_Stmt
|
||||
{
|
||||
}
|
@ -72,6 +72,10 @@ class PrettyPrinter_Zend extends PrettyPrinterAbstract
|
||||
return $this->p($node->var) . ' = ' . $this->p($node->expr);
|
||||
}
|
||||
|
||||
public function pExpr_AssignRef(Node_Expr_AssignRef $node) {
|
||||
return $this->p($node->var) . ' =& ' . $this->p($node->refVar);
|
||||
}
|
||||
|
||||
public function pExpr_AssignPlus(Node_Expr_AssignPlus $node) {
|
||||
return $this->p($node->var) . ' += ' . $this->p($node->expr);
|
||||
}
|
||||
@ -116,6 +120,19 @@ class PrettyPrinter_Zend extends PrettyPrinterAbstract
|
||||
return $this->p($node->var) . ' >>= ' . $this->p($node->expr);
|
||||
}
|
||||
|
||||
public function pExpr_List(Node_Expr_List $node) {
|
||||
$pAssignList = array();
|
||||
foreach ($node->assignList as $element) {
|
||||
if (null === $element) {
|
||||
$pAssignList[] = '';
|
||||
} else {
|
||||
$pAssignList[] = $this->p($element);
|
||||
}
|
||||
}
|
||||
|
||||
return 'list(' . implode(', ', $pAssignList) . ') = ' . $this->p($node->expr);
|
||||
}
|
||||
|
||||
// Binary expressions
|
||||
|
||||
public function pExpr_Plus(Node_Expr_Plus $node) {
|
||||
@ -281,6 +298,12 @@ class PrettyPrinter_Zend extends PrettyPrinterAbstract
|
||||
. '(' . $this->pCommaSeparated($node->args) . ')';
|
||||
}
|
||||
|
||||
public function pExpr_StaticCall(Node_Expr_StaticCall $node) {
|
||||
return $this->p($node->class) . '::'
|
||||
. ($node->func instanceof Node_Variable ? $this->p($node->func) : $node->func)
|
||||
. '(' . $this->pCommaSeparated($node->args) . ')';
|
||||
}
|
||||
|
||||
public function pExpr_Empty(Node_Expr_Empty $node) {
|
||||
return 'empty(' . $this->p($node->var) . ')';
|
||||
}
|
||||
@ -328,10 +351,7 @@ class PrettyPrinter_Zend extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
public function pExpr_StaticPropertyFetch(Node_Expr_StaticPropertyFetch $node) {
|
||||
// TODO
|
||||
|
||||
return $this->p($node->class) . '::'
|
||||
. ($node->name instanceof Node_Expr ? $this->p($node->name) : '$' . $node->name);
|
||||
return $this->p($node->class) . '::$' . $this->pObjectProperty($node->name);
|
||||
}
|
||||
|
||||
public function pExpr_LambdaFunc(Node_Expr_LambdaFunc $node) {
|
||||
@ -355,15 +375,11 @@ class PrettyPrinter_Zend extends PrettyPrinterAbstract
|
||||
. ': ' . $this->p($node->else);
|
||||
}
|
||||
|
||||
// Statements
|
||||
|
||||
public function pStmt_Break(Node_Stmt_Break $node) {
|
||||
return 'break' . ($node->num !== null ? ' ' . $node->num : '');
|
||||
public function pExpr_Exit(Node_Expr_Exit $node) {
|
||||
return 'die' . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : '');
|
||||
}
|
||||
|
||||
public function pStmt_Continue(Node_Stmt_Continue $node) {
|
||||
return 'continue' . ($node->num !== null ? ' ' . $node->num : '');
|
||||
}
|
||||
// Declarations
|
||||
|
||||
public function pStmt_Class(Node_Stmt_Class $node) {
|
||||
return $this->pModifiers($node->type)
|
||||
@ -373,12 +389,13 @@ class PrettyPrinter_Zend extends PrettyPrinterAbstract
|
||||
. "\n" . '{' . "\n" . $this->pIndent($this->pStmts($node->stmts)) . '}';
|
||||
}
|
||||
|
||||
public function pStmt_ClassConst(Node_Stmt_ClassConst $node) {
|
||||
return 'const ' . $this->pCommaSeparated($node->consts);
|
||||
public function pStmt_Property(Node_Stmt_Property $node) {
|
||||
return $this->pModifiers($node->type) . $this->pCommaSeparated($node->props);
|
||||
}
|
||||
|
||||
public function pStmt_ClassConstConst(Node_Stmt_ClassConstConst $node) {
|
||||
return $node->name . ' = ' . $this->p($node->value);
|
||||
public function pStmt_PropertyProperty(Node_Stmt_PropertyProperty $node) {
|
||||
return '$' . $node->name
|
||||
. (null !== $node->default ? ' = ' . $this->p($node->default) : '');
|
||||
}
|
||||
|
||||
public function pStmt_ClassMethod(Node_Stmt_ClassMethod $node) {
|
||||
@ -388,15 +405,12 @@ class PrettyPrinter_Zend extends PrettyPrinterAbstract
|
||||
. "\n" . '{' . "\n" . $this->pIndent($this->pStmts($node->stmts)) . '}';
|
||||
}
|
||||
|
||||
public function pStmt_Echo(Node_Stmt_Echo $node) {
|
||||
return 'echo ' . $this->pCommaSeparated($node->exprs);
|
||||
public function pStmt_ClassConst(Node_Stmt_ClassConst $node) {
|
||||
return 'const ' . $this->pCommaSeparated($node->consts);
|
||||
}
|
||||
|
||||
public function pStmt_Foreach(Node_Stmt_Foreach $node) {
|
||||
return 'foreach (' . $this->p($node->expr) . ' '
|
||||
. (null !== $node->keyVar ? $this->p($node) . ' as ' : '')
|
||||
. ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {' . "\n"
|
||||
. $this->pIndent($this->pStmts($node->stmts)) . '}';
|
||||
public function pStmt_ClassConstConst(Node_Stmt_ClassConstConst $node) {
|
||||
return $node->name . ' = ' . $this->p($node->value);
|
||||
}
|
||||
|
||||
public function pStmt_Func(Node_Stmt_Func $node) {
|
||||
@ -412,6 +426,16 @@ class PrettyPrinter_Zend extends PrettyPrinterAbstract
|
||||
. ($node->default ? ' = ' . $this->p($node->default) : '');
|
||||
}
|
||||
|
||||
public function pStmt_Const(Node_Stmt_Const $node) {
|
||||
return 'const ' . $this->pCommaSeparated($node->consts);
|
||||
}
|
||||
|
||||
public function pStmt_ConstConst(Node_Stmt_ConstConst $node) {
|
||||
return $node->name . ' = ' . $this->p($node->value);
|
||||
}
|
||||
|
||||
// Control flow
|
||||
|
||||
public function pStmt_If(Node_Stmt_If $node) {
|
||||
return 'if (' . $this->p($node->cond) . ') {' . "\n"
|
||||
. $this->pIndent($this->pStmts($node->stmts)) . '}'
|
||||
@ -420,7 +444,7 @@ class PrettyPrinter_Zend extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
public function pStmt_Elseif(Node_Stmt_Elseif $node) {
|
||||
return ' elseif {' . "\n"
|
||||
return ' elseif (' . $this->p($node->cond) . ') {' . "\n"
|
||||
. $this->pIndent($this->pStmts($node->stmts)) . '}';
|
||||
}
|
||||
|
||||
@ -429,19 +453,62 @@ class PrettyPrinter_Zend extends PrettyPrinterAbstract
|
||||
. $this->pIndent($this->pStmts($node->stmts)) . '}';
|
||||
}
|
||||
|
||||
public function pStmt_Property(Node_Stmt_Property $node) {
|
||||
return $this->pModifiers($node->type) . $this->pCommaSeparated($node->props);
|
||||
public function pStmt_For(Node_Stmt_For $node) {
|
||||
return 'for ('
|
||||
. $this->pCommaSeparated($node->init) . ';'
|
||||
. $this->pCommaSeparated($node->cond) . ';'
|
||||
. $this->pCommaSeparated($node->loop)
|
||||
. ') {' . "\n" . $this->pIndent($this->pStmts($node->stmts)) . '}';
|
||||
}
|
||||
|
||||
public function pStmt_PropertyProperty(Node_Stmt_PropertyProperty $node) {
|
||||
return '$' . $node->name
|
||||
. (null !== $node->default ? ' = ' . $this->p($node->default) : '');
|
||||
public function pStmt_Foreach(Node_Stmt_Foreach $node) {
|
||||
return 'foreach (' . $this->p($node->expr) . ' as '
|
||||
. (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '')
|
||||
. ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {' . "\n"
|
||||
. $this->pIndent($this->pStmts($node->stmts)) . '}';
|
||||
}
|
||||
|
||||
public function pStmt_While(Node_Stmt_While $node) {
|
||||
return 'while (' . $this->p($node->cond) . ') {'
|
||||
. "\n" . $this->pIndent($this->pStmts($node->stmts)) . '}';
|
||||
}
|
||||
|
||||
public function pStmt_Switch(Node_Stmt_Switch $node) {
|
||||
return 'switch (' . $this->p($node->cond) . ') {'
|
||||
. "\n" . $this->pIndent($this->pImplode($node->caseList)) . '}';
|
||||
}
|
||||
|
||||
public function pStmt_Case(Node_Stmt_Case $node) {
|
||||
return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':'
|
||||
. "\n" . $this->pIndent($this->pStmts($node->stmts));
|
||||
}
|
||||
|
||||
public function pStmt_Break(Node_Stmt_Break $node) {
|
||||
return 'break' . ($node->num !== null ? ' ' . $node->num : '');
|
||||
}
|
||||
|
||||
public function pStmt_Continue(Node_Stmt_Continue $node) {
|
||||
return 'continue' . ($node->num !== null ? ' ' . $node->num : '');
|
||||
}
|
||||
|
||||
public function pStmt_Return(Node_Stmt_Return $node) {
|
||||
return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '');
|
||||
}
|
||||
|
||||
public function pStmt_Throw(Node_Stmt_Throw $node) {
|
||||
return 'throw' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '');
|
||||
}
|
||||
|
||||
// Other
|
||||
|
||||
public function pStmt_Echo(Node_Stmt_Echo $node) {
|
||||
return 'echo ' . $this->pCommaSeparated($node->exprs);
|
||||
}
|
||||
|
||||
public function pStmt_Noop(Node_Stmt_Noop $node) {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function pStmt_Static(Node_Stmt_Static $node) {
|
||||
return 'static ' . $this->pCommaSeparated($node->vars);
|
||||
}
|
||||
@ -451,7 +518,7 @@ class PrettyPrinter_Zend extends PrettyPrinterAbstract
|
||||
. (null !== $node->default ? ' = ' . $this->p($node->default) : '');
|
||||
}
|
||||
|
||||
// helpers
|
||||
// Helpers
|
||||
|
||||
public function pObjectProperty($node) {
|
||||
if ($node instanceof Node_Expr) {
|
||||
|
@ -78,11 +78,14 @@ abstract class PrettyPrinterAbstract
|
||||
foreach ($nodes as $node) {
|
||||
$return .= $this->p($node);
|
||||
|
||||
if ($node instanceof Node_Stmt_Func
|
||||
if ( $node instanceof Node_Stmt_Func
|
||||
|| $node instanceof Node_Stmt_Class
|
||||
|| $node instanceof Node_Stmt_ClassMethod
|
||||
|| $node instanceof Node_Stmt_For
|
||||
|| $node instanceof Node_Stmt_Foreach
|
||||
|| $node instanceof Node_Stmt_If
|
||||
|| $node instanceof Node_Stmt_Switch
|
||||
|| $node instanceof Node_Stmt_While
|
||||
) {
|
||||
$return .= "\n";
|
||||
} else {
|
||||
|
32
test.php
32
test.php
@ -23,6 +23,7 @@ $stmts = $parser->yyparse(new Lexer(
|
||||
echo $msg;
|
||||
}
|
||||
);
|
||||
|
||||
if (false !== $stmts) {
|
||||
foreach ($stmts as $stmt) {
|
||||
echo htmlspecialchars($stmt), "\n";
|
||||
@ -34,38 +35,9 @@ echo "\n\n";
|
||||
$prettyPrinter = new PrettyPrinter_Zend;
|
||||
echo htmlspecialchars($prettyPrinter->pStmts(
|
||||
$parser->yyparse(
|
||||
new Lexer(file_get_contents('./lib/Parser.php')),
|
||||
new Lexer(file_get_contents('./grammar/analyzer.php')),
|
||||
function ($msg) {
|
||||
echo $msg;
|
||||
}
|
||||
)
|
||||
));
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
// Correctness Demo
|
||||
$GST = microtime(true);
|
||||
foreach (new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator('.'),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY)
|
||||
as $file) {
|
||||
if ('.php' !== substr($file, -4)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
set_time_limit(5);
|
||||
|
||||
$startTime = microtime(true);
|
||||
$stmts = $parser->yyparse(
|
||||
new Lexer(file_get_contents($file)),
|
||||
function($msg) {
|
||||
echo $msg, "\n";
|
||||
}
|
||||
);
|
||||
$endTime = microtime(true);
|
||||
|
||||
echo str_pad($file . ': ', 120, ' '), (false !== $stmts ? 'successful' : 'ERROR'), ' (', $endTime - $startTime, ')', "\n";
|
||||
|
||||
flush();
|
||||
}
|
||||
echo microtime(true) - $GST;
|
120
test/testAgainstDirectory.php
Normal file
120
test/testAgainstDirectory.php
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
$DIR = '..';
|
||||
|
||||
function __autoload($class) {
|
||||
is_file($file = '../lib/' . strtr($class, '_', '/') . '.php') && require_once $file;
|
||||
}
|
||||
|
||||
$parser = new Parser();
|
||||
$parser->yydebug = false;
|
||||
|
||||
$prettyPrinter = new PrettyPrinter_Zend;
|
||||
|
||||
echo '<!DOCTYPE html>
|
||||
<style>
|
||||
body {
|
||||
font-family: "Trebuchet MS", sans-serif;
|
||||
}
|
||||
|
||||
.pass {
|
||||
color: white;
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.fail {
|
||||
color: white;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.failReason {
|
||||
background-color: rgba(255, 0, 0, 0.3);
|
||||
}
|
||||
</style>
|
||||
<table>
|
||||
<tr>
|
||||
<td>File</td>
|
||||
<td>Parse</td>
|
||||
<td>Time</td>
|
||||
<td>PrettyPrint</td>
|
||||
<td>Same</td>
|
||||
</tr>';
|
||||
|
||||
$GST = microtime(true);
|
||||
foreach (new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($DIR),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY)
|
||||
as $file) {
|
||||
if ('.php' !== substr($file, -4)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
echo '
|
||||
<tr>
|
||||
<td>' . $file . '</td>';
|
||||
|
||||
set_time_limit(5);
|
||||
|
||||
$errMsg = '';
|
||||
$startTime = microtime(true);
|
||||
|
||||
$stmts = $parser->yyparse(
|
||||
new Lexer(file_get_contents($file)),
|
||||
function($msg) use (&$errMsg) {
|
||||
$errMsg = $msg;
|
||||
}
|
||||
);
|
||||
|
||||
$time = microtime(true) - $startTime;
|
||||
|
||||
if (false !== $stmts) {
|
||||
$code = '<?php' . "\n" . $prettyPrinter->pStmts($stmts);
|
||||
|
||||
$ppStmts = $parser->yyparse(
|
||||
new Lexer($code),
|
||||
function($msg) use (&$errMsg) {
|
||||
$errMsg = $msg;
|
||||
}
|
||||
);
|
||||
|
||||
if (false !== $ppStmts) {
|
||||
if ($stmts == $ppStmts) {
|
||||
echo '
|
||||
<td class="pass">PASS</td>
|
||||
<td>' . $time . 's</td>
|
||||
<td class="pass">PASS</td>
|
||||
<td class="pass">PASS</td>
|
||||
</tr>';
|
||||
} else {
|
||||
echo '
|
||||
<td class="pass">PASS</td>
|
||||
<td>' . $time . 's</td>
|
||||
<td class="pass">PASS</td>
|
||||
<td class="fail">FAIL</td>
|
||||
</tr>';
|
||||
}
|
||||
} else {
|
||||
echo '
|
||||
<td class="pass">PASS</td>
|
||||
<td>' . $time . 's</td>
|
||||
<td class="fail">FAIL</td>
|
||||
<td></td>
|
||||
</tr>';
|
||||
}
|
||||
} else {
|
||||
echo '
|
||||
<td class="fail">FAIL</td>
|
||||
<td>' . $time . 's</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr class="failReason"><td colspan="5">' . $errMsg . '</td></tr>';
|
||||
}
|
||||
|
||||
flush();
|
||||
}
|
||||
|
||||
echo '
|
||||
</table>';
|
||||
|
||||
echo 'Total time: ', microtime(true) - $GST;
|
Loading…
Reference in New Issue
Block a user