Giter Site home page Giter Site logo

php-parser's Introduction

PHP Parser

Coverage Status

This is a PHP parser written in PHP. Its purpose is to simplify static code analysis and manipulation.

Documentation for version 5.x (current; for running on PHP >= 7.4; for parsing PHP 7.0 to PHP 8.3, with limited support for parsing PHP 5.x).

Documentation for version 4.x (supported; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 8.3).

Features

The main features provided by this library are:

  • Parsing PHP 7, and PHP 8 code into an abstract syntax tree (AST).
    • Invalid code can be parsed into a partial AST.
    • The AST contains accurate location information.
  • Dumping the AST in human-readable form.
  • Converting an AST back to PHP code.
    • Formatting can be preserved for partially changed ASTs.
  • Infrastructure to traverse and modify ASTs.
  • Resolution of namespaced names.
  • Evaluation of constant expressions.
  • Builders to simplify AST construction for code generation.
  • Converting an AST into JSON and back.

Quick Start

Install the library using composer:

php composer.phar require nikic/php-parser

Parse some PHP code into an AST and dump the result in human-readable form:

<?php
use PhpParser\Error;
use PhpParser\NodeDumper;
use PhpParser\ParserFactory;

$code = <<<'CODE'
<?php

function test($foo)
{
    var_dump($foo);
}
CODE;

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

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

This dumps an AST looking something like this:

array(
    0: Stmt_Function(
        attrGroups: array(
        )
        byRef: false
        name: Identifier(
            name: test
        )
        params: array(
            0: Param(
                attrGroups: array(
                )
                flags: 0
                type: null
                byRef: false
                variadic: false
                var: Expr_Variable(
                    name: foo
                )
                default: null
            )
        )
        returnType: null
        stmts: array(
            0: Stmt_Expression(
                expr: Expr_FuncCall(
                    name: Name(
                        name: var_dump
                    )
                    args: array(
                        0: Arg(
                            name: null
                            value: Expr_Variable(
                                name: foo
                            )
                            byRef: false
                            unpack: false
                        )
                    )
                )
            )
        )
    )
)

Let's traverse the AST and perform some kind of modification. For example, drop all function bodies:

use PhpParser\Node;
use PhpParser\Node\Stmt\Function_;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitorAbstract;

$traverser = new NodeTraverser();
$traverser->addVisitor(new class extends NodeVisitorAbstract {
    public function enterNode(Node $node) {
        if ($node instanceof Function_) {
            // Clean out the function body
            $node->stmts = [];
        }
    }
});

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

This gives us an AST where the Function_::$stmts are empty:

array(
    0: Stmt_Function(
        attrGroups: array(
        )
        byRef: false
        name: Identifier(
            name: test
        )
        params: array(
            0: Param(
                attrGroups: array(
                )
                type: null
                byRef: false
                variadic: false
                var: Expr_Variable(
                    name: foo
                )
                default: null
            )
        )
        returnType: null
        stmts: array(
        )
    )
)

Finally, we can convert the new AST back to PHP code:

use PhpParser\PrettyPrinter;

$prettyPrinter = new PrettyPrinter\Standard;
echo $prettyPrinter->prettyPrintFile($ast);

This gives us our original code, minus the var_dump() call inside the function:

<?php

function test($foo)
{
}

For a more comprehensive introduction, see the documentation.

Documentation

  1. Introduction
  2. Usage of basic components

Component documentation:

  • Walking the AST
    • Node visitors
    • Modifying the AST from a visitor
    • Short-circuiting traversals
    • Interleaved visitors
    • Simple node finding API
    • Parent and sibling references
  • Name resolution
    • Name resolver options
    • Name resolution context
  • Pretty printing
    • Converting AST back to PHP code
    • Customizing formatting
    • Formatting-preserving code transformations
  • AST builders
    • Fluent builders for AST nodes
  • Lexer
    • Emulation
    • Tokens, positions and attributes
  • Error handling
    • Column information for errors
    • Error recovery (parsing of syntactically incorrect code)
  • Constant expression evaluation
    • Evaluating constant/property/etc initializers
    • Handling errors and unsupported expressions
  • JSON representation
    • JSON encoding and decoding of ASTs
  • Performance
    • Disabling Xdebug
    • Reusing objects
    • Garbage collection impact
  • Frequently asked questions
    • Parent and sibling references

php-parser's People

Contributors

