Created
February 16, 2015 07:55
-
-
Save julbouln/af2b052e78aa32e465e8 to your computer and use it in GitHub Desktop.
java to cpp
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
require 'pp' | |
require 'java' | |
require '/usr/share/java/javaparser.jar' | |
module Java2cpp | |
class JavaFile | |
attr_accessor :class_dependencies, :class_defined | |
include_package "japa.parser" | |
java_import "java.io.FileInputStream" | |
java_import "japa.parser.ast.CompilationUnit" | |
java_import "japa.parser.ast.visitor.VoidVisitorAdapter" | |
def initialize | |
@class_dependencies=[] | |
@class_defined=[] | |
end | |
def to_c_bit_op(op) | |
case op.to_s | |
when "or" | |
"||" | |
when "and" | |
"&&" | |
when "binOr" | |
"|" | |
when "binAnd" | |
"&" "" | |
when "xor" | |
"^" | |
when "equals" | |
"==" | |
when "notEquals" | |
"!=" | |
when "less" | |
"<" | |
when "greater" | |
">" | |
when "lessEquals" | |
"<=" | |
when "greaterEquals" | |
">=" | |
when "lShift" | |
"<<" | |
when "rSignedShift" | |
">>" | |
when "rUnsignedShift" | |
">>>" | |
when "plus" | |
"+" | |
when "minus" | |
"-" | |
when "times" | |
"*" | |
when "divide" | |
"/" | |
when "remainder" | |
"%" | |
end | |
end | |
def to_c_assign_op(op) | |
case op.to_s | |
when "assign" | |
"=" | |
when "plus" | |
"+=" | |
when "minus" | |
"-=" | |
when "star" | |
"*=" | |
when "slash" | |
"/=" | |
when "and" | |
"&=" | |
when "or" | |
"|=" | |
when "xor" | |
"^=" | |
when "rem" | |
"%=" | |
when "lShift" | |
"<<=" | |
when "rSignedShift" | |
">>=" | |
when "rUnsignedShift" | |
">>>=" | |
end | |
end | |
def to_c_unary_op(op) | |
case op.to_s | |
when "positive" | |
"+" | |
when "negative" | |
"-" | |
when "preIncrement" | |
"++" | |
when "preDecrement" | |
"--" | |
when "not" | |
"!" | |
when "inverse" | |
"~" | |
when "posIncrement" | |
"++" | |
when "posDecrement" | |
"-" | |
end | |
end | |
def id_to_c_name(id) | |
id.getName().to_s | |
end | |
def to_c_type_array(type) | |
case type | |
when Java::JapaParserAstType::ReferenceType | |
if type.getArrayCount() > 0 | |
"[]"*type.getArrayCount() | |
else | |
"" | |
end | |
else | |
"" | |
end | |
end | |
def to_c_type_args(type) | |
c_type_args="" | |
type_args=type.getTypeArgs() | |
if type_args | |
c_type_args+="<" | |
targs=type_args.map do |ta| | |
self.to_c_type(ta) | |
end | |
c_type_args+=targs.join(",") | |
c_type_args+=">" | |
end | |
c_type_args | |
end | |
def to_c_type(type) | |
case type | |
when Java::JapaParserAstType::ReferenceType | |
class_type=type.getType() | |
self.to_c_type(class_type) | |
when Java::JapaParserAstType::ClassOrInterfaceType | |
class_name=type.getName().to_s | |
# std type | |
case class_name | |
when "String" | |
class_name="string" | |
when "ArrayList" | |
class_name="vector" | |
when "LinkedHashMap", "HashMap" | |
class_name="map" | |
when "LinkedHashSet" | |
class_name="set" | |
when "Integer" | |
class_name="int" | |
when "Double" | |
class_name="double" | |
when "Random" | |
class_name="int" | |
else | |
@class_dependencies << class_name | |
@class_dependencies.uniq! | |
end | |
scope=type.getScope() | |
while scope | |
class_name=scope.getName().to_s+"::"+class_name | |
scope=scope.getScope() | |
end | |
class_name+=self.to_c_type_args(type) | |
class_name | |
when Java::JapaParserAstType::WildcardType | |
"T" | |
when Java::JapaParserAstType::PrimitiveType | |
prim_type=type.getType().to_s.downcase | |
case prim_type | |
when "boolean" | |
prim_type="bool" | |
end | |
prim_type | |
when Java::JapaParserAstType::VoidType | |
"void" | |
else | |
"TODO_ctype#{type.inspect}" | |
end | |
end | |
def to_c_parameters(parameters) | |
c_params=[] | |
if parameters | |
parameters.each do |p| | |
param_name=self.id_to_c_name(p.getId()) | |
param_type=self.to_c_type(p.getType()) | |
param_array=self.to_c_type_array(p.getType()) | |
c_params << "#{param_type} #{param_name}#{param_array}" | |
end | |
end | |
c_params.join(",") | |
end | |
def to_c_decl_parameters(parameters) | |
c_params=[] | |
if parameters | |
parameters.each do |p| | |
param_name=self.id_to_c_name(p.getId()) | |
param_type=self.to_c_type(p.getType()) | |
param_array=self.to_c_type_array(p.getType()) | |
c_params << "#{param_type}#{param_array}" | |
end | |
end | |
c_params.join(",") | |
end | |
def to_c_expr(expr) | |
case expr | |
when Java::JapaParserAstExpr::NameExpr | |
name_expr=expr.getName().to_s | |
name_expr | |
when Java::JapaParserAstExpr::ThisExpr | |
"this" | |
when Java::JapaParserAstExpr::NullLiteralExpr | |
"NULL" | |
when Java::JapaParserAstExpr::BooleanLiteralExpr | |
expr.getValue() ? "true" : "false" | |
when Java::JapaParserAstExpr::CharLiteralExpr, | |
Java::JapaParserAstExpr::IntegerLiteralExpr, | |
Java::JapaParserAstExpr::DoubleLiteralExpr, | |
Java::JapaParserAstExpr::LongLiteralExpr | |
expr.getValue() | |
when Java::JapaParserAstExpr::StringLiteralExpr | |
"\"#{expr.getValue()}\"" | |
when Java::JapaParserAstExpr::EnclosedExpr | |
"("+self.to_c_expr(expr.getInner())+")" | |
when Java::JapaParserAstExpr::CastExpr | |
"("+self.to_c_type(expr.getType())+")"+self.to_c_expr(expr.getExpr()); | |
when Java::JapaParserAstExpr::ArrayAccessExpr | |
self.to_c_expr(expr.getName())+"["+self.to_c_expr(expr.getIndex())+"]" | |
when Java::JapaParserAstExpr::AssignExpr | |
self.to_c_expr(expr.getTarget())+" "+self.to_c_assign_op(expr.getOperator())+" "+self.to_c_expr(expr.getValue()) | |
when Java::JapaParserAstExpr::BinaryExpr | |
self.to_c_expr(expr.getLeft())+" "+self.to_c_bit_op(expr.getOperator())+" "+self.to_c_expr(expr.getRight()) | |
when Java::JapaParserAstExpr::UnaryExpr | |
self.to_c_unary_op(expr.getOperator())+self.to_c_expr(expr.getExpr()) | |
when Java::JapaParserAstExpr::ClassExpr | |
self.to_c_type(expr.getType()) | |
when Java::JapaParserAstExpr::ArrayInitializerExpr | |
c_values=[] | |
values=expr.getValues() | |
if values | |
values.each do |v| | |
c_values << self.to_c_expr(v) | |
end | |
end | |
"{"+c_values.join(",")+"}" | |
when Java::JapaParserAstExpr::ConditionalExpr | |
if_expr=expr.getThenExpr() | |
else_expr=expr.getElseExpr() | |
self.to_c_expr(expr.getCondition()) + " ? " + self.to_c_expr(if_expr) + " : " + self.to_c_expr(else_expr) | |
when Java::JapaParserAstExpr::FieldAccessExpr | |
from_class=nil | |
if expr.getScope() | |
if expr.getScope().class==Java::JapaParserAstExpr::ThisExpr | |
from_class="this->" | |
else | |
from_class=self.to_c_expr(expr.getScope()).to_s + "." | |
end | |
else | |
from_class="this->" | |
end | |
from_class + expr.getField() | |
when Java::JapaParserAstExpr::MethodCallExpr | |
params=[] | |
args=expr.getArgs() | |
method_name=expr.getName().to_s | |
# self.to_c_type_args(expr) | |
if args | |
args.each do |a| | |
params << self.to_c_expr(a) | |
end | |
end | |
from_class=nil | |
if expr.getScope() | |
from_class=self.to_c_expr(expr.getScope()).to_s + "." | |
else | |
from_class="this->" | |
end | |
suffix="" | |
case from_class | |
when "System.out." | |
from_class="cout " | |
method_name=" << " | |
suffix=" << endl" | |
when "Math." | |
from_class="" | |
end | |
from_class + method_name+"("+params.join(",")+")"+suffix | |
when Java::JapaParserAstExpr::ObjectCreationExpr | |
params=[] | |
args=expr.getArgs() | |
if args | |
args.each do |a| | |
params << self.to_c_expr(a) | |
end | |
end | |
class_name=expr.getType().getName().to_s | |
case class_name | |
when "Random" | |
class_name="rand" | |
end | |
class_name+"("+params.join(",")+")" | |
when Java::JapaParserAstExpr::VariableDeclarationExpr | |
expr_type=self.to_c_type(expr.getType()) | |
expr_name="TODO_expr_name" | |
expr_array=self.to_c_type_array(expr.getType()) | |
expr.getVars().each do |v| | |
case v | |
when Java::JapaParserAstBody::VariableDeclarator | |
expr_name=self.id_to_c_name(v.getId())+expr_array | |
init_expr=v.getInit() | |
if init_expr | |
expr_name+=" = "+self.to_c_expr(init_expr) | |
end | |
else | |
expr_name="TODO_var#{v}" | |
end | |
end | |
"#{expr_type} #{expr_name}" | |
when Java::JapaParserAstExpr::ArrayCreationExpr | |
# pp expr.getType() | |
# pp expr.getArrayCount() | |
# pp expr.getInitializer() | |
dims=expr.getDimensions() | |
if dims | |
d=dims.map do |dim| | |
"["+self.to_c_expr(dim)+"]" | |
end.join(",") | |
else | |
init=expr.getInitializer() | |
if init | |
values=init.getValues() | |
if values | |
d="["+values.length.to_s+"]"+self.to_c_expr(expr.getInitializer()); | |
end | |
end | |
end | |
"new #{self.to_c_type(expr.getType())}#{d}" | |
when nil | |
"NIL" | |
else | |
"TODO_expr#{expr.inspect}" | |
end | |
end | |
def to_c_stmt(stmt, level=0) | |
c_stmt="" | |
case stmt | |
when Java::JapaParserAstStmt::BlockStmt | |
stmts=stmt.getStmts() | |
if stmts | |
stmts.each do |s| | |
c_stmt+=" "*level + self.to_c_stmt(s, level+1) | |
end | |
end | |
when Java::JapaParserAstStmt::ExpressionStmt | |
c_stmt=" "*level + self.to_c_expr(stmt.getExpression())+";\n" | |
when Java::JapaParserAstStmt::ReturnStmt | |
c_stmt=" "*level + "return "+self.to_c_expr(stmt.getExpr())+";\n" | |
when Java::JapaParserAstStmt::BreakStmt | |
c_stmt=" "*level + "break;\n" | |
when Java::JapaParserAstStmt::SwitchStmt | |
c_stmt=" "*level +"switch("+self.to_c_expr(stmt.getSelector())+"){\n" | |
stmt.getEntries().each do |c| | |
c_stmt+=" "*(level+2) +"case "+self.to_c_expr(c.getLabel())+":\n" | |
c.getStmts().each do |s| | |
c_stmt+=self.to_c_stmt(s, level+3) | |
end | |
end | |
c_stmt+=" "*level +"}\n" | |
when Java::JapaParserAstStmt::ForeachStmt | |
c_stmt+=" "*level +"for("+self.to_c_expr(stmt.getVariable())+":"+self.to_c_expr(stmt.getIterable())+"){\n" | |
c_stmt+=self.to_c_stmt(stmt.getBody(), level+1) | |
c_stmt+=" "*level +"}\n" | |
when Java::JapaParserAstStmt::WhileStmt | |
c_stmt=" "*level +"while("+self.to_c_expr(stmt.getCondition())+"){\n" | |
c_stmt+=self.to_c_stmt(stmt.getBody(), level+1) | |
c_stmt+=" "*level +"}\n" | |
when Java::JapaParserAstStmt::DoStmt | |
c_stmt=" "*level +"do{\n" | |
c_stmt+=self.to_c_stmt(stmt.getBody(), level+1) | |
c_stmt+=" "*level +"}\n" | |
c_stmt+=" "*level +"while("+self.to_c_expr(stmt.getCondition())+");\n" | |
when Java::JapaParserAstStmt::ForStmt | |
init_exprs=stmt.getInit() | |
compare_expr=stmt.getCompare() | |
update_exprs=stmt.getUpdate() | |
c_stmt+=" "*level +"for(" | |
c_stmt+=init_exprs.map do |i| | |
self.to_c_expr(i) | |
end.join(",") | |
c_stmt+=";" | |
c_stmt+=self.to_c_expr(compare_expr) | |
c_stmt+=";" | |
c_stmt+=update_exprs.map do |u| | |
self.to_c_expr(u) | |
end.join(",") | |
c_stmt+=" "*level +"){\n" | |
c_stmt+=self.to_c_stmt(stmt.getBody(), level+2) | |
c_stmt+=" "*level +"}\n" | |
when Java::JapaParserAstStmt::IfStmt | |
if_stmt=stmt.getThenStmt() | |
else_stmt=stmt.getElseStmt() | |
c_stmt+=" "*level +"if("+self.to_c_expr(stmt.getCondition())+") {\n" | |
c_stmt+=self.to_c_stmt(if_stmt, level+1) | |
c_stmt+=" "*level +"}\n" | |
if else_stmt | |
c_stmt+=" "*level +"else {\n" | |
c_stmt+=self.to_c_stmt(else_stmt, level+1) | |
c_stmt+=" "*level +"}\n" | |
end | |
else | |
c_stmt="// TODO_stmt#{stmt.inspect};\n" | |
c_stmt+="/*"+stmt.to_s+"*/\n" | |
end | |
c_stmt | |
end | |
def convert(filename) | |
puts "Convert #{filename}" | |
out_c=filename.gsub(/.java/, ".cpp") | |
out_h=filename.gsub(/.java/, ".h") | |
c_code="" | |
method_decl="" | |
data = FileInputStream.new(filename) | |
cu = JavaParser.parse(data) | |
imports=cu.getImports() | |
cu.getTypes().each do |t| | |
class_name=t.getName() | |
@class_defined << class_name | |
@class_defined.uniq! | |
struct_members=[] | |
inherits=[] | |
is_iface=false | |
case t | |
when Java::JapaParserAstBody::ClassOrInterfaceDeclaration | |
is_iface=t.isInterface() | |
exts=t.getExtends() | |
if exts | |
exts.each do |e| | |
inherits << self.to_c_type(e) | |
end | |
end | |
impls=t.getImplements() | |
if impls | |
impls.each do |i| | |
inherits << self.to_c_type(i) | |
end | |
end | |
t.getMembers().each do |m| | |
case m | |
when Java::JapaParserAstBody::FieldDeclaration | |
var_type=self.to_c_type(m.getType()) | |
var_array=self.to_c_type_array(m.getType()) | |
m.getVariables().each do |v| | |
var_name=self.id_to_c_name(v.getId()) | |
struct_members << "#{var_type} #{var_name}#{var_array}" | |
end | |
when Java::JapaParserAstBody::ConstructorDeclaration | |
params=self.to_c_parameters(m.getParameters()) | |
c_code+="#{class_name}::#{class_name}(#{params}) {\n" | |
c_code+= self.to_c_stmt(m.getBlock()) | |
c_code+="}\n" | |
params_decl=self.to_c_decl_parameters(m.getParameters()) | |
method_decl+=" #{class_name}(#{params_decl});\n" | |
# when Java::JapaParserAstBody::ClassOrInterfaceDeclaration | |
# puts m.to_s | |
# when Java::JapaParserAstBody::InitializerDeclaration | |
# c_code+=self.to_c_stmt(m.getBlock()) | |
when Java::JapaParserAstBody::MethodDeclaration | |
method_name=m.getName().to_s | |
method_type=self.to_c_type(m.getType()) | |
method_array=self.to_c_type_array(m.getType()) | |
params=self.to_c_parameters(m.getParameters()) | |
c_code+="#{method_type}#{method_array} #{class_name}::#{method_name}(#{params}) {\n" | |
c_code+= self.to_c_stmt(m.getBody()) | |
c_code+="}\n" | |
params_decl=self.to_c_decl_parameters(m.getParameters()) | |
method_decl+=" #{method_type}#{method_array} #{method_name}(#{params_decl});\n" | |
else | |
c_code+="//TODO_declr#{m.inspect}\n" | |
c_code+="/*"+m.to_s+"*/\n" | |
end | |
end | |
else | |
c_code+="//TODO_declr#{t.inspect}\n" | |
c_code+="/*"+t.to_s+"*/\n" | |
end | |
header=File.open(out_h, "w") | |
header.write "#ifndef #{class_name.upcase}_H\n" | |
header.write "#define #{class_name.upcase}_H\n" | |
header.write "#include <iostream>\n" | |
header.write "#include <cmath>\n" | |
header.write "#include <string>\n" | |
header.write "#include <vector>\n" | |
header.write "#include <map>\n" | |
header.write "#include <set>\n" | |
(@class_dependencies - @class_defined - ["Class","Object","T","StringBuilder","Iterator","Offset","Collection","File","Pattern","ScriptGetter"]).each do |cl| | |
header.write "#include \"#{cl}.h\"\n" | |
end | |
# if imports | |
# imports.each do |i| | |
# puts i.getName() | |
# end | |
# end | |
header.write "using namespace std;\n" | |
header.write "class #{class_name}" | |
if inherits.length>0 | |
header.write " : "+inherits.map { |i| "public #{i}" }.join(",") | |
end | |
header.write " {\n" | |
struct_members.each do |member| | |
header.write " #{member};\n" | |
end | |
header.write "public:\n" | |
header.write method_decl | |
header.write "};\n" | |
header.write "#endif // #{class_name.upcase}_H\n" | |
header.close | |
unless is_iface | |
code=File.open(out_c, "w") | |
code.write "#include \"#{File.basename(out_h)}\"\n" | |
code.write c_code | |
code.close | |
end | |
end | |
end | |
end | |
end | |
f=Java2cpp::JavaFile.new | |
f.convert(ARGV[0]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment