Skip to content

Commit

Permalink
Merge pull request #57 from ipk2015/master
Browse files Browse the repository at this point in the history
121111914:中序表达式和jvm解析字段和方法
  • Loading branch information
DonaldY authored Apr 15, 2017
2 parents d6f9c24 + e209bd5 commit d0f9d27
Show file tree
Hide file tree
Showing 14 changed files with 649 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.github.ipk2015.coding2017.basic.stack.expr;

import com.github.ipk2015.coding2017.basic.stack.Stack;

public class InfixExpr {
String expr = null;

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

public float evaluate() {
String[] elements = getElementArray(expr);

Stack numStack = new Stack();
Stack operStack = new Stack();

manageMultiAndDivOper(elements,numStack,operStack);

return manageAddAndMinusOper(numStack,operStack);
}

private void manageMultiAndDivOper(String[] elements,Stack numStack,Stack operStack){
float preElement,nextElement;
for(int i = 0; i < elements.length;i++){
if(i%2 == 0){
numStack.push(Float.valueOf(elements[i]));
}else{

if(elements[i].equals("+") || elements[i].equals("-")){
operStack.push(elements[i]);
}else{
preElement = (Float)numStack.pop();
i++;
nextElement = Float.valueOf(elements[i]);
numStack.push(doBaseOper(preElement,nextElement,elements[i-1]));
}
}
}
}

private float manageAddAndMinusOper(Stack numStack,Stack operStack){
float result = 0f;;
while(!operStack.isEmpty()){
result = doBaseOper(result,(Float)numStack.pop(),(String)operStack.pop());
}
result += (Float)numStack.pop();
return result;
}

private float doBaseOper(float preData,float nextData,String oper){
switch(oper){
case "+":
return preData+nextData;
case "-":
return preData-nextData;
case "*":
return preData*nextData;
case "/":
return preData/nextData;
default:
throw new RuntimeException("could not recognise oper:"+oper);
}
}

public String[] getElementArray(String expression){
char[] charArray = expression.toCharArray();
StringBuffer stringBuffer = new StringBuffer();

for(int i = 0;i<charArray.length;i++){
if(charArray[i] == '+' || charArray[i] == '-' || charArray[i] == '*' || charArray[i] == '/'){
stringBuffer.append(","+charArray[i]+",");
}else{
stringBuffer.append(charArray[i]);
}
}

return stringBuffer.toString().split(",");
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.github.ipk2015.coding2017.basic.stack.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,21 @@
package com.github.ipk2015.coding2017.minijvm.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;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.github.ipk2015.coding2017.minijvm.attr;

import com.github.ipk2015.coding2017.minijvm.clz.ClassFile;
import com.github.ipk2015.coding2017.minijvm.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.nextUNToInt(2);
int attrLen = iter.nextUNToInt(4);
int maxStack = iter.nextUNToInt(2);
int maxLocals = iter.nextUNToInt(2);
int codeLen = iter.nextUNToInt(4);
String code = iter.nextUNToHexString(codeLen);
CodeAttr codeAttr = new CodeAttr(attrNameIndex,attrLen,maxStack,maxLocals,codeLen,code);
int exceptionTableLen = iter.nextUNToInt(2);
if(exceptionTableLen != 0){
throw new RuntimeException("code属性里的异常table长度为:"+exceptionTableLen);
}
int attrCount = iter.nextUNToInt(2);
for(int i = 0;i<attrCount;i++){
addSonAttr(clzFile,codeAttr,iter);
}
return codeAttr;
}
private void setStackMapTable(StackMapTable t) {
this.stackMapTable = t;

}
private static void addSonAttr(ClassFile clzFile,CodeAttr codeAttr,ByteCodeIterator iter){
int attrNameIndex = iter.nextUNToInt(2);
iter.back(2);
String name = clzFile.getConstantPool().getUTF8String(attrNameIndex);
switch(name){
case AttributeInfo.LINE_NUM_TABLE:
codeAttr.setLineNumberTable(LineNumberTable.parse(iter));
break;
case AttributeInfo.LOCAL_VAR_TABLE:
codeAttr.setLocalVariableTable(LocalVariableTable.parse(iter));
break;
case AttributeInfo.STACK_MAP_TABLE:
codeAttr.setStackMapTable(StackMapTable.parse(iter));
break;
default:
throw new RuntimeException("此属性不存在:"+name);
}
}





}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.github.ipk2015.coding2017.minijvm.attr;

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

import com.github.ipk2015.coding2017.minijvm.loader.ByteCodeIterator;



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 attrNameIndex = iter.nextUNToInt(2);
int attrLength = iter.nextUNToInt(4);
LineNumberTable lineNumberTable = new LineNumberTable(attrNameIndex,attrLength);
int lineNumTableLen = iter.nextUNToInt(2);
for(int i = 0;i < lineNumTableLen;i++){
LineNumberItem lineNumberItem = new LineNumberItem();
lineNumberItem.setStartPC(iter.nextUNToInt(2));
lineNumberItem.setLineNum(iter.nextUNToInt(2));
lineNumberTable.addLineNumberItem(lineNumberItem);
}
return lineNumberTable;
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.github.ipk2015.coding2017.minijvm.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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.github.ipk2015.coding2017.minijvm.attr;


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


import com.github.ipk2015.coding2017.minijvm.loader.ByteCodeIterator;



public class LocalVariableTable extends AttributeInfo{

List<LocalVariableItem> items = new ArrayList<LocalVariableItem>();

public LocalVariableTable(int attrNameIndex, int attrLen) {
super(attrNameIndex, attrLen);
}

public static LocalVariableTable parse(ByteCodeIterator iter){
int attrNameIndex = iter.nextUNToInt(2);
int attrLength = iter.nextUNToInt(4);
LocalVariableTable table = new LocalVariableTable(attrNameIndex,attrLength);
int tableLen = iter.nextUNToInt(2);
for(int i = 0;i < tableLen;i++){
LocalVariableItem item = new LocalVariableItem();
item.setStartPC(iter.nextUNToInt(2));
item.setLength(iter.nextUNToInt(2));
item.setNameIndex(iter.nextUNToInt(2));
item.setDescIndex(iter.nextUNToInt(2));
item.setIndex(iter.nextUNToInt(2));
table.addLocalVariableItem(item);
}
return table;
}
private void addLocalVariableItem(LocalVariableItem item) {
this.items.add(item);
}


}
Loading

0 comments on commit d0f9d27

Please sign in to comment.