Skip to content

Commit

Permalink
L6
Browse files Browse the repository at this point in the history
  • Loading branch information
colawoo committed Apr 16, 2017
1 parent 5619b1c commit c8dd999
Show file tree
Hide file tree
Showing 28 changed files with 1,778 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package io.github.vxzh.datastructure.less6.expr;

import java.util.Stack;

public class InfixExpr {
String expr = null;

public InfixExpr(String expr) {
this.expr = expr;
}

public float evaluate() {

check();

Stack<Character> operateStack = new Stack<Character>();
Stack<Integer> numStack = new Stack<Integer>();

char[] ch = expr.toCharArray();

for (int i = 0; i < ch.length; i++) {

if (Character.isDigit(ch[i])) {
int tmp = Integer.parseInt("" + ch[i]);
while (i < ch.length - 1 && Character.isDigit(ch[++i])) {
tmp = tmp * 10 + Integer.parseInt("" + ch[i]);
}
numStack.push(tmp);

}
if (ch[i] == '+' || ch[i] == '-' || ch[i] == '*' || ch[i] == '/') {
operateStack.push(ch[i]);
}

if (!(operateStack.isEmpty()) && (char) operateStack.peek() == '*') {
int tmp = Integer.parseInt("" + ch[++i]);
while (i < ch.length - 1 && Character.isDigit(ch[++i])) {
tmp = tmp * 10 + Integer.parseInt("" + ch[i]);
}
if (i != ch.length - 1) {
i--;
}
numStack.push(tmp);

int tmp1 = Integer.parseInt("" + numStack.pop());
int tmp2 = Integer.parseInt("" + numStack.pop());
numStack.push(tmp1 * tmp2);
operateStack.pop();

}
if (!(operateStack.isEmpty()) && (char) operateStack.peek() == '/') {
int tmp = Integer.parseInt("" + ch[++i]);
while (i < ch.length - 1 && Character.isDigit(ch[++i])) {
tmp = tmp * 10 + Integer.parseInt("" + ch[i]);
}
if (i != ch.length - 1) {
i--;
}
numStack.push(tmp);

int tmp1 = Integer.parseInt("" + numStack.pop());
int tmp2 = Integer.parseInt("" + numStack.pop());
numStack.push(tmp2 / tmp1);
operateStack.pop();
}
}
// 将栈中的数字和运算法逆置,便于计算
reverse(numStack);
reverse(operateStack);

while (!(operateStack.isEmpty())) {
if ((char) operateStack.peek() == '+') {
int tmp1 = Integer.parseInt("" + numStack.pop());
int tmp2 = Integer.parseInt("" + numStack.pop());
numStack.push(tmp1 + tmp2);
}

if ((char) operateStack.peek() == '-') {
int tmp1 = Integer.parseInt("" + numStack.pop());
int tmp2 = Integer.parseInt("" + numStack.pop());
numStack.push(tmp1 - tmp2);
}
operateStack.pop();
}

return Float.parseFloat("" + numStack.pop());
}

private void reverse(Stack s) {

if (s.isEmpty()) {
return;
}
// 如果s里面只有一个元素,就返回。具体实现是先pop出来一个,判断剩下的是不是空栈。
Object tmp1 = s.pop();
reverse(s);
if (s.isEmpty()) {
s.push(tmp1);
return;
}
Object temp2 = s.pop();
reverse(s);
s.push(tmp1);
reverse(s);
s.push(temp2);

}

private boolean check() {
if (expr.length() <= 0) {
return false;
} else if ('+' == expr.charAt(0) || '-' == expr.charAt(0) || '*' == expr.charAt(0) || '/' == expr.charAt(0)) {
return false;
} else if ('+' == expr.charAt(expr.length() - 1) || '-' == expr.charAt(expr.length() - 1) || '*' == expr.charAt(expr.length() - 1) || '/' == expr.charAt(expr.length() - 1)) {
return false;
}

return true;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package io.github.vxzh.datastructure.less6.expr;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class InfixExprTest {

@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);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.github.vxzh.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;
}


}
116 changes: 116 additions & 0 deletions group13/2729382520/L6/src/io/github/vxzh/jvm/attr/CodeAttr.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package io.github.vxzh.jvm.attr;


import io.github.vxzh.jvm.clz.ClassFile;
import io.github.vxzh.jvm.clz.ConstantPool;
import io.github.vxzh.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) {

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);

//ByteCodeCommand[] cmds = ByteCodeCommand.parse(clzFile,code);

CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code);

int exceptionTableLen = iter.nextU2ToInt();
//TODO 处理exception
if (exceptionTableLen > 0) {
String exTable = iter.nextUxToHexString(exceptionTableLen);
System.out.println("Encountered exception table , just ignore it :" + exTable);

}


int subAttrCount = iter.nextU2ToInt();

for (int x = 1; x <= subAttrCount; x++) {
int subAttrIndex = iter.nextU2ToInt();
String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex);

//已经向前移动了U2, 现在退回去。
iter.back(2);
//line item table
if (AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)) {

LineNumberTable t = LineNumberTable.parse(iter);
codeAttr.setLineNumberTable(t);
} else if (AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(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 code to process " + subAttrName);
}


}

return codeAttr;
}


public String toString(ConstantPool pool) {
StringBuilder buffer = new StringBuilder();
buffer.append("Code:").append(code).append("\n");
/*for(int i=0;i<cmds.length;i++){
buffer.append(cmds[i].toString(pool)).append("\n");
}*/
buffer.append("\n");
buffer.append(this.lineNumTable.toString());
buffer.append(this.localVarTable.toString(pool));
return buffer.toString();
}

private void setStackMapTable(StackMapTable t) {
this.stackMapTable = t;

}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package io.github.vxzh.jvm.attr;

import io.github.vxzh.jvm.loader.ByteCodeIterator;

import java.util.ArrayList;
import java.util.List;

public class LineNumberTable extends AttributeInfo {
List<LineNumberItem> items = new ArrayList<LineNumberItem>();

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) {

int index = iter.nextU2ToInt();
int len = iter.nextU4ToInt();

LineNumberTable table = new LineNumberTable(index, len);

int itemLen = iter.nextU2ToInt();

for (int i = 1; i <= itemLen; i++) {
LineNumberItem item = new LineNumberItem();
item.setStartPC(iter.nextU2ToInt());
item.setLineNum(iter.nextU2ToInt());
table.addLineNumberItem(item);
}
return table;
}

public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("Line Number Table:\n");
for (LineNumberItem item : items) {
buffer.append("startPC:" + item.getStartPC()).append(",");
buffer.append("lineNum:" + item.getLineNum()).append("\n");
}
buffer.append("\n");
return buffer.toString();

}


}
Loading

0 comments on commit c8dd999

Please sign in to comment.