From fb5e6c9a3b75668af62e9d6a3f16d27107aee110 Mon Sep 17 00:00:00 2001
From: bdemsky <bdemsky>
Date: Wed, 22 Feb 2006 19:36:20 +0000
Subject: [PATCH] checking in changes

---
 Robust/src/IR/AssignOperation.java       |  28 ++++
 Robust/src/IR/ClassDescriptor.java       |  44 ++++--
 Robust/src/IR/FieldDescriptor.java       |   4 +
 Robust/src/IR/Flat/BuildFlat.java        | 109 +++++++++++--
 Robust/src/IR/Flat/FlatCall.java         |  26 ++++
 Robust/src/IR/Flat/FlatCastNode.java     |  18 +++
 Robust/src/IR/Flat/FlatCondBranch.java   |  10 ++
 Robust/src/IR/Flat/FlatFieldNode.java    |  22 +++
 Robust/src/IR/Flat/FlatLiteralNode.java  |  40 +++++
 Robust/src/IR/Flat/FlatMethod.java       |  70 ++++++++-
 Robust/src/IR/Flat/FlatNew.java          |  16 ++
 Robust/src/IR/Flat/FlatNode.java         |  22 ++-
 Robust/src/IR/MethodDescriptor.java      |  26 ++++
 Robust/src/IR/State.java                 |  15 +-
 Robust/src/IR/SymbolTable.java           |  15 +-
 Robust/src/IR/Tree/AssignmentNode.java   |  12 ++
 Robust/src/IR/Tree/BlockNode.java        |   8 +
 Robust/src/IR/Tree/BuildIR.java          |  14 +-
 Robust/src/IR/Tree/CastNode.java         |   8 +
 Robust/src/IR/Tree/CreateObjectNode.java |  22 +++
 Robust/src/IR/Tree/ExpressionNode.java   |   4 +
 Robust/src/IR/Tree/FieldAccessNode.java  |  14 ++
 Robust/src/IR/Tree/LiteralNode.java      |   7 +-
 Robust/src/IR/Tree/MethodInvokeNode.java |  24 +++
 Robust/src/IR/Tree/SemanticCheck.java    | 189 +++++++++++++++++++++++
 Robust/src/IR/TypeDescriptor.java        |  26 +++-
 Robust/src/IR/VarDescriptor.java         |   4 +
 Robust/src/Main/Main.java                |   5 +
 Robust/src/Parse/java14.cup              |  15 +-
 Robust/src/t.test                        |   5 +
 30 files changed, 771 insertions(+), 51 deletions(-)
 create mode 100644 Robust/src/IR/Flat/FlatCall.java
 create mode 100644 Robust/src/IR/Flat/FlatCastNode.java
 create mode 100644 Robust/src/IR/Flat/FlatFieldNode.java
 create mode 100644 Robust/src/IR/Flat/FlatLiteralNode.java
 create mode 100644 Robust/src/IR/Flat/FlatNew.java
 create mode 100644 Robust/src/IR/Tree/SemanticCheck.java

diff --git a/Robust/src/IR/AssignOperation.java b/Robust/src/IR/AssignOperation.java
index e8dce7de..2abd7c8e 100644
--- a/Robust/src/IR/AssignOperation.java
+++ b/Robust/src/IR/AssignOperation.java
@@ -23,6 +23,34 @@ public class AssignOperation {
 	this.operation=parseOp(op);
     }
 