algo13 avatar carusogabriel avatar codeliner avatar grahamcampbell avatar hason avatar jesseschalken avatar kix avatar kukulich avatar lisachenko avatar localheinz avatar maks-rafalko avatar mathiasreker avatar muglug avatar nikic avatar ondrejmirtes avatar ovr avatar progminer avatar reedy avatar remicollet avatar samsonasik avatar sasezaki avatar schmittjoh avatar simivar avatar staabm avatar theofidry avatar theseer avatar tomasvotruba avatar tysonandre avatar wes0617 avatar wintersilence avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

php-parser's Issues

Namespace support

When the code uses namespaces, the namespace node should be the root node for all the code within the namespace:

namespace Foo {
    echo 'Hello';
}

namespace Bar {
    echo 'Hello';
}

Current output:

0: Stmt_Namespace(
    ns: Name(
        parts: array(
            0: Foo
        )
    )
)
1: array(
    0: Stmt_Echo(
        exprs: array(
            0: Scalar_String(
                value: Hello
                isBinary: false
                type: 0
            )
        )
    )
)
2: Stmt_Namespace(
    ns: Name(
        parts: array(
            0: Bar
        )
    )
)
3: array(
    0: Stmt_Echo(
        exprs: array(
            0: Scalar_String(
                value: Hello
                isBinary: false
                type: 0
            )
        )
    )
)

Global constants (define) do not appear to be interpreted

When parsing the test file

<?php

define("CONST", "test");

I would have expected to get an instance of PHPParser_Node_Stmt_Const but I receive the following tokens

string(28) "PHPParser_Node_Expr_FuncCall"
string(19) "PHPParser_Node_Name"
string(18) "PHPParser_Node_Arg"
string(28) "PHPParser_Node_Scalar_String"
string(18) "PHPParser_Node_Arg"
string(28) "PHPParser_Node_Scalar_String"

Upon inspection the instance of PHPParser_Node_Expr_FuncCall contains the define function definition.

Am I misinterpreting the way constants are interpreted by PHP-Parser?

Even more fluid code generation

I looked at
https://github.com/nikic/PHP-Parser/blob/master/doc/4_Code_generation.markdown

I think it could be even more fluid :)

This is a snippet from here,
Ocramius/ProxyManager#36 (comment)
(further down)
I wrote this without knowledge of PHP-Parser syntax, so I don't insist on the exact identifiers.

$engine = new GeneratorEngine(..);

$blueprint = $engine->newClassBlueprint();

$blueprint->extend(..);

// Start with an empty public non-abstract method, then enhance it.
$blueprint->addMethod('foo')
  ->setProtected()
  ->setArguments(..)
  ->setBody(..)
;

// This will automatically scan the interface for methods
$blueprint->implement(..);

// Take the signature directly from the interface
// The interface needs to be added *before* this.
$blueprint->overrideMethod('bar')
  ->setBody(..)
;

// Class name is not decided before the end.
// Decisions about file generation vs eval() are made in GeneratorEngine,
// we don't have to worry about it.
$reflectionClass = $blueprint->createAtName('MyClass');

// We now have a reflection class to work with.
$object = $reflectionClass->newInstance(..);

// Just for fun, we can create a copy of this class with a different name,
// and a different implementation of foo().

$blueprint->addMethodIfNotExists('foo')
  // Set the body to something else.
  ->setBody(..)
;

$blueprint->createAtName('AlternativeClass');

parser fails to handle return(new Foo); syntax

This is used in at least one file inside of the wordpress code: wp/wp-includes/class-wp-xmlrpc-server.php

Here's a constrained test case that appears to fail in the parser. The important bit is the return with a new embedded in it.

something = $a; } public function __toString() { return $this->something; } } function foo() { return(new Simple); } print foo() . "\n"; ?>

Unable to run any of test

Hey all,

A small intro, i am Toshendra Sharma from IIT Bombay. I need to use this parser for one of my proj.

I was trying to run tests from PHP-Parser-master\test\PHPParser\Tests\

i tried ParserTest.php but one class "PHPParser_Tests_CodeTestAbstract" couldn't be found.

In Terminal error was: PHP Fatal error: Class 'PHPParser_Tests_CodeTestAbstract' not found in /root/PHP-Parser-master/testsPHPParser/Tests/CodeTestAbstract.php on line 4

Feature request (wishful thinking mostly): Transcode PHP 5.5 code to older PHP 5.2 code or vice-versa

