Last active
August 9, 2023 13:26
-
-
Save eridal/a850a8a665a255b74d2c to your computer and use it in GitHub Desktop.
Java to PHP Compilation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace j2p; | |
use japa\parser\JavaParser; | |
use japa\parser\ParseException; | |
use japa\parser\ast\CompilationUnit; | |
use japa\parser\ast\ImportDeclaration; | |
use japa\parser\ast\PackageDeclaration; | |
use japa\parser\ast\body\BodyDeclaration; | |
use japa\parser\ast\body\ClassOrInterfaceDeclaration; | |
use japa\parser\ast\body\FieldDeclaration; | |
use japa\parser\ast\body\InitializerDeclaration; | |
use japa\parser\ast\body\MethodDeclaration; | |
use japa\parser\ast\body\Parameter; | |
use japa\parser\ast\body\TypeDeclaration; | |
use japa\parser\ast\body\VariableDeclarator; | |
use japa\parser\ast\body\VariableDeclaratorId; | |
use japa\parser\ast\expr\AssignExpr; | |
use japa\parser\ast\expr\BinaryExpr; | |
use japa\parser\ast\expr\BooleanLiteralExpr; | |
use japa\parser\ast\expr\ClassExpr; | |
use japa\parser\ast\expr\ConditionalExpr; | |
use japa\parser\ast\expr\DoubleLiteralExpr; | |
use japa\parser\ast\expr\Expression; | |
use japa\parser\ast\expr\FieldAccessExpr; | |
use japa\parser\ast\expr\InstanceOfExpr; | |
use japa\parser\ast\expr\IntegerLiteralExpr; | |
use japa\parser\ast\expr\LiteralExpr; | |
use japa\parser\ast\expr\LongLiteralExpr; | |
use japa\parser\ast\expr\MethodCallExpr; | |
use japa\parser\ast\expr\NameExpr; | |
use japa\parser\ast\expr\NullLiteralExpr; | |
use japa\parser\ast\expr\ObjectCreationExpr; | |
use japa\parser\ast\expr\QualifiedNameExpr; | |
use japa\parser\ast\expr\StringLiteralExpr; | |
use japa\parser\ast\expr\VariableDeclarationExpr; | |
use japa\parser\ast\stmt\BlockStmt; | |
use japa\parser\ast\stmt\CatchClause; | |
use japa\parser\ast\stmt\ContinueStmt; | |
use japa\parser\ast\stmt\ExpressionStmt; | |
use japa\parser\ast\stmt\ForeachStmt; | |
use japa\parser\ast\stmt\IfStmt; | |
use japa\parser\ast\stmt\ReturnStmt; | |
use japa\parser\ast\stmt\Statement; | |
use japa\parser\ast\stmt\SwitchEntryStmt; | |
use japa\parser\ast\stmt\SwitchStmt; | |
use japa\parser\ast\stmt\ThrowStmt; | |
use japa\parser\ast\stmt\TryStmt; | |
use japa\parser\ast\type\ClassOrInterfaceType; | |
use japa\parser\ast\type\PrimitiveType; | |
use japa\parser\ast\type\ReferenceType; | |
use japa\parser\ast\type\Type; | |
use java\io\File; | |
use java\io\IOException; | |
use java\util\Arrays; | |
use java\util\HashMap; | |
use java\util\List_; | |
use java\util\Map; | |
class Compiler { | |
function main($paths) { | |
foreach ($paths as $path) { | |
try { | |
$this->file($path); | |
} | |
catch (Exception $e) { | |
$System->err->println($e->getMessage()); | |
} | |
} | |
} | |
function file($path) { | |
$file = new File($path); | |
$unit = $JavaParser->parse($file); | |
$System->out->println('<?php\n'); | |
$System->out->println($this->stmt_namespace($unit->getPackage())); | |
$System->out->println(''); | |
foreach ($unit->getImports() as $i) { | |
$System->out->println($this->stmt_use($i)); | |
} | |
foreach ($unit->getTypes() as $type) { | |
$System->out->println(''); | |
$System->out->println($this->stmt_type($type)); | |
} | |
} | |
function stmt_namespace(PackageDeclaration $pkg) { | |
return $String->format('namespace %s;', $this->expr_name($pkg->getName())); | |
} | |
function stmt_use(ImportDeclaration $import_) { | |
return $String->format('use %s;', $this->expr_name($import_->getName())); | |
} | |
function stmt_type(TypeDeclaration $type) { | |
if ($type instanceof ClassOrInterfaceDeclaration) { | |
return $this->decl_class($expr); | |
} | |
else { | |
throw $this->missing('php_type'); | |
} | |
} | |
function decl_class(ClassOrInterfaceDeclaration $type) { | |
$sb = new StringBuilder(); | |
$extends_ = $type->getExtends(); | |
$implements_ = $type->getImplements(); | |
$sb->append($type->isInterface() ? 'interface' : 'class'); | |
$sb->append(' '); | |
$sb->append($type->getName()); | |
if (null != $extends_) { | |
$sb->append(' extends '); | |
$sb->append($this->decl_class_list($extends_)); | |
} | |
if (null != $implements_) { | |
$sb->append(' implements '); | |
$sb->append($this->decl_class_list($implements_)); | |
} | |
$sb->append(' {\n'); | |
foreach ($type->getMembers() as $member) { | |
$sb->append('\n'); | |
$sb->append($this->tab($this->decl_member($member))); | |
} | |
$sb->append('\n}'); | |
return $sb->toString(); | |
} | |
function decl_class_list(List_ $list) { | |
$sb = new StringBuilder(); | |
$first = true; | |
foreach ($list as $type) { | |
if ($first) { | |
$first = false; | |
} | |
else { | |
$sb->append(', '); | |
} | |
$sb->append($type->getName()); | |
} | |
return $sb->toString(); | |
} | |
function decl_member(BodyDeclaration $member) { | |
if ($member instanceof MethodDeclaration) { | |
return $this->decl_method($expr); | |
} | |
if ($member instanceof FieldDeclaration) { | |
return $this->decl_field($expr); | |
} | |
if ($member instanceof InitializerDeclaration) { | |
return $this->decl_initializer($expr); | |
} | |
throw $this->missing('decl_member', $member); | |
} | |
function decl_method(MethodDeclaration $method) { | |
$sb = new StringBuilder(); | |
$body = $method->getBody(); | |
if (null == $body) { | |
$sb->append('abstract '); | |
} | |
$sb->append('function '); | |
$sb->append($this->keyword($method->getName())); | |
$sb->append('('); | |
$params = $method->getParameters(); | |
if (null != $params) { | |
$sb->append($this->decl_param_list($params)); | |
} | |
$sb->append(')'); | |
if (null == $body) { | |
$sb->append(';'); | |
} | |
else { | |
$sb->append(' '); | |
$sb->append($this->stmt_block($body)); | |
} | |
return $sb->toString(); | |
} | |
function decl_field(FieldDeclaration $field) { | |
return '/* decl_field */'; | |
} | |
function decl_initializer(InitializerDeclaration $init) { | |
return '/* decl_initializer */'; | |
} | |
function decl_param_list(List_ $params) { | |
$sb = new StringBuilder(); | |
$first = true; | |
foreach ($params as $p) { | |
if ($first) { | |
$first = false; | |
} | |
else { | |
$sb->append(', '); | |
} | |
$sb->append($this->decl_param($p)); | |
} | |
return $sb->toString(); | |
} | |
function decl_param(Parameter $param) { | |
$sb = new StringBuilder(); | |
$type; | |
$type = $this->type($param->getType()); | |
if (null != $type) { | |
$sb->append($type); | |
$sb->append(' '); | |
} | |
if ($param->isVarArgs()) { | |
$sb->append('...'); | |
} | |
$sb->append($this->var_($param->getId())); | |
return $sb->toString(); | |
} | |
function decl_var(VariableDeclarator $var) { | |
$sb = new StringBuilder(); | |
$init = $var->getInit(); | |
$sb->append($this->var_($var->getId())); | |
if (null != $init) { | |
$sb->append(' = '); | |
$sb->append($this->expr($var->getInit())); | |
} | |
return $sb->toString(); | |
} | |
function decl_vars(List_ $vars) { | |
$sb = new StringBuilder(); | |
$first = true; | |
foreach ($vars as $v) { | |
if ($first) { | |
$first = false; | |
} | |
else { | |
$sb->append(', '); | |
} | |
$sb->append($this->decl_var($v)); | |
} | |
return $sb->toString(); | |
} | |
function stmt_list(List_ $list) { | |
$sb = new StringBuilder(); | |
foreach ($list as $s) { | |
$sb->append($this->stmt($s)); | |
$sb->append('\n'); | |
} | |
return $sb->toString(); | |
} | |
function stmt(Statement $stmt) { | |
if ($stmt instanceof IfStmt) { | |
return $this->stmt_if($expr); | |
} | |
if ($stmt instanceof ForeachStmt) { | |
return $this->stmt_foreach($expr); | |
} | |
if ($stmt instanceof SwitchStmt) { | |
return $this->stmt_switch($expr); | |
} | |
if ($stmt instanceof TryStmt) { | |
return $this->stmt_try($expr); | |
} | |
if ($stmt instanceof ReturnStmt) { | |
return $this->stmt_return($expr); | |
} | |
if ($stmt instanceof ContinueStmt) { | |
return $this->stmt_continue($expr); | |
} | |
if ($stmt instanceof ThrowStmt) { | |
return $this->stmt_throw($expr); | |
} | |
if ($stmt instanceof BlockStmt) { | |
return $this->stmt_block($expr); | |
} | |
if ($stmt instanceof ExpressionStmt) { | |
return $this->stmt_expr($expr); | |
} | |
throw $this->missing('stmt', $stmt); | |
} | |
function stmt_if(IfStmt $if_) { | |
$sb = new StringBuilder(); | |
$sb->append('if ('); | |
$sb->append($this->expr($if_->getCondition())); | |
$sb->append(') '); | |
$sb->append($this->stmt_block($if_->getThenStmt())); | |
$else_ = $if_->getElseStmt(); | |
if (null != $else_) { | |
$sb->append('\nelse'); | |
if ($else_ instanceof IfStmt) { | |
$sb->append($this->stmt_if($expr)); | |
} | |
else { | |
$sb->append(' '); | |
$sb->append($this->stmt_block($else_)); | |
} | |
} | |
return $sb->toString(); | |
} | |
function stmt_foreach(ForeachStmt $forEach) { | |
$sb = new StringBuilder(); | |
$sb->append('foreach ('); | |
$sb->append($this->expr($forEach->getIterable())); | |
$sb->append(' as '); | |
$sb->append($this->decl_vars($forEach->getVariable()->getVars())); | |
$sb->append(') '); | |
$sb->append($this->stmt_block($forEach->getBody())); | |
return $sb->toString(); | |
} | |
function stmt_switch(SwitchStmt $switch_) { | |
$sb = new StringBuilder(); | |
$sb->append('switch ('); | |
$sb->append($this->expr($switch_->getSelector())); | |
$sb->append('){\n'); | |
foreach ($switch_->getEntries() as $case_) { | |
$sb->append($this->stmt_switch_case($case_)); | |
} | |
$sb->append('}'); | |
return $sb->toString(); | |
} | |
function stmt_switch_case(SwitchEntryStmt $case_) { | |
$sb = new StringBuilder(); | |
$label = $case_->getLabel(); | |
$list = $case_->getStmts(); | |
if (null == $label) { | |
$sb->append('default:'); | |
} | |
else { | |
$sb->append('case '); | |
$sb->append($this->expr($label)); | |
$sb->append(':'); | |
} | |
$sb->append('\n'); | |
if (null != $list) { | |
$sb->append($this->tab($this->stmt_list($list))); | |
} | |
return $sb->toString(); | |
} | |
function stmt_try(TryStmt $try_) { | |
$sb = new StringBuilder(); | |
$sb->append('try '); | |
$sb->append($this->stmt_block($try_->getTryBlock())); | |
$catchs = $try_->getCatchs(); | |
if (null != $catchs) { | |
foreach ($catchs as $catch_) { | |
$sb->append('\ncatch ('); | |
$sb->append($this->decl_param($catch_->getExcept())); | |
$sb->append(') '); | |
$sb->append($this->stmt_block($catch_->getCatchBlock())); | |
} | |
} | |
$finally_ = $try_->getFinallyBlock(); | |
if (null != $finally_) { | |
$sb->append('\nfinally '); | |
$sb->append($this->stmt_block($finally_)); | |
} | |
return $sb->toString(); | |
} | |
function stmt_return(ReturnStmt $return_) { | |
return $String->format('return %s;', $this->expr($return_->getExpr())); | |
} | |
function stmt_continue(ContinueStmt $continue_) { | |
$id = $continue_->getId(); | |
if (null != $id) { | |
return $String->format('continue %s;', $id); | |
} | |
else { | |
return 'continue;'; | |
} | |
} | |
function stmt_throw(ThrowStmt $throw_) { | |
return $String->format('throw %s;', $this->expr($throw_->getExpr())); | |
} | |
function stmt_expr(ExpressionStmt $exprStmt) { | |
$expression = $exprStmt->getExpression(); | |
if ($expression instanceof VariableDeclarationExpr) { | |
return $this->stmt_expr_vars($expr); | |
} | |
else { | |
return $this->stmt_expr_expr($expression); | |
} | |
} | |
function stmt_expr_vars(VariableDeclarationExpr $vars) { | |
$sb = new StringBuilder(); | |
foreach ($vars->getVars() as $var) { | |
$sb->append($this->decl_var($var)); | |
$sb->append(';'); | |
} | |
return $sb->toString(); | |
} | |
function stmt_expr_expr(Expression $expr) { | |
$sb = new StringBuilder(); | |
if (null != $expr) { | |
$sb->append($this->expr($expr)); | |
} | |
$sb->append(';'); | |
return $sb->toString(); | |
} | |
function stmt_block(Statement $stmt) { | |
if ($stmt instanceof BlockStmt) { | |
return $this->stmt_block($expr); | |
} | |
else { | |
return $this->stmt_block(new BlockStmt($Arrays->asList($stmt))); | |
} | |
} | |
function stmt_block(BlockStmt $block) { | |
$sb = new StringBuilder(); | |
$list = $block->getStmts(); | |
$sb->append('{\n'); | |
if (null != $list) { | |
$sb->append($this->tab($this->stmt_list($list))); | |
} | |
$sb->append('}'); | |
return $sb->toString(); | |
} | |
function expr_list(List_ $list) { | |
$sb = new StringBuilder(); | |
$first = true; | |
foreach ($list as $e) { | |
if ($first) { | |
$first = false; | |
} | |
else { | |
$sb->append(', '); | |
} | |
$sb->append($this->expr($e)); | |
} | |
return $sb->toString(); | |
} | |
function expr(Expression $expr) { | |
if ($expr instanceof LiteralExpr) { | |
return $this->expr_literal($expr); | |
} | |
if ($expr instanceof NameExpr) { | |
return $this->expr_var($expr); | |
} | |
if ($expr instanceof AssignExpr) { | |
return $this->expr_assign($expr); | |
} | |
if ($expr instanceof BinaryExpr) { | |
return $this->expr_binary($expr); | |
} | |
if ($expr instanceof ConditionalExpr) { | |
return $this->expr_conditional($expr); | |
} | |
if ($expr instanceof ObjectCreationExpr) { | |
return $this->expr_new($expr); | |
} | |
if ($expr instanceof InstanceOfExpr) { | |
return $this->expr_instanceOf($expr); | |
} | |
if ($expr instanceof ClassExpr) { | |
return $this->expr_class($expr); | |
} | |
if ($expr instanceof MethodCallExpr) { | |
return $this->expr_method($expr); | |
} | |
if ($expr instanceof FieldAccessExpr) { | |
return $this->expr_field_access($expr); | |
} | |
return '$expr'; | |
} | |
function expr_var(NameExpr $name) { | |
return $this->var_($name->getName()); | |
} | |
function expr_literal(LiteralExpr $lit) { | |
if ($lit instanceof NullLiteralExpr) { | |
return 'null'; | |
} | |
if ($lit instanceof BooleanLiteralExpr) { | |
$bool_ = $expr; | |
return $bool_->getValue() ? 'true' : 'false'; | |
} | |
$value = $expr->getValue(); | |
if ($lit instanceof DoubleLiteralExpr || $lit instanceof IntegerLiteralExpr || $lit instanceof LongLiteralExpr) { | |
return $value; | |
} | |
return $String->format('\'%s\'', $value->replace('\'', '\\\'')); | |
} | |
function expr_name(NameExpr $expr) { | |
if ($expr instanceof QualifiedNameExpr) { | |
$qualif = $expr->getQualifier(); | |
$pkg = $qualif->toString()->replace('.', '\\'); | |
return $String->format('%s\\%s', $pkg, $this->name($expr->getName())); | |
} | |
else { | |
return $this->keyword($expr->getName()); | |
} | |
} | |
function expr_assign(AssignExpr $expr) { | |
$sb = new StringBuilder(); | |
$sb->append($this->expr($expr->getTarget())); | |
$sb->append(' '); | |
$sb->append($ASSIGN->get($expr->getOperator())); | |
$sb->append(' '); | |
$sb->append($this->expr($expr->getValue())); | |
return $sb->toString(); | |
} | |
/* decl_field */ | |
/* decl_initializer */ | |
function expr_binary(BinaryExpr $expr) { | |
$sb = new StringBuilder(); | |
$left = $expr->getLeft(); | |
$right = $expr->getRight(); | |
$sb->append($this->expr($left)); | |
$sb->append(' '); | |
$sb->append($BINARY->get($expr->getOperator())); | |
$sb->append(' '); | |
$sb->append($this->expr($right)); | |
return $sb->toString(); | |
} | |
/* decl_field */ | |
/* decl_initializer */ | |
function expr_conditional(ConditionalExpr $expr) { | |
$sb = new StringBuilder(); | |
$sb->append($this->expr($expr->getCondition())); | |
$sb->append(' ? '); | |
$sb->append($this->expr($expr->getThenExpr())); | |
$sb->append(' : '); | |
$sb->append($this->expr($expr->getElseExpr())); | |
return $sb->toString(); | |
} | |
function expr_new(ObjectCreationExpr $expr) { | |
$sb = new StringBuilder(); | |
$args = $expr->getArgs(); | |
$sb->append('new '); | |
$sb->append($this->type($expr->getType())); | |
$sb->append('('); | |
if (null != $args) { | |
$sb->append($this->expr_list($args)); | |
} | |
$sb->append(')'); | |
return $sb->toString(); | |
} | |
function expr_instanceOf(InstanceOfExpr $expr) { | |
$sb = new StringBuilder(); | |
$sb->append($this->expr($expr->getExpr())); | |
$sb->append(' instanceof '); | |
$sb->append($this->type($expr->getType())); | |
return $sb->toString(); | |
} | |
function expr_class(ClassExpr $expr) { | |
throw $this->missing('expr_class', $expr); | |
} | |
function expr_method(MethodCallExpr $expr) { | |
$sb = new StringBuilder(); | |
$args = $expr->getArgs(); | |
$sb->append($this->scope($expr->getScope())); | |
$sb->append('->'); | |
$sb->append($this->keyword($expr->getName())); | |
$sb->append('('); | |
if (null != $args) { | |
$sb->append($this->expr_list($args)); | |
} | |
$sb->append(')'); | |
return $sb->toString(); | |
} | |
function expr_field_access(FieldAccessExpr $expr) { | |
$sb = new StringBuilder(); | |
$sb->append($this->scope($expr->getScope())); | |
$sb->append('->'); | |
$sb->append($this->keyword($expr->getField())); | |
return $sb->toString(); | |
} | |
function scope(Expression $scope) { | |
if (null == $scope) { | |
return '$this'; | |
} | |
else { | |
return $this->expr($scope); | |
} | |
} | |
function type(Type $type) { | |
if ($type instanceof PrimitiveType) { | |
return null; | |
} | |
if ($type instanceof ReferenceType) { | |
return $this->type($expr->getType()); | |
} | |
if ($type instanceof ClassOrInterfaceType) { | |
$name = $expr->getName(); | |
return $this->name($name); | |
} | |
throw $this->missing('type', $type); | |
} | |
function keyword($name) { | |
switch ($name->toLowerCase()){ | |
case 'list': | |
case 'var': | |
case 'array': | |
return $String->format('%s_', $name); | |
default: | |
return $name; | |
} | |
} | |
function name($name) { | |
switch ($name){ | |
case 'String': | |
case 'Object': | |
return null; | |
default: | |
return $this->keyword($name); | |
} | |
} | |
function var_(VariableDeclaratorId $var) { | |
return $this->var_($var->getName()); | |
} | |
function var_($name) { | |
return $String->format('$%s', $name); | |
} | |
function tab($value) { | |
$tabs = $value->replaceAll('\n', '\n '); | |
return $String->format(' %s\n', $tabs->trim()); | |
} | |
function missing($method) { | |
throw new RuntimeException($String->format('missing impl %s', $method)); | |
} | |
function missing($method, $value) { | |
throw new RuntimeException($String->format('missing impl %s for %s', $method, $value->getClass())); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package j2p; | |
import japa.parser.JavaParser; | |
import japa.parser.ParseException; | |
import japa.parser.ast.CompilationUnit; | |
import japa.parser.ast.ImportDeclaration; | |
import japa.parser.ast.PackageDeclaration; | |
import japa.parser.ast.body.BodyDeclaration; | |
import japa.parser.ast.body.ClassOrInterfaceDeclaration; | |
import japa.parser.ast.body.FieldDeclaration; | |
import japa.parser.ast.body.InitializerDeclaration; | |
import japa.parser.ast.body.MethodDeclaration; | |
import japa.parser.ast.body.Parameter; | |
import japa.parser.ast.body.TypeDeclaration; | |
import japa.parser.ast.body.VariableDeclarator; | |
import japa.parser.ast.body.VariableDeclaratorId; | |
import japa.parser.ast.expr.AssignExpr; | |
import japa.parser.ast.expr.BinaryExpr; | |
import japa.parser.ast.expr.BooleanLiteralExpr; | |
import japa.parser.ast.expr.ClassExpr; | |
import japa.parser.ast.expr.ConditionalExpr; | |
import japa.parser.ast.expr.DoubleLiteralExpr; | |
import japa.parser.ast.expr.Expression; | |
import japa.parser.ast.expr.FieldAccessExpr; | |
import japa.parser.ast.expr.InstanceOfExpr; | |
import japa.parser.ast.expr.IntegerLiteralExpr; | |
import japa.parser.ast.expr.LiteralExpr; | |
import japa.parser.ast.expr.LongLiteralExpr; | |
import japa.parser.ast.expr.MethodCallExpr; | |
import japa.parser.ast.expr.NameExpr; | |
import japa.parser.ast.expr.NullLiteralExpr; | |
import japa.parser.ast.expr.ObjectCreationExpr; | |
import japa.parser.ast.expr.QualifiedNameExpr; | |
import japa.parser.ast.expr.StringLiteralExpr; | |
import japa.parser.ast.expr.VariableDeclarationExpr; | |
import japa.parser.ast.stmt.BlockStmt; | |
import japa.parser.ast.stmt.CatchClause; | |
import japa.parser.ast.stmt.ContinueStmt; | |
import japa.parser.ast.stmt.ExpressionStmt; | |
import japa.parser.ast.stmt.ForeachStmt; | |
import japa.parser.ast.stmt.IfStmt; | |
import japa.parser.ast.stmt.ReturnStmt; | |
import japa.parser.ast.stmt.Statement; | |
import japa.parser.ast.stmt.SwitchEntryStmt; | |
import japa.parser.ast.stmt.SwitchStmt; | |
import japa.parser.ast.stmt.ThrowStmt; | |
import japa.parser.ast.stmt.TryStmt; | |
import japa.parser.ast.type.ClassOrInterfaceType; | |
import japa.parser.ast.type.PrimitiveType; | |
import japa.parser.ast.type.ReferenceType; | |
import japa.parser.ast.type.Type; | |
import java.io.File; | |
import java.io.IOException; | |
import java.util.Arrays; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
/** | |
* @author eridal | |
*/ | |
public class Compiler { | |
public static void main(String paths[]) { | |
for (String path : paths) { | |
try { | |
file(path); | |
} catch (Exception e) { | |
System.err.println(e.getMessage()); | |
} | |
} | |
} | |
static void file(String path) throws ParseException, IOException { | |
final File file = new File(path); | |
final CompilationUnit unit = JavaParser.parse(file); | |
System.out.println("<?php\n"); | |
System.out.println(stmt_namespace(unit.getPackage())); | |
System.out.println(""); | |
for (ImportDeclaration i : unit.getImports()) { | |
System.out.println(stmt_use(i)); | |
} | |
for (TypeDeclaration type : unit.getTypes()) { | |
System.out.println(""); | |
System.out.println(stmt_type(type)); | |
} | |
} | |
static String stmt_namespace(PackageDeclaration pkg) { | |
return String.format("namespace %s;", expr_name(pkg.getName())); | |
} | |
static String stmt_use(ImportDeclaration import_) { | |
return String.format("use %s;", expr_name(import_.getName())); | |
} | |
static String stmt_type(TypeDeclaration type) { | |
if (type instanceof ClassOrInterfaceDeclaration) { | |
return decl_class((ClassOrInterfaceDeclaration) type); | |
} else { | |
throw missing("php_type"); | |
} | |
} | |
static String decl_class(ClassOrInterfaceDeclaration type) { | |
final StringBuilder sb = new StringBuilder(); | |
final List<ClassOrInterfaceType> extends_ = type.getExtends(); | |
final List<ClassOrInterfaceType> implements_ = type.getImplements(); | |
sb.append(type.isInterface() ? "interface" : "class"); | |
sb.append(' '); | |
sb.append(type.getName()); | |
if (null != extends_) { | |
sb.append(" extends "); | |
sb.append(decl_class_list(extends_)); | |
} | |
if (null != implements_) { | |
sb.append(" implements "); | |
sb.append(decl_class_list(implements_)); | |
} | |
sb.append(" {\n"); | |
for (BodyDeclaration member : type.getMembers()) { | |
sb.append("\n"); | |
sb.append(tab(decl_member(member))); | |
} | |
sb.append("\n}"); | |
return sb.toString(); | |
} | |
static String decl_class_list(List<ClassOrInterfaceType> list) { | |
final StringBuilder sb = new StringBuilder(); | |
boolean first = true; | |
for (ClassOrInterfaceType type : list) { | |
if (first) { | |
first = false; | |
} else { | |
sb.append(", "); | |
} | |
sb.append(type.getName()); | |
} | |
return sb.toString(); | |
} | |
static String decl_member(BodyDeclaration member) { | |
if (member instanceof MethodDeclaration) { | |
return decl_method((MethodDeclaration) member); | |
} | |
if (member instanceof FieldDeclaration) { | |
return decl_field((FieldDeclaration) member); | |
} | |
if (member instanceof InitializerDeclaration) { | |
return decl_initializer((InitializerDeclaration) member); | |
} | |
throw missing("decl_member", member); | |
} | |
static String decl_method(MethodDeclaration method) { | |
final StringBuilder sb = new StringBuilder(); | |
final BlockStmt body = method.getBody(); | |
if (null == body) { | |
sb.append("abstract "); | |
} | |
sb.append("function "); | |
sb.append(keyword(method.getName())); | |
sb.append('('); | |
final List<Parameter> params = method.getParameters(); | |
if (null != params) { | |
sb.append(decl_param_list(params)); | |
} | |
sb.append(')'); | |
if (null == body) { | |
sb.append(";"); | |
} else { | |
sb.append(' '); | |
sb.append(stmt_block(body)); | |
} | |
return sb.toString(); | |
} | |
static String decl_field(FieldDeclaration field) { | |
// FIXME | |
return "/* decl_field */"; | |
} | |
static String decl_initializer(InitializerDeclaration init) { | |
// FIXME | |
return "/* decl_initializer */"; | |
} | |
static String decl_param_list(List<Parameter> params) { | |
final StringBuilder sb = new StringBuilder(); | |
boolean first = true; | |
for (Parameter p : params) { | |
if (first) { | |
first = false; | |
} else { | |
sb.append(", "); | |
} | |
sb.append(decl_param(p)); | |
} | |
return sb.toString(); | |
} | |
static String decl_param(Parameter param) { | |
final StringBuilder sb = new StringBuilder(); | |
final String type; | |
type = type(param.getType()); | |
if (null != type) { | |
sb.append(type); | |
sb.append(' '); | |
} | |
if (param.isVarArgs()) { | |
sb.append("..."); | |
} | |
sb.append(var(param.getId())); | |
return sb.toString(); | |
} | |
static String decl_var(VariableDeclarator var) { | |
final StringBuilder sb = new StringBuilder(); | |
final Expression init = var.getInit(); | |
sb.append(var(var.getId())); | |
if (null != init) { | |
sb.append(" = "); | |
sb.append(expr(var.getInit())); | |
} | |
return sb.toString(); | |
} | |
static String decl_vars(List<VariableDeclarator> vars) { | |
final StringBuilder sb = new StringBuilder(); | |
boolean first = true; | |
for (VariableDeclarator v : vars) { | |
if (first) { | |
first = false; | |
} else { | |
sb.append(", "); | |
} | |
sb.append(decl_var(v)); | |
} | |
return sb.toString(); | |
} | |
static String stmt_list(List<Statement> list) { | |
final StringBuilder sb = new StringBuilder(); | |
for (Statement s : list) { | |
sb.append(stmt(s)); | |
sb.append('\n'); | |
} | |
return sb.toString(); | |
} | |
static String stmt(Statement stmt) { | |
if (stmt instanceof IfStmt) { | |
return stmt_if((IfStmt) stmt); | |
} | |
if (stmt instanceof ForeachStmt) { | |
return stmt_foreach((ForeachStmt) stmt); | |
} | |
if (stmt instanceof SwitchStmt) { | |
return stmt_switch((SwitchStmt) stmt); | |
} | |
if (stmt instanceof TryStmt) { | |
return stmt_try((TryStmt) stmt); | |
} | |
if (stmt instanceof ReturnStmt) { | |
return stmt_return((ReturnStmt) stmt); | |
} | |
if (stmt instanceof ContinueStmt) { | |
return stmt_continue((ContinueStmt) stmt); | |
} | |
if (stmt instanceof ThrowStmt) { | |
return stmt_throw((ThrowStmt) stmt); | |
} | |
if (stmt instanceof BlockStmt) { | |
return stmt_block((BlockStmt) stmt); | |
} | |
if (stmt instanceof ExpressionStmt) { | |
return stmt_expr((ExpressionStmt) stmt); | |
} | |
throw missing("stmt", stmt); | |
} | |
static String stmt_if(IfStmt if_) { | |
final StringBuilder sb = new StringBuilder(); | |
sb.append("if ("); | |
sb.append(expr(if_.getCondition())); | |
sb.append(") "); | |
sb.append(stmt_block(if_.getThenStmt())); | |
final Statement else_ = if_.getElseStmt(); | |
if (null != else_) { | |
sb.append("\nelse"); | |
if (else_ instanceof IfStmt) { | |
sb.append(stmt_if((IfStmt) else_)); | |
} | |
else { | |
sb.append(' '); | |
sb.append(stmt_block(else_)); | |
} | |
} | |
return sb.toString(); | |
} | |
static String stmt_foreach(ForeachStmt forEach) { | |
final StringBuilder sb = new StringBuilder(); | |
sb.append("foreach ("); | |
sb.append(expr(forEach.getIterable())); | |
sb.append(" as "); | |
sb.append(decl_vars(forEach.getVariable().getVars())); | |
sb.append(") "); | |
sb.append(stmt_block(forEach.getBody())); | |
return sb.toString(); | |
} | |
static String stmt_switch(SwitchStmt switch_) { | |
final StringBuilder sb = new StringBuilder(); | |
sb.append("switch ("); | |
sb.append(expr(switch_.getSelector())); | |
sb.append("){\n"); | |
for (SwitchEntryStmt case_ : switch_.getEntries()) { | |
sb.append(stmt_switch_case(case_)); | |
} | |
sb.append("}"); | |
return sb.toString(); | |
} | |
static String stmt_switch_case(SwitchEntryStmt case_) { | |
final StringBuilder sb = new StringBuilder(); | |
final Expression label = case_.getLabel(); | |
final List<Statement> list = case_.getStmts(); | |
if (null == label) { | |
sb.append("default:"); | |
} else { | |
sb.append("case "); | |
sb.append(expr(label)); | |
sb.append(":"); | |
} | |
sb.append('\n'); | |
if (null != list) { | |
sb.append(tab(stmt_list(list))); | |
} | |
return sb.toString(); | |
} | |
static String stmt_try(TryStmt try_) { | |
final StringBuilder sb = new StringBuilder(); | |
sb.append("try "); | |
sb.append(stmt_block(try_.getTryBlock())); | |
final List<CatchClause> catchs = try_.getCatchs(); | |
if (null != catchs) { | |
for (CatchClause catch_ : catchs) { | |
sb.append("\ncatch ("); | |
sb.append(decl_param(catch_.getExcept())); | |
sb.append(") "); | |
sb.append(stmt_block(catch_.getCatchBlock())); | |
} | |
} | |
final BlockStmt finally_ = try_.getFinallyBlock(); | |
if (null != finally_) { | |
sb.append("\nfinally "); | |
sb.append(stmt_block(finally_)); | |
} | |
return sb.toString(); | |
} | |
static String stmt_return(ReturnStmt return_) { | |
return String.format("return %s;", expr(return_.getExpr())); | |
} | |
static String stmt_continue(ContinueStmt continue_) { | |
final String id = continue_.getId(); | |
if (null != id) { | |
return String.format("continue %s;", id); | |
} else { | |
return "continue;"; | |
} | |
} | |
static String stmt_throw(ThrowStmt throw_) { | |
return String.format("throw %s;", expr(throw_.getExpr())); | |
} | |
static String stmt_expr(ExpressionStmt exprStmt) { | |
final Expression expression = exprStmt.getExpression(); | |
if (expression instanceof VariableDeclarationExpr) { | |
return stmt_expr_vars((VariableDeclarationExpr) expression); | |
} else { | |
return stmt_expr_expr(expression); | |
} | |
} | |
static String stmt_expr_vars(VariableDeclarationExpr vars) { | |
final StringBuilder sb = new StringBuilder(); | |
for (VariableDeclarator var : vars.getVars()) { | |
sb.append(decl_var(var)); | |
sb.append(";"); | |
} | |
return sb.toString(); | |
} | |
static String stmt_expr_expr(Expression expr) { | |
final StringBuilder sb = new StringBuilder(); | |
if (null != expr) { | |
sb.append(expr(expr)); | |
} | |
sb.append(';'); | |
return sb.toString(); | |
} | |
static String stmt_block(Statement stmt) { | |
if (stmt instanceof BlockStmt) { | |
return stmt_block((BlockStmt) stmt); | |
} else { | |
return stmt_block(new BlockStmt(Arrays.asList(stmt))); | |
} | |
} | |
static String stmt_block(BlockStmt block) { | |
final StringBuilder sb = new StringBuilder(); | |
List<Statement> list = block.getStmts(); | |
sb.append("{\n"); | |
if (null != list) { | |
sb.append(tab(stmt_list(list))); | |
} | |
sb.append("}"); | |
return sb.toString(); | |
} | |
static String expr_list(List<Expression> list) { | |
final StringBuilder sb = new StringBuilder(); | |
boolean first = true; | |
for (Expression e : list) { | |
if (first) { | |
first = false; | |
} else { | |
sb.append(", "); | |
} | |
sb.append(expr(e)); | |
} | |
return sb.toString(); | |
} | |
static String expr(Expression expr) { | |
if (expr instanceof LiteralExpr) { | |
return expr_literal((LiteralExpr) expr); | |
} | |
if (expr instanceof NameExpr) { | |
return expr_var((NameExpr) expr); | |
} | |
if (expr instanceof AssignExpr) { | |
return expr_assign((AssignExpr) expr); | |
} | |
if (expr instanceof BinaryExpr) { | |
return expr_binary((BinaryExpr) expr); | |
} | |
if (expr instanceof ConditionalExpr) { | |
return expr_conditional((ConditionalExpr) expr); | |
} | |
if (expr instanceof ObjectCreationExpr) { | |
return expr_new((ObjectCreationExpr) expr); | |
} | |
if (expr instanceof InstanceOfExpr) { | |
return expr_instanceOf((InstanceOfExpr) expr); | |
} | |
if (expr instanceof ClassExpr) { | |
return expr_class((ClassExpr) expr); | |
} | |
if (expr instanceof MethodCallExpr) { | |
return expr_method((MethodCallExpr) expr); | |
} | |
if (expr instanceof FieldAccessExpr) { | |
return expr_field_access((FieldAccessExpr) expr); | |
} | |
return "$expr"; | |
} | |
static String expr_var(NameExpr name) { | |
return var(name.getName()); | |
} | |
static String expr_literal(LiteralExpr lit) { | |
if (lit instanceof NullLiteralExpr) { | |
return "null"; | |
} | |
if (lit instanceof BooleanLiteralExpr) { | |
BooleanLiteralExpr bool_ = (BooleanLiteralExpr) lit; | |
return bool_.getValue() ? "true" : "false"; | |
} | |
final String value = ((StringLiteralExpr) lit).getValue(); | |
if (lit instanceof DoubleLiteralExpr || | |
lit instanceof IntegerLiteralExpr || | |
lit instanceof LongLiteralExpr) { | |
return value; | |
} | |
return String.format("'%s'", value.replace("'", "\\'")); | |
} | |
static String expr_name(NameExpr expr) { | |
if (expr instanceof QualifiedNameExpr) { | |
final NameExpr qualif = ((QualifiedNameExpr) expr).getQualifier(); | |
final String pkg = qualif.toString().replace('.', '\\'); | |
return String.format("%s\\%s", pkg, name(expr.getName())); | |
} else { | |
return keyword(expr.getName()); | |
} | |
} | |
static String expr_assign(AssignExpr expr) { | |
final StringBuilder sb = new StringBuilder(); | |
sb.append(expr(expr.getTarget())); | |
sb.append(' '); | |
sb.append(ASSIGN.get(expr.getOperator())); | |
sb.append(' '); | |
sb.append(expr(expr.getValue())); | |
return sb.toString(); | |
} | |
static Map<AssignExpr.Operator, String> ASSIGN = new HashMap<AssignExpr.Operator, String>(); | |
static { | |
ASSIGN.put(AssignExpr.Operator.assign , "="); | |
ASSIGN.put(AssignExpr.Operator.plus , "+="); | |
ASSIGN.put(AssignExpr.Operator.minus , "-="); | |
ASSIGN.put(AssignExpr.Operator.star , "*="); | |
ASSIGN.put(AssignExpr.Operator.slash , "/="); | |
ASSIGN.put(AssignExpr.Operator.and , "&="); | |
ASSIGN.put(AssignExpr.Operator.or , "|="); | |
ASSIGN.put(AssignExpr.Operator.xor , "^="); | |
ASSIGN.put(AssignExpr.Operator.rem , "%="); | |
ASSIGN.put(AssignExpr.Operator.lShift , "<<="); | |
ASSIGN.put(AssignExpr.Operator.rSignedShift , ">>="); | |
ASSIGN.put(AssignExpr.Operator.rUnsignedShift , ">>>="); | |
} | |
static String expr_binary(BinaryExpr expr) { | |
final StringBuilder sb = new StringBuilder(); | |
final Expression left = expr.getLeft(); | |
final Expression right = expr.getRight(); | |
sb.append(expr(left)); | |
sb.append(' '); | |
sb.append(BINARY.get(expr.getOperator())); | |
sb.append(' '); | |
sb.append(expr(right)); | |
return sb.toString(); | |
} | |
static Map<BinaryExpr.Operator, String> BINARY = new HashMap<BinaryExpr.Operator, String>(); | |
static { | |
BINARY.put(BinaryExpr.Operator.or , "||"); | |
BINARY.put(BinaryExpr.Operator.and , "&&"); | |
BINARY.put(BinaryExpr.Operator.binOr , "|"); | |
BINARY.put(BinaryExpr.Operator.binAnd , "&"); | |
BINARY.put(BinaryExpr.Operator.xor , "^"); | |
BINARY.put(BinaryExpr.Operator.equals , "=="); | |
BINARY.put(BinaryExpr.Operator.notEquals , "!="); | |
BINARY.put(BinaryExpr.Operator.less , "<"); | |
BINARY.put(BinaryExpr.Operator.greater , ">"); | |
BINARY.put(BinaryExpr.Operator.lessEquals , "<="); | |
BINARY.put(BinaryExpr.Operator.greaterEquals , ">="); | |
BINARY.put(BinaryExpr.Operator.lShift , "<<"); | |
BINARY.put(BinaryExpr.Operator.rSignedShift , ">>"); | |
BINARY.put(BinaryExpr.Operator.rUnsignedShift , ">>>"); | |
BINARY.put(BinaryExpr.Operator.plus , "+"); | |
BINARY.put(BinaryExpr.Operator.minus , "-"); | |
BINARY.put(BinaryExpr.Operator.times , "*"); | |
BINARY.put(BinaryExpr.Operator.divide , "/"); | |
BINARY.put(BinaryExpr.Operator.remainder , "/"); | |
} | |
static String expr_conditional(ConditionalExpr expr) { | |
final StringBuilder sb = new StringBuilder(); | |
sb.append(expr(expr.getCondition())); | |
sb.append(" ? "); | |
sb.append(expr(expr.getThenExpr())); | |
sb.append(" : "); | |
sb.append(expr(expr.getElseExpr())); | |
return sb.toString(); | |
} | |
static String expr_new(ObjectCreationExpr expr) { | |
final StringBuilder sb = new StringBuilder(); | |
final List<Expression >args = expr.getArgs(); | |
sb.append("new "); | |
sb.append(type(expr.getType())); | |
sb.append('('); | |
if (null != args) { | |
sb.append(expr_list(args)); | |
} | |
sb.append(')'); | |
return sb.toString(); | |
} | |
static String expr_instanceOf(InstanceOfExpr expr) { | |
final StringBuilder sb = new StringBuilder(); | |
sb.append(expr(expr.getExpr())); | |
sb.append(" instanceof "); | |
sb.append(type(expr.getType())); | |
return sb.toString(); | |
} | |
static String expr_class(ClassExpr expr) { | |
throw missing("expr_class", expr); | |
} | |
static String expr_method(MethodCallExpr expr) { | |
final StringBuilder sb = new StringBuilder(); | |
final List<Expression> args = expr.getArgs(); | |
sb.append(scope(expr.getScope())); | |
sb.append("->"); | |
sb.append(keyword(expr.getName())); | |
sb.append('('); | |
if (null != args) { | |
sb.append(expr_list(args)); | |
} | |
sb.append(')'); | |
return sb.toString(); | |
} | |
static String expr_field_access(FieldAccessExpr expr) { | |
final StringBuilder sb = new StringBuilder(); | |
sb.append(scope(expr.getScope())); | |
sb.append("->"); | |
sb.append(keyword(expr.getField())); | |
return sb.toString(); | |
} | |
static String scope(Expression scope) { | |
if (null == scope) { | |
return "$this"; | |
} else { | |
return expr(scope); | |
} | |
} | |
static String type(Type type) { | |
if (type instanceof PrimitiveType) { | |
return null; | |
} | |
if (type instanceof ReferenceType) { | |
return type(((ReferenceType) type).getType()); | |
} | |
if (type instanceof ClassOrInterfaceType) { | |
String name = ((ClassOrInterfaceType) type).getName(); | |
return name(name); | |
} | |
throw missing("type", type); | |
} | |
static String keyword(String name) { | |
switch(name.toLowerCase()) { | |
case "list": | |
case "var": | |
case "array": | |
return String.format("%s_", name); | |
default: | |
return name; | |
} | |
} | |
static String name(String name) { | |
switch(name) { | |
case "String": | |
case "Object": | |
return null; | |
default: | |
return keyword(name); | |
} | |
} | |
static String var(VariableDeclaratorId var) { | |
return var(var.getName()); | |
} | |
static String var(String name) { | |
return String.format("$%s", name); | |
} | |
static String tab(String value) { | |
final String tabs = value.replaceAll("\n", "\n "); | |
return String.format(" %s\n", tabs.trim()); | |
} | |
private static RuntimeException missing(String method) { | |
throw new RuntimeException(String.format("missing impl %s", method)); | |
} | |
private static RuntimeException missing(String method, Object value) { | |
throw new RuntimeException(String.format("missing impl %s for %s", method, value.getClass())); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@eridal, great work, it looks great. Keep it up.