summaryrefslogtreecommitdiff
path: root/poc/poc01-parsing-includes/src
diff options
context:
space:
mode:
Diffstat (limited to 'poc/poc01-parsing-includes/src')
-rw-r--r--poc/poc01-parsing-includes/src/composer.json6
-rwxr-xr-xpoc/poc01-parsing-includes/src/get_deps.sh2
-rw-r--r--poc/poc01-parsing-includes/src/php-weave/main.php64
-rw-r--r--poc/poc01-parsing-includes/src/php-weave/to_parse.php5
-rw-r--r--poc/poc01-parsing-includes/src/php-weave/visitors.inc.php91
5 files changed, 168 insertions, 0 deletions
diff --git a/poc/poc01-parsing-includes/src/composer.json b/poc/poc01-parsing-includes/src/composer.json
new file mode 100644
index 0000000..a366739
--- /dev/null
+++ b/poc/poc01-parsing-includes/src/composer.json
@@ -0,0 +1,6 @@
+{
+ "require": {
+ "nikic/php-parser": "0.9.2"
+ }
+}
+
diff --git a/poc/poc01-parsing-includes/src/get_deps.sh b/poc/poc01-parsing-includes/src/get_deps.sh
new file mode 100755
index 0000000..67c84c3
--- /dev/null
+++ b/poc/poc01-parsing-includes/src/get_deps.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+php ../../../composer.phar install
diff --git a/poc/poc01-parsing-includes/src/php-weave/main.php b/poc/poc01-parsing-includes/src/php-weave/main.php
new file mode 100644
index 0000000..2a4df55
--- /dev/null
+++ b/poc/poc01-parsing-includes/src/php-weave/main.php
@@ -0,0 +1,64 @@
+<?php
+require '../vendor/nikic/php-parser/lib/bootstrap.php';
+require './visitors.inc.php';
+
+ini_set('xdebug.max_nesting_level', 2000);
+
+function dbg($indent, $text) {
+ for($i=0;$i<$indent;$i++) echo ".";
+ echo "$text\n";
+}
+
+function recursive_parse($src_filepath, $stmts1_filepath, $stmts2_filepath, $level=0) {
+ global $parser,$nodeDumper;
+
+ try {
+ dbg($level,"Parsing '$src_filepath'");
+ $stmts = $parser->parse(file_get_contents($src_filepath));
+
+ if (strlen($stmts1_filepath) > 0 ) {
+ dbg($level,"Dumping1 '$src_filepath' AST to '$stmts1_filepath'");
+ file_put_contents($stmts1_filepath, $nodeDumper->dump($stmts));
+ }
+
+ dbg($level,"Transforming '$src_filepath'");
+ $traverser = new PHPParser_NodeTraverser;
+/*
+ $traverser->addVisitor(new PHPParser_NodeVisitor_NameResolver);
+ $traverser->addVisitor(new NodeVisitor_NamespaceConverter);
+*/
+ // FIXME : getcwd is quick and dirty here
+ $traverser->addVisitor(new NodeVisitor_PreprocessInclude($level, getcwd(), $src_filepath));
+ $stmts = $traverser->traverse($stmts);
+ $traverser=null; //Destroy
+
+ if (strlen($stmts2_filepath) > 0) {
+ dbg($level,"Dumping2 '$src_filepath' AST to '$stmts2_filepath'");
+ file_put_contents($stmts2_filepath, $nodeDumper->dump($stmts));
+ }
+
+ } catch (PHPParser_Error $e) {
+ echo 'Parse Error: ', $e->getMessage();
+ }
+ return $stmts;
+}
+
+
+// Main
+$src_filepath = "./main.php";
+#$src_filepath = "./to_parse.php";
+$stmts1_filepath = "out/stmts1.ast";
+$stmts2_filepath = "out/stmts2.ast";
+$dest_filepath = "out/result.php";
+
+$parser = new PHPParser_Parser(new PHPParser_Lexer);
+$nodeDumper = new PHPParser_NodeDumper;
+
+$level=0;
+$stmts=recursive_parse($src_filepath, $stmts1_filepath, $stmts2_filepath);
+
+dbg(0,"Outputing '$dest_filepath'");
+$prettyPrinter = new PHPParser_PrettyPrinter_Zend;
+file_put_contents($dest_filepath, "<?php\n" . $prettyPrinter->prettyPrint($stmts) . "\n?>");
+
+?>
diff --git a/poc/poc01-parsing-includes/src/php-weave/to_parse.php b/poc/poc01-parsing-includes/src/php-weave/to_parse.php
new file mode 100644
index 0000000..7b953d5
--- /dev/null
+++ b/poc/poc01-parsing-includes/src/php-weave/to_parse.php
@@ -0,0 +1,5 @@
+<?php
+if (1){
+include('./inc.php');
+}
+?>
diff --git a/poc/poc01-parsing-includes/src/php-weave/visitors.inc.php b/poc/poc01-parsing-includes/src/php-weave/visitors.inc.php
new file mode 100644
index 0000000..3f997ad
--- /dev/null
+++ b/poc/poc01-parsing-includes/src/php-weave/visitors.inc.php
@@ -0,0 +1,91 @@
+<?php
+/*
+class NodeVisitor_NamespaceConverter extends PHPParser_NodeVisitorAbstract
+{
+ public function leaveNode(PHPParser_Node $node) {
+ if ($node instanceof PHPParser_Node_Name) {
+ return new PHPParser_Node_Name($node->toString('_'));
+ } elseif ($node instanceof PHPParser_Node_Stmt_Class
+ || $node instanceof PHPParser_Node_Stmt_Interface
+ || $node instanceof PHPParser_Node_Stmt_Function) {
+ $node->name = $node->namespacedName->toString('_');
+ } elseif ($node instanceof PHPParser_Node_Stmt_Const) {
+ foreach ($node->consts as $const) {
+ $const->name = $const->namespacedName->toString('_');
+ }
+ } elseif ($node instanceof PHPParser_Node_Stmt_Namespace) {
+ // returning an array merges is into the parent array
+ return $node->stmts;
+ } elseif ($node instanceof PHPParser_Node_Stmt_Use) {
+ // returning false removed the node altogether
+ return false;
+ }
+ }
+}
+*/
+
+class NodeVisitor_PreprocessInclude extends PHPParser_NodeVisitorAbstract {
+ protected $level;
+ protected $cwd;
+ protected $filepath;
+ protected $prettyPrinter;
+
+ public function __construct($level, $cwd, $filepath) {
+ $this->level=$level;
+ $this->cwd=$cwd;
+ $this->filepath=$filepath;
+ $this->prettyPrinter = new PHPParser_PrettyPrinter_Zend;
+ }
+
+ protected function resolveIncludePath($node) {
+ //FIXME : Quick and dirty
+ // no classpath checks...
+ // no check if compound value like "dirname(__FILE__) . '/PHPParser/Autoloader.php'"
+ return $node->expr->value;
+ }
+
+ public function enterNode(PHPParser_Node $node) {
+ if ($node instanceof PHPParser_Node_Expr_Include) {
+ // Already processed, go out (occurs if an unresolved include has left as is in the previous recursion level)
+ if (is_array($node->attributes) && array_key_exists('NodeVisitor_PreprocessInclude', $node->attributes)) return $node;
+
+ switch($node->type) {
+ case PHPParser_Node_Expr_Include::TYPE_INCLUDE:
+ case PHPParser_Node_Expr_Include::TYPE_REQUIRE:
+ $once=0;
+ break;
+ case PHPParser_Node_Expr_Include::TYPE_INCLUDE_ONCE:
+ case PHPParser_Node_Expr_Include::TYPE_REQUIRE_ONCE:
+ $once=1;
+ echo "TODO : include_once or require_once\n";
+ break;
+ default:
+ echo "FIXME : BUG NodeVisitor_PreprocessInclude::enterNode !!\n";
+ return $node;
+ }
+
+ $path=$this->resolveIncludePath($node);
+
+ //FIXME : No infinite recursion check like test.php contains include('./test.php');
+ // Preprocess include if readable
+ $comment_suffix=" */";
+ if ( ($this->level < 3) && is_readable($path)) {
+ $comment_prefix="/* ";
+ //FIXME : use a closure or sort of here (dependancy injection)
+ //$stmts=recursive_parse($path, "out/rec.out1", "out/rec.out2", $this->level+1);
+ $stmts=recursive_parse($path, "", "", $this->level+1);
+ } else {
+ $comment_prefix="/* UNRESOLVED : ";
+ $node->attributes['NodeVisitor_PreprocessInclude']='unresolved';
+ $stmts=array($node); // Caution : can cause infinite loop (will be tried at the next step)
+ }
+
+ $comment= new PHPParser_Comment($comment_prefix . $this->prettyPrinter->prettyPrint(array($node)) . $comment_suffix);
+
+ // FIXME : Get out this if() that is a trick for not returning here an array instead of a node
+ return new PHPParser_Node_Stmt_If(new PHPParser_Node_Scalar_LNumber(1),array('stmts'=>$stmts),array('comments'=>array($comment)));
+ }
+
+ }
+}
+