Skip to content
Merged

L6 #5

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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