Don't know if this should be a separate project or not, but a real benefit it will be to use the parser to transcode newer code to older code that could run on older versions of PHP. This should be one of the logical next steps with this parser.

So the parser can run on older versions of PHP, read newer code then transcode and maybe run the adapted code on the old version of PHP. Basically you could run PHP 5.5 code on PHP 5.2 for example via the Parser and an Adaptor or Transcoder or whatever you want to call it. The reverse process should be possible also, backporting code or forwardporting code auto-magically would be awesome.

But I know such a thing is hugely complex and probably it will never become a reality.

LATER EDIT:

Discovered https://github.com/ircmaxell/PHPPHP (PHPPHP VM) maybe this project is more appropriate for this idea :)

Prettyprinter renders Embedded \n in " strings is into a newline

Is there an option to preserver the embedded new-line char? Either the parser or the pretty-printer is processing them into the real thing, which corrupts my code.
thanks, (observed in 0.9.3

<?php>
require '../lib/bootstrap.php';
$parser        = new PHPParser_Parser(new PHPParser_Lexer);
$prettyPrinter = new PHPParser_PrettyPrinter_Default;
$filenames = array('testfiles/BarClass.php');
try {
    foreach ($filenames as $filename) {

        $code = file_get_contents($filename);
        // parse
        $stmts = $parser->parse($code);
        // pretty print
        $code = "<?php \n" . $prettyPrinter->prettyPrint($stmts) . "\n";
        file_put_contents($filename . '.f.php', $code);
    }
} catch (PHPParser_Error $e) {
    echo 'Parse Error: ', $e->getMessage();
}

File:

<?php
input file BarClass.php
class BarClass {
 // sample
    public function bar2() {
        echo "foo bar";
        echo "foo\nbar";
        echo 'baz\nmo';
        echo "happy birthday";
    }
}

Output file BarClass.php.f.php

<?php 
class BarClass
{
    // sample
    public function bar2()
    {
        echo 'foo bar';
        echo 'foo
bar';
        echo 'baz\\nmo';
        echo 'happy birthday';
    }
}

thanks

RFC: Traversal through all nodes

I'm not sure whether this is intended, but currently the iterator of the single nodes does not always iterate over all children.

As an example, the IF statement does not return the condition as one of its sub nodes thus it is not traversed.

Is that the intended behavior?

Optionally add nodes for whitespace

I don't know if that's part of the scope of PHP-Parser, but it would be useful (at least for me as it would greatly simplify the code for my PHP CS fixer -- http://cs.sensiolabs.org/) to be able to have nodes for whitespace. This should probably be an option as most of the time, you don't care about whitespace, and also because it would add many nodes.

Add support for parsing PHP 5.4

The parser should support parsing of PHP 5.4.

The following additional syntaxes were added:

  • traits
  • array dereferecing
  • callable typehint
  • short array syntax
  • static method name expressions
  • static closures

The following features were removed:

  • break and continue with non-positive-integer expressions
  • call time pass by reference

For now the syntax additions should be added, but the removals not to keep 5.3 compatibility. (And as the removals happened outside of the parser one could implement a NodeVisitor checking that those features are not used.)

Parse phpdoc comments

With your recent changes, I'm now able to parse pretty much everything. There is still one feature that's missing for me: the ability to get the phpdoc (token_get_all() returns them). Do you think this is something you can add easily?

RFC: PHP-Rapidgen, a more comfortable templating system based on PHP-Parser

This is still very much a work in progress (couple days away from being ready for use), but I would love to hear what other users of PHP-Parser think of my project:

https://github.com/daviddeutsch/php-rapidgen

It mainly does three things:

  • Introduce a shorthand JSON syntax that makes hand-coding of AST for PHP-Parser (more) comfortable
  • Canonical handling of templates, context and helper functions
  • Mix in handlebars.php for quick and dirty templates that need little precision and/or rendering

If anybody has input on the concept, the syntax or the code - either here or on the project tracker - I'm all ears! PR's are welcome, too, of course.

(fingers crossed filing this as an issue here is not a problem!)

Node/Scalar/String.php's parseEscapeSequences() breaks binary strings for (xml) serialization

Due to the internal call to parseEscapeSequences() uppon construction, the "original" string value is lost, causing invalid xml (invalid unicode bytes) to be written when serializing the nodes.

There is also no way to actually overwrite the value of a string with binary data and still get a "save" xml output.

What i found to be fixing the issue is to bin2hex the data and prepend \x to each byte, e.g. something like this:

$field= '\x' . substr(chunk_split(bin2hex($value),2,"\x"), 0, -2);

This would obviously encode all chars though, not only the original binary ones...

Trait classes in use statements are not expanded to their FQCN

Hey @nikic,

I have been implementing full trait support in phpDocumentor and encountered an issue with the use statement.

Given the following example:

<?php
namespace MySpace;

trait myTrait
{
    public function test()
    {
        echo 'test';
    }
}

class A {
    use myTrait;
}

$a = new A();
$a->test();

I get the following object:

object(PHPParser_Node_Stmt_Class)#598 (2) {
  ["subNodes":protected]=>
  array(6) {
    ["type"]=>
    int(0)
    ["extends"]=>
    NULL
    ["implements"]=>
    array(0) {
    }
    ["stmts"]=>
    array(1) {
      [0]=>
      object(PHPParser_Node_Stmt_TraitUse)#597 (2) {
        ["subNodes":protected]=>
        array(2) {
          ["traits"]=>
          array(1) {
            [0]=>
            object(PHPParser_Node_Name)#596 (2) {
              ["subNodes":protected]=>
              array(1) {
                ["parts"]=>
                array(1) {
                  [0]=>
                  string(7) "myTrait"
                }
              }
              ["attributes":protected]=>
              array(2) {
                ["startLine"]=>
                int(13)
                ["endLine"]=>
                int(13)
              }
            }
          }
          ["adaptations"]=>
          array(0) {
          }
        }
        ["attributes":protected]=>
        array(2) {
          ["startLine"]=>
          int(13)
          ["endLine"]=>
          int(13)
        }
      }
    }
    ["name"]=>
    string(1) "A"
    ["namespacedName"]=>
    object(PHPParser_Node_Name)#613 (2) {
      ["subNodes":protected]=>
      array(1) {
        ["parts"]=>
        array(2) {
          [0]=>
          string(7) "MySpace"
          [1]=>
          string(1) "A"
        }
      }
      ["attributes":protected]=>
      array(2) {
        ["startLine"]=>
        int(2)
        ["endLine"]=>
        int(2)
      }
    }
  }
  ["attributes":protected]=>
  array(2) {
    ["startLine"]=>
    int(12)
    ["endLine"]=>
    int(14)
  }
}

