Main { // main program (@ public static void main(String args[]) throws Exception { Program parsed = Program.parse(System.in); Program.theProgram = parsed; parsed.GenerateCopyCode(); } @) } Program { traversal GenerateCopyTraversal(GenerateCopyVisitor t) { to Part; } (@ static Program theProgram; @) (@ void GenerateCopyCode() { GenerateCopyVisitor gcv = new GenerateCopyVisitor(); this.GenerateCopyTraversal(gcv); } @) traversal IsDemeterClassTraversal(IsDemeterClassVisitor v) { bypassing { ClassParts, ClassMethods, -> *, parameters, * } to ClassName; } (@ boolean IsDemeterClass(String className) { IsDemeterClassVisitor idcv = new IsDemeterClassVisitor(); idcv.Init(); idcv.SetTheClass(className); this.IsDemeterClassTraversal(idcv); return idcv.IsIt(); } @) (@ boolean IsDemeterTerminalClass(String className) { if(className.compareTo("Integer") == 0) { return true; } else if(className.compareTo("Ident") == 0) { return true; } else if(className.compareTo("String") == 0) { return true; } else if(className.compareTo("Text") == 0) { return true; } else if(className.compareTo("Boolean") == 0) { return true; } else if(className.compareTo("Float") == 0) { return true; } else if(className.compareTo("Double") == 0) { return true; } else { return false; } } @) } GenerateCopyVisitor { (@ Vector ndParts = new Vector(); @) before Program (@ System.out.println(""); System.out.println(""); System.out.println("CopyVisitor {"); System.out.println(" (@"); System.out.println(""); System.out.println(" Stack history;"); System.out.println(""); System.out.println(" void Init(String firstClass) {"); System.out.println(" this.history = new Stack();"); System.out.println(""); System.out.println(" try {"); System.out.println(" this.history.push(Class.forName(firstClass).newInstance());"); System.out.println(" } catch(Exception e) {"); System.out.println(" e.printStackTrace();"); System.out.println(" }"); System.out.println(" }"); System.out.println(""); System.out.println(" Object GetResult() {"); System.out.println(" return history.peek();"); System.out.println(" }"); System.out.println(""); System.out.println(" @" + ")"); System.out.println(""); @) after Program (@ System.out.println("}"); @) before ClassDef (@ this.set_ClassDefName(host.GetName()); @) after ClassDef (@ if(this.ndParts.size() > 0) { System.out.println(" before " + this.get_ClassDefName() + " (@"); System.out.println(" " + this.get_ClassDefName() + " theObject = (" + this.get_ClassDefName() + ")history.peek();"); while(this.ndParts.size() > 0) { System.out.println(""); if(Program.theProgram.IsDemeterTerminalClass((String)this.ndParts.elementAt(1))) { System.out.println(" theObject.set_" + this.ndParts.elementAt(0) + "(host.get_" + this.ndParts.elementAt(0) + "());"); } else { System.out.println(" try {"); System.out.println(" theObject.set_" + this.ndParts.elementAt(0) + "((" + this.ndParts.elementAt(1) + ")(host.get_" + this.ndParts.elementAt(0) + "().clone()))"); System.out.println(" } catch (CloneNotSupportedException e) {"); System.out.println(" theObject.set_" + this.ndParts.elementAt(0) + "(host.get_" + this.ndParts.elementAt(0) + "());"); System.out.println(" }"); } this.ndParts.removeElementAt(0); this.ndParts.removeElementAt(0); } System.out.println(" @" + ")"); System.out.println(""); } @) before Part (@ this.set_PartName(host.GetPartName()); this.set_PartClass(host.GetClassName()); String cont = this.get_ClassDefName().toString(); String part = this.get_PartName().toString(); String dest = this.get_PartClass().toString(); if(Program.theProgram.IsDemeterClass(dest)) { // output a before wraper to copy it... // I could output slightly better code by checking to see if the // dest class is an alternation class or not. For now I'll // keep it simple. System.out.println(" before -> " + cont + "," + part + "," + dest + " (@"); System.out.println(" " + cont + " containingObject = (" + cont + ")history.peek();"); System.out.println(" Class theClass = dest.getClass();"); System.out.println(" Object newPartObject = null;"); System.out.println(""); System.out.println(" try {"); System.out.println(" newPartObject = theClass.newInstance();"); System.out.println(" } catch(Exception e) {"); System.out.println(" e.printStackTrace();"); System.out.println(" }"); System.out.println(""); System.out.println(" containingObject.set_" + part + "((" + dest + ")newPartObject);"); System.out.println(" this.history.push(newPartObject);"); System.out.println(" @" + ")"); System.out.println(""); System.out.println(" after -> " + cont + "," + part + "," + dest + " (@"); System.out.println(" this.history.pop();"); System.out.println(" @" + ")"); System.out.println(""); } else { // save the part so that later we can chack to see if it needs // cloneing. this.ndParts.addElement(part); this.ndParts.addElement(dest); } @) } IsDemeterClassVisitor { (@ String theClass; boolean isIt; void Init() { this.isIt = false; } boolean IsIt() { return this.isIt; } void SetTheClass(String theClass) { this.theClass = theClass; } @) before ClassName (@ if(this.theClass.compareTo(host.get_name().toString()) == 0) { this.isIt = true; } @) } // Utility functions // ClassSpec : GetName() -> Ident // ClassDef : GetName() -> Ident // Part : GetName() -> Ident - returns a name if it's in the cd or null // Part : GetPartName() -> String - returns part.GetName() if it exists // or the name demjava will generate if // it doesn't. // Part : GetClassName() -> Ident // ClassSpec: GetName() -> Ident ClassSpec { traversal GetCSNameTraversal(GetCSNameVisitor v) { to ClassName; } (@ Ident GetName() { GetCSNameVisitor gnv = new GetCSNameVisitor(); this.GetCSNameTraversal(gnv); return gnv.get_theName(); } @) } GetCSNameVisitor { before ClassName (@ this.set_theName(host.get_name()); @) } // ClassSpec: GetName() -> Ident ClassDef { traversal GetCDNameTraversal(GetCDNameVisitor v) { bypassing { ClassParts, -> *, parameters, * } to ClassName; } (@ Ident GetName() { GetCDNameVisitor gnv = new GetCDNameVisitor(); this.GetCDNameTraversal(gnv); return gnv.get_theName(); } @) } GetCDNameVisitor { before ClassName (@ this.set_theName(host.get_name()); @) } // Part : GetName() -> Ident Part { traversal GetPNameTraversal(GetPNameVisitor v) { to PartName; } (@ Ident GetName() { GetPNameVisitor gnv = new GetPNameVisitor(); this.GetPNameTraversal(gnv); return gnv.get_theName(); } @) } GetPNameVisitor { before PartName (@ this.set_theName(host.get_name()); @) } // returns the name that demjava will generate for this part Part { (@ String GetPartName() { String partName; if(this.GetName() != null) { partName = this.GetName().toString(); } else { partName = this.get_classspec().GetName().toString().toLowerCase(); } return partName; } @) } // Part : GetClassName() -> Ident Part { traversal GetPCNameTraversal(GetPCNameVisitor v) { to ClassName; } (@ Ident GetClassName() { GetPCNameVisitor gnv = new GetPCNameVisitor(); this.GetPCNameTraversal(gnv); return gnv.get_theName(); } @) } GetPCNameVisitor { before ClassName (@ this.set_theName(host.get_name()); @) }