Add support for static inner classes in mgc version. Currently we only implemented...
authorjzhou <jzhou>
Fri, 29 Oct 2010 00:15:37 +0000 (00:15 +0000)
committerjzhou <jzhou>
Fri, 29 Oct 2010 00:15:37 +0000 (00:15 +0000)
Robust/src/IR/ClassDescriptor.java
Robust/src/IR/Tree/BuildIR.java
Robust/src/Parse/java14.cup

index d16940e49af6a32cca6960a7becfcdd71a7113f7..8e00b5bf7f9fc375003dbfb9113cb9522d28f50f 100644 (file)
@@ -23,6 +23,12 @@ public class ClassDescriptor extends Descriptor {
   // for interfaces
   Vector<String> superinterfaces;
   SymbolTable superIFdesc;
+  
+  // for inner classes
+  boolean isInnerClass=false;
+  String surroundingclass=null;
+  ClassDescriptor surroudingdesc=null;
+  SymbolTable innerdescs;
 
   public ClassDescriptor(String classname, boolean isInterface) {
     this("", classname, isInterface);
@@ -43,6 +49,7 @@ public class ClassDescriptor extends Descriptor {
     this.packagename=packagename;
     superinterfaces = new Vector<String>();
     superIFdesc = new SymbolTable();
+    this.innerdescs = new SymbolTable();
   }
 
   public int getId() {
@@ -126,6 +133,14 @@ public class ClassDescriptor extends Descriptor {
     }
     if (printcr)
       st+="\n";
+    
+    for(Iterator it=this.getInnerClasses(); it.hasNext();) {
+      ClassDescriptor icd=(ClassDescriptor)it.next();
+      st+=icd.printTree(state)+"\n";
+      printcr=true;
+    }
+    if (printcr)
+      st+="\n";
 
     for(Iterator it=getMethods(); it.hasNext();) {
       MethodDescriptor md=(MethodDescriptor)it.next();
@@ -217,4 +232,60 @@ public class ClassDescriptor extends Descriptor {
   public boolean isInterface() {
     return this.classid == -2;
   }
+  
+  public boolean isStatic() {
+    return this.modifiers.isStatic();
+  }
+  
+  public void setAsInnerClass() {
+    this.isInnerClass = true;
+  }
+  
+  public boolean isInnerClass() {
+    return this.isInnerClass;
+  }
+  
+  public void setSurroundingClass(String sclass) {
+    this.surroundingclass=sclass;
+  }
+
+  public String getSurrounding() {
+    return this.surroundingclass;
+  }
+
+  public ClassDescriptor getSurroundingDesc() {
+    return this.surroudingdesc;
+  }
+
+  public void setSurrounding(ClassDescriptor scd) {
+    this.surroudingdesc=scd;
+  }
+  
+  public void addInnerClass(ClassDescriptor icd) {
+    this.innerdescs.add(icd);
+  }
+  
+  public Iterator getInnerClasses() {
+    return this.innerdescs.getDescriptorsIterator();
+  }
+
+  public SymbolTable getInnerClassTable() {
+    return this.innerdescs;
+  }
+  
+  /*public String getSymbol() {
+    if(this.isInnerClass) {
+      return this.surroudingdesc.getSymbol() + "." + name;
+    } else {
+      return name;
+    }
+  }
+
+  public String getSafeSymbol() {
+    if(this.isInnerClass) {
+      return this.surroudingdesc.getSafeSymbol()+ "." + safename;
+    } else {
+      return safename;
+    }
+  }*/
 }
index f1372753f6ee0f72ea519da589c2939ce2b042db..cf43c80c96a53861a7aaf83b5d14a683a5f99304 100644 (file)
@@ -55,6 +55,30 @@ public class BuildIR {
          if (toanalyze!=null)
            toanalyze.add(cn);
          state.addClass(cn);
+      // for inner classes
+      if(state.MGC) {
+        // TODO add version for normal Java later
+        HashSet tovisit = new HashSet();
+        Iterator it_icds = cn.getInnerClasses();
+        while(it_icds.hasNext()) {
+          tovisit.add(it_icds.next());
+        }
+        
+        while(!tovisit.isEmpty()) {
+          ClassDescriptor cd = (ClassDescriptor)tovisit.iterator().next();
+          tovisit.remove(cd);
+          
+          if(toanalyze != null) {
+            toanalyze.add(cd);
+          }
+          state.addClass(cd);
+          
+          Iterator it_ics = cd.getInnerClasses();
+          while(it_ics.hasNext()) {
+            tovisit.add(it_ics.next());
+          }
+        }
+      }
        } else if (isNode(type_pn,"task_declaration")) {
          TaskDescriptor td=parseTaskDecl(type_pn);
          if (toanalyze!=null)
@@ -361,7 +385,6 @@ public class BuildIR {
   
   private void parseClassMember(ClassDescriptor cn, ParseNode pn) {
     ParseNode fieldnode=pn.getChild("field");
-
     if (fieldnode!=null) {
       parseFieldDecl(cn,fieldnode.getChild("field_declaration"));
       return;
@@ -371,6 +394,16 @@ public class BuildIR {
       parseMethodDecl(cn,methodnode.getChild("method_declaration"));
       return;
     }
+    ParseNode innerclassnode=pn.getChild("inner_class_declaration");
+    if (innerclassnode!=null) {
+      if(state.MGC){
+        parseInnerClassDecl(cn,innerclassnode);
+        return;
+      } else {
+        // TODO add version for noraml Java later
+        throw new Error("Error: inner class in Class " + cn.getSymbol() + " is not supported yet");
+      }
+    }
     ParseNode flagnode=pn.getChild("flag");
     if (flagnode!=null) {
       parseFlagDecl(cn, flagnode.getChild("flag_declaration"));
@@ -378,6 +411,44 @@ public class BuildIR {
     }
     throw new Error();
   }
+  
+  private ClassDescriptor parseInnerClassDecl(ClassDescriptor cn, ParseNode pn) {
+    ClassDescriptor icn=new ClassDescriptor(pn.getChild("name").getTerminal(), false);
+    icn.setAsInnerClass();
+    icn.setSurroundingClass(cn.getSymbol());
+    icn.setSurrounding(cn);
+    cn.addInnerClass(icn);
+    if (!isEmpty(pn.getChild("super").getTerminal())) {
+      /* parse superclass name */
+      ParseNode snn=pn.getChild("super").getChild("type").getChild("class").getChild("name");
+      NameDescriptor nd=parseName(snn);
+      icn.setSuper(nd.toString());
+    } else {
+      if (!(icn.getSymbol().equals(TypeUtil.ObjectClass)||
+          icn.getSymbol().equals(TypeUtil.TagClass)))
+        icn.setSuper(TypeUtil.ObjectClass);
+    }
+    // check inherited interfaces
+    if (!isEmpty(pn.getChild("superIF").getTerminal())) {
+      /* parse inherited interface name */
+      ParseNode snlist=pn.getChild("superIF").getChild("interface_type_list");
+      ParseNodeVector pnv=snlist.getChildren();
+      for(int i=0; i<pnv.size(); i++) {
+        ParseNode decl=pnv.elementAt(i);
+        if (isNode(decl,"type")) {
+          NameDescriptor nd=parseName(decl.getChild("class").getChild("name"));
+          icn.addSuperInterface(nd.toString());
+        }
+      }
+    }
+    icn.setModifiers(parseModifiersList(pn.getChild("modifiers")));
+    if(!icn.isStatic()) {
+      throw new Error("Error: inner class " + icn.getSymbol() + " in Class " + 
+          cn.getSymbol() + " is not a nested class and is not supported yet!");
+    }
+    parseClassBody(icn, pn.getChild("classbody"));
+    return icn;
+  }
 
   private TypeDescriptor parseTypeDescriptor(ParseNode pn) {
     ParseNode tn=pn.getChild("type");
index 866831ee50a979bd2b5c40321b1451a9e1c53bac..630ca714694532fc59d28ac28665dec4f23cd018 100644 (file)
@@ -820,19 +820,19 @@ class_member_declaration ::=
        RESULT=(new ParseNode("method")).addChild(method).getRoot(); 
        :}
        /* repeat the prod for 'class_declaration' here: */
-//     |       modifiers_opt:mo CLASS IDENTIFIER:id super_opt:so interfaces_opt:ifo class_body:body
-//     {:
-//     ParseNode pn=new ParseNode("inner_class_declaration");
-//     pn.addChild("modifiers").addChild(mo);
-//     pn.addChild("name").addChild(id);
-//     pn.addChild("super").addChild(so);
-//     pn.addChild("superIF").addChild(ifo);
-//     pn.addChild("classbody").addChild(body);
-//     RESULT=pn;
-//     :}
-    |       interface_declaration:interfaced {: 
-       RESULT=(new ParseNode("interface")).addChild(interfaced).getRoot(); 
+       |       modifiers_opt:mo CLASS IDENTIFIER:id super_opt:so interfaces_opt:ifo class_body:body
+       {:
+       ParseNode pn=new ParseNode("inner_class_declaration");
+       pn.addChild("modifiers").addChild(mo);
+       pn.addChild("name").addChild(id);
+       pn.addChild("super").addChild(so);
+       pn.addChild("superIF").addChild(ifo);
+       pn.addChild("classbody").addChild(body);
+       RESULT=pn;
        :}
+//    |       interface_declaration:interfaced {: 
+//     RESULT=(new ParseNode("interface")).addChild(interfaced).getRoot(); 
+//     :}
        |       SEMICOLON       {: RESULT=new ParseNode("empty"); :}
        ;