Here you can see that the Trait name in the USE statement is not expanded to the FQCN.

Am I doing something wrong or is this a bug? As far as I can see are the classes in the extends and implements statements expanded to their FQCN

PHP-Parser PEAR channel

Is there any chance that you will add a PEAR channel for the PHP-Parser project, so that PEAR based projects like PHP_Depend can reference the library without duplicating the code?

Parsing for safe eval

Is there any way for PHP Parser to help in making any user submitted code to be evalled to be more secure?

Like maybe limiting a subset of all functions, or even limiting how the code has to be written in an exact match?

PHP-Parser apparently does not like long fluent interfaces

Hi Nikita,

I am afraid I have ran into a real issue this time ;)

While doing pre-release tests I was testing against the Symfony2 codebase and phpDocumentor crashed with the notification "Maximum nesting level of '100' reached".

After a bit of debugging I found out that fluent interfaces are the issue since they are apparently parsed by a recursive function.

Example scenario file:

<?php

class A
{

    function getOrmEntityManagersNode()
    {
        $treeBuilder = new TreeBuilder();
        $node = $treeBuilder->root('entity_managers');

        $node
            ->requiresAtLeastOneElement()
            ->useAttributeAsKey('name')
            ->prototype('array')
                ->addDefaultsIfNotSet()
                ->append($this->getOrmCacheDriverNode('query_cache_driver'))
                ->append($this->getOrmCacheDriverNode('metadata_cache_driver'))
                ->append($this->getOrmCacheDriverNode('result_cache_driver'))
                ->children()
                    ->scalarNode('connection')->end()
                    ->scalarNode('class_metadata_factory_name')->defaultValue('Doctrine\ORM\Mapping\ClassMetadataFactory')->end()
                    ->scalarNode('auto_mapping')->defaultFalse()->end()
                ->end()
                ->fixXmlConfig('hydrator')
                ->children()
                    ->arrayNode('hydrators')
                        ->useAttributeAsKey('name')
                        ->prototype('scalar')->end()
                    ->end()
                ->end()
                ->fixXmlConfig('mapping')
                ->children()
                    ->arrayNode('mappings')
                        ->useAttributeAsKey('name')
                        ->prototype('array')
                            ->beforeNormalization()
                                ->ifString()
                                ->then(function($v) { return array('type' => $v); })
                            ->end()
                            ->treatNullLike(array())
                            ->treatFalseLike(array('mapping' => false))
                            ->performNoDeepMerging()
                            ->children()
                                ->scalarNode('mapping')->defaultValue(true)->end()
                                ->scalarNode('type')->end()
                                ->scalarNode('dir')->end()
                                ->scalarNode('alias')->end()
                                ->scalarNode('prefix')->end()
                                ->booleanNode('is_bundle')->end()
                            ->end()
                        ->end()
                    ->end()
                    ->arrayNode('dql')
                        ->fixXmlConfig('string_function')
                        ->fixXmlConfig('numeric_function')
                        ->fixXmlConfig('datetime_function')
                        ->children()
                            ->arrayNode('string_functions')
                                ->useAttributeAsKey('name')
                                ->prototype('scalar')->end()
                            ->end()
                            ->arrayNode('numeric_functions')
                                ->useAttributeAsKey('name')
                                ->prototype('scalar')->end()
                            ->end()
                            ->arrayNode('datetime_functions')
                                ->useAttributeAsKey('name')
                                ->prototype('scalar')->end()
                            ->end()
                        ->end()
                    ->end()
                ->end()
            ->end();

        return $node;
    }
}

Output:


PHP Fatal error:  Maximum function nesting level of '100' reached, aborting! in /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/nikic/php-parser/lib/PHPParser/PrettyPrinterAbstract.php on line 69
PHP Stack trace:
PHP   1. {main}() /media/Elements/Projects/phpDocumentor/phpDocumentor2/bin/phpdoc.php:0
PHP   2. phpDocumentor\Application->run() /media/Elements/Projects/phpDocumentor/phpDocumentor2/bin/phpdoc.php:28
PHP   3. Symfony\Component\Console\Application->run() /media/Elements/Projects/phpDocumentor/phpDocumentor2/src/phpDocumentor/Application.php:65
PHP   4. Symfony\Component\Console\Application->doRun() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/symfony/console/Symfony/Component/Console/Application.php:106
PHP   5. Symfony\Component\Console\Command\Command->run() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/symfony/console/Symfony/Component/Console/Application.php:193
PHP   6. phpDocumentor\Command\Project\RunCommand->execute() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/symfony/console/Symfony/Component/Console/Command/Command.php:239
PHP   7. Symfony\Component\Console\Command\Command->run() /media/Elements/Projects/phpDocumentor/phpDocumentor2/src/phpDocumentor/Command/Project/RunCommand.php:215
PHP   8. phpDocumentor\Command\Project\ParseCommand->execute() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/symfony/console/Symfony/Component/Console/Command/Command.php:239
PHP   9. phpDocumentor\Parser\Parser->parseFiles() /media/Elements/Projects/phpDocumentor/phpDocumentor2/src/phpDocumentor/Command/Project/ParseCommand.php:249
PHP  10. phpDocumentor\Parser\Parser->parseFile() /media/Elements/Projects/phpDocumentor/phpDocumentor2/src/phpDocumentor/Parser/Parser.php:474
PHP  11. phpDocumentor\Reflection\FileReflector->process() /media/Elements/Projects/phpDocumentor/phpDocumentor2/src/phpDocumentor/Parser/Parser.php:400
PHP  12. phpDocumentor\Reflection\Traverser->traverse() /media/Elements/Projects/phpDocumentor/phpDocumentor2/src/phpDocumentor/Reflection/FileReflector.php:100
PHP  13. PHPParser_NodeTraverser->traverse() /media/Elements/Projects/phpDocumentor/phpDocumentor2/src/phpDocumentor/Reflection/Traverser.php:46
PHP  14. PHPParser_NodeTraverser->traverseArray() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/nikic/php-parser/lib/PHPParser/NodeTraverser.php:40
PHP  15. PHPParser_NodeTraverser->traverseNode() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/nikic/php-parser/lib/PHPParser/NodeTraverser.php:92
PHP  16. PHPParser_NodeTraverser->traverseArray() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/nikic/php-parser/lib/PHPParser/NodeTraverser.php:58
PHP  17. PHPParser_NodeTraverser->traverseNode() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/nikic/php-parser/lib/PHPParser/NodeTraverser.php:92
PHP  18. PHPParser_NodeTraverser->traverseArray() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/nikic/php-parser/lib/PHPParser/NodeTraverser.php:58
PHP  19. PHPParser_NodeTraverser->traverseNode() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/nikic/php-parser/lib/PHPParser/NodeTraverser.php:92
PHP  20. PHPParser_NodeTraverser->traverseNode() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/nikic/php-parser/lib/PHPParser/NodeTraverser.php:66
...
PHP  96. PHPParser_NodeTraverser->traverseArray() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/nikic/php-parser/lib/PHPParser/NodeTraverser.php:58
PHP  97. PHPParser_NodeTraverser->traverseNode() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/nikic/php-parser/lib/PHPParser/NodeTraverser.php:92
PHP  98. phpDocumentor\Reflection\FileReflector->enterNode() /media/Elements/Projects/phpDocumentor/phpDocumentor2/vendor/nikic/php-parser/lib/PHPParser/NodeTraverser.php:61
PHP  99. PHPParser_PrettyPrinterAbstract->__construct() /media/Elements/Projects/phpDocumentor/phpDocumentor2/src/phpDocumentor/Reflection/FileReflector.php:190

