diff --git a/group02/727171008/.classpath b/group02/727171008/.classpath index 3e0fb272a8..429701a6eb 100644 --- a/group02/727171008/.classpath +++ b/group02/727171008/.classpath @@ -3,5 +3,6 @@ + diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/CodeAttr.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/CodeAttr.java index 47a8bd2b1c..9ecd803572 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/CodeAttr.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/attr/CodeAttr.java @@ -1,6 +1,8 @@ package com.github.HarryHook.coding2017.jvm.attr; import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.cmd.ByteCodeCommand; +import com.github.HarryHook.coding2017.jvm.cmd.CommandParser; import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; import com.github.HarryHook.coding2017.jvm.loader.ByteCodeIterator; import com.sun.org.apache.bcel.internal.generic.NEW; @@ -15,22 +17,24 @@ public String getCode() { return code; } - // private ByteCodeCommand[] cmds ; - // public ByteCodeCommand[] getCmds() { - // return cmds; - // } + 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 */) { + 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; + this.cmds = cmds; } public void setLineNumberTable(LineNumberTable t) { @@ -42,40 +46,44 @@ public void setLocalVariableTable(LocalVariableTable t) { } public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter) { - + int attrNameIndex = iter.nextU2ToInt(); int attrLen = iter.nextU4ToInt(); int maxStack = iter.nextU2ToInt(); int maxLocals = iter.nextU2ToInt(); int codeLen = iter.nextU4ToInt(); - + String code = iter.nextUxToHexString(codeLen); System.out.println(code); - - CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); - + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code, cmds); + int exceptionLength = iter.nextU2ToInt(); - if(exceptionLength > 0) { + if (exceptionLength > 0) { String exceptionTable = iter.nextUxToHexString(exceptionLength); System.out.println("exception Table has not complemented" + exceptionTable); } - //解析子属性 + // 解析子属性 int subAttrCount = iter.nextU2ToInt(); - - for(int j=1; j<=subAttrCount; j++) { - + + for (int j = 1; j <= subAttrCount; j++) { + int subAttrIndex = iter.nextU2ToInt(); String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); iter.back(2); - - if(AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)) { + + if (AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)) { LineNumberTable t = LineNumberTable.parse(iter); codeAttr.setLineNumberTable(t); - - } else if(AttributeInfo.LOCAL_VAR_TABLE.equals(subAttrName)) { + + } else if (AttributeInfo.LOCAL_VAR_TABLE.equals(subAttrName)) { LocalVariableTable t = LocalVariableTable.parse(iter); codeAttr.setLocalVariableTable(t); - + + } else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)) { + StackMapTable t = StackMapTable.parse(iter); + codeAttr.setStackMapTable(t); } else { throw new RuntimeException("Need implement" + subAttrName); } @@ -87,14 +95,17 @@ private void setStackMapTable(StackMapTable t) { this.stackMapTable = t; } + public String toString(ConstantPool pool) { StringBuffer buffer = new StringBuffer(); - buffer.append("Code:").append(code).append("\n"); + for(int i=0;i fields = new ArrayList(); - private List methods = new ArrayList();; + private List methods = new ArrayList(); public ClassIndex getClzIndex() { return clzIndex; } + public void setClzIndex(ClassIndex clzIndex) { this.clzIndex = clzIndex; } + public AccessFlag getAccessFlag() { return accessFlag; } @@ -72,32 +73,61 @@ public void print() { } - private String getClassName() { + public String getClassName() { int thisClassIndex = clzIndex.getThisClassIndex(); ClassInfo thisClass = (ClassInfo) this.getConstantPool().getConstantInfo(thisClassIndex); return thisClass.getClassName(); } - private String getSuperClassName() { + public String getSuperClassName() { ClassInfo superClass = (ClassInfo) this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); return superClass.getClassName(); } - + public void addField(Field f) { fields.add(f); } - + public List getFields() { return fields; } - + public void addMethod(Method m) { methods.add(m); - + } + public List getMethods() { return methods; } + public Method getMethod(String methodName, String paramAndReturnType) { + + for (Method m : methods) { + + int nameIndex = m.getNameIndex(); + int descriptionIndex = m.getDescriptorIndex(); + + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descriptionIndex); + if (name.equals(methodName) && desc.equals(paramAndReturnType)) { + return m; + } + } + return null; + } + + public Method getMainMethod() { + for (Method m : methods) { + int nameIndex = m.getNameIndex(); + int descIndex = m.getDescriptorIndex(); + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descIndex); + if (name.equals("main") && desc.equals("([Ljava/lang/String;)V")) { + return m; + } + } + return null; + } } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/BiPushCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..6b1c020682 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/BiPushCmd.java @@ -0,0 +1,23 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ConstantInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; + + +public class BiPushCmd extends OneOperandCmd { + + public BiPushCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); + } + + + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/ByteCodeCommand.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..f5e6705a8a --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,128 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ConstantInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; + + +public abstract class ByteCodeCommand { + + String opCode; + ClassFile clzFile; + private int offset; + + private static Map codeMap = new HashMap(); + + static{ + codeMap.put("01", "aconst_null"); + + codeMap.put("BB", "new"); + codeMap.put("37", "lstore"); + codeMap.put("B7", "invokespecial"); + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield"); + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0"); + codeMap.put("2B", "aload_1"); + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + + + + protected ByteCodeCommand(ClassFile clzFile, String opCode){ + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + protected ConstantInfo getConstantInfo(int index){ + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/CommandParser.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..b982fa7aa4 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/CommandParser.java @@ -0,0 +1,155 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; + +public class CommandParser { + + public static final String aconst_null = "01"; + public static final String new_object = "BB"; + public static final String lstore = "37"; + public static final String invokespecial = "B7"; + public static final String invokevirtual = "B6"; + public static final String getfield = "B4"; + public static final String putfield = "B5"; + public static final String getstatic = "B2"; + public static final String ldc = "12"; + public static final String dup = "59"; + public static final String bipush = "10"; + public static final String aload_0 = "2A"; + public static final String aload_1 = "2B"; + public static final String aload_2 = "2C"; + public static final String iload = "15"; + public static final String iload_1 = "1B"; + public static final String iload_2 = "1C"; + public static final String iload_3 = "1D"; + public static final String fload_3 = "25"; + + public static final String voidreturn = "B1"; + public static final String ireturn = "AC"; + public static final String freturn = "AE"; + + public static final String astore_1 = "4C"; + public static final String if_icmp_ge = "A2"; + public static final String if_icmple = "A4"; + public static final String goto_no_condition = "A7"; + public static final String iconst_0 = "03"; + public static final String iconst_1 = "04"; + public static final String istore_1 = "3C"; + public static final String istore_2 = "3D"; + public static final String iadd = "60"; + public static final String iinc = "84"; + + public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { + + if ((codes == null) || (codes.length() == 0) || (codes.length() % 2) != 0) { + throw new RuntimeException("the orignal code is not correct"); + + } + + codes = codes.toUpperCase(); + + CommandIterator iter = new CommandIterator(codes); + List cmds = new ArrayList(); + + while (iter.hasNext()) { + String opCode = iter.next2CharAsString(); + + if (new_object.equals(opCode)) { + NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); + + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (invokespecial.equals(opCode)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + // System.out.println( cmd.toString(clzFile.getConstPool())); + cmds.add(cmd); + } else if (invokevirtual.equals(opCode)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (getfield.equals(opCode)) { + GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (getstatic.equals(opCode)) { + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (putfield.equals(opCode)) { + PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ldc.equals(opCode)) { + LdcCmd cmd = new LdcCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (bipush.equals(opCode)) { + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (dup.equals(opCode) || aload_0.equals(opCode) || aload_1.equals(opCode) || aload_2.equals(opCode) + || iload_1.equals(opCode) || iload_2.equals(opCode) || iload_3.equals(opCode) + || fload_3.equals(opCode) || voidreturn.equals(opCode) || astore_1.equals(opCode)) { + + NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); + cmds.add(cmd); + } else { + throw new RuntimeException("Sorry, the java instruction " + opCode + " has not been implemented"); + } + + } + + calcuateOffset(cmds); + + ByteCodeCommand[] result = new ByteCodeCommand[cmds.size()]; + cmds.toArray(result); + return result; + } + + private static void calcuateOffset(List cmds) { + + int offset = 0; + for (ByteCodeCommand cmd : cmds) { + cmd.setOffset(offset); + offset += cmd.getLength(); + } + + } + + private static class CommandIterator { + String codes = null; + int pos = 0; + + CommandIterator(String codes) { + this.codes = codes; + } + + public boolean hasNext() { + return pos < this.codes.length(); + } + + public String next2CharAsString() { + String result = codes.substring(pos, pos + 2); + pos += 2; + return result; + } + + public int next2CharAsInt() { + String s = this.next2CharAsString(); + return Integer.valueOf(s, 16).intValue(); + } + + } +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetFieldCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..ec34e7b4a7 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,18 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetStaticFieldCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..1090e17374 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,24 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ClassInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.jvm.constant.FieldRefInfo; +import com.github.HarryHook.coding2017.jvm.constant.UTF8Info; + + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeSpecialCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..4afc337f47 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,23 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.jvm.constant.MethodRefInfo; + + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeVirtualCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..6b494dceda --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,21 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; + +public class InvokeVirtualCmd extends TwoOperandCmd { + + public InvokeVirtualCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + + + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/LdcCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..073ddd73a9 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ConstantInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.jvm.constant.StringInfo; + +public class LdcCmd extends OneOperandCmd { + + public LdcCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + + String value = "TBD"; + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + value = strInfo.toString(); + } + + return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; + + } + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NewObjectCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..9c959e31dd --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; + +public class NewObjectCmd extends TwoOperandCmd{ + + public NewObjectCmd(ClassFile clzFile, String opCode){ + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsClassInfo(pool); + } + + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NoOperandCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..554eac0690 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; + +public class NoOperandCmd extends ByteCodeCommand{ + + public NoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool) { + return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); + } + + + + public int getLength(){ + return 1; + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/OneOperandCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..77bf40708b --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; + +public abstract class OneOperandCmd extends ByteCodeCommand { + + private int operand; + + public OneOperandCmd(ClassFile clzFile,String opCode) { + super(clzFile, opCode); + + } + public int getOperand() { + + return this.operand; + } + + public void setOperand(int oprand1) { + this.operand = oprand1; + + } + public int getLength(){ + return 2; + } + + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/PutFieldCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..f3a197114c --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; + +public class PutFieldCmd extends TwoOperandCmd { + + public PutFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/TwoOperandCmd.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..13edc86215 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.github.HarryHook.coding2017.jvm.cmd; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ClassInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.jvm.constant.FieldRefInfo; +import com.github.HarryHook.coding2017.jvm.constant.MethodRefInfo; + +public abstract class TwoOperandCmd extends ByteCodeCommand{ + + int oprand1 = -1; + int oprand2 = -1; + + public int getOprand1() { + return oprand1; + } + + public void setOprand1(int oprand1) { + this.oprand1 = oprand1; + } + + public void setOprand2(int oprand2) { + this.oprand2 = oprand2; + } + + public int getOprand2() { + return oprand2; + } + + public TwoOperandCmd(ClassFile clzFile,String opCode) { + super(clzFile, opCode); + } + + public int getIndex(){ + int oprand1 = this.getOprand1(); + int oprand2 = this.getOprand2(); + int index = oprand1 << 8 | oprand2; + return index; + } + + protected String getOperandAsClassInfo(ConstantPool pool){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ClassInfo info = (ClassInfo)pool.getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" "+ codeTxt +" "+ info.getClassName(); + } + + protected String getOperandAsMethod(ConstantPool pool){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ConstantInfo constInfo = this.getConstantInfo(index); + MethodRefInfo info = (MethodRefInfo)this.getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); + } + + protected String getOperandAsField(ConstantPool pool){ + int index = getIndex(); + + String codeTxt = getReadableCodeText(); + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); + } + public int getLength(){ + return 3; + } +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ClassInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ClassInfo.java index 305ac57f5a..e4822e2bbb 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ClassInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ClassInfo.java @@ -25,4 +25,8 @@ public String getClassName() { UTF8Info utf8Info = (UTF8Info) constantPool.getConstantInfo(index); return utf8Info.getValue(); } + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } } diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantInfo.java index 3d81ed1adb..6c502016a3 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantInfo.java @@ -28,7 +28,16 @@ public ConstantInfo getConstantInfo(int index) { return this.constantPool.getConstantInfo(index); } - - - + public abstract void accept(Visitor visitor); + + public static interface Visitor{ + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visistUTF8(UTF8Info info); + + } + } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantPool.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantPool.java index 9d06349f3b..92d1b381d1 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantPool.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/ConstantPool.java @@ -25,7 +25,7 @@ public String getUTF8String(int index) { return ((UTF8Info) this.constantInfos.get(index)).getValue(); } - public Object getSize() { + public int getSize() { return this.constantInfos.size() - 1; } } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/FieldRefInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/FieldRefInfo.java index 6e8ddcb91b..d2d6a19f90 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/FieldRefInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/FieldRefInfo.java @@ -55,4 +55,9 @@ public String getFieldType() { NameAndTypeInfo typeInfo = (NameAndTypeInfo) this.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + } } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/MethodRefInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/MethodRefInfo.java index 7815c8a6a2..a1055932a0 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/MethodRefInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/MethodRefInfo.java @@ -54,4 +54,9 @@ public String getParamAndReturnType() { return typeInfo.getTypeInfo(); } + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } + } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NameAndTypeInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NameAndTypeInfo.java index 519656f681..29495489f4 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NameAndTypeInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NameAndTypeInfo.java @@ -45,4 +45,10 @@ public String getTypeInfo() { public String toString() { return "(" + getName() + "," + getTypeInfo() + ")"; } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + + } } diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NullConstantInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NullConstantInfo.java index 59489a965c..b0f5ad9b80 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NullConstantInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/NullConstantInfo.java @@ -11,4 +11,9 @@ public int getType() { return -1; } + @Override + public void accept(Visitor visitor) { + + } + } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/StringInfo.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/StringInfo.java index 1d625069be..442405aa36 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/StringInfo.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/StringInfo.java @@ -24,4 +24,10 @@ public String toString() { return this.getConstantPool().getUTF8String(index); } + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + + } + } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/UTF8Info.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/UTF8Info.java index 27c2ec9059..5c740bf402 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/UTF8Info.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/constant/UTF8Info.java @@ -29,8 +29,14 @@ public String toString() { public void setValue(String value) { this.value = value; } - public String getValue(){ + + public String getValue() { return value; } + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + + } } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/method/Method.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/method/Method.java index d7dedc0439..08b8ff029b 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/method/Method.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/method/Method.java @@ -2,6 +2,7 @@ package com.github.HarryHook.coding2017.jvm.method; import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.cmd.ByteCodeCommand; import javax.management.RuntimeErrorException; @@ -76,8 +77,11 @@ public String toString(ConstantPool pool) { StringBuffer buffer = new StringBuffer(); String name = ((UTF8Info) pool.getConstantInfo(this.nameIndex)).getValue(); String desc = ((UTF8Info) pool.getConstantInfo(this.descriptorIndex)).getValue(); - buffer.append(name); - buffer.append(desc); + buffer.append(name).append(":").append(desc).append("\n"); + buffer.append(this.codeAttr.toString(pool)); return buffer.toString(); } + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); +} } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ClassFilePrinter.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..6ede47692c --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ClassFilePrinter.java @@ -0,0 +1,51 @@ +package com.github.HarryHook.coding2017.jvm.print; + +import com.github.HarryHook.coding2017.jvm.clz.ClassFile; +import com.github.HarryHook.coding2017.jvm.constant.ClassInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.jvm.constant.FieldRefInfo; +import com.github.HarryHook.coding2017.jvm.constant.MethodRefInfo; +import com.github.HarryHook.coding2017.jvm.constant.NameAndTypeInfo; +import com.github.HarryHook.coding2017.jvm.constant.StringInfo; +import com.github.HarryHook.coding2017.jvm.constant.UTF8Info; +import com.github.HarryHook.coding2017.jvm.loader.ClassFileLoader; + +public class ClassFilePrinter { + ClassFile clzFile = null; + + public ClassFilePrinter(ClassFile clzFile) { + this.clzFile = clzFile; + } + + public void print() { + + if (clzFile.getAccessFlag().isPublicClass()) { + System.out.println("Access flag : public "); + } + System.out.println("Class Name:" + clzFile.getClassName()); + + System.out.println("Super Class Name:" + clzFile.getSuperClassName()); + + System.out.println("minor version:" + clzFile.getMinorVersion()); + + System.out.println("major version:" + clzFile.getMinorVersion()); + + ConstantPoolPrinter cnstPoolPrinter = new ConstantPoolPrinter(clzFile.getConstantPool()); + cnstPoolPrinter.print(); + + } + + public static void main(String[] args) { + String path = "F:\\Coding2017\\group02\\727171008\\bin"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "com.github.HarryHook.coding2017.jvm.test.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ConstantPoolPrinter.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..3d6c791185 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,25 @@ +package com.github.HarryHook.coding2017.jvm.print; + +import com.github.HarryHook.coding2017.jvm.constant.ClassInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantInfo; +import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; +import com.github.HarryHook.coding2017.jvm.constant.FieldRefInfo; +import com.github.HarryHook.coding2017.jvm.constant.MethodRefInfo; +import com.github.HarryHook.coding2017.jvm.constant.NameAndTypeInfo; +import com.github.HarryHook.coding2017.jvm.constant.StringInfo; +import com.github.HarryHook.coding2017.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + + + + } +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/test/ClassFileloaderTest.java b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/test/ClassFileloaderTest.java index 524907ce9f..ee7e3b3092 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/jvm/test/ClassFileloaderTest.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/jvm/test/ClassFileloaderTest.java @@ -9,6 +9,10 @@ import com.github.HarryHook.coding2017.jvm.clz.ClassFile; import com.github.HarryHook.coding2017.jvm.clz.ClassIndex; +import com.github.HarryHook.coding2017.jvm.cmd.BiPushCmd; +import com.github.HarryHook.coding2017.jvm.cmd.ByteCodeCommand; +import com.github.HarryHook.coding2017.jvm.cmd.OneOperandCmd; +import com.github.HarryHook.coding2017.jvm.cmd.TwoOperandCmd; import com.github.HarryHook.coding2017.jvm.constant.ClassInfo; import com.github.HarryHook.coding2017.jvm.constant.ConstantPool; import com.github.HarryHook.coding2017.jvm.constant.MethodRefInfo; @@ -259,5 +263,80 @@ private void assertMethodEquals(ConstantPool pool,Method m , String expectedName Assert.assertEquals(expectedDesc, methodDesc); Assert.assertEquals(expectedCode, code); } - + /* + * 第四次测试 + */ + @Test + public void testByteCodeCommand(){ + { + Method initMethod = this.clzFile.getMethod("", "(Ljava/lang/String;I)V"); + ByteCodeCommand [] cmds = initMethod.getCmds(); + + assertOpCodeEquals("0: aload_0", cmds[0]); + assertOpCodeEquals("1: invokespecial #12", cmds[1]); + assertOpCodeEquals("4: aload_0", cmds[2]); + assertOpCodeEquals("5: aload_1", cmds[3]); + assertOpCodeEquals("6: putfield #15", cmds[4]); + assertOpCodeEquals("9: aload_0", cmds[5]); + assertOpCodeEquals("10: iload_2", cmds[6]); + assertOpCodeEquals("11: putfield #17", cmds[7]); + assertOpCodeEquals("14: return", cmds[8]); + } + + { + Method setNameMethod = this.clzFile.getMethod("setName", "(Ljava/lang/String;)V"); + ByteCodeCommand [] cmds = setNameMethod.getCmds(); + + assertOpCodeEquals("0: aload_0", cmds[0]); + assertOpCodeEquals("1: aload_1", cmds[1]); + assertOpCodeEquals("2: putfield #15", cmds[2]); + assertOpCodeEquals("5: return", cmds[3]); + + } + + { + Method sayHelloMethod = this.clzFile.getMethod("sayHello", "()V"); + ByteCodeCommand [] cmds = sayHelloMethod.getCmds(); + + assertOpCodeEquals("0: getstatic #28", cmds[0]); + assertOpCodeEquals("3: ldc #34", cmds[1]); + assertOpCodeEquals("5: invokevirtual #36", cmds[2]); + assertOpCodeEquals("8: return", cmds[3]); + + } + + { + Method mainMethod = this.clzFile.getMainMethod(); + + ByteCodeCommand [] cmds = mainMethod.getCmds(); + + assertOpCodeEquals("0: new #1", cmds[0]); + assertOpCodeEquals("3: dup", cmds[1]); + assertOpCodeEquals("4: ldc #43", cmds[2]); + assertOpCodeEquals("6: bipush 29", cmds[3]); + assertOpCodeEquals("8: invokespecial #45", cmds[4]); + assertOpCodeEquals("11: astore_1", cmds[5]); + assertOpCodeEquals("12: aload_1", cmds[6]); + assertOpCodeEquals("13: invokevirtual #47", cmds[7]); + assertOpCodeEquals("16: return", cmds[8]); + } + + } + + private void assertOpCodeEquals(String expected, ByteCodeCommand cmd){ + + String acctual = cmd.getOffset()+": "+cmd.getReadableCodeText(); + + if(cmd instanceof OneOperandCmd){ + if(cmd instanceof BiPushCmd){ + acctual += " " + ((OneOperandCmd)cmd).getOperand(); + } else{ + acctual += " #" + ((OneOperandCmd)cmd).getOperand(); + } + } + if(cmd instanceof TwoOperandCmd){ + acctual += " #" + ((TwoOperandCmd)cmd).getIndex(); + } + Assert.assertEquals(expected, acctual); + } } diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/queue/CircleQueue.java b/group02/727171008/src/com/github/HarryHook/coding2017/queue/CircleQueue.java new file mode 100644 index 0000000000..cd82fb2550 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/queue/CircleQueue.java @@ -0,0 +1,38 @@ +package com.github.HarryHook.coding2017.queue; + +/** + * 用数组实现循环队列 + * + * @author liuxin + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + // 用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE]; + + // 队头 + private int front = 0; + // 队尾 + private int rear = 0; + + public boolean isEmpty() { + return false; + + } + + public int size() { + return -1; + } + + public void enQueue(E data) { + + } + + public E deQueue() { + return null; + } +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/queue/Josephus.java b/group02/727171008/src/com/github/HarryHook/coding2017/queue/Josephus.java new file mode 100644 index 0000000000..7b5fe53f5e --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/queue/Josephus.java @@ -0,0 +1,18 @@ +package com.github.HarryHook.coding2017.queue; + +import java.util.List; + +/** + * 用Queue来实现Josephus问题 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), + * 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 该方法返回一个List, 包含了被杀死人的次序 + * + * @author liuxin + * + */ +public class Josephus { + + public static List execute(int n, int m) { + return null; + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/queue/JosephusTest.java b/group02/727171008/src/com/github/HarryHook/coding2017/queue/JosephusTest.java new file mode 100644 index 0000000000..39d2ef9971 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/queue/JosephusTest.java @@ -0,0 +1,25 @@ +package com.github.HarryHook.coding2017.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/queue/Queue.java b/group02/727171008/src/com/github/HarryHook/coding2017/queue/Queue.java new file mode 100644 index 0000000000..3be0147770 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/queue/Queue.java @@ -0,0 +1,55 @@ +package com.github.HarryHook.coding2017.queue; + +import java.util.NoSuchElementException; + +public class Queue { + private Node first; + private Node last; + private int size; + + private static class Node { + private E item; + private Node next; + } + + public Queue() { + first = null; + last = null; + size = 0; + } + + public boolean isEmpty() { + return first == null; + } + + public int size() { + return size; + } + + public void enQueue(E data) { + Node oldlast = last; + last = new Node(); + last.item = data; + last.next = null; + if (isEmpty()) { + first = last; + } else { + oldlast.next = last; + } + size++; + } + + public E deQueue() { + if (isEmpty()) { + throw new NoSuchElementException("Queue underflow"); + } + E item = first.item; + first = first.next; + size--; + if (isEmpty()) { + last = null; + } + return item; + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/queue/QueueWithTwoStacks.java b/group02/727171008/src/com/github/HarryHook/coding2017/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..c72abadcd2 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/queue/QueueWithTwoStacks.java @@ -0,0 +1,37 @@ +package com.github.HarryHook.coding2017.queue; + +import java.util.Stack; + +/** + * 用两个栈来实现一个队列 + * + * @author liuxin + * + * @param + */ +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public boolean isEmpty() { + return false; + } + + public int size() { + return -1; + } + + public void enQueue(E item) { + + } + + public E deQueue() { + return null; + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixExpr.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixExpr.java index 5b1dbd7fa4..b9667fdaac 100644 --- a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixExpr.java +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixExpr.java @@ -13,73 +13,64 @@ public InfixExpr(String expr) { public float evaluate() { char[] ch = expr.toCharArray(); - MyStack stackOfTocken = new MyStack(); + MyStack stackOfOperator = new MyStack(); MyStack stackOfNumber = new MyStack(); for (int i = 0; i < ch.length; i++) { if (Character.isDigit(ch[i])) { - int tmp = Integer.parseInt("" + ch[i]); + float tmp = Float.parseFloat("" + ch[i]); while (i < ch.length - 1 && Character.isDigit(ch[++i])) { - tmp = tmp * 10 + Integer.parseInt("" + ch[i]); + tmp = tmp * 10 + Float.parseFloat("" + ch[i]); } - + stackOfNumber.push(tmp); } if (ch[i] == '+' || ch[i] == '-' || ch[i] == '*' || ch[i] == '/') { - stackOfTocken.push(ch[i]); + stackOfOperator.push(ch[i]); } - if (!(stackOfTocken.isEmpty()) && (char) stackOfTocken.peek() == '*') { - int tmp = Integer.parseInt("" + ch[++i]); + char operator = (char) stackOfOperator.peek(); + if (operator == '*' || operator == '/') { + float tmp = Float.parseFloat("" + ch[++i]); while (i < ch.length - 1 && Character.isDigit(ch[++i])) { - tmp = tmp * 10 + Integer.parseInt("" + ch[i]); + tmp = tmp * 10 + Float.parseFloat("" + ch[i]); } if (i != ch.length - 1) { i--; } stackOfNumber.push(tmp); - int tmp1 = Integer.parseInt("" + stackOfNumber.pop()); - int tmp2 = Integer.parseInt("" + stackOfNumber.pop()); - stackOfNumber.push(tmp1 * tmp2); - stackOfTocken.pop(); - - } - if (!(stackOfTocken.isEmpty()) && (char) stackOfTocken.peek() == '/') { - int tmp = Integer.parseInt("" + ch[++i]); - while (i < ch.length - 1 && Character.isDigit(ch[++i])) { - tmp = tmp * 10 + Integer.parseInt("" + ch[i]); + float tmp1 = Float.parseFloat("" + stackOfNumber.pop()); + float tmp2 = Float.parseFloat("" + stackOfNumber.pop()); + if (operator == '*') { + stackOfNumber.push(tmp1 * tmp2); + } else { + stackOfNumber.push(tmp2 / tmp1); } - if (i != ch.length - 1) { - i--; - } - stackOfNumber.push(tmp); - int tmp1 = Integer.parseInt("" + stackOfNumber.pop()); - int tmp2 = Integer.parseInt("" + stackOfNumber.pop()); - stackOfNumber.push(tmp2 / tmp1); - stackOfTocken.pop(); + stackOfOperator.pop(); } + } - // 将栈中的数字和运算法逆置,便于计算 + // 将栈中的数字和运算符逆置,从左往右结合 reverse(stackOfNumber); - reverse(stackOfTocken); - - while (!(stackOfTocken.isEmpty())) { - if ((char) stackOfTocken.peek() == '+') { - int tmp1 = Integer.parseInt("" + stackOfNumber.pop()); - int tmp2 = Integer.parseInt("" + stackOfNumber.pop()); - stackOfNumber.push(tmp1 + tmp2); - } - - if ((char) stackOfTocken.peek() == '-') { - int tmp1 = Integer.parseInt("" + stackOfNumber.pop()); - int tmp2 = Integer.parseInt("" + stackOfNumber.pop()); - stackOfNumber.push(tmp1 - tmp2); + reverse(stackOfOperator); + + while (!(stackOfOperator.isEmpty())) { + char operator = (char) stackOfOperator.peek(); + if (operator == '+' || operator == '-') { + float tmp1 = Float.parseFloat("" + stackOfNumber.pop()); + float tmp2 = Float.parseFloat("" + stackOfNumber.pop()); + if (operator == '+') { + stackOfNumber.push(tmp1 + tmp2); + } else { + stackOfNumber.push(tmp1 - tmp2); + } } - stackOfTocken.pop(); + + stackOfOperator.pop(); } return Float.parseFloat("" + stackOfNumber.pop()); @@ -104,4 +95,9 @@ private void reverse(MyStack s) { s.push(temp2); } + + public static void main(String[] args) { + InfixExpr expr = new InfixExpr("2+3*4+5"); + System.out.println(expr.evaluate()); + } } \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixToPostfix.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..10088e28cd --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/InfixToPostfix.java @@ -0,0 +1,53 @@ +package com.github.HarryHook.coding2017.stack.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader.Array; + +//中序表达式: 3*20+12*5-40/2 转换成后续表达式:3 20 * 12 5 * + 40 2 / - +//思路:当前token依次从左往右读取, 数字依次append, 当前入栈的运算符的优先级小于等于栈顶的运算符,栈顶操作符出栈 +public class InfixToPostfix { + + public List convert(String expr) { + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + + List listOfTokens = new ArrayList<>(); + + Stack opsStack = new Stack<>(); + + for (Token token : tokens) { + + if (token.isNumber()) { + listOfTokens.add(token); + } else if (token.isOperator()) { // 还需判断当前操作符和栈顶操作符的优先级 + if (opsStack.isEmpty()) { + opsStack.push(token); + } else { + if (!token.hasHigherPriority(opsStack.peek())) { + listOfTokens.add(opsStack.pop()); + } + opsStack.push(token); + } + + } + } + while (!(opsStack.isEmpty())) { // exprStack 为空,但操作符栈还有元素 + listOfTokens.add(opsStack.pop()); + } + return listOfTokens; + } + + public static void main(String[] args) { + InfixToPostfix toPostfix = new InfixToPostfix(); + List t = new ArrayList(); + String expr = "3+20+12*5+40/2"; + t = toPostfix.convert(expr); + System.out.println("expr: " + expr); + System.out.println("PostfixExpr: " + t); + } + +} diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExpr.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..49bebad1a7 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExpr.java @@ -0,0 +1,54 @@ +package com.github.HarryHook.coding2017.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + Stack numStack = new Stack<>(); + for (Token token : tokens) { + + if (token.isNumber()) { + numStack.push(new Float(token.getIntValue())); + } else { + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(), f1, f2)); + } + } + return numStack.pop().floatValue(); + } + + // 注意,此时计算的顺序和前序的次序相反 + private Float calculate(String op, Float f1, Float f2) { + if (op.equals("+")) { + return f1 + f2; + } + if (op.equals("-")) { + return f1 - f2; + } + if (op.equals("*")) { + return f1 * f2; + } + if (op.equals("/")) { + return f1 / f2; + } + throw new RuntimeException(op + " is not supported"); + } + + public static void main(String[] args) { + PostfixExpr expr = new PostfixExpr("9 3 1-3*+ 10 2/+"); + System.out.println("The result of the expression: " + expr.evaluate()); + } + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExprTest.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..7e78fa3997 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PostfixExprTest.java @@ -0,0 +1,37 @@ +package com.github.HarryHook.coding2017.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class PostfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + { + PostfixExpr expr = new PostfixExpr("6 5 2 3 + 8 * + 3 + *"); + Assert.assertEquals(288, expr.evaluate(), 0.0f); + } + { + // 9+(3-1)*3+10/2 + PostfixExpr expr = new PostfixExpr("9 3 1-3*+ 10 2/+"); + Assert.assertEquals(20, expr.evaluate(), 0.0f); + } + + { + // 10-2*3+50 + PostfixExpr expr = new PostfixExpr("10 2 3 * - 50 +"); + Assert.assertEquals(54, expr.evaluate(), 0.0f); + } + } + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..d93b6e32fe --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExpr.java @@ -0,0 +1,58 @@ +package com.github.HarryHook.coding2017.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + Stack exprStack = new Stack<>(); + Stack numStack = new Stack<>(); + for (Token token : tokens) { + exprStack.push(token); + } + System.out.println(tokens); + while (!exprStack.isEmpty()) { + Token t = exprStack.pop(); + if (t.isNumber()) { + numStack.push(new Float(t.getIntValue())); + } else if(t.isOperator()){ + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + numStack.push(calculate(t.toString(), f1, f2)); + } + } + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2) { + if (op.equals("+")) { + return f1 + f2; + } + if (op.equals("-")) { + return f1 - f2; + } + if (op.equals("*")) { + return f1 * f2; + } + if (op.equals("/")) { + return f1 / f2; + } + throw new RuntimeException(op + " is not supported"); + } + + public static void main(String[] args) { + PrefixExpr expr = new PrefixExpr("-++6/*2 9 3 * 4 2 8"); + System.out.println("The result of the expression: " + expr.evaluate()); + } + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExprTest.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..3dbef83ca2 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/PrefixExprTest.java @@ -0,0 +1,43 @@ +package com.github.HarryHook.coding2017.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class PrefixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + { + // 2*3+4*5 + PrefixExpr expr = new PrefixExpr("+ * 2 3* 4 5"); + Assert.assertEquals(26, expr.evaluate(), 0.001f); + } + { + // 4*2 + 6+9*2/3 -8 + PrefixExpr expr = new PrefixExpr("-++6/*2 9 3 * 4 2 8"); + Assert.assertEquals(12, expr.evaluate(), 0.001f); + } + { + // (3+4)*5-6 + PrefixExpr expr = new PrefixExpr("- * + 3 4 5 6"); + Assert.assertEquals(29, expr.evaluate(), 0.001f); + } + { + // 1+((2+3)*4)-5 + PrefixExpr expr = new PrefixExpr("- + 1 * + 2 3 4 5"); + Assert.assertEquals(16, expr.evaluate(), 0.001f); + } + + } + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/Token.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/Token.java new file mode 100644 index 0000000000..097d635bd2 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/Token.java @@ -0,0 +1,50 @@ +package com.github.HarryHook.coding2017.stack.expr; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class Token { + public static final List OPERATORS = Arrays.asList("+", "-", "*", "/"); + private static final Map priorities = new HashMap<>(); + static { + priorities.put("+", 1); + priorities.put("-", 1); + priorities.put("*", 2); + priorities.put("/", 2); + } + static final int OPERATOR = 1; + static final int NUMBER = 2; + String value; + int type; + + public Token(int type, String value) { + this.type = type; + this.value = value; + } + + public boolean isNumber() { + return type == NUMBER; + } + + public boolean isOperator() { + return type == OPERATOR; + } + + public int getIntValue() { + return Integer.valueOf(value).intValue(); + } + + public String toString() { + return value; + } + + public boolean hasHigherPriority(Token t) { + if (!this.isOperator() && !t.isOperator()) { + throw new RuntimeException("numbers can't compare priority"); + } + return priorities.get(this.value) - priorities.get(t.value) > 0; + } + +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParser.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParser.java new file mode 100644 index 0000000000..8d520fd68a --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParser.java @@ -0,0 +1,56 @@ +package com.github.HarryHook.coding2017.stack.expr; + +import java.util.ArrayList; +import java.util.List; + +public class TokenParser { + + public List parse(String expr) { + List tokens = new ArrayList<>(); + + int i = 0; + + while (i < expr.length()) { + + char c = expr.charAt(i); + + if (isOperator(c)) { + + Token t = new Token(Token.OPERATOR, String.valueOf(c)); + tokens.add(t); + i++; + + } else if (Character.isDigit(c)) { + + int nextOperatorIndex = indexOfNextOperator(i, expr); + String value = expr.substring(i, nextOperatorIndex); + Token t = new Token(Token.NUMBER, value); + tokens.add(t); + i = nextOperatorIndex; + + } else { + System.out.println("char :[" + c + "] is not number or operator,ignore"); + i++; + } + + } + return tokens; + } + + private int indexOfNextOperator(int i, String expr) { + + while (Character.isDigit(expr.charAt(i))) { + i++; + if (i == expr.length()) { + break; + } + } + return i; + + } + + private boolean isOperator(char c) { + String sc = String.valueOf(c); + return Token.OPERATORS.contains(sc); + } +} \ No newline at end of file diff --git a/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParserTest.java b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..3067467a10 --- /dev/null +++ b/group02/727171008/src/com/github/HarryHook/coding2017/stack/expr/TokenParserTest.java @@ -0,0 +1,39 @@ +package com.github.HarryHook.coding2017.stack.expr; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class TokenParserTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + + TokenParser parser = new TokenParser(); + List tokens = parser.parse("300*20+12*5-20/4"); + + Assert.assertEquals(300, tokens.get(0).getIntValue()); + Assert.assertEquals("*", tokens.get(1).toString()); + Assert.assertEquals(20, tokens.get(2).getIntValue()); + Assert.assertEquals("+", tokens.get(3).toString()); + Assert.assertEquals(12, tokens.get(4).getIntValue()); + Assert.assertEquals("*", tokens.get(5).toString()); + Assert.assertEquals(5, tokens.get(6).getIntValue()); + Assert.assertEquals("-", tokens.get(7).toString()); + Assert.assertEquals(20, tokens.get(8).getIntValue()); + Assert.assertEquals("/", tokens.get(9).toString()); + Assert.assertEquals(4, tokens.get(10).getIntValue()); + } + +} \ No newline at end of file