+    public Operation getBaseOp() {
+	switch(operation) {
+	case EQ:
+	    return null;
+	case MULTEQ:
+	    return new Operation(Operation.MULT);
+	case DIVEQ:
+	    return new Operation(Operation.DIV);
+	case MODEQ:
+	    return new Operation(Operation.MOD);
+	case PLUSEQ:
+	    return new Operation(Operation.ADD);
+	case MINUSEQ:
+	    return new Operation(Operation.SUB);
+	case LSHIFTEQ:
+	    return new Operation(Operation.LEFTSHIFT);
+	case RSHIFTEQ:
+	    return new Operation(Operation.RIGHTSHIFT);
+	case ANDEQ:
+	    return new Operation(Operation.BIT_AND);
+	case XOREQ:
+	    return new Operation(Operation.BIT_XOR);
+	case OREQ:
+	    return new Operation(Operation.BIT_OR);
+	}
+	throw new Error();
+    }
+
     public static int parseOp(String st) {
 	if (st.equals("eq"))
 	    return EQ;
diff --git a/Robust/src/IR/ClassDescriptor.java b/Robust/src/IR/ClassDescriptor.java
index 353ab00f..72b0802a 100644
--- a/Robust/src/IR/ClassDescriptor.java
+++ b/Robust/src/IR/ClassDescriptor.java
@@ -1,27 +1,40 @@
 package IR;
 import java.util.*;
 import IR.Tree.*;
+import IR.SymbolTable;
 import IR.FieldDescriptor;
 import IR.MethodDescriptor;
 import IR.NameDescriptor;
 
-public class ClassDescriptor {
-    public ClassDescriptor() {
-	classname=null;
+public class ClassDescriptor extends Descriptor {
+    public ClassDescriptor(String classname) {
+	super(classname);
+	this.classname=classname;
 	superclass=null;
-	fields=new Vector();
-	methods=new Vector();
+	fields=new SymbolTable();
+	methods=new SymbolTable();
     }
+
     String classname;
-    NameDescriptor superclass;
+    String superclass;
     Modifiers modifiers;
-    Vector fields;
-    Vector methods;
+
+    SymbolTable fields;
+    SymbolTable methods;
+
     
     public Iterator getMethods() {
-	return methods.iterator();
+	return methods.getDescriptorsIterator();
+    }
+
+    public Iterator getFields() {
+	return fields.getDescriptorsIterator();
     }
     
+    public SymbolTable getFieldTable() {
+	return fields;
+    }
+
     public String printTree(State state) {
 	int indent;
 	String st=modifiers.toString()+"class "+classname;
@@ -29,15 +42,16 @@ public class ClassDescriptor {
 	    st+="extends "+superclass.toString();
 	st+=" {\n";
 	indent=TreeNode.INDENT;
-	for(int i=0;i<fields.size();i++) {
-	    FieldDescriptor fd=(FieldDescriptor)fields.get(i);
+	
+	for(Iterator it=getFields();it.hasNext();) {
+	    FieldDescriptor fd=(FieldDescriptor)it.next();
 	    st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
 	}
 	if (fields.size()>0)
 	    st+="\n";
 
-	for(int i=0;i<methods.size();i++) {
-	    MethodDescriptor md=(MethodDescriptor)methods.get(i);
+	for(Iterator it=getMethods();it.hasNext();) {
+	    MethodDescriptor md=(MethodDescriptor)it.next();
 	    st+=TreeNode.printSpace(indent)+md.toString()+" ";
 	    BlockNode bn=state.getMethodBody(md);
 	    st+=bn.printNode(indent)+"\n\n";
@@ -47,6 +61,8 @@ public class ClassDescriptor {
     }
 
     public void addField(FieldDescriptor fd) {
+	if (fields.contains(fd.getSymbol()))
+	    throw new Error(fd.getSymbol()+" already defined");
 	fields.add(fd);
     }
 
@@ -62,7 +78,7 @@ public class ClassDescriptor {
 	classname=name;
     }
 
-    public void setSuper(NameDescriptor superclass) {
+    public void setSuper(String superclass) {
 	this.superclass=superclass;
     }
 }
diff --git a/Robust/src/IR/FieldDescriptor.java b/Robust/src/IR/FieldDescriptor.java
index a0469d8f..ce57b627 100644
--- a/Robust/src/IR/FieldDescriptor.java
+++ b/Robust/src/IR/FieldDescriptor.java
@@ -25,6 +25,10 @@ public class FieldDescriptor extends Descriptor {
 	this.uniqueid=count++;
     }
 
+    public TypeDescriptor getType() {
+	return td;
+    }
+
     public String toString() {
 	if (en==null)
 	    return modifier.toString()+td.toString()+" "+identifier+";";
diff --git a/Robust/src/IR/Flat/BuildFlat.java b/Robust/src/IR/Flat/BuildFlat.java
index d14bc6a3..13735871 100644
--- a/Robust/src/IR/Flat/BuildFlat.java
+++ b/Robust/src/IR/Flat/BuildFlat.java
@@ -13,7 +13,7 @@ public class BuildFlat {
     }
 
     public void buildFlat() {
-	Iterator it=state.classset.iterator();
+	Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
 	while(it.hasNext()) {
 	    ClassDescriptor cn=(ClassDescriptor)it.next();
 	    flattenClass(cn);
@@ -56,27 +56,114 @@ public class BuildFlat {
 	return flattenExpressionNode(en.getExpression(),tmp);
     }
 
-    private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) {
-	throw new Error();
+    private NodePair flattenCastNode(CastNode cn,TempDescriptor out_temp) {
+	TempDescriptor tmp=TempDescriptor.tempFactory("tocast");
+	NodePair np=flattenExpressionNode(cn.getExpression(), tmp);
+	FlatCastNode fcn=new FlatCastNode(cn.getType(), tmp, out_temp);
+	np.getEnd().addNext(fcn);
+	return new NodePair(np.getBegin(),fcn);
     }
 
-    private NodePair flattenCastNode(CastNode cn,TempDescriptor out_temp) {
-	throw new Error();
+    private NodePair flattenLiteralNode(LiteralNode ln,TempDescriptor out_temp) {
+	FlatLiteralNode fln=new FlatLiteralNode(ln.getType(), ln.getValue(), out_temp);
+	return new NodePair(fln,fln);
     }
 
+
     private NodePair flattenCreateObjectNode(CreateObjectNode con,TempDescriptor out_temp) {
-	throw new Error();
+	TypeDescriptor td=con.getType();
+	FlatNew fn=new FlatNew(td, out_temp);
+	TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
+	FlatNode last=fn;
+	//Build arguments
+	for(int i=0;i<con.numArgs();i++) {
+	    ExpressionNode en=con.getArg(i);
+	    TempDescriptor tmp=TempDescriptor.tempFactory("arg");
+	    temps[i]=tmp;
+	    NodePair np=flattenExpressionNode(en, tmp);
+	    last.addNext(np.getBegin());
+	    last=np.getEnd();
+	}
+	MethodDescriptor md=con.getConstructor();
+	//Call to constructor
+	FlatCall fc=new FlatCall(md, null, out_temp, temps);
+	last.addNext(fc);
+	return new NodePair(fn,fc);
     }
 
-    private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) {
-	throw new Error();
+    private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) {
+	TempDescriptor[] temps=new TempDescriptor[min.numArgs()];
+	FlatNode first=null;
+	FlatNode last=null;
+	TempDescriptor thisarg=null;
+
+	if (min.getExpression()==null) {
+	    thisarg=TempDescriptor.tempFactory("thisarg");
+	    NodePair np=flattenExpressionNode(min.getExpression(),temps[0]);
+	    first=np.getBegin();
+	    last=np.getEnd();
+	}
+	
+	//Build arguments
+	for(int i=0;i<min.numArgs();i++) {
+	    ExpressionNode en=min.getArg(i);
+	    TempDescriptor td=TempDescriptor.tempFactory("arg");
+	    temps[i]=td;
+	    NodePair np=flattenExpressionNode(en, td);
+	    if (first==null)
+		first=np.getBegin();
+	    else 
+		last.addNext(np.getBegin());
+	    last=np.getEnd();
+	}
+
+	MethodDescriptor md=min.getMethod();
+	
+	//Call to constructor
+	FlatCall fc=new FlatCall(md, out_temp, thisarg, temps);
+	if (first==null) {
+	    first=fc;
+	} else
+	    last.addNext(fc);
+	return new NodePair(first,fc);
     }
 
-    private NodePair flattenLiteralNode(LiteralNode ln,TempDescriptor out_temp) {
-	throw new Error();
+    private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) {
+	TempDescriptor tmp=TempDescriptor.tempFactory("temp");
+	NodePair npe=flattenExpressionNode(fan.getExpression(),tmp);
+	FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
+	npe.getEnd().addNext(fn);
+	return new NodePair(npe.getBegin(),fn);
     }
 
-    private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) {
+    private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) {
+	// Two cases:
+	// left side is variable
+	// left side is field
+	
+	Operation base=an.getOperation().getBaseOp();
+	TempDescriptor src_tmp=TempDescriptor.tempFactory("src");
+	NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
+	FlatNode last=np_src.getEnd();
+	if (base!=null) {
+	    TempDescriptor src_tmp2=TempDescriptor.tempFactory("tmp");
+	    NodePair np_dst_init=flattenExpressionNode(an.getDest(),src_tmp2);
+	    last.addNext(np_dst_init.getBegin());
+	    TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst_tmp");
+	    FlatOpNode fon=new FlatOpNode(dst_tmp, src_tmp,src_tmp2, base);
+	    np_dst_init.getEnd().addNext(fon);
+	    last=fon;
+	    src_tmp=dst_tmp;
+	}
+	
+	if (an.getDest().kind()==Kind.FieldAccessNode) {
+	    FieldAccessNode fan=(FieldAccessNode)an.getDest();
+
+
+	    // Need to assign field
+	} else if (an.getDest().kind()==Kind.NameNode) {
+	    
+	} 
 	throw new Error();
     }
 
diff --git a/Robust/src/IR/Flat/FlatCall.java b/Robust/src/IR/Flat/FlatCall.java
new file mode 100644
index 00000000..057cb3c2
--- /dev/null
+++ b/Robust/src/IR/Flat/FlatCall.java
@@ -0,0 +1,26 @@
+package IR.Flat;
+import IR.MethodDescriptor;
+
+public class FlatCall extends FlatNode {
+    TempDescriptor args[];
+    TempDescriptor this_temp;
+    TempDescriptor dst;
+    MethodDescriptor method;
+    
+    public FlatCall(MethodDescriptor md, TempDescriptor dst, TempDescriptor this_temp, TempDescriptor[] args) {
+	this.method=md;
+	this.dst=dst;
+	this.this_temp=this_temp;
+	this.args=args;
+    }
+
+    public String toString() {
+	String st=dst+"="+method.toString()+"("+this_temp;
+	for(int i=0;i<args.length;i++) {
+	    st+=args[i].toString();
+	    if ((i+1)<args.length)
+		st+=", ";
+	}
+	return st+")";
+    }
+}
diff --git a/Robust/src/IR/Flat/FlatCastNode.java b/Robust/src/IR/Flat/FlatCastNode.java
new file mode 100644
index 00000000..2b3e45a7
--- /dev/null
+++ b/Robust/src/IR/Flat/FlatCastNode.java
@@ -0,0 +1,18 @@
+package IR.Flat;
+import IR.TypeDescriptor;
+
+public class FlatCastNode extends FlatNode {
+    TempDescriptor src;
+    TempDescriptor dst;
+    TypeDescriptor type;
+    
+    public FlatCastNode(TypeDescriptor type, TempDescriptor src, TempDescriptor dst) {
+	this.type=type;
+	this.src=src;
+	this.dst=dst;
+    }
+
+    public String toString() {
+	return dst.toString()+"=("+type.toString()+")"+src.toString();
+    }
+}
diff --git a/Robust/src/IR/Flat/FlatCondBranch.java b/Robust/src/IR/Flat/FlatCondBranch.java
index fa0f9817..9ebee1ee 100644
--- a/Robust/src/IR/Flat/FlatCondBranch.java
+++ b/Robust/src/IR/Flat/FlatCondBranch.java
@@ -10,10 +10,20 @@ public class FlatCondBranch extends FlatNode {
 
     public void addTrueNext(FlatNode n) {
 	next.setElementAt(n,0);
+	n.addPrev(this);
     }
 
     public void addFalseNext(FlatNode n) {
 	next.setElementAt(n,1);
+	n.addPrev(this);
+    }
+
+    public String toString() {
+	return "conditional branch";
+    }
+
+    public String toString(String negjump) {
+	return "if (!"+test_cond.toString()+") goto "+negjump;
     }
 
     public void addNext(FlatNode n) {
diff --git a/Robust/src/IR/Flat/FlatFieldNode.java b/Robust/src/IR/Flat/FlatFieldNode.java
new file mode 100644
index 00000000..79d7f6a4
--- /dev/null
+++ b/Robust/src/IR/Flat/FlatFieldNode.java
@@ -0,0 +1,22 @@
+package IR.Flat;
+import IR.FieldDescriptor;
+
+public class FlatFieldNode extends FlatNode {
+    TempDescriptor src;
+    TempDescriptor dst;
+    FieldDescriptor field;
+    
+    public FlatFieldNode(FieldDescriptor field, TempDescriptor src, TempDescriptor dst) {
+	this.field=field;
+	this.src=src;
+	this.dst=dst;
+    }
+
+    public FieldDescriptor getField() {
+	return field;
+    }
+
+    public String toString() {
+	return dst.toString()+"="+src.toString()+"."+field.toString();
+    }
+}
diff --git a/Robust/src/IR/Flat/FlatLiteralNode.java b/Robust/src/IR/Flat/FlatLiteralNode.java
new file mode 100644
index 00000000..b7aa9a91
--- /dev/null
+++ b/Robust/src/IR/Flat/FlatLiteralNode.java
@@ -0,0 +1,40 @@
+package IR.Flat;
+import IR.TypeDescriptor;
+
+public class FlatLiteralNode extends FlatNode {
+    Object value;
+    TypeDescriptor type;
+    TempDescriptor dst;
+
+    public FlatLiteralNode(TypeDescriptor type, Object o, TempDescriptor dst) {
+	this.type=type;
+	value=o;
+	this.dst=dst;
+    }
+
+    public Object getValue() {
+	return value;
+    }
+
+    public String printNode(int indent) {
+	/*	if (type==NULL)
+	    return dst+"=null";
+	    if (type==STRING) {
+	    return dst+"="+'"'+escapeString(value.toString())+'"';
+	    }*/
+	//return dst+"="+"/*"+getType()+ "*/"+value.toString();
+	return "";
+    }
+    private static String escapeString(String st) {
+	String new_st="";
+	for(int i=0;i<st.length();i++) {
+	    char x=st.charAt(i);
+	    if (x=='\n')
+		new_st+="\\n";
+	    else if (x=='"')
+		new_st+="'"+'"'+"'";
+	    else new_st+=x;
+	}
+	return new_st;
+    }
+}
diff --git a/Robust/src/IR/Flat/FlatMethod.java b/Robust/src/IR/Flat/FlatMethod.java
index 53c4e6c9..7845df9f 100644
--- a/Robust/src/IR/Flat/FlatMethod.java
+++ b/Robust/src/IR/Flat/FlatMethod.java
@@ -1,5 +1,6 @@
 package IR.Flat;
 import IR.MethodDescriptor;
+import java.util.*;
 
 public class FlatMethod extends FlatNode {
     FlatNode method_entry;
@@ -11,6 +12,73 @@ public class FlatMethod extends FlatNode {
     }
     
     public String toString() {
-	return method.toString()+"\n"+method_entry.toString();
+	return method.toString();
     }
+    
+    public String printMethod() {
+	String st="";
+	HashSet tovisit=new HashSet();
+	HashSet visited=new HashSet();
+	int labelindex=0;
+	Hashtable nodetolabel=new Hashtable();
+	tovisit.add(method_entry);
+	FlatNode current_node=null;
+	//Assign labels 1st
+	//Node needs a label if it is
+	while(!tovisit.isEmpty()) {
+	    FlatNode fn=(FlatNode)tovisit.iterator().next();
+	    tovisit.remove(fn);
+	    visited.add(fn);
+	    for(int i=0;i<fn.numNext();i++) {
+		FlatNode nn=fn.getNext(i);
+		if(i>0) {
+		    //1) Edge >1 of node
+		    nodetolabel.put(nn,new Integer(labelindex++));
+		}
+		if (!visited.contains(nn)) {
+		    tovisit.add(nn);
+		} else {
+		    //2) Join point
+		    nodetolabel.put(nn,new Integer(labelindex++));
+		}
+	    }
+	}
+
+	//Do the actual printing
+	tovisit=new HashSet();
+	visited=new HashSet();
+	tovisit.add(method_entry);
+	while(!tovisit.isEmpty()) {
+	    if (current_node==null) {
+		current_node=(FlatNode)tovisit.iterator().next();
+		tovisit.remove(current_node);
+	    }
+	    visited.add(current_node);
+	    if (nodetolabel.containsKey(current_node))
+		st+="L"+nodetolabel.get(current_node)+":\n";
+	    st+=current_node.toString();
+	    if (current_node.numNext()==0) {
+		current_node=null;
+	    } else if(current_node.numNext()==1) {
+		FlatNode nextnode=current_node.getNext(0);
+		if (visited.contains(nextnode)) {
+		    st+="goto L"+nodetolabel.get(nextnode)+"\n";
+		    current_node=null;
+		} else
+		    current_node=nextnode;
+	    } else if (current_node.numNext()==2) {
+		/* Branch */
+		st+=((FlatCondBranch)current_node).toString("L"+nodetolabel.get(current_node.getNext(1)));
+		if (visited.contains(current_node.getNext(0))) {
+		    st+="goto L"+nodetolabel.get(current_node.getNext(0))+"\n";
+		    current_node=null;
+		} else
+		    current_node=current_node.getNext(0);
+		if (!visited.contains(current_node.getNext(1)))
+		    tovisit.add(current_node.getNext(1));
+	    } else throw new Error();
+	}
+	return st;
+    }
+
 }
diff --git a/Robust/src/IR/Flat/FlatNew.java b/Robust/src/IR/Flat/FlatNew.java
new file mode 100644
index 00000000..e8aeaa63
--- /dev/null
+++ b/Robust/src/IR/Flat/FlatNew.java
@@ -0,0 +1,16 @@
+package IR.Flat;
+import IR.TypeDescriptor;
+
+public class FlatNew extends FlatNode {
+    TempDescriptor dst;
+    TypeDescriptor type;
+    
+    public FlatNew(TypeDescriptor type, TempDescriptor dst) {
+	this.type=type;
+	this.dst=dst;
+    }
+
+    public String toString() {
+	return dst.toString()+"= NEW "+type.toString();
+    }
+}
diff --git a/Robust/src/IR/Flat/FlatNode.java b/Robust/src/IR/Flat/FlatNode.java
index b53eb433..4824875a 100644
--- a/Robust/src/IR/Flat/FlatNode.java
+++ b/Robust/src/IR/Flat/FlatNode.java
@@ -2,13 +2,31 @@ package IR.Flat;
 import java.util.Vector;
 
 public class FlatNode {
-    Vector next;
-
+    protected Vector next;
+    protected Vector prev;
 
     public String toString() {
 	throw new Error();
     }
+    public int numNext() {
+	return next.size();
+    }
+    public FlatNode getNext(int i) {
+	return (FlatNode) next.get(i);
+    }
+
+    public int numPrev() {
+	return prev.size();
+    }
+    public FlatNode getPrev(int i) {
+	return (FlatNode) prev.get(i);
+    }
+    
     public void addNext(FlatNode n) {
 	next.add(n);
+	n.addPrev(this);
+    }
+    protected void addPrev(FlatNode p) {
+	prev.add(p);
     }
 }
diff --git a/Robust/src/IR/MethodDescriptor.java b/Robust/src/IR/MethodDescriptor.java
index a7df7866..28eb9724 100644
--- a/Robust/src/IR/MethodDescriptor.java
+++ b/Robust/src/IR/MethodDescriptor.java
@@ -16,6 +16,7 @@ public class MethodDescriptor extends Descriptor {
     protected String identifier;
     protected Vector param_name;
     protected Vector param_type;
+    protected SymbolTable paramtable;
     
     public MethodDescriptor(Modifiers m, TypeDescriptor rt, String identifier) {
 	super(identifier);
@@ -26,10 +27,35 @@ public class MethodDescriptor extends Descriptor {
 	this.uniqueid=count++;
 	param_name=new Vector();
 	param_type=new Vector();
+	paramtable=new SymbolTable();
     }
+    public TypeDescriptor getReturnType() {
+	return returntype;
+    }
+
+    public SymbolTable getParameterTable() {
+	return paramtable;
+    }
+
     public void addParameter(TypeDescriptor type, String paramname) {
 	param_name.add(paramname);
 	param_type.add(type);
+	if (paramtable.getFromSameScope(paramname)!=null) {
+	    throw new Error("Parameter "+paramname+" already defined");
+	}
+	paramtable.add(paramname,type);
+    }
+
+    public int numParameters() {
+	return param_name.size();
+    }
+
+    public String getParamName(int i) {
+	return (String) param_name.get(i);
+    }
+
+    public TypeDescriptor getParamType(int i) {
+	return (TypeDescriptor) param_type.get(i);
     }
 
     public String toString() {
diff --git a/Robust/src/IR/State.java b/Robust/src/IR/State.java
index 1bd8067e..a83b1af7 100644
--- a/Robust/src/IR/State.java
+++ b/Robust/src/IR/State.java
@@ -6,16 +6,14 @@ import java.util.*;
 
 public class State {
     public State(ParseNode parsetree) {
-	globals=new SymbolTable();
 	this.parsetree=parsetree;
-	this.classset=new HashSet();
+	this.classes=new SymbolTable();
 	this.treemethodmap=new Hashtable();
 	this.flatmethodmap=new Hashtable();
     }
 
-    public SymbolTable globals;
+    public SymbolTable classes;
     public ParseNode parsetree;
-    public HashSet classset;
     public Hashtable treemethodmap;
     public Hashtable flatmethodmap;
 
@@ -30,12 +28,17 @@ public class State {
     }
 
     public void addClass(ClassDescriptor tdn) {
-	classset.add(tdn);
+	if (classes.contains(tdn.getSymbol()))
+	    throw new Error("Class "+tdn.getSymbol()+" defined twice");
+	classes.add(tdn);
     }
 
     public BlockNode getMethodBody(MethodDescriptor md) {
 	return (BlockNode)treemethodmap.get(md);
-	
+    }
+
+    public SymbolTable getClassSymbolTable() {
+	return classes;
     }
 
     public FlatMethod getMethodFlat(MethodDescriptor md) {
diff --git a/Robust/src/IR/SymbolTable.java b/Robust/src/IR/SymbolTable.java
index 7203183e..a7218ffd 100644
--- a/Robust/src/IR/SymbolTable.java
+++ b/Robust/src/IR/SymbolTable.java
@@ -17,17 +17,12 @@ public class SymbolTable {
 	this.parent = parent;
     }
 
-    //public void add(String name, Descriptor d) {
-	//table.put(name, d);
-    //}
-
     public void add(Descriptor d) {
-	table.put(d.getSymbol(), d);
+	add(d.getSymbol(), d);
     }
     
     public void add(String name, Descriptor d) {
 	table.put(name, d);
-	
     }
 
     public void dump() {
@@ -59,10 +54,18 @@ public class SymbolTable {
 	return table.keys();
     }
 
+    public Iterator getNamesIterator() {
+	return table.keySet().iterator();
+    }
+
     public Enumeration getDescriptors() {
 	return table.elements();
     }
 
+    public Iterator getDescriptorsIterator() {
+	return table.values().iterator();
+    }
+
     public Iterator descriptors() {
         return table.values().iterator();
     }
diff --git a/Robust/src/IR/Tree/AssignmentNode.java b/Robust/src/IR/Tree/AssignmentNode.java
index f30ccb56..31f5b4fa 100644
--- a/Robust/src/IR/Tree/AssignmentNode.java
+++ b/Robust/src/IR/Tree/AssignmentNode.java
@@ -11,6 +11,18 @@ public class AssignmentNode extends ExpressionNode {
 	right=r;
 	this.op=op;
     }
+    
+    public ExpressionNode getDest() {
+	return left;
+    }
+
+    public ExpressionNode getSrc() {
+	return right;
+    }
+
+    public AssignOperation getOperation() {
+	return op;
+    }
 
     public String printNode(int indent) {
 	return left.printNode(indent)+" "+op.toString()+" "+right.printNode(indent);
diff --git a/Robust/src/IR/Tree/BlockNode.java b/Robust/src/IR/Tree/BlockNode.java
index 94179eea..62b3b67d 100644
--- a/Robust/src/IR/Tree/BlockNode.java
+++ b/Robust/src/IR/Tree/BlockNode.java
@@ -1,15 +1,23 @@
 package IR.Tree;
 import java.util.Vector;
+import IR.*;
 
 public class BlockNode extends TreeNode {
     Vector blockstatements;
     int printStyle=0;
+    protected SymbolTable table;
+
     public final static int NORMAL=0;
     public final static int NOBRACES=1;
     public final static int EXPRLIST=2;
     
     public BlockNode() {
 	blockstatements=new Vector();
+	table=new SymbolTable();
+    }
+
+    public SymbolTable getVarTable() {
+	return table;
     }
 
     public void addBlockStatement(BlockStatementNode bsn) {
diff --git a/Robust/src/IR/Tree/BuildIR.java b/Robust/src/IR/Tree/BuildIR.java
index 0dafcc9d..0995b447 100644
--- a/Robust/src/IR/Tree/BuildIR.java
+++ b/Robust/src/IR/Tree/BuildIR.java
@@ -29,10 +29,12 @@ public class BuildIR {
 
     public ClassDescriptor parseTypeDecl(ParseNode pn) {
 	if (isNode(pn, "class_declaration")) {
-	    ClassDescriptor cn=new ClassDescriptor();
-	    cn.setName(pn.getChild("name").getTerminal());
+	    ClassDescriptor cn=new ClassDescriptor(pn.getChild("name").getTerminal());
 	    if (!isEmpty(pn.getChild("super").getTerminal())) {
 		/* parse superclass name */
+		ParseNode snn=pn.getChild("super").getChild("type").getChild("class").getChild("name");
+		NameDescriptor nd=parseName(snn);
+		cn.setSuper(nd.toString());
 	    }
 	    cn.setModifiers(parseModifiersList(pn.getChild("modifiers")));
 	    parseClassBody(cn, pn.getChild("classbody"));
@@ -315,6 +317,14 @@ public class BuildIR {
 	    ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild());
 	    BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild());
 	    blockstatements.add(new LoopNode(init,condition,update,body));
+	} else if (isNode(pn,"whilestatement")) {
+	    ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild());
+	    BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild());
+	    blockstatements.add(new LoopNode(condition,body,LoopNode.WHILELOOP));
+	} else if (isNode(pn,"dowhilestatement")) {
+	    ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild());
+	    BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild());
+	    blockstatements.add(new LoopNode(condition,body,LoopNode.DOWHILELOOP));
    	} else {
 	    System.out.println("---------------");
 	    System.out.println(pn.PPrint(3,true));
diff --git a/Robust/src/IR/Tree/CastNode.java b/Robust/src/IR/Tree/CastNode.java
index e4f82ec4..4e7dd8dd 100644
--- a/Robust/src/IR/Tree/CastNode.java
+++ b/Robust/src/IR/Tree/CastNode.java
@@ -18,6 +18,14 @@ public class CastNode extends ExpressionNode  {
 	this.etd=type;
     }
 
+    public TypeDescriptor getType() {
+	return td;
+    }
+
+    public ExpressionNode getExpression() {
+	return exp;
+    }
+
     public String printNode(int indentlevel) {
 	if (etd==null)
 	    return "("+td.toString()+")"+exp.printNode(indentlevel);
diff --git a/Robust/src/IR/Tree/CreateObjectNode.java b/Robust/src/IR/Tree/CreateObjectNode.java
index 99b6783b..1d28efcf 100644
--- a/Robust/src/IR/Tree/CreateObjectNode.java
+++ b/Robust/src/IR/Tree/CreateObjectNode.java
@@ -1,10 +1,12 @@
 package IR.Tree;
 import java.util.Vector;
 import IR.TypeDescriptor;
+import IR.MethodDescriptor;
 
 public class CreateObjectNode extends ExpressionNode {
     TypeDescriptor td;
     Vector argumentlist;
+    MethodDescriptor md;
 
     public CreateObjectNode(TypeDescriptor type) {
 	td=type;
@@ -14,6 +16,26 @@ public class CreateObjectNode extends ExpressionNode {
 	argumentlist.add(en);
     }
 
+    public void setConstructor(MethodDescriptor md) {
+	this.md=md;
+    }
+
+    public MethodDescriptor getConstructor() {
+	return md;
+    }
+
+    public TypeDescriptor getType() {
+	return td;
+    }
+
+    public int numArgs() {
+	return argumentlist.size();
+    }
+
+    public ExpressionNode getArg(int i) {
+	return (ExpressionNode) argumentlist.get(i);
+    }
+
     public String printNode(int indent) {
 	String st="new "+td.toString()+"(";
 	for(int i=0;i<argumentlist.size();i++) {
diff --git a/Robust/src/IR/Tree/ExpressionNode.java b/Robust/src/IR/Tree/ExpressionNode.java
index 058d6294..a2cab155 100644
--- a/Robust/src/IR/Tree/ExpressionNode.java
+++ b/Robust/src/IR/Tree/ExpressionNode.java
@@ -1,6 +1,10 @@
 package IR.Tree;
+import IR.TypeDescriptor;
 
 public class ExpressionNode extends TreeNode {
+    public TypeDescriptor getType() {
+	throw new Error();
+    }
 
     public String printNode(int indentlevel) {
 	return null;
diff --git a/Robust/src/IR/Tree/FieldAccessNode.java b/Robust/src/IR/Tree/FieldAccessNode.java
index a2284d19..eee8ffb4 100644
--- a/Robust/src/IR/Tree/FieldAccessNode.java
+++ b/Robust/src/IR/Tree/FieldAccessNode.java
@@ -1,14 +1,28 @@
 package IR.Tree;
+import IR.FieldDescriptor;
 
 public class FieldAccessNode extends ExpressionNode {
     ExpressionNode left;
     String fieldname;
+    FieldDescriptor field;
 
     public FieldAccessNode(ExpressionNode l, String field) {
 	fieldname=field;
 	left=l;
     }
 
+    public void setField(FieldDescriptor fd) {
+	field=fd;
+    }
+
+    public FieldDescriptor getField() {
+	return field;
+    }
+
+    public ExpressionNode getExpression() {
+	return left;
+    }
+
     public String printNode(int indent) {
 	return left.printNode(indent)+"."+fieldname;
     }
diff --git a/Robust/src/IR/Tree/LiteralNode.java b/Robust/src/IR/Tree/LiteralNode.java
index 4f273fde..db1f90cb 100644
--- a/Robust/src/IR/Tree/LiteralNode.java
+++ b/Robust/src/IR/Tree/LiteralNode.java
@@ -8,7 +8,6 @@ public class LiteralNode extends ExpressionNode {
     public final static int STRING=5;
     public final static int NULL=6;
 
-
     Object value;
     int type;
     
@@ -17,6 +16,10 @@ public class LiteralNode extends ExpressionNode {
 	value=o;
     }
 
+    public Object getValue() {
+	return value;
+    }
+
     private static int parseType(String type) {
 	if (type.equals("integer"))
 	    return INTEGER;
@@ -33,7 +36,7 @@ public class LiteralNode extends ExpressionNode {
 	else throw new Error();
     }
 
-    private String getType() {
+    private String getStringType() {
 	if (type==INTEGER)
 	    return "integer";
 	else if (type==FLOAT)
diff --git a/Robust/src/IR/Tree/MethodInvokeNode.java b/Robust/src/IR/Tree/MethodInvokeNode.java
index 705b316c..08ad56f9 100644
--- a/Robust/src/IR/Tree/MethodInvokeNode.java
+++ b/Robust/src/IR/Tree/MethodInvokeNode.java
@@ -1,18 +1,21 @@
 package IR.Tree;
 import java.util.Vector;
 import IR.NameDescriptor;
+import IR.MethodDescriptor;
 
 public class MethodInvokeNode extends ExpressionNode {
     NameDescriptor nd;
     Vector argumentlist;
     String methodid;
     ExpressionNode en;
+    MethodDescriptor md;
 
     public MethodInvokeNode(NameDescriptor name) {
 	nd=name;
 	argumentlist=new Vector();
 	methodid=null;
 	en=null;
+	md=null;
     }
 
     public MethodInvokeNode(String methodid, ExpressionNode exp) {
@@ -20,12 +23,33 @@ public class MethodInvokeNode extends ExpressionNode {
 	this.en=exp;
 	nd=null;
 	argumentlist=new Vector();
+	md=null;
+    }
+
+    public ExpressionNode getExpression() {
+	return en;
+    }
+
+    public void setMethod(MethodDescriptor md) {
+	this.md=md;
+    }
+
+    public MethodDescriptor getMethod() {
+	return md;
     }
 
     public void addArgument(ExpressionNode en) {
 	argumentlist.add(en);
     }
 
+    public int numArgs() {
+	return argumentlist.size();
+    }
+
+    public ExpressionNode getArg(int i) {
+	return (ExpressionNode) argumentlist.get(i);
+    }
+
     public String printNode(int indent) {
 	String st;
 	if (nd==null) {
diff --git a/Robust/src/IR/Tree/SemanticCheck.java b/Robust/src/IR/Tree/SemanticCheck.java
new file mode 100644
index 00000000..9c8294b7
--- /dev/null
+++ b/Robust/src/IR/Tree/SemanticCheck.java
@@ -0,0 +1,189 @@
+package IR.Tree;
+
+import java.util.*;
+import IR.*;
+
+public class SemanticCheck {
+    State state;
+
+    public SemanticCheck(State state) {
+	this.state=state;
+    }
+
+    public void semanticCheck() {
+	SymbolTable classtable=state.getClassSymbolTable();
+	Iterator it=classtable.getDescriptorsIterator();
+	while(it.hasNext()) {
+	    ClassDescriptor cd=(ClassDescriptor)it.next();
+	    System.out.println("Checking class: "+cd);
+	    for(Iterator field_it=cd.getFields();field_it.hasNext();) {
+		FieldDescriptor fd=(FieldDescriptor)field_it.next();
+		System.out.println("Checking field: "+fd);
+		checkField(cd,fd);
+	    }
+
+	    for(Iterator method_it=cd.getMethods();method_it.hasNext();) {
+		MethodDescriptor md=(MethodDescriptor)method_it.next();
+		checkMethod(cd,md);
+	    }
+	}
+    }
+
+    public void checkTypeDescriptor(TypeDescriptor td) {
+	if (td.isPrimitive())
+	    return; /* Done */
+	if (td.isClass()) {
+	    String name=td.toString();
+	    ClassDescriptor field_cd=(ClassDescriptor)state.getClassSymbolTable().get(name);
+	    if (field_cd==null)
+		throw new Error("Undefined class "+name);
+	    td.setClassDescriptor(field_cd);
+	    return;
+	}
+	throw new Error();
+    }
+
+    public void checkField(ClassDescriptor cd, FieldDescriptor fd) {
+	checkTypeDescriptor(fd.getType());
+    }
+
+    public void checkMethod(ClassDescriptor cd, MethodDescriptor md) {
+	/* Check return type */
+	if (!md.getReturnType().isVoid())
+	    checkTypeDescriptor(md.getReturnType());
+	for(int i=0;i<md.numParameters();i++) {
+	    TypeDescriptor param_type=md.getParamType(i);
+	    checkTypeDescriptor(param_type);
+	}
+	BlockNode bn=state.getMethodBody(md);
+	/* Link the naming environments */
+	md.getParameterTable().setParent(cd.getFieldTable());
+	checkBlockNode(md, md.getParameterTable(),bn);
+    }
+    
+    public void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
+	/* Link in the naming environment */
+	bn.getVarTable().setParent(nametable);
+	for(int i=0;i<bn.size();i++) {
+	    BlockStatementNode bsn=bn.get(i);
+	    checkBlockStatementNode(md, bn.getVarTable(),bsn);
+	}
+    }
+    
+    public void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable, BlockStatementNode bsn) {
+	switch(bsn.kind()) {
+	case Kind.BlockExpressionNode:
+	    checkBlockExpressionNode(md, nametable,(BlockExpressionNode)bsn);
+	    return;
+
+	case Kind.DeclarationNode:
+	    checkDeclarationNode(md, nametable, (DeclarationNode)bsn);
+	    return;
+	    
+	case Kind.IfStatementNode:
+	    checkIfStatementNode(md, nametable, (IfStatementNode)bsn);
+	    return;
+	    
+	case Kind.LoopNode:
+	    checkLoopNode(md, nametable, (LoopNode)bsn);
+	    return;
+	    
+	case Kind.ReturnNode:
+	    checkReturnNode(md, nametable, (ReturnNode)bsn);
+	    return;
+
+	case Kind.SubBlockNode:
+	    checkSubBlockNode(md, nametable, (SubBlockNode)bsn);
+	    return;
+	}
+	throw new Error();
+    }
+
+    void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable, BlockExpressionNode ben) {
+	checkExpressionNode(md, nametable, ben.getExpression(), null);
+    }
+
+    void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable,  DeclarationNode dn) {
+	VarDescriptor vd=dn.getVarDescriptor();
+	checkTypeDescriptor(vd.getType());
+	Descriptor d=nametable.get(vd.getSymbol());
+	if ((d==null)||
+	    (d instanceof FieldDescriptor)) {
+	    nametable.add(vd);
+	} else
+	    throw new Error(vd.getSymbol()+" defined a second time");
+	checkExpressionNode(md, nametable, dn.getExpression(), vd.getType());
+    }
+    
+    void checkSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn) {
+	checkBlockNode(md, nametable, sbn.getBlockNode());
+    }
+
+    void checkReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn) {
+	checkExpressionNode(md, nametable, rn.getReturnExpression(), md.getReturnType());
+    }
+
+    void checkIfStatementNode(MethodDescriptor md, SymbolTable nametable, IfStatementNode isn) {
+	checkExpressionNode(md, nametable, isn.getCondition(), new TypeDescriptor(TypeDescriptor.BOOLEAN));
+	checkBlockNode(md, nametable, isn.getTrueBlock());
+	checkBlockNode(md, nametable, isn.getFalseBlock());
+    }
+    
+    void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) {
+	switch(en.kind()) {
+        case Kind.AssignmentNode:
+            checkAssignmentNode(md,nametable,(AssignmentNode)en,td);
+	    return;
+        case Kind.CastNode:
+	    checkCastNode(md,nametable,(CastNode)en,td);
+	    return;
+        case Kind.CreateObjectNode:
+	    checkCreateObjectNode(md,nametable,(CreateObjectNode)en,td);
+	    return;
+        case Kind.FieldAccessNode:
+	    checkFieldAccessNode(md,nametable,(FieldAccessNode)en,td);
+	    return;
+        case Kind.LiteralNode:
+	    checkLiteralNode(md,nametable,(LiteralNode)en,td);
+	    return;
+        case Kind.MethodInvokeNode:
+	    checkMethodInvokeNode(md,nametable,(MethodInvokeNode)en,td);
+	    return;
+        case Kind.NameNode:
+	    checkNameNode(md,nametable,(NameNode)en,td);
+	    return;
+        case Kind.OpNode:
+            checkOpNode(md,nametable,(OpNode)en,td);
+	    return;
+        }
+	throw new Error();
+    }
+
+    void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an, TypeDescriptor td) {
+	
+    }
+
+    void checkCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn, TypeDescriptor td) {
+    }
+
+    void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable, CreateObjectNode con, TypeDescriptor td) {
+    }
+
+    void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable, FieldAccessNode fan, TypeDescriptor td) {
+    }
+
+    void checkLiteralNode(MethodDescriptor md, SymbolTable nametable, LiteralNode ln, TypeDescriptor td) {
+    }
+
+    void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable, MethodInvokeNode min, TypeDescriptor td) {
+    }
+
+    void checkNameNode(MethodDescriptor md, SymbolTable nametable, NameNode nn, TypeDescriptor td) {
+    }
+
+    void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on,TypeDescriptor td) {
+    }
+
+    void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln) {
+    }
+}
diff --git a/Robust/src/IR/TypeDescriptor.java b/Robust/src/IR/TypeDescriptor.java
index e7a79eef..1832c571 100644
--- a/Robust/src/IR/TypeDescriptor.java
+++ b/Robust/src/IR/TypeDescriptor.java
@@ -16,16 +16,36 @@ public class TypeDescriptor extends Descriptor {
     public static final int FLOAT=7;
     public static final int DOUBLE=8;
     public static final int VOID=9;
-    public static final int CLASS=10;
+    public static final int NULL=10;
+    public static final int CLASS=11;
+
 
 
     int type;
     NameDescriptor name_desc;
-    
+    ClassDescriptor class_desc;
+
+    public void setClassDescriptor(ClassDescriptor cd) {
+	class_desc=cd;
+    }
+
+    public boolean isVoid() {
+	return type==VOID;
+    }
+
+    public boolean isPrimitive() {
+	return ((type>=BYTE)&&(type<=DOUBLE));
+    }
+
+    public boolean isClass() {
+	return type==CLASS;
+    }
+
     public TypeDescriptor(NameDescriptor name) {
 	super(name.toString());
 	this.type=CLASS;
 	this.name_desc=name;
+	this.class_desc=null;
     }
 
     public TypeDescriptor(int t) {
@@ -59,6 +79,8 @@ public class TypeDescriptor extends Descriptor {
 	    return "double";
 	else if (type==VOID)
 	    return "void";
+	else if (type==NULL)
+	    return "null";
 	else throw new Error();
     }
 }
diff --git a/Robust/src/IR/VarDescriptor.java b/Robust/src/IR/VarDescriptor.java
index d8726f28..42038b2a 100644
--- a/Robust/src/IR/VarDescriptor.java
+++ b/Robust/src/IR/VarDescriptor.java
@@ -25,6 +25,10 @@ public class VarDescriptor extends Descriptor {
 	return identifier;
     }
 
+    public TypeDescriptor getType() {
+	return td;
+    }
+
     public String toString() {
 	    return td.toString()+" "+identifier;
     }
diff --git a/Robust/src/Main/Main.java b/Robust/src/Main/Main.java
index 8eebe0a1..e9d89b96 100644
--- a/Robust/src/Main/Main.java
+++ b/Robust/src/Main/Main.java
@@ -5,6 +5,7 @@ import java.io.BufferedReader;
 import java.io.FileReader;
 import IR.Tree.ParseNode;
 import IR.Tree.BuildIR;
+import IR.Tree.SemanticCheck;
 import IR.Flat.BuildFlat;
 import IR.State;
 
@@ -21,8 +22,12 @@ public class Main {
     ParseNode p=(ParseNode) g./*debug_*/parse().value;
     //    System.out.println(p.PPrint(2,true));
     State state=new State(p);
+
     BuildIR bir=new BuildIR(state);
     bir.buildtree();
+
+    SemanticCheck sc=new SemanticCheck(state);
+    sc.semanticCheck();
     
     BuildFlat bf=new BuildFlat(state);
     bf.buildFlat();
diff --git a/Robust/src/Parse/java14.cup b/Robust/src/Parse/java14.cup
index 74945097..761df786 100644
--- a/Robust/src/Parse/java14.cup
+++ b/Robust/src/Parse/java14.cup
@@ -178,7 +178,7 @@ non terminal ParseNode if_then_else_statement, if_then_else_statement_no_short_i
 //non terminal ParseNode switch_block_statement_group;
 //non terminal ParseNode switch_labels, switch_label;
 non terminal ParseNode while_statement, while_statement_no_short_if;
-//non terminal ParseNode do_statement;
+non terminal ParseNode do_statement;
 non terminal ParseNode for_statement, for_statement_no_short_if;
 non terminal ParseNode for_init_opt, for_init;
 non terminal ParseNode for_update_opt, for_update;
@@ -774,7 +774,7 @@ statement_without_trailing_substatement ::=
 	|	empty_statement:st {: RESULT=st; :}
 	|	expression_statement:st {: RESULT=st; :}
 //	|	switch_statement
-//	|	do_statement
+	|	do_statement
 	|	break_statement:st {: RESULT=st; :}
 	|	continue_statement:st {: RESULT=st; :}
 	|	return_statement:st {: RESULT=st; :}
@@ -876,9 +876,14 @@ while_statement_no_short_if ::=
 		RESULT=pn;
 		:}
 	;
-//do_statement ::=
-//		DO statement WHILE LPAREN expression RPAREN SEMICOLON
-//	;
+do_statement ::=
+		DO statement:st WHILE LPAREN expression:exp RPAREN SEMICOLON {: 
+		ParseNode pn=new ParseNode("dowhilestatement");
+		pn.addChild("condition").addChild(exp);
+		pn.addChild("statement").addChild(st);
+		RESULT=pn;
+	:}
+	;
 for_statement ::=
 		FOR LPAREN for_init_opt:init SEMICOLON expression_opt:exp SEMICOLON
 			for_update_opt:update RPAREN statement:st {: 
diff --git a/Robust/src/t.test b/Robust/src/t.test
index 9e40fa59..1e99ef98 100644
--- a/Robust/src/t.test
+++ b/Robust/src/t.test
@@ -216,3 +216,8 @@ public class ParseNode {
 
 }
 
+public class String {}
+
+public class ParseNodeVector {}
+
+public class Object {}
-- 
2.34.1