Java to PHP Compilation
<?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())); | |
} | |
} |
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
This comment has been minimized.
@eridal, great work, it looks great. Keep it up.