Do you know of any solution to this issue?

Syntax error on return (...);

When the expression to return is surrounded by parentheses, PHP-Parser throws a syntax error.

For example:

return(new IXR_Error(404, __('Sorry, no such page.')));

Throws:

PHP Fatal error:  Uncaught exception 'PHPParser_Error' with message 'Unexpected token ';' on line 3' in .../php-parser/lib/PHPParser/Parser.php:995

how to get the code str which a PHPParser Node is representing?

for example ,from

"<?php echo 'Hi ', hi\\getTarget();"

i get

array(
    0: Stmt_Echo(
        exprs: array(
            0: Scalar_String(
                value: Hi
            )
            1: Expr_FuncCall(
                name: Name(
                    parts: array(
                        0: hi
                        1: getTarget
                    )
                )
                args: array(
                )
            )
        )
    )
)

then how can i get "'Hi ', hi\getTarget();" from "$stmts[0]->exprs"

just like

$stmts[0]->expres->metadata === "'Hi ', hi\\getTarget();"

Is 0.9.3 really beta ?

I'd like to upgrade my phpdox, via pear, but I get the following error:

Failed to download nikic/PHPParser within preferred state "stable", latest release is version 0.9.3, stability "beta", use "channel://nikic.github.com/pear/PHPParser-0.9.3" to install
theseer/phpDox requires package "nikic/PHPParser" (version >= 0.9.3)
No valid packages found
upgrade failed

I've tried this command last months and today, but same error

Would it be possible to put 0.9.3 to a stable state so that users can install phpDox ?

ArrayItem pretty print

I've had an idea for a while to use PHP's function syntax as a concise way of representing JSON structures. I've created POC's for myself before, but none were more than hacks. I came across your library, which I think could help me create a proper implementation of this. Please note below, the different syntaxes "pretty-printed" to show how much easier (fewer keystrokes, easier to read in my opinion) it would be if we could represent JSON structures in this way in PHP. It's still not 100% correct (note the 'g' and 'h' are inside arrays in the pretty-printed array / json versions, which they shouldn't be based on this structure). Nonetheless I think these examples show how this could be useful (My initial plan would be to implement this for a simple ElasticSearch client).

EDIT (on second thought the 'g' and 'h' may be represented correctly below in the array / json representations)

ALTERNATIVE SYNTAX:
a(
  g(
    d(
      e('g')
    )
  ),
  b(
    c(
      d('h')
    )
  )
)

PRETTY PRINT ARRAYS (showing long-form array syntax for effect): 
array('a' =>
   array('g' =>
      array('d' =>
         array('e' =>
            array('g')
         )
      ),
  'b' =>
      array('c' =>
         array('d' =>
            array('h')
         )
      )
   )
);

PRETTY PRINT JSON: 
{
    "a": {
        "g": {
            "d": {
                "e": [
                    "g"
                ]
            }
        },
        "b": {
            "c": {
                "d": [
                    "h"
                ]
            }
        }
    }
}

The problem I'm running into is how to get the pretty print to work correctly on ArrayItem. It's likely I'm doing things incorrectly. From the example above (function syntax) the parser is giving me the following (note the 'array(' prefix is missing, as well as the ending ')' just before the semicolon):

'a' => array('g' => array('d' => array('e' => array('g'))), 'b' => array('c' => array('d' => array('h'))));

My "visitor" is as follows:

class MyNodeVisitor extends PHPParser_NodeVisitorAbstract
{
    public function enterNode(PHPParser_Node $node){
        if ($node instanceof PHPParser_Node_Expr_FuncCall) {
            return new PHPParser_Node_Expr_ArrayItem(
                new PHPParser_Node_Expr_Array($node->args),
                new PHPParser_Node_Scalar_String($node->name)
            );
        }
    }
}

I know the above 'visitor' implementation is likely broken for many use cases, but from what I can tell this is what I should be doing for this particular conversion, but I seem to be getting unexpected results.

PSR-2

Does anyone have a PrettyPrinter compatible with PSR-2 ? Just in case...

"Expecting" info for PHPParser_Error

Is it possible to provide execting tokens info for parse error?
Could you explain please how to extract this info from yacc-generated tables ?

And another question: is it possible to force yacc to use the same token constants as internal php contstants (to match with token_name() value) ? Maybe some post-generated processing?

"Else if" not properly parsed

Giving the following code to the parser

<?php if(false) {} else if(true) {} else {}

outputs (via pretty printer)

if (false) {

} else {
    if (true) {

    } else {

    }
}

Tolerant parser with option to recover from unexpected token error

Is it possible for a parser to recover from an unexpected token and return the nodes that it was able to parse?

Consider the following PHP code:

<?php
class MyClass {
    public function myMethod() {
        $this->something
    }
}

(Notice the missing semicolon)

When I parse this code, I get the following error:

Unexpected token '}' on line 5

And this is the expected behavior.

But what I would like is to parse the statements that the parser knows about. In other words, I'd like to be able to traverse the Stmt_Class and Stmt_ClassMethod nodes even in spite of the error.

Is this even possible?

I tried working my way through the parse method of PHPParser_Parser to figure it out. But I do not understand the complexities of how the parser works. Even if someone could point me in the right direction as to how to solve this problem myself, I would appreciate it.

My reason for the request is this: I'm writing a PHP autocompletion plugin for Sublime Text and I am using PHP-Parser to try to extract the context of the class while the user is typing.

Introducing PHPParser_Node_Stmt_Block

I'd like to get rid of the statement arrays and instead introduce a PHPParser_Node_Stmt_Block.

arrays might be a bit faster, but they make the code operating on the AST unnecessary complex by requiring constant type checking and two different APIs, e.g. traverse(Node $node) and traverseArray(array $nodes).

To reduce the BC break, we could implement ArrayAccess, and Countable on that node class.

What do you think?

Adding type information to the AST

What do you think about adding a type inferencing visitor which attaches type information to some nodes of the AST? For example, what type the return value of a method is, or what type a variable has?

Right now, I'm doing that in each visitor that needs that information, it is probably faster if we run one visitor over the AST which adds the types, so that all other visitors can simply use it.

Line Numbers for CASE statements

There seems to be a bug for line numbers of CASE statments.

All CASE statements have the line number of the first CASE statement of the given SWITCH statement instead of their own line number.

PHP-Parser will cache the last code stmts?

$parser = new PHPParser_Parser(new PHPParser_Lexer);
$code1 = "...some code...";
$stmts1 = $parser->parse($code1);
$code2 = "...another code...";
$stmts2 = $parser->parse($code2);

It seems $code1 get cached and cause $stmts1 is a subset of $stmts2, How could I disable this caching?

Support request: how do I get a DocBlock when there are no nodes

Hey @nikic,

I received the following bug report in phpDocumentor/phpDocumentor2: phpDocumentor/phpDocumentor#604

The reporter indicates that the first DocBlock could not be found when there are no nodes. This is verified behaviour since I try to claim the file-level DocBlock in a NodeVisitor using the beforeTraverse method.

Can you provide me with a clue what the best way would be to still obtain the first DocComment in a file using PHP-Parser? (if PHP-Parser supports that)

Single line comments get lost

Is there a reason, why all single line comments get lost?

I could fix that by adding this in line 94 in PHP-Parser/Lexer.php

if (T_DOC_COMMENT === $token[0] || T_COMMENT === $token[0]) {

Implement PHP 5.5 syntax

This is a tracking bug for the syntactical changes that PHP 5.5 introduces (as of now).

Implemented:

  • drop of ref restrictions in foreach (this was already working ^^)
  • list in foreach (f8f1e17)
  • finally clause (ae3774f)
  • yield expression (417a8bb)
  • constant string and array dereferencing (4259b44)
  • empty with expressions (af5d288)

Php parser array and comments trubble

Php parser doesn't generate full ast for this example code:

    public function relations()
    {

//return parent::relations();
//return array_merge(parent::relations(),array());

        return array(
            'sites'=>array(self::MANY_MANY,ISite::NS.NS_SEPARATOR.'Site','Catalog2SL(idCatalog,idSite)'),
            'countries'=>array(self::MANY_MANY,ISite::NS.NS_SEPARATOR.'Country','Catalog2SL(idCatalog,idSite)'),
            //'locations'=>array(self::MANY_MANY,'Location','Catalog2SL(idCatalog,idLocation)'),
        );

    }

The generated ast tree doesn't have PHPParser_Comment(//'locations'=>array(self::MANY_MANY,'Location','Catalog2SL(idCatalog,idLocation)'),) in PHPParser_Node_Stmt_Array
so the generated/pretty printed code is not the same as original.

Support for the "global" namespace

The following construct is valid but not supported by PHP-Parser:

namespace {
    echo 'Hello';
}

Here is the error:

PHP Catchable fatal error:  Argument 1 passed to PHPParser_PrettyPrinterAbstract::p() must be an instance of PHPParser_NodeAbstract, array given, called in lib/PHPParser/PrettyPrinterAbstract.php on line 105 and defined in lib/PHPParser/PrettyPrinterAbstract.php on line 127

Question: PrettyPrint pStmt_Namespace

Am i correctly assuming, that pStmt_Namespace is always wrapped in brackets in the Zend Printer, even if the original code does not use brackets?

Would a PR be merged that adds "PSR0" printer that changes this to using non-bracketed namespaces?

Userfriendly API for Namespace, Function, Class, Methods and Properties

Hey!

i've been thinking about using your Parser to create a Tool to Manipulate Classes. This has been a common practice among the TYPO3 Community with the old kickstarter and now the ExtensionBuilder. The biggest caveat to date is the manipulation of those generated classes once the developer started to modify them. it's has been quite a buggy hassle to modfiy manually modified classes. This could simply be improved by your PHP-Parser.

To make this easier i'd propose to add some simple to use API to PHP-Parser make it easier to accomplish this task.
I've forked your Repo and started to implement some of these.

Main thing i would like to know, is if you would be willing to integrate it directly into your Parser or if you think, that this doesn't really belong directly in the Parser and instead in a seperate library.

For Example:

General

  • getByType(Class|Method|Property|...)

Namespace

  • getClasses()
  • getFunctions()
  • getName(), getType(), etc

Class

  • getMethods()
  • getProperties()
  • addMethod()
  • createMethod()
  • addProperty()
  • createProperty()
  • getName(), getType(), etc

Method

  • getArguments()
  • getName(), getType(), etc

Property

  • getName(), getType(), etc

Greetings Marc

Missing xsd reference

If I use PHPParser_Serializer_XML to serialize AST in XML, XSD references link to http 404 pages.

<AST xmlns:node="http://nikic.github.com/PHPParser/XML/node" xmlns:subNode="http://nikic.github.com/PHPParser/XML/subNode" xmlns:attribute="http://nikic.github.com/PHPParser/XML/attribute" xmlns:scalar="http://nikic.github.com/PHPParser/XML/scalar">
    ...
</AST>

Could you update links to valide location ?

(PHPParser must be the old version of PHP-Parser :) )

DocComments are empty for global 'const'

If you try to interpret a global const with a DocComment then the getDocComment() method of that node still returns NULL.

Reproduction case:

<?php
/**
 * A constant to show the bug.
 */
const A_CONSTANT = 'some value';

Getting the untransformed version of a string

When consuming PHPParser_Node_Scalar_String I noticed that all escape codes are transformed into actual characters. This is actually causing issues and I want the unescaped versions to use in phpDocumentor.

I would not mind adding this feature but I'd like to know how you would prefer this? (my preference would even be to skip the escaping all together to improve performance)

Redundant php tags

The following code:

var_dump(
    (new \PHPParser_PrettyPrinter_Default())
        ->prettyPrint(
            (new \PHPParser_Parser(
                new \PHPParser_Lexer()
            ))->parse('<h1><?= $var ?></h1>')
       );
);

produces the following result:

string(37) "?><h1><?php
echo $var;
?></h1><?php "

Expected output is:

string(xx) "<h1>Hello <?php echo $var; ?></h1>"

or

string(xx) "<h1>Hello <?= $var; ?></h1>"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.