提交 f24105c1 authored 作者: Thomas Mueller's avatar Thomas Mueller

A Java parser / Java to C converter.

上级 4ead520a
...@@ -54,6 +54,8 @@ public class ClassObj { ...@@ -54,6 +54,8 @@ public class ClassObj {
*/ */
LinkedHashMap<String, MethodObj> methods = new LinkedHashMap<String, MethodObj>(); LinkedHashMap<String, MethodObj> methods = new LinkedHashMap<String, MethodObj>();
ArrayList<Statement> nativeInitializers = new ArrayList<Statement>();
/** /**
* Add a method. * Add a method.
* *
...@@ -134,6 +136,11 @@ class MethodObj { ...@@ -134,6 +136,11 @@ class MethodObj {
* Whether this method is public. * Whether this method is public.
*/ */
boolean isPublic; boolean isPublic;
/**
* Whether this method is native.
*/
boolean isNative;
} }
/** /**
...@@ -146,6 +153,11 @@ class FieldObj { ...@@ -146,6 +153,11 @@ class FieldObj {
*/ */
Type type; Type type;
/**
* Whether this is a local field.
*/
boolean isLocal;
/** /**
* The field name. * The field name.
*/ */
...@@ -194,13 +206,13 @@ class Type { ...@@ -194,13 +206,13 @@ class Type {
int arrayLevel; int arrayLevel;
public String toString() { public String toString() {
if (arrayLevel == 0) {
return type.name;
}
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
buff.append(JavaParser.toC(type.name)); buff.append(JavaParser.toC(type.name));
if (!type.isPrimitive) {
buff.append("*");
}
for (int i = 0; i < arrayLevel; i++) { for (int i = 0; i < arrayLevel; i++) {
buff.append("[]"); buff.append("*");
} }
return buff.toString(); return buff.toString();
} }
......
...@@ -13,17 +13,21 @@ import java.util.ArrayList; ...@@ -13,17 +13,21 @@ import java.util.ArrayList;
*/ */
public interface Expr { public interface Expr {
// toString // toString
Type getType();
} }
/** /**
* A method call. * A method call.
*/ */
class CallExpr implements Expr { class CallExpr implements Expr {
String object;
Expr expr;
String name;
ArrayList<Expr> args = new ArrayList<Expr>(); ArrayList<Expr> args = new ArrayList<Expr>();
public String toString() { public String toString() {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
buff.append(JavaParser.toC(object)).append("("); buff.append(expr.toString() + "_" + JavaParser.toC(name)).append("(");
int i = 0; int i = 0;
for (Expr a : args) { for (Expr a : args) {
if (i > 0) { if (i > 0) {
...@@ -34,12 +38,17 @@ class CallExpr implements Expr { ...@@ -34,12 +38,17 @@ class CallExpr implements Expr {
} }
return buff.append(")").toString(); return buff.append(")").toString();
} }
public Type getType() {
// TODO
return null;
}
} }
/** /**
* A assignment expression. * A assignment expression.
*/ */
class AssignExpr implements Expr { class AssignExpr implements Expr {
Expr left; Expr left;
String op; String op;
Expr right; Expr right;
...@@ -47,36 +56,60 @@ class AssignExpr implements Expr { ...@@ -47,36 +56,60 @@ class AssignExpr implements Expr {
public String toString() { public String toString() {
return left + " " + op + " " + right; return left + " " + op + " " + right;
} }
public Type getType() {
// TODO
return null;
}
} }
/** /**
* A conditional expression. * A conditional expression.
*/ */
class ConditionalExpr implements Expr { class ConditionalExpr implements Expr {
Expr condition; Expr condition;
Expr ifTrue, ifFalse; Expr ifTrue, ifFalse;
public String toString() { public String toString() {
return condition + " ? " + ifTrue + " : " + ifFalse; return condition + " ? " + ifTrue + " : " + ifFalse;
} }
public Type getType() {
// TODO
return null;
}
} }
/** /**
* A literal. * A literal.
*/ */
class LiteralExpr implements Expr { class LiteralExpr implements Expr {
String literal; String literal;
public String toString() { public String toString() {
return literal; return literal;
} }
public Type getType() {
// TODO
return null;
}
} }
/** /**
* An operation. * An operation.
*/ */
class OpExpr implements Expr { class OpExpr implements Expr {
Expr left; Expr left;
String op; String op;
Expr right; Expr right;
public String toString() { public String toString() {
if (left == null) { if (left == null) {
return op + right; return op + right;
...@@ -85,16 +118,38 @@ class OpExpr implements Expr { ...@@ -85,16 +118,38 @@ class OpExpr implements Expr {
} }
return left + " " + op + " " + right; return left + " " + op + " " + right;
} }
public Type getType() {
// TODO
return null;
}
} }
/** /**
* A "new" expression. * A "new" expression.
*/ */
class NewExpr implements Expr { class NewExpr implements Expr {
String className;
ClassObj type;
ArrayList<Expr> arrayInitExpr = new ArrayList<Expr>();
public String toString() { public String toString() {
return "new " + className; StringBuilder buff = new StringBuilder();
buff.append("new " + type);
for (Expr e : arrayInitExpr) {
buff.append("[").append(e).append("]");
}
return buff.toString();
} }
public Type getType() {
Type t = new Type();
t.type = type;
t.arrayLevel = arrayInitExpr.size();
return t;
}
} }
/** /**
...@@ -111,6 +166,11 @@ class StringExpr implements Expr { ...@@ -111,6 +166,11 @@ class StringExpr implements Expr {
return "\"" + javaEncode(text) + "\""; return "\"" + javaEncode(text) + "\"";
} }
public Type getType() {
// TODO
return null;
}
/** /**
* Encode the String to Java syntax. * Encode the String to Java syntax.
* *
...@@ -165,3 +225,57 @@ class StringExpr implements Expr { ...@@ -165,3 +225,57 @@ class StringExpr implements Expr {
return buff.toString(); return buff.toString();
} }
} }
/**
* A variable.
*/
class VariableExpr implements Expr {
Expr base;
FieldObj field;
String name;
public String toString() {
StringBuilder buff = new StringBuilder();
if (base != null) {
buff.append(base.toString()).append("->");
}
if (field != null) {
buff.append(field.name);
} else {
buff.append(JavaParser.toC(name));
}
return buff.toString();
}
public Type getType() {
if (field == null) {
return null;
}
return field.type;
}
}
/**
* A array access expression.
*/
class ArrayExpr implements Expr {
Expr obj;
ArrayList<Expr> indexes = new ArrayList<Expr>();
public String toString() {
StringBuilder buff = new StringBuilder();
buff.append(obj.toString());
for (Expr e : indexes) {
buff.append('[').append(e.toString()).append(']');
}
return buff.toString();
}
public Type getType() {
return obj.getType();
}
}
...@@ -12,6 +12,7 @@ import java.io.RandomAccessFile; ...@@ -12,6 +12,7 @@ import java.io.RandomAccessFile;
import java.text.ParseException; import java.text.ParseException;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap;
/** /**
* Converts Java to C. * Converts Java to C.
...@@ -29,15 +30,16 @@ public class JavaParser { ...@@ -29,15 +30,16 @@ public class JavaParser {
private static final HashMap<String, ClassObj> BUILT_IN_TYPES = new HashMap<String, ClassObj>(); private static final HashMap<String, ClassObj> BUILT_IN_TYPES = new HashMap<String, ClassObj>();
private static final HashMap<String, String> JAVA_IMPORT_MAP = new HashMap<String, String>(); private static final HashMap<String, String> JAVA_IMPORT_MAP = new HashMap<String, String>();
private final String fileName;
private String source; private String source;
private ParseState current = new ParseState(); private ParseState current = new ParseState();
private String packageName; private String packageName;
private ClassObj classObj; private ClassObj classObj;
private FieldObj thisPointer;
private HashMap<String, String> importMap = new HashMap<String, String>(); private HashMap<String, String> importMap = new HashMap<String, String>();
private HashMap<String, ClassObj> classes = new HashMap<String, ClassObj>(); private HashMap<String, ClassObj> classes = new HashMap<String, ClassObj>();
private LinkedHashMap<String, FieldObj> localFields = new LinkedHashMap<String, FieldObj>();
static { static {
String[] list = new String[] { "abstract", "continue", "for", "new", "switch", "assert", "default", "if", String[] list = new String[] { "abstract", "continue", "for", "new", "switch", "assert", "default", "if",
...@@ -67,10 +69,6 @@ public class JavaParser { ...@@ -67,10 +69,6 @@ public class JavaParser {
} }
} }
JavaParser(String baseDir, String className) {
this.fileName = baseDir + "/" + className.replace('.', '/') + ".java";
}
private static void addBuiltInType(boolean primitive, String type) { private static void addBuiltInType(boolean primitive, String type) {
ClassObj typeObj = new ClassObj(); ClassObj typeObj = new ClassObj();
typeObj.name = type; typeObj.name = type;
...@@ -80,8 +78,13 @@ public class JavaParser { ...@@ -80,8 +78,13 @@ public class JavaParser {
/** /**
* Parse the source code. * Parse the source code.
*
* @param baseDir the base directory
* @param className the fully qualified name of the class to parse
*/ */
void parse() { void parse(String baseDir, String className) {
String fileName = baseDir + "/" + className.replace('.', '/') + ".java";
current = new ParseState();
try { try {
RandomAccessFile file = new RandomAccessFile(fileName, "r"); RandomAccessFile file = new RandomAccessFile(fileName, "r");
byte[] buff = new byte[(int) file.length()]; byte[] buff = new byte[(int) file.length()];
...@@ -91,6 +94,7 @@ public class JavaParser { ...@@ -91,6 +94,7 @@ public class JavaParser {
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
source = replaceUnicode(source);
source = removeRemarks(source); source = removeRemarks(source);
try { try {
readToken(); readToken();
...@@ -100,14 +104,21 @@ public class JavaParser { ...@@ -100,14 +104,21 @@ public class JavaParser {
} }
} }
private String cleanPackageName(String name) {
if (name.startsWith("org.h2.java.lang") || name.startsWith("org.h2.java.io")) {
return name.substring("org.h2.".length());
}
return name;
}
private void parseCompilationUnit() { private void parseCompilationUnit() {
if (readIf("package")) { if (readIf("package")) {
packageName = readQualifiedIdentifier(); packageName = cleanPackageName(readQualifiedIdentifier());
read(";"); read(";");
} }
while (readIf("import")) { while (readIf("import")) {
String importPackageName = readQualifiedIdentifier(); String importPackageName = cleanPackageName(readQualifiedIdentifier());
String importClass = importPackageName.substring(importPackageName.lastIndexOf('.')); String importClass = importPackageName.substring(importPackageName.lastIndexOf('.') + 1);
importMap.put(importClass, importPackageName); importMap.put(importClass, importPackageName);
read(";"); read(";");
} }
...@@ -132,7 +143,22 @@ public class JavaParser { ...@@ -132,7 +143,22 @@ public class JavaParser {
} }
} }
private boolean isTypeOrIdentifier() {
if (BUILT_IN_TYPES.containsKey(current.token)) {
return true;
}
return current.type == TOKEN_IDENTIFIER;
}
private ClassObj getClass(String type) { private ClassObj getClass(String type) {
ClassObj c = getClassIf(type);
if (c == null) {
throw new RuntimeException("Unknown type: " + type);
}
return c;
}
private ClassObj getClassIf(String type) {
ClassObj c = BUILT_IN_TYPES.get(type); ClassObj c = BUILT_IN_TYPES.get(type);
if (c != null) { if (c != null) {
return c; return c;
...@@ -145,7 +171,7 @@ public class JavaParser { ...@@ -145,7 +171,7 @@ public class JavaParser {
if (mappedType == null) { if (mappedType == null) {
mappedType = JAVA_IMPORT_MAP.get(type); mappedType = JAVA_IMPORT_MAP.get(type);
if (mappedType == null) { if (mappedType == null) {
throw new RuntimeException("Unknown type: " + type); return null;
} }
} }
c = classes.get(mappedType); c = classes.get(mappedType);
...@@ -158,31 +184,31 @@ public class JavaParser { ...@@ -158,31 +184,31 @@ public class JavaParser {
return c; return c;
} }
private boolean isClass() {
if (BUILT_IN_TYPES.containsKey(current.token)) {
return true;
}
if (current.type != TOKEN_IDENTIFIER) {
return false;
}
return Character.isUpperCase(current.token.charAt(0));
}
private void parseClassBody() { private void parseClassBody() {
read("{"); read("{");
localFields.clear();
while (true) { while (true) {
if (readIf("}")) { if (readIf("}")) {
break; break;
} }
thisPointer = null;
Statement s = readNativeStatementIf();
if (s != null) {
classObj.nativeInitializers.add(s);
}
thisPointer = null;
boolean isStatic = false; boolean isStatic = false;
boolean isFinal = false; boolean isFinal = false;
boolean isPrivate = false; boolean isPrivate = false;
boolean isPublic = false; boolean isPublic = false;
boolean isNative = false;
while (true) { while (true) {
if (readIf("static")) { if (readIf("static")) {
isStatic = true; isStatic = true;
} else if (readIf("final")) { } else if (readIf("final")) {
isFinal = true; isFinal = true;
} else if (readIf("native")) {
isNative = true;
} else if (readIf("private")) { } else if (readIf("private")) {
isPrivate = true; isPrivate = true;
} else if (readIf("public")) { } else if (readIf("public")) {
...@@ -193,52 +219,81 @@ public class JavaParser { ...@@ -193,52 +219,81 @@ public class JavaParser {
} }
if (readIf("{")) { if (readIf("{")) {
MethodObj method = new MethodObj(); MethodObj method = new MethodObj();
method.name = "init"; method.name = isStatic ? "cl_init_obj" : "init_obj";
method.isStatic = isStatic; method.isStatic = isStatic;
localFields.clear();
if (!isStatic) {
initThisPointer();
}
method.block = readStatement(); method.block = readStatement();
classObj.addMethod(method); classObj.addMethod(method);
} else { } else {
Type type = readType(); String typeName = readTypeOrIdentifier();
String name = readIdentifier(); Type type = readType(typeName);
MethodObj method = new MethodObj();
method.returnType = type;
method.isStatic = isStatic;
method.isFinal = isFinal;
method.isPublic = isPublic;
method.isPrivate = isPrivate;
method.isNative = isNative;
localFields.clear();
if (!isStatic) {
initThisPointer();
}
if (readIf("(")) { if (readIf("(")) {
MethodObj method = new MethodObj(); if (type.type != classObj) {
method.name = name; throw getSyntaxException("Constructor of wrong type: " + type);
method.returnType = type; }
method.isStatic = isStatic; method.name = "init_obj";
method.isFinal = isFinal;
method.isPublic = isPublic;
method.isPrivate = isPrivate;
parseFormalParameters(method); parseFormalParameters(method);
if (!readIf(";")) { if (!readIf(";")) {
method.block = readStatement(); method.block = readStatement();
} }
classObj.addMethod(method); classObj.addMethod(method);
} else { } else {
FieldObj field = new FieldObj(); String name = readIdentifier();
field.type = type; method.name = name;
field.name = name; if (readIf("(")) {
field.isStatic = isStatic; parseFormalParameters(method);
field.isFinal = isFinal; if (!readIf(";")) {
field.isPublic = isPublic; method.block = readStatement();
field.isPrivate = isPrivate; }
if (isStatic) { classObj.addMethod(method);
classObj.addStaticField(field);
} else { } else {
classObj.addInstanceField(field); FieldObj field = new FieldObj();
} field.type = type;
if (readIf("=")) { field.name = name;
field.value = readExpr(); field.isStatic = isStatic;
field.isFinal = isFinal;
field.isPublic = isPublic;
field.isPrivate = isPrivate;
if (isStatic) {
classObj.addStaticField(field);
} else {
classObj.addInstanceField(field);
}
if (readIf("=")) {
field.value = readExpr();
}
read(";");
} }
read(";");
} }
} }
} }
} }
private Type readType() { private void initThisPointer() {
String typeName = readTypeOrIdentifier(); thisPointer = new FieldObj();
thisPointer.isLocal = true;
thisPointer.name = "this";
thisPointer.type = new Type();
thisPointer.type.type = classObj;
}
private Type readType(String name) {
Type type = new Type(); Type type = new Type();
type.type = getClass(typeName); type.type = getClass(name);
while (readIf("[")) { while (readIf("[")) {
read("]"); read("]");
type.arrayLevel++; type.arrayLevel++;
...@@ -255,7 +310,9 @@ public class JavaParser { ...@@ -255,7 +310,9 @@ public class JavaParser {
} }
while (true) { while (true) {
FieldObj field = new FieldObj(); FieldObj field = new FieldObj();
field.type = readType(); field.isLocal = true;
String typeName = readTypeOrIdentifier();
field.type = readType(typeName);
field.name = readIdentifier(); field.name = readIdentifier();
method.parameters.add(field); method.parameters.add(field);
if (readIf(")")) { if (readIf(")")) {
...@@ -271,14 +328,46 @@ public class JavaParser { ...@@ -271,14 +328,46 @@ public class JavaParser {
return read(); return read();
} }
} }
return readIdentifier(); String s = readIdentifier();
while (readIf(".")) {
s += "." + readIdentifier();
}
return s;
}
private Statement readNativeStatementIf() {
if (readIf("//")) {
read();
int start = current.index;
while (source.charAt(current.index) != '\n') {
current.index++;
}
StatementNative stat = new StatementNative();
stat.code = source.substring(start, current.index).trim();
read();
return stat;
} else if (readIf("/*")) {
read();
int start = current.index;
while (source.charAt(current.index) != '*' || source.charAt(current.index + 1) != '/') {
current.index++;
}
StatementNative stat = new StatementNative();
stat.code = source.substring(start, current.index).trim();
read();
return stat;
}
return null;
} }
private Statement readStatement() { private Statement readStatement() {
Statement s = readNativeStatementIf();
if (s != null) {
return s;
}
if (readIf(";")) { if (readIf(";")) {
return new EmptyStatement(); return new EmptyStatement();
} } else if (readIf("{")) {
if (readIf("{")) {
StatementBlock stat = new StatementBlock(); StatementBlock stat = new StatementBlock();
while (true) { while (true) {
stat.instructions.add(readStatement()); stat.instructions.add(readStatement());
...@@ -346,12 +435,24 @@ public class JavaParser { ...@@ -346,12 +435,24 @@ public class JavaParser {
} else if (readIf("for")) { } else if (readIf("for")) {
ForStatement forStat = new ForStatement(); ForStatement forStat = new ForStatement();
read("("); read("(");
forStat.init = readStatement(); ParseState back = copyParseState();
forStat.condition = readExpr(); try {
read(";"); String typeName = readTypeOrIdentifier();
do { Type type = readType(typeName);
forStat.updates.add(readExpr()); String name = readIdentifier();
} while (readIf(",")); read(":");
forStat.iterableType = type;
forStat.iterableVariable = name;
forStat.iterable = readExpr();
} catch (Exception e) {
current = back;
forStat.init = readStatement();
forStat.condition = readExpr();
read(";");
do {
forStat.updates.add(readExpr());
} while (readIf(","));
}
read(")"); read(")");
forStat.block = readStatement(); forStat.block = readStatement();
return forStat; return forStat;
...@@ -372,22 +473,25 @@ public class JavaParser { ...@@ -372,22 +473,25 @@ public class JavaParser {
} }
return returnStat; return returnStat;
} else { } else {
if (isClass()) { if (isTypeOrIdentifier()) {
ParseState start = copyParseState(); ParseState start = copyParseState();
Type type = readType(); String name = readTypeOrIdentifier();
if (readIf(".")) { ClassObj c = getClassIf(name);
current = start; if (c != null) {
// ExprStatement
} else {
VarDecStatement dec = new VarDecStatement(); VarDecStatement dec = new VarDecStatement();
dec.type = type; dec.type = readType(name);
while (true) { while (true) {
String name = readIdentifier(); String varName = readIdentifier();
Expr value = null; Expr value = null;
if (readIf("=")) { if (readIf("=")) {
value = readExpr(); value = readExpr();
} }
dec.variables.add(name); FieldObj f = new FieldObj();
f.isLocal = true;
f.type = dec.type;
f.name = varName;
localFields.put(varName, f);
dec.variables.add(varName);
dec.values.add(value); dec.values.add(value);
if (readIf(";")) { if (readIf(";")) {
break; break;
...@@ -396,6 +500,8 @@ public class JavaParser { ...@@ -396,6 +500,8 @@ public class JavaParser {
} }
return dec; return dec;
} }
current = start;
// ExprStatement
} }
ExprStatement stat = new ExprStatement(); ExprStatement stat = new ExprStatement();
stat.expr = readExpr(); stat.expr = readExpr();
...@@ -442,15 +548,19 @@ public class JavaParser { ...@@ -442,15 +548,19 @@ public class JavaParser {
private Expr readExpr2() { private Expr readExpr2() {
Expr expr = readExpr3(); Expr expr = readExpr3();
String infixOp = current.token; while (true) {
if (readIf("||") || readIf("&&") || readIf("|") || readIf("^") || readIf("&") || readIf("==") || readIf("!=") String infixOp = current.token;
|| readIf("<") || readIf(">") || readIf("<=") || readIf(">=") || readIf("<<") || readIf(">>") if (readIf("||") || readIf("&&") || readIf("|") || readIf("^") || readIf("&") || readIf("==") || readIf("!=")
|| readIf(">>>") || readIf("+") || readIf("-") || readIf("*") || readIf("/") || readIf("%")) { || readIf("<") || readIf(">") || readIf("<=") || readIf(">=") || readIf("<<") || readIf(">>")
OpExpr opExpr = new OpExpr(); || readIf(">>>") || readIf("+") || readIf("-") || readIf("*") || readIf("/") || readIf("%")) {
opExpr.left = expr; OpExpr opExpr = new OpExpr();
opExpr.op = infixOp; opExpr.left = expr;
opExpr.right = readExpr3(); opExpr.op = infixOp;
expr = opExpr; opExpr.right = readExpr3();
expr = opExpr;
} else {
break;
}
} }
return expr; return expr;
} }
...@@ -480,13 +590,6 @@ public class JavaParser { ...@@ -480,13 +590,6 @@ public class JavaParser {
} }
private Expr readExpr4() { private Expr readExpr4() {
if (readIf("new")) {
NewExpr expr = new NewExpr();
expr.className = readQualifiedIdentifier();
read("(");
read(")");
return expr;
}
if (readIf("false")) { if (readIf("false")) {
LiteralExpr expr = new LiteralExpr(); LiteralExpr expr = new LiteralExpr();
expr.literal = "false"; expr.literal = "false";
...@@ -508,16 +611,96 @@ public class JavaParser { ...@@ -508,16 +611,96 @@ public class JavaParser {
readToken(); readToken();
return expr; return expr;
} }
Expr expr;
expr = readExpr5();
Type t = expr.getType();
while (true) {
if (readIf(".")) {
String n = readIdentifier();
if (readIf("(")) {
CallExpr e2 = new CallExpr();
e2.expr = expr;
e2.name = n;
if (!readIf(")")) {
while (true) {
e2.args.add(readExpr());
if (!readIf(",")) {
read(")");
break;
}
}
}
expr = e2;
} else {
VariableExpr e2 = new VariableExpr();
e2.base = expr;
expr = e2;
if (n.equals("length") && t.arrayLevel > 0) {
e2.field = new FieldObj();
e2.field.name = "length";
} else {
if (t == null || t.type == null) {
e2.name = n;
} else {
FieldObj f = t.type.instanceFields.get(n);
if (f == null) {
throw getSyntaxException("Unknown field: " + expr + "." + n);
}
e2.field = f;
}
}
}
} else if (readIf("[")) {
if (t.arrayLevel == 0) {
throw getSyntaxException("Not an array: " + expr);
}
Expr arrayIndex = readExpr();
read("]");
// TODO arrayGet or arraySet
return arrayIndex;
} else {
break;
}
}
return expr;
}
private Expr readExpr5() {
if (readIf("new")) {
NewExpr expr = new NewExpr();
String typeName = readTypeOrIdentifier();
expr.type = getClass(typeName);
if (readIf("(")) {
read(")");
} else {
while (readIf("[")) {
expr.arrayInitExpr.add(readExpr());
read("]");
}
}
return expr;
}
if (current.type == TOKEN_LITERAL_STRING) { if (current.type == TOKEN_LITERAL_STRING) {
StringExpr expr = new StringExpr(); StringExpr expr = new StringExpr();
expr.text = current.token.substring(1); expr.text = current.token.substring(1);
readToken(); readToken();
return expr; return expr;
} }
String name = readQualifiedIdentifier(); if (readIf("this")) {
VariableExpr expr = new VariableExpr();
expr.field = thisPointer;
if (thisPointer == null) {
throw getSyntaxException("this usage in static context");
}
return expr;
}
String name = readIdentifier();
if (readIf("(")) { if (readIf("(")) {
CallExpr expr = new CallExpr(); CallExpr expr = new CallExpr();
expr.object = name; expr.name = name;
VariableExpr ve = new VariableExpr();
ve.field = thisPointer;
expr.expr = ve;
if (!readIf(")")) { if (!readIf(")")) {
while (true) { while (true) {
expr.args.add(readExpr()); expr.args.add(readExpr());
...@@ -530,6 +713,28 @@ public class JavaParser { ...@@ -530,6 +713,28 @@ public class JavaParser {
return expr; return expr;
} }
VariableExpr expr = new VariableExpr(); VariableExpr expr = new VariableExpr();
FieldObj f = localFields.get(name);
if (f == null) {
f = classObj.staticFields.get(name);
if (f == null) {
f = classObj.instanceFields.get(name);
if (f == null) {
String imp = importMap.get(name);
if (imp != null) {
name = imp;
}
}
}
}
expr.field = f;
if (f != null && (!f.isLocal && !f.isStatic)) {
VariableExpr ve = new VariableExpr();
ve.field = thisPointer;
expr.base = ve;
if (thisPointer == null) {
throw getSyntaxException("this usage in static context");
}
}
expr.name = name; expr.name = name;
return expr; return expr;
} }
...@@ -542,6 +747,21 @@ public class JavaParser { ...@@ -542,6 +747,21 @@ public class JavaParser {
private String readQualifiedIdentifier() { private String readQualifiedIdentifier() {
String id = readIdentifier(); String id = readIdentifier();
if (localFields.containsKey(id)) {
return id;
}
if (classObj != null) {
if (classObj.staticFields.containsKey(id)) {
return id;
}
if (classObj.instanceFields.containsKey(id)) {
return id;
}
}
String fullName = importMap.get(id);
if (fullName != null) {
return fullName;
}
while (readIf(".")) { while (readIf(".")) {
id += "." + readIdentifier(); id += "." + readIdentifier();
} }
...@@ -582,6 +802,9 @@ public class JavaParser { ...@@ -582,6 +802,9 @@ public class JavaParser {
* @return the cleaned text * @return the cleaned text
*/ */
static String replaceUnicode(String s) { static String replaceUnicode(String s) {
if (s.indexOf("\\u") < 0) {
return s;
}
StringBuilder buff = new StringBuilder(s.length()); StringBuilder buff = new StringBuilder(s.length());
for (int i = 0; i < s.length(); i++) { for (int i = 0; i < s.length(); i++) {
if (s.substring(i).startsWith("\\\\")) { if (s.substring(i).startsWith("\\\\")) {
...@@ -609,10 +832,6 @@ public class JavaParser { ...@@ -609,10 +832,6 @@ public class JavaParser {
* @return the cleaned source code * @return the cleaned source code
*/ */
static String removeRemarks(String s) { static String removeRemarks(String s) {
int idx = s.indexOf("\\u");
if (idx > 0) {
s = replaceUnicode(s);
}
char[] chars = s.toCharArray(); char[] chars = s.toCharArray();
for (int i = 0; i >= 0 && i < s.length(); i++) { for (int i = 0; i >= 0 && i < s.length(); i++) {
if (s.charAt(i) == '\'') { if (s.charAt(i) == '\'') {
...@@ -639,7 +858,7 @@ public class JavaParser { ...@@ -639,7 +858,7 @@ public class JavaParser {
continue; continue;
} }
String sub = s.substring(i); String sub = s.substring(i);
if (sub.startsWith("/*")) { if (sub.startsWith("/*") && !sub.startsWith("/* c:")) {
int j = i; int j = i;
i = s.indexOf("*/", i + 2) + 2; i = s.indexOf("*/", i + 2) + 2;
for (; j < i; j++) { for (; j < i; j++) {
...@@ -647,7 +866,7 @@ public class JavaParser { ...@@ -647,7 +866,7 @@ public class JavaParser {
chars[j] = ' '; chars[j] = ' ';
} }
} }
} else if (sub.startsWith("//")) { } else if (sub.startsWith("//") && !sub.startsWith("// c:")) {
int j = i; int j = i;
i = s.indexOf('\n', i); i = s.indexOf('\n', i);
while (j < i) { while (j < i) {
...@@ -769,8 +988,12 @@ public class JavaParser { ...@@ -769,8 +988,12 @@ public class JavaParser {
current.index++; current.index++;
} }
break; break;
case '*':
case '/': case '/':
if (source.charAt(current.index) == '*' || source.charAt(current.index) == '/') {
current.index++;
}
break;
case '*':
case '~': case '~':
case '!': case '!':
case '=': case '=':
...@@ -915,11 +1138,11 @@ public class JavaParser { ...@@ -915,11 +1138,11 @@ public class JavaParser {
} }
/** /**
* Write the C representation. * Write the C header.
* *
* @param out the output writer * @param out the output writer
*/ */
void writeC(PrintWriter out) { void writeHeader(PrintWriter out) {
for (ClassObj c : classes.values()) { for (ClassObj c : classes.values()) {
out.println("/* " + c.name + ".h */"); out.println("/* " + c.name + ".h */");
for (FieldObj f : c.staticFields.values()) { for (FieldObj f : c.staticFields.values()) {
...@@ -945,6 +1168,10 @@ public class JavaParser { ...@@ -945,6 +1168,10 @@ public class JavaParser {
for (MethodObj m : c.methods.values()) { for (MethodObj m : c.methods.values()) {
out.print(m.returnType + " " + toC(c.name) + "_" + m.name + "("); out.print(m.returnType + " " + toC(c.name) + "_" + m.name + "(");
int i = 0; int i = 0;
if (!m.isStatic) {
out.print(toC(c.name) + "* this");
i++;
}
for (FieldObj p : m.parameters) { for (FieldObj p : m.parameters) {
if (i > 0) { if (i > 0) {
out.print(", "); out.print(", ");
...@@ -954,13 +1181,28 @@ public class JavaParser { ...@@ -954,13 +1181,28 @@ public class JavaParser {
} }
out.println(");"); out.println(");");
} }
out.println();
} }
out.println(); }
/**
* Write the C source code.
*
* @param out the output writer
*/
void writeSource(PrintWriter out) {
for (ClassObj c : classes.values()) { for (ClassObj c : classes.values()) {
out.println("/* " + c.name + ".c */"); out.println("/* " + c.name + ".c */");
for (Statement s : c.nativeInitializers) {
out.println(s);
}
for (MethodObj m : c.methods.values()) { for (MethodObj m : c.methods.values()) {
out.print(m.returnType + " " + toC(c.name) + "_" + m.name + "("); out.print(m.returnType + " " + toC(c.name) + "_" + m.name + "(");
int i = 0; int i = 0;
if (!m.isStatic) {
out.print(toC(c.name) + "* this");
i++;
}
for (FieldObj p : m.parameters) { for (FieldObj p : m.parameters) {
if (i > 0) { if (i > 0) {
out.print(", "); out.print(", ");
...@@ -969,8 +1211,11 @@ public class JavaParser { ...@@ -969,8 +1211,11 @@ public class JavaParser {
i++; i++;
} }
out.println(") {"); out.println(") {");
out.print(m.block.toString()); if (m.block != null) {
out.print(m.block.toString());
}
out.println("}"); out.println("}");
out.println();
} }
} }
} }
...@@ -1018,8 +1263,24 @@ public class JavaParser { ...@@ -1018,8 +1263,24 @@ public class JavaParser {
* The parse state. * The parse state.
*/ */
class ParseState { class ParseState {
/**
* The parse index.
*/
int index; int index;
/**
* The token type
*/
int type; int type;
/**
* The token text.
*/
String token; String token;
/**
* The line number.
*/
int line; int line;
} }
\ No newline at end of file
...@@ -136,15 +136,25 @@ class ForStatement implements Statement { ...@@ -136,15 +136,25 @@ class ForStatement implements Statement {
Expr update; Expr update;
Statement block; Statement block;
ArrayList<Expr> updates = new ArrayList<Expr>(); ArrayList<Expr> updates = new ArrayList<Expr>();
Type iterableType;
String iterableVariable;
Expr iterable;
public String toString() { public String toString() {
StringBuffer buff = new StringBuffer(); StringBuffer buff = new StringBuffer();
buff.append("for (").append(init.toString()); buff.append("for (");
buff.append(" ").append(condition.toString()).append("; "); if (iterableType != null) {
for (int i = 0; i < updates.size(); i++) { buff.append(iterableType).append(' ');
if (i > 0) { buff.append(iterableVariable).append(": ");
buff.append(", "); buff.append(iterable);
} else {
buff.append(init.toString());
buff.append(" ").append(condition.toString()).append("; ");
for (int i = 0; i < updates.size(); i++) {
if (i > 0) {
buff.append(", ");
}
buff.append(updates.get(i));
} }
buff.append(updates.get(i));
} }
buff.append(") {\n"); buff.append(") {\n");
buff.append(block.toString()).append("}"); buff.append(block.toString()).append("}");
...@@ -192,11 +202,12 @@ class VarDecStatement implements Statement { ...@@ -192,11 +202,12 @@ class VarDecStatement implements Statement {
} }
/** /**
* A variable. * A native statement.
*/ */
class VariableExpr implements Expr { class StatementNative implements Statement {
public String name; String code;
public String toString() { public String toString() {
return name; return code;
} }
} }
...@@ -27,17 +27,18 @@ public class Test extends TestBase { ...@@ -27,17 +27,18 @@ public class Test extends TestBase {
public void test() throws IOException { public void test() throws IOException {
// not supported yet: // not supported yet:
// annotations
// HexadecimalFloatingPointLiteral // HexadecimalFloatingPointLiteral
// int x()[] { return null; }
// annotations
// import static // import static
// import * // import *
// only public or default level classes
// initializer blocks // initializer blocks
// access to static fields with instance variable
// method call with "this": this.toString()
// final variables (within blocks, parameter list) // final variables (within blocks, parameter list)
// Identifier : (labels) // Identifier : (labels)
// ClassOrInterfaceDeclaration within blocks (or any other nested classes) // ClassOrInterfaceDeclaration within blocks (or any other nested classes)
// assert // assert
// array declaration at weird places: int x() [] { return null; }
assertEquals("\\\\" + "u0000", JavaParser.replaceUnicode("\\\\" + "u0000")); assertEquals("\\\\" + "u0000", JavaParser.replaceUnicode("\\\\" + "u0000"));
assertEquals("\u0000", JavaParser.replaceUnicode("\\" + "u0000")); assertEquals("\u0000", JavaParser.replaceUnicode("\\" + "u0000"));
...@@ -54,14 +55,19 @@ public class Test extends TestBase { ...@@ -54,14 +55,19 @@ public class Test extends TestBase {
assertEquals(".3d", JavaParser.readNumber(".3dx")); assertEquals(".3d", JavaParser.readNumber(".3dx"));
assertEquals("6.022137e+23f", JavaParser.readNumber("6.022137e+23f+1")); assertEquals("6.022137e+23f", JavaParser.readNumber("6.022137e+23f+1"));
JavaParser parser = new JavaParser("src/tools", "org.h2.java.TestApp"); JavaParser parser = new JavaParser();
parser.parse(); parser.parse("src/tools/org/h2", "java.lang.String");
parser.parse("src/tools/org/h2", "java.io.PrintStream");
parser.parse("src/tools/org/h2", "java.lang.System");
parser.parse("src/tools", "org.h2.java.TestApp");
PrintWriter w = new PrintWriter(System.out); PrintWriter w = new PrintWriter(System.out);
parser.writeC(w); parser.writeHeader(w);
parser.writeSource(w);
w.flush(); w.flush();
w = new PrintWriter(new FileWriter("bin/test.c")); w = new PrintWriter(new FileWriter("bin/test.c"));
parser.writeC(w); parser.writeHeader(w);
parser.writeSource(w);
w.close(); w.close();
} }
......
...@@ -9,11 +9,18 @@ package org.h2.java; ...@@ -9,11 +9,18 @@ package org.h2.java;
/** /**
* A test application. * A test application.
*/ */
/// #include <stdio.h>
public class TestApp { public class TestApp {
private static final int FINAL_VALUE = 10; // private static final int FINAL_VALUE = 10;
/**
* Run this application.
*
* @param args the command line arguments
*/
public static void main(String... args) { public static void main(String... args) {
// c:printf("Hello\n");
System.out.println("Hello World"); System.out.println("Hello World");
} }
...@@ -27,7 +34,7 @@ public class TestApp { ...@@ -27,7 +34,7 @@ public class TestApp {
public int getName(int name, int x) { public int getName(int name, int x) {
System.out.println("Hello"); System.out.println("Hello");
int m = x; int m = x;
m = FINAL_VALUE; // m = FINAL_VALUE;
switch (x) { switch (x) {
case 1: case 1:
m = 3; m = 3;
......
package org.h2.java.io;
import org.h2.java.lang.System;
/**
* A print stream.
*/
public class PrintStream {
/**
* Print the given string.
*
* @param s the string
*/
public void println(String s) {
System.arraycopy(null, 0, null, 0, 1);
// c: printf("%s\n");
}
}
package org.h2.java.lang;
/**
* A java.lang.Object implementation.
*/
public class Object {
public int hashCode() {
return 0;
}
public boolean equals(Object other) {
return this == other;
}
}
package org.h2.java.lang;
/**
* A java.lang.String implementation.
*/
public class String {
private char[] chars;
private int hashCode;
public String(char[] chars) {
this.chars = new char[chars.length];
System.arraycopy(chars, 0, this.chars, 0, chars.length);
}
public int hashCode() {
if (hashCode == 0) {
if (chars.length == 0) {
return 0;
}
int h = 0;
for (char c : chars) {
h = h * 31 + c;
}
hashCode = h;
return h;
}
return hashCode;
}
/**
* Get the length of the string.
*
* @return the length
*/
public int length() {
return chars.length;
}
}
package org.h2.java.lang;
import java.io.PrintStream;
/**
* A simple java.lang.System implementation.
*/
public class System {
// c: #include <stdio>
/**
* The stdout stream.
*/
public static PrintStream out;
/**
* Copy data from the source to the target.
* Source and target may overlap.
*
* @param src the source array
* @param srcPos the first element in the source array
* @param dest the destination
* @param destPos the first element in the destination
* @param length the number of element to copy
*/
public static void arraycopy(java.lang.Object src, int srcPos, java.lang.Object dest, int destPos, int length) {
// c: memmove(src + srcPos, dest + destPos, length);
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论