diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/AttributeInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..7db7a49c32 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.attr; + +public abstract class AttributeInfo { + public static final String CODE = "Code"; + public static final String CONST_VALUE = "ConstantValue"; + public static final String EXCEPTIONS = "Exceptions"; + public static final String LINE_NUM_TABLE = "LineNumberTable"; + public static final String LOCAL_VAR_TABLE = "LocalVariableTable"; + public static final String STACK_MAP_TABLE = "StackMapTable"; + int attrNameIndex; + int attrLen ; + public AttributeInfo(int attrNameIndex, int attrLen) { + + this.attrNameIndex = attrNameIndex; + this.attrLen = attrLen; + } + + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/CodeAttr.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..ee04b856d7 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,89 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.attr; + + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.coderising.jvm.loader.ByteCodeIterator; + +public class CodeAttr extends AttributeInfo { + private int maxStack ; + private int maxLocals ; + private int codeLen ; + private String code; + public String getCode() { + return code; + } + + //private ByteCodeCommand[] cmds ; + //public ByteCodeCommand[] getCmds() { + // return cmds; + //} + private LineNumberTable lineNumTable; + private LocalVariableTable localVarTable; + private StackMapTable stackMapTable; + + public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen,String code /*ByteCodeCommand[] cmds*/) { + super(attrNameIndex, attrLen); + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.codeLen = codeLen; + this.code = code; + //this.cmds = cmds; + } + + public void setLineNumberTable(LineNumberTable t) { + this.lineNumTable = t; + } + + public void setLocalVariableTable(LocalVariableTable t) { + this.localVarTable = t; + } + + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ + + //回退2个字节 + iter.back(ByteCodeIterator.U2); + int attrNameIndex = iter.readTwoBytesToInt(); + int attrLen = iter.readFourBytesToInt(); + int maxStack = iter.readTwoBytesToInt(); + int maxLocal = iter.readTwoBytesToInt(); + int codeLen = iter.readFourBytesToInt(); + String code = iter.readBytesToString(codeLen); + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocal, codeLen, code); + + //异常表长度 + int exceptionTableLen = iter.readTwoBytesToInt(); + if (exceptionTableLen > 0) { + throw new RuntimeException("not impl yet"); + } + + //子属性个数 + int attrCount = iter.readTwoBytesToInt(); + for (int i = 0; i < attrCount; i++) { + attrNameIndex = iter.readTwoBytesToInt(); + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + if ("LineNumberTable".equals(attrName)) { + LineNumberTable lineNumberTable = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(lineNumberTable); + } else if ("LocalVariableTable".equals(attrName)) { + LocalVariableTable localVariableTable = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(localVariableTable); + } else if ("StackMapTable".equals(attrName)) { + StackMapTable stackMapTable = StackMapTable.parse(iter); + codeAttr.setStackMapTable(stackMapTable); + } else { + throw new RuntimeException("not impl yet"); + } + } + + return codeAttr; + } + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + } + + + + + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LineNumberTable.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..93e7d9b7a8 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LineNumberTable.java @@ -0,0 +1,52 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.attr; + +import com.coding.mini_jvm.src.com.coderising.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + + +public class LineNumberTable extends AttributeInfo { + List items = new ArrayList(); + + private static class LineNumberItem{ + int startPC; + int lineNum; + public int getStartPC() { + return startPC; + } + public void setStartPC(int startPC) { + this.startPC = startPC; + } + public int getLineNum() { + return lineNum; + } + public void setLineNum(int lineNum) { + this.lineNum = lineNum; + } + } + public void addLineNumberItem(LineNumberItem item){ + this.items.add(item); + } + public LineNumberTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static LineNumberTable parse(ByteCodeIterator iter){ + iter.back(ByteCodeIterator.U2); + int attrNameIndex = iter.readTwoBytesToInt(); + int attrLen = iter.readFourBytesToInt(); + LineNumberTable lineNumberTable = new LineNumberTable(attrNameIndex, attrLen); + int itemCount = iter.readTwoBytesToInt(); + for (int i = 0; i < itemCount; i++) { + LineNumberItem lineNumberItem = new LineNumberItem(); + lineNumberItem.setStartPC(iter.readTwoBytesToInt()); + lineNumberItem.setLineNum(iter.readTwoBytesToInt()); + lineNumberTable.addLineNumberItem(lineNumberItem); + } + return lineNumberTable; + } + + + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableItem.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..9e9e1d9e21 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.attr; + +public class LocalVariableItem { + private int startPC; + private int length; + private int nameIndex; + private int descIndex; + private int index; + public int getStartPC() { + return startPC; + } + public void setStartPC(int startPC) { + this.startPC = startPC; + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getNameIndex() { + return nameIndex; + } + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } + public int getDescIndex() { + return descIndex; + } + public void setDescIndex(int descIndex) { + this.descIndex = descIndex; + } + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableTable.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..2900349fa5 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,39 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.attr; + + +import com.coding.mini_jvm.src.com.coderising.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +public class LocalVariableTable extends AttributeInfo{ + + List items = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static LocalVariableTable parse(ByteCodeIterator iter){ + iter.back(ByteCodeIterator.U2); + int attrNameIdex = iter.readTwoBytesToInt(); + int attrLen = iter.readFourBytesToInt(); + LocalVariableTable localVariableTable = new LocalVariableTable(attrNameIdex, attrLen); + int varCount = iter.readTwoBytesToInt(); + for (int i = 0; i < varCount; i++) { + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(iter.readTwoBytesToInt()); + item.setLength(iter.readTwoBytesToInt()); + item.setNameIndex(iter.readTwoBytesToInt()); + item.setDescIndex(iter.readTwoBytesToInt()); + item.setIndex(iter.readTwoBytesToInt()); + localVariableTable.addLocalVariableItem(item); + } + return localVariableTable; + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/StackMapTable.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..a6e55353f1 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.attr; + + +import com.coding.mini_jvm.src.com.coderising.jvm.loader.ByteCodeIterator; + +public class StackMapTable extends AttributeInfo{ + + private String originalCode; + + public StackMapTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static StackMapTable parse(ByteCodeIterator iter){ + iter.back(ByteCodeIterator.U2); + int index = iter.readTwoBytesToInt(); + int len = iter.readFourBytesToInt(); + StackMapTable t = new StackMapTable(index,len); + + //后面的StackMapTable太过复杂, 不再处理, 只把原始的代码读进来保存 + String code = iter.readBytesToString(len); + t.setOriginalCode(code); + return t; + } + + private void setOriginalCode(String code) { + this.originalCode = code; + + } +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java index 0d2525e416..047c65195f 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java @@ -3,28 +3,50 @@ import com.coding.mini_jvm.src.com.coderising.jvm.constant.ClassInfo; import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.coderising.jvm.field.Field; +import com.coding.mini_jvm.src.com.coderising.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; public class ClassFile { - + private int minorVersion; private int majorVersion; - + private AccessFlag accessFlag; private ClassIndex clzIndex; private ConstantPool pool; - - + private List fields = new ArrayList(); + private List methods = new ArrayList(); + public ClassIndex getClzIndex() { return clzIndex; } + public AccessFlag getAccessFlag() { return accessFlag; } + public void setAccessFlag(AccessFlag accessFlag) { this.accessFlag = accessFlag; } - - + + public void addField(Field f) { + this.fields.add(f); + } + + public List getFields() { + return this.fields; + } + + public void addMethod(Method m) { + this.methods.add(m); + } + + public List getMethods() { + return methods; + } public ConstantPool getConstantPool() { return pool; @@ -49,19 +71,12 @@ public void setClassIndex(ClassIndex clzIndex) { this.clzIndex = clzIndex; } - - - public void print(){ - if(this.accessFlag.isPublicClass()){ System.out.println("Access flag : public "); } System.out.println("Class Name:"+ getClassName()); - System.out.println("Super Class Name:"+ getSuperClassName()); - - } private String getClassName(){ diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/field/Field.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..18bcdb2851 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,38 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.field; + + +import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.coderising.jvm.loader.ByteCodeIterator; + +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + + private ConstantPool pool; + + public Field(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool pool) { + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.pool = pool; + } + + + public static Field parse(ConstantPool pool,ByteCodeIterator iter){ + int accessFlag = iter.readTwoBytesToInt(); + int nameIndex = iter.readTwoBytesToInt(); + int descIndex = iter.readTwoBytesToInt(); + int attributesCount = iter.readTwoBytesToInt(); + if (attributesCount > 0) + throw new RuntimeException("attributeCount of field not impl"); + return new Field(accessFlag, nameIndex, descIndex, pool); + } + + + @Override + public String toString() { + return pool.getUTF8String(nameIndex)+":"+pool.getUTF8String(descriptorIndex); + } +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java index 27d0c63af0..1fe59b5bdb 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -3,10 +3,10 @@ import com.coding.mini_jvm.src.com.coderising.jvm.util.Util; public class ByteCodeIterator { - private static final int U1 = 1; - private static final int U2 = 2; - private static final int U4 = 4; - private static final int U8 = 8; + public static final int U1 = 1; + public static final int U2 = 2; + public static final int U4 = 4; + public static final int U8 = 8; private byte[] bytes; private int cursor; @@ -33,6 +33,12 @@ public int readTwoBytesToInt() { return ret; } + public int readFourBytesToInt() { + int ret = Util.bytes2Int(bytes, cursor, U4); + cursor += U4; + return ret; + } + public int readByteToInt() { int ret = Util.bytes2Int(bytes, cursor, U1); cursor += U1; @@ -49,4 +55,12 @@ public int skip(int len) { cursor += len; return cursor; } + + public int back(int len) { + if (cursor + len < 0 || cursor + len > bytes.length - 1) { + throw new IndexOutOfBoundsException(); + } + cursor -= len; + return cursor; + } } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileParser.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileParser.java index 542968c809..afe40a2156 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileParser.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileParser.java @@ -4,6 +4,8 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassIndex; import com.coding.mini_jvm.src.com.coderising.jvm.constant.*; +import com.coding.mini_jvm.src.com.coderising.jvm.field.Field; +import com.coding.mini_jvm.src.com.coderising.jvm.method.Method; public class ClassFileParser { @@ -18,11 +20,22 @@ public ClassFile parse(byte[] codes) { //主版本号 classFile.setMajorVersion(iterator.readTwoBytesToInt()); //解析常量池 - classFile.setConstPool(parseConstantPool(iterator)); + ConstantPool constantPool = parseConstantPool(iterator); + classFile.setConstPool(constantPool); //访问限制符 classFile.setAccessFlag(parseAccessFlag(iterator)); //当前类/父类 classFile.setClassIndex(parseClassIndex(iterator)); + + //接口数量暂时不实现 + int intefaceCount = iterator.readTwoBytesToInt(); + if (intefaceCount > 0) { + throw new RuntimeException(); + } + //解析字段 + parseFields(classFile,iterator, constantPool); + //解析方法 + parseMethod(classFile, iterator, constantPool); return classFile; } @@ -99,5 +112,19 @@ private ConstantPool parseConstantPool(ByteCodeIterator iterator) { return constantPool; } - + + private void parseFields(ClassFile classFile, ByteCodeIterator iterator, ConstantPool constantPool) { + int fieldCount = iterator.readTwoBytesToInt(); + for (int i = 0; i < fieldCount; i++) + classFile.addField(Field.parse(constantPool, iterator)); + } + + + private void parseMethod(ClassFile clzFile, ByteCodeIterator iter, ConstantPool pool) { + int methodCount = iter.readTwoBytesToInt(); + for (int i = 0; i < methodCount; i++) { + clzFile.addMethod(Method.parse(clzFile, iter)); + } + } + } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java new file mode 100644 index 0000000000..fd5734e6b6 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java @@ -0,0 +1,66 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.method; + + +import com.coding.mini_jvm.src.com.coderising.jvm.attr.CodeAttr; +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.coderising.jvm.loader.ByteCodeIterator; + +public class Method { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private CodeAttr codeAttr; + + private ClassFile clzFile; + + public ClassFile getClzFile() { + return clzFile; + } + + public int getNameIndex() { + return nameIndex; + } + + public int getDescriptorIndex() { + return descriptorIndex; + } + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + public void setCodeAttr(CodeAttr code) { + this.codeAttr = code; + } + + public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorIndex) { + this.clzFile = clzFile; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + + public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ + int accessFlag = iter.readTwoBytesToInt(); + int nameIndex = iter.readTwoBytesToInt(); + int descIndex = iter.readTwoBytesToInt(); + Method method = new Method(clzFile, accessFlag, nameIndex, descIndex); + System.out.println(clzFile.getConstantPool().getUTF8String(descIndex)); + int attrCount = iter.readTwoBytesToInt(); + if (attrCount > 1) + throw new RuntimeException("other attrbute not impl yet"); + for (int i = 0; i < attrCount; i++) { + int attrNameIndex = iter.readTwoBytesToInt(); + if ("Code".equals(clzFile.getConstantPool().getUTF8String(attrNameIndex))) { + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + method.setCodeAttr(codeAttr); + } else + throw new RuntimeException("not impl yet"); + } + return method; + } + +} diff --git a/group24/494800949/src/main/java/com/coding/weak1/Stack.java b/group24/494800949/src/main/java/com/coding/weak1/Stack.java index ffa00f99e7..0eecd9d684 100644 --- a/group24/494800949/src/main/java/com/coding/weak1/Stack.java +++ b/group24/494800949/src/main/java/com/coding/weak1/Stack.java @@ -18,6 +18,8 @@ public Object pop(){ } public Object peek(){ + if (size() == 0) + return null; return elementData.get(elementData.size()-1); } public boolean isEmpty(){ diff --git a/group24/494800949/src/main/java/com/coding/week6/expr/InfixExpr.java b/group24/494800949/src/main/java/com/coding/week6/expr/InfixExpr.java new file mode 100644 index 0000000000..34c1b15123 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week6/expr/InfixExpr.java @@ -0,0 +1,127 @@ +package com.coding.week6.expr; + +import com.coding.weak1.Stack; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class InfixExpr { + String expr = null; + private Stack numberStack; + private Stack operatorStack; + private List tokens; + public InfixExpr(String expr) { + this.expr = expr; + this.numberStack = new Stack(); + this.operatorStack = new Stack(); + tokens = new ArrayList<>(); + } + + + public float evaluate() { + fillStack(); + while (!operatorStack.isEmpty()) { + char symbol = (char) operatorStack.pop(); + float operTop1 = (float) numberStack.pop(); + float operTop2 = (float) numberStack.pop(); + numberStack.push(caculate(symbol, operTop2, operTop1)); + } + return (float)numberStack.pop(); + } + + public void parseTokens() { + char[] chars = expr.toCharArray(); + for (int i = 0; i < chars.length; i++) { + char c = chars[i]; + if (Token.isOperator(c)) { + Token token = new Token(c+""); + tokens.add(token); + } else { + String t = ""; + while (Token.isDigit(c)){ + t += c; + i++; + if (i == chars.length) + break; + c = chars[i]; + } + Token token = new Token(t); + tokens.add(token); + i--; + } + } + } + + + public void fillStack() { + parseTokens(); + Iterator iterator = tokens.iterator(); + while (iterator.hasNext()) { + Token token = iterator.next(); + if (token.isNumber()) { + numberStack.push((float)token.parseInt()); + continue; + } + if (token.isOperator()) { + char operator = token.parseOperator(); + if (operatorStack.isEmpty()) { + operatorStack.push(operator); + }else { + char topSymbol = (char)operatorStack.peek(); + if (compare(operator, topSymbol) > 0) { + operatorStack.push(operator); + } else { + float operTop1 = (float) numberStack.pop(); + float operTop2 = (float) numberStack.pop(); + numberStack.push(caculate(topSymbol, operTop2, operTop1)); + operatorStack.pop(); + operatorStack.push(operator); + } + } + } + + } + } + + + private float caculate(char symbol, float oper1, float oper2) { + if ('*' == symbol) + return oper1 * oper2; + else if ('/' == symbol) + return oper1 / oper2; + else if ('+' == symbol) + return oper1 + oper2; + else if ('-' == symbol) + return oper1 - oper2; + else + throw new RuntimeException("this operation has not implement"); + } + + public int compare(char opertor1, char opertor2) { + if (!Token.isOperator(opertor1) ) + throw new IllegalArgumentException(opertor1 + "is not supported opertor"); + if (!Token.isOperator(opertor2)) + throw new IllegalArgumentException(opertor2 + "is not supported opertor"); + if (Token.isAddOrSub(opertor1)) { + if (Token.isAddOrSub(opertor2)) + return 0; + else + return -1; + } + else { + if (Token.isAddOrSub(opertor2)) + return 1; + else + return 0; + } + } + + public String printNumberStack() { + return numberStack.toString(); + } + + public String printOperatorStack() { + return operatorStack.toString(); + } +} diff --git a/group24/494800949/src/main/java/com/coding/week6/expr/Token.java b/group24/494800949/src/main/java/com/coding/week6/expr/Token.java new file mode 100644 index 0000000000..b58aa36968 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week6/expr/Token.java @@ -0,0 +1,52 @@ +package com.coding.week6.expr; + +/** + * Created by Administrator on 2017/4/16 0016. + */ +public class Token { + + private String symbol; + + public Token(String symbol) { + this.symbol = symbol; + } + + public boolean isNumber() { + return symbol.matches("^\\d+$"); + } + + + public boolean isOperator() { + return symbol.matches("^[\\+|\\*|\\-|\\/]$"); + } + + public int parseInt() { + return Integer.valueOf(symbol); + } + + public char parseOperator() { + return symbol.charAt(0); + } + + + public static boolean isOperator(char c) { + return isAddOrSub(c) || isMulityOrDivide(c); + } + + public static boolean isAddOrSub(char c) { + return c == '+' || c == '-'; + } + + public static boolean isMulityOrDivide(char c) { + return c == '/' || c == '*'; + } + + public static boolean isDigit(char c) { + return c >= '0' && c <= '9'; + } + + @Override + public String toString(){ + return symbol; + } +} diff --git a/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java b/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java index a03f29c0c3..00812bcd80 100644 --- a/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java +++ b/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java @@ -3,22 +3,22 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassIndex; import com.coding.mini_jvm.src.com.coderising.jvm.constant.*; +import com.coding.mini_jvm.src.com.coderising.jvm.field.Field; import com.coding.mini_jvm.src.com.coderising.jvm.loader.ClassFileLoader; +import com.coding.mini_jvm.src.com.coderising.jvm.method.Method; import com.coding.mini_jvm.src.com.coderising.jvm.util.Util; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; - - - +import java.util.List; public class ClassFileloaderTest { - static String path1 = "H:\\sourceCode\\coding2017\\group24\\494800949\\build\\classes\\test"; + static String path1 = "H:\\sourceCode\\coding2017\\group24\\494800949"; static String path2 = "C:\temp"; private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; @@ -27,7 +27,7 @@ public class ClassFileloaderTest { static { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); - String className = "com.coding.mini_jvm.test.EmployeeV1"; + String className = "EmployeeV1"; clzFile = loader.loadClass(className); // clzFile.print(); @@ -170,4 +170,78 @@ public void testClassIndex(){ Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); } + + + + /** + * 下面是第三次JVM课应实现的测试用例 + */ + @Test + public void testReadFields(){ + + List fields = clzFile.getFields(); + Assert.assertEquals(2, fields.size()); + { + Field f = fields.get(0); + Assert.assertEquals("name:Ljava/lang/String;", f.toString()); + } + { + Field f = fields.get(1); + Assert.assertEquals("age:I", f.toString()); + } + } + @Test + public void testMethods(){ + + List methods = clzFile.getMethods(); + ConstantPool pool = clzFile.getConstantPool(); + + { + Method m = methods.get(0); + assertMethodEquals(pool,m, + "", + "(Ljava/lang/String;I)V", + "2ab7000c2a2bb5000f2a1cb50011b1"); + + } + { + Method m = methods.get(1); + assertMethodEquals(pool,m, + "setName", + "(Ljava/lang/String;)V", + "2a2bb5000fb1"); + + } + { + Method m = methods.get(2); + assertMethodEquals(pool,m, + "setAge", + "(I)V", + "2a1bb50011b1"); + } + { + Method m = methods.get(3); + assertMethodEquals(pool,m, + "sayHello", + "()V", + "b2001c1222b60024b1"); + + } + { + Method m = methods.get(4); + assertMethodEquals(pool,m, + "main", + "([Ljava/lang/String;)V", + "bb000159122b101db7002d4c2bb6002fb1"); + } + } + + private void assertMethodEquals(ConstantPool pool,Method m , String expectedName, String expectedDesc,String expectedCode){ + String methodName = pool.getUTF8String(m.getNameIndex()); + String methodDesc = pool.getUTF8String(m.getDescriptorIndex()); + String code = m.getCodeAttr().getCode(); + Assert.assertEquals(expectedName, methodName); + Assert.assertEquals(expectedDesc, methodDesc); + Assert.assertEquals(expectedCode, code); + } } diff --git a/group24/494800949/src/test/java/com/coding/week6/expr/InfixExprTestTest.java b/group24/494800949/src/test/java/com/coding/week6/expr/InfixExprTestTest.java new file mode 100644 index 0000000000..7ef4b9ccfa --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week6/expr/InfixExprTestTest.java @@ -0,0 +1,77 @@ +package com.coding.week6.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Administrator on 2017/4/16 0016. + */ +public class InfixExprTestTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + + + @Test + public void testFillStack() { + InfixExpr expr = new InfixExpr("10-30+50"); + expr.fillStack(); + Assert.assertEquals(expr.printNumberStack(), "50.0,-20.0"); + Assert.assertEquals(expr.printOperatorStack(), "+"); + expr = new InfixExpr("3*20+12*5-40/2"); + expr.fillStack(); + Assert.assertEquals(expr.printNumberStack(), "2.0,40.0,60.0,60.0"); + Assert.assertEquals(expr.printOperatorStack(), "/,-,+"); + expr = new InfixExpr("3*20/2"); + expr.fillStack(); + Assert.assertEquals(expr.printNumberStack(), "2.0,60.0"); + Assert.assertEquals(expr.printOperatorStack(), "/"); + expr = new InfixExpr("20/2*3"); + expr.fillStack(); + Assert.assertEquals(expr.printNumberStack(), "3.0,10.0"); + Assert.assertEquals(expr.printOperatorStack(), "*"); + expr = new InfixExpr("10-30+50"); + expr.fillStack(); + Assert.assertEquals(expr.printNumberStack(), "50.0,-20.0"); + Assert.assertEquals(expr.printOperatorStack(), "+"); + } + + + +} \ No newline at end of file