Fix a bug of default constructor: the default constructor should construct the super...
[IRC.git] / Robust / src / IR / Tree / BuildIR.java
1 package IR.Tree;
2 import IR.*;
3
4 import java.util.*;
5
6
7 public class BuildIR {
8   State state;
9
10   private int m_taskexitnum;
11
12   public BuildIR(State state) {
13     this.state=state;
14     this.m_taskexitnum = 0;
15   }
16
17   public void buildtree(ParseNode pn, Set toanalyze) {
18     parseFile(pn, toanalyze);
19   }
20
21   Vector singleimports;
22   Vector multiimports;
23   NameDescriptor packages;
24
25   /** Parse the classes in this file */
26   public void parseFile(ParseNode pn, Set toanalyze) {
27     singleimports=new Vector();
28     multiimports=new Vector();
29
30     ParseNode ipn=pn.getChild("imports").getChild("import_decls_list");
31     if (ipn!=null) {
32       ParseNodeVector pnv=ipn.getChildren();
33       for(int i=0; i<pnv.size(); i++) {
34         ParseNode pnimport=pnv.elementAt(i);
35         NameDescriptor nd=parseName(pnimport.getChild("name"));
36         if (isNode(pnimport,"import_single"))
37           singleimports.add(nd);
38         else
39           multiimports.add(nd);
40       }
41     }
42     ParseNode ppn=pn.getChild("packages").getChild("package");
43     if (ppn!=null) {
44       packages=parseName(ppn.getChild("name"));
45     }
46     ParseNode tpn=pn.getChild("type_declaration_list");
47     if (tpn!=null) {
48       ParseNodeVector pnv=tpn.getChildren();
49       for(int i=0; i<pnv.size(); i++) {
50         ParseNode type_pn=pnv.elementAt(i);
51         if (isEmpty(type_pn))         /* Skip the semicolon */
52           continue;
53         if (isNode(type_pn,"class_declaration")) {
54           ClassDescriptor cn=parseTypeDecl(type_pn);
55           parseInitializers(cn);
56           if (toanalyze!=null)
57             toanalyze.add(cn);
58           state.addClass(cn);
59       // for inner classes/enum
60       if(state.MGC) {
61         // TODO add version for normal Java later
62         HashSet tovisit = new HashSet();
63         Iterator it_icds = cn.getInnerClasses();
64         while(it_icds.hasNext()) {
65           tovisit.add(it_icds.next());
66         }
67         
68         while(!tovisit.isEmpty()) {
69           ClassDescriptor cd = (ClassDescriptor)tovisit.iterator().next();
70           tovisit.remove(cd);
71           parseInitializers(cd);
72           if(toanalyze != null) {
73             toanalyze.add(cd);
74           }
75           state.addClass(cd);
76           
77           Iterator it_ics = cd.getInnerClasses();
78           while(it_ics.hasNext()) {
79             tovisit.add(it_ics.next());
80           }
81           
82           Iterator it_ienums = cd.getEnum();
83           while(it_ienums.hasNext()) {
84             ClassDescriptor iecd = (ClassDescriptor)it_ienums.next();
85             if(toanalyze != null) {
86               toanalyze.add(iecd);
87             }
88             state.addClass(iecd);
89           }
90         }
91         
92         Iterator it_enums = cn.getEnum();
93         while(it_enums.hasNext()) {
94           ClassDescriptor ecd = (ClassDescriptor)it_enums.next();
95           if(toanalyze != null) {
96             toanalyze.add(ecd);
97           }
98           state.addClass(ecd);
99         }
100       }
101         } else if (isNode(type_pn,"task_declaration")) {
102           TaskDescriptor td=parseTaskDecl(type_pn);
103           if (toanalyze!=null)
104             toanalyze.add(td);
105           state.addTask(td);
106         } else if ((state.MGC) && isNode(type_pn,"interface_declaration")) {
107       // TODO add version for normal Java later
108       ClassDescriptor cn = parseInterfaceDecl(type_pn);
109       if (toanalyze!=null)
110         toanalyze.add(cn);
111       state.addClass(cn);
112       
113       // for enum
114       if(state.MGC) {
115         // TODO add version for normal Java later        
116         Iterator it_enums = cn.getEnum();
117         while(it_enums.hasNext()) {
118           ClassDescriptor ecd = (ClassDescriptor)it_enums.next();
119           if(toanalyze != null) {
120             toanalyze.add(ecd);
121           }
122           state.addClass(ecd);
123         }
124       }
125     } else if ((state.MGC) && isNode(type_pn,"enum_declaration")) {
126       // TODO add version for normal Java later
127       ClassDescriptor cn = parseEnumDecl(null, type_pn);
128       if (toanalyze!=null)
129         toanalyze.add(cn);
130       state.addClass(cn);
131     } else {
132           throw new Error(type_pn.getLabel());
133         }
134       }
135     }
136   }
137
138  public void parseInitializers(ClassDescriptor cn){
139         Vector fv=cn.getFieldVec();
140         for(int i=0;i<fv.size();i++) {
141             FieldDescriptor fd=(FieldDescriptor)fv.get(i);
142             if(fd.getExpressionNode()!=null) {
143                 Iterator methodit = cn.getMethods();
144                 while(methodit.hasNext()){
145                     MethodDescriptor currmd=(MethodDescriptor)methodit.next();
146                     if(currmd.isConstructor()){
147                         BlockNode bn=state.getMethodBody(currmd);
148                         NameNode nn=new NameNode(new NameDescriptor(fd.getSymbol()));
149                         AssignmentNode an=new AssignmentNode(nn,fd.getExpressionNode(),new AssignOperation(1));
150                         bn.addFirstBlockStatement(new BlockExpressionNode(an));                 
151                     }
152                 }
153             }
154         }
155     }  
156
157   private ClassDescriptor parseEnumDecl(ClassDescriptor cn, ParseNode pn) {
158     ClassDescriptor ecd=new ClassDescriptor(pn.getChild("name").getTerminal(), false);
159     ecd.setAsEnum();
160     if(cn != null) {
161       ecd.setSurroundingClass(cn.getSymbol());
162       ecd.setSurrounding(cn);
163       cn.addEnum(ecd);
164     }
165     if (!(ecd.getSymbol().equals(TypeUtil.ObjectClass)||
166         ecd.getSymbol().equals(TypeUtil.TagClass))) {
167       ecd.setSuper(TypeUtil.ObjectClass);
168     }
169     ecd.setModifiers(parseModifiersList(pn.getChild("modifiers")));
170     parseEnumBody(ecd, pn.getChild("enumbody"));
171     return ecd;
172   }
173   
174   private void parseEnumBody(ClassDescriptor cn, ParseNode pn) {
175     ParseNode decls=pn.getChild("enum_constants_list");
176     if (decls!=null) {
177       ParseNodeVector pnv=decls.getChildren();
178       for(int i=0; i<pnv.size(); i++) {
179         ParseNode decl=pnv.elementAt(i);
180         if (isNode(decl,"enum_constant")) {
181           parseEnumConstant(cn,decl);
182         } else throw new Error();
183       }
184     }
185   }
186   
187   private void parseEnumConstant(ClassDescriptor cn, ParseNode pn) {
188     cn.addEnumConstant(pn.getChild("name").getTerminal());
189   }
190   
191   public ClassDescriptor parseInterfaceDecl(ParseNode pn) {
192     ClassDescriptor cn=new ClassDescriptor(pn.getChild("name").getTerminal(), true);
193     //cn.setAsInterface();
194     if (!isEmpty(pn.getChild("superIF").getTerminal())) {
195       /* parse inherited interface name */
196       ParseNode snlist=pn.getChild("superIF").getChild("extend_interface_list");
197       ParseNodeVector pnv=snlist.getChildren();
198       for(int i=0; i<pnv.size(); i++) {
199         ParseNode decl=pnv.elementAt(i);
200         if (isNode(decl,"type")) {
201           NameDescriptor nd=parseName(decl.getChild("class").getChild("name"));
202           cn.addSuperInterface(nd.toString());
203         }
204       }
205     }
206     cn.setModifiers(parseModifiersList(pn.getChild("modifiers")));
207     parseInterfaceBody(cn, pn.getChild("interfacebody"));
208     return cn;
209   }
210   
211   private void parseInterfaceBody(ClassDescriptor cn, ParseNode pn) {
212     assert(cn.isInterface());
213     ParseNode decls=pn.getChild("interface_member_declaration_list");
214     if (decls!=null) {
215       ParseNodeVector pnv=decls.getChildren();
216       for(int i=0; i<pnv.size(); i++) {
217         ParseNode decl=pnv.elementAt(i);
218         if (isNode(decl,"constant")) {
219           parseInterfaceConstant(cn,decl);
220         } else if (isNode(decl,"method")) {
221           parseInterfaceMethod(cn,decl.getChild("method_declaration"));
222         } else throw new Error();
223       }
224     }
225   }
226   
227   private void parseInterfaceConstant(ClassDescriptor cn, ParseNode pn) {
228     if (pn!=null) {
229       parseFieldDecl(cn,pn.getChild("field_declaration"));
230       return;
231     }
232     throw new Error();
233   }
234   
235   private void parseInterfaceMethod(ClassDescriptor cn, ParseNode pn) {
236     ParseNode headern=pn.getChild("header");
237     ParseNode bodyn=pn.getChild("body");
238     MethodDescriptor md=parseMethodHeader(headern.getChild("method_header"));
239     md.getModifiers().addModifier(Modifiers.PUBLIC);
240     md.getModifiers().addModifier(Modifiers.ABSTRACT);
241     try {
242       BlockNode bn=parseBlock(bodyn);
243       cn.addMethod(md);
244       state.addTreeCode(md,bn);
245
246       // this is a hack for investigating new language features
247       // at the AST level, someday should evolve into a nice compiler
248       // option *wink*
249       //if( cn.getSymbol().equals( ***put a class in here like:     "Test" ) &&
250       //    md.getSymbol().equals( ***put your method in here like: "main" ) 
251       //) {
252       //  bn.setStyle( BlockNode.NORMAL );
253       //  System.out.println( bn.printNode( 0 ) );
254       //}
255
256     } catch (Exception e) {
257       System.out.println("Error with method:"+md.getSymbol());
258       e.printStackTrace();
259       throw new Error();
260     } catch (Error e) {
261       System.out.println("Error with method:"+md.getSymbol());
262       e.printStackTrace();
263       throw new Error();
264     }
265   }
266
267   public TaskDescriptor parseTaskDecl(ParseNode pn) {
268     TaskDescriptor td=new TaskDescriptor(pn.getChild("name").getTerminal());
269     ParseNode bodyn=pn.getChild("body");
270     BlockNode bn=parseBlock(bodyn);
271     parseParameterList(td, pn);
272     state.addTreeCode(td,bn);
273     if (pn.getChild("flag_effects_list")!=null)
274       td.addFlagEffects(parseFlags(pn.getChild("flag_effects_list")));
275     return td;
276   }
277
278   public Vector parseFlags(ParseNode pn) {
279     Vector vfe=new Vector();
280     ParseNodeVector pnv=pn.getChildren();
281     for(int i=0; i<pnv.size(); i++) {
282       ParseNode fn=pnv.elementAt(i);
283       FlagEffects fe=parseFlagEffects(fn);
284       vfe.add(fe);
285     }
286     return vfe;
287   }
288
289   public FlagEffects parseFlagEffects(ParseNode pn) {
290     if (isNode(pn,"flag_effect")) {
291       String flagname=pn.getChild("name").getTerminal();
292       FlagEffects fe=new FlagEffects(flagname);
293       if (pn.getChild("flag_list")!=null)
294         parseFlagEffect(fe, pn.getChild("flag_list"));
295       if (pn.getChild("tag_list")!=null)
296         parseTagEffect(fe, pn.getChild("tag_list"));
297       return fe;
298     } else throw new Error();
299   }
300
301   public void parseTagEffect(FlagEffects fes, ParseNode pn) {
302     ParseNodeVector pnv=pn.getChildren();
303     for(int i=0; i<pnv.size(); i++) {
304       ParseNode pn2=pnv.elementAt(i);
305       boolean status=true;
306       if (isNode(pn2,"not")) {
307         status=false;
308         pn2=pn2.getChild("name");
309       }
310       String name=pn2.getTerminal();
311       fes.addTagEffect(new TagEffect(name,status));
312     }
313   }
314
315   public void parseFlagEffect(FlagEffects fes, ParseNode pn) {
316     ParseNodeVector pnv=pn.getChildren();
317     for(int i=0; i<pnv.size(); i++) {
318       ParseNode pn2=pnv.elementAt(i);
319       boolean status=true;
320       if (isNode(pn2,"not")) {
321         status=false;
322         pn2=pn2.getChild("name");
323       }
324       String name=pn2.getTerminal();
325       fes.addEffect(new FlagEffect(name,status));
326     }
327   }
328
329   public FlagExpressionNode parseFlagExpression(ParseNode pn) {
330     if (isNode(pn,"or")) {
331       ParseNodeVector pnv=pn.getChildren();
332       ParseNode left=pnv.elementAt(0);
333       ParseNode right=pnv.elementAt(1);
334       return new FlagOpNode(parseFlagExpression(left), parseFlagExpression(right), new Operation(Operation.LOGIC_OR));
335     } else if (isNode(pn,"and")) {
336       ParseNodeVector pnv=pn.getChildren();
337       ParseNode left=pnv.elementAt(0);
338       ParseNode right=pnv.elementAt(1);
339       return new FlagOpNode(parseFlagExpression(left), parseFlagExpression(right), new Operation(Operation.LOGIC_AND));
340     } else if (isNode(pn, "not")) {
341       ParseNodeVector pnv=pn.getChildren();
342       ParseNode left=pnv.elementAt(0);
343       return new FlagOpNode(parseFlagExpression(left), new Operation(Operation.LOGIC_NOT));
344
345     } else if (isNode(pn,"name")) {
346       return new FlagNode(pn.getTerminal());
347     } else {
348       throw new Error();
349     }
350   }
351
352   public Vector parseChecks(ParseNode pn) {
353     Vector ccs=new Vector();
354     ParseNodeVector pnv=pn.getChildren();
355     for(int i=0; i<pnv.size(); i++) {
356       ParseNode fn=pnv.elementAt(i);
357       ConstraintCheck cc=parseConstraintCheck(fn);
358       ccs.add(cc);
359     }
360     return ccs;
361   }
362
363   public ConstraintCheck parseConstraintCheck(ParseNode pn) {
364     if (isNode(pn,"cons_check")) {
365       String specname=pn.getChild("name").getChild("identifier").getTerminal();
366       Vector[] args=parseConsArgumentList(pn);
367       ConstraintCheck cc=new ConstraintCheck(specname);
368       for(int i=0; i<args[0].size(); i++) {
369         cc.addVariable((String)args[0].get(i));
370         cc.addArgument((ExpressionNode)args[1].get(i));
371       }
372       return cc;
373     } else throw new Error();
374   }
375
376   public void parseParameterList(TaskDescriptor td, ParseNode pn) {
377
378     boolean optional;
379     ParseNode paramlist=pn.getChild("task_parameter_list");
380     if (paramlist==null)
381       return;
382     ParseNodeVector pnv=paramlist.getChildren();
383     for(int i=0; i<pnv.size(); i++) {
384       ParseNode paramn=pnv.elementAt(i);
385       if(paramn.getChild("optional")!=null) {
386         optional = true;
387         paramn = paramn.getChild("optional").getFirstChild();
388         System.out.println("OPTIONAL FOUND!!!!!!!");
389       } else { optional = false;
390                System.out.println("NOT OPTIONAL");}
391
392       TypeDescriptor type=parseTypeDescriptor(paramn);
393
394       String paramname=paramn.getChild("single").getTerminal();
395       FlagExpressionNode fen=null;
396       if (paramn.getChild("flag")!=null)
397         fen=parseFlagExpression(paramn.getChild("flag").getFirstChild());
398
399       ParseNode tagnode=paramn.getChild("tag");
400
401       TagExpressionList tel=null;
402       if (tagnode!=null) {
403         tel=parseTagExpressionList(tagnode);
404       }
405
406       td.addParameter(type,paramname,fen, tel, optional);
407     }
408   }
409
410   public TagExpressionList parseTagExpressionList(ParseNode pn) {
411     //BUG FIX: change pn.getChildren() to pn.getChild("tag_expression_list").getChildren()
412     //To test, feed in any input program that uses tags
413     ParseNodeVector pnv=pn.getChild("tag_expression_list").getChildren();
414     TagExpressionList tel=new TagExpressionList();
415     for(int i=0; i<pnv.size(); i++) {
416       ParseNode tn=pnv.elementAt(i);
417       String type=tn.getChild("type").getTerminal();
418       String name=tn.getChild("single").getTerminal();
419       tel.addTag(type, name);
420     }
421     return tel;
422   }
423
424   public ClassDescriptor parseTypeDecl(ParseNode pn) {
425     ClassDescriptor cn=new ClassDescriptor(pn.getChild("name").getTerminal(), false);
426     if (!isEmpty(pn.getChild("super").getTerminal())) {
427       /* parse superclass name */
428       ParseNode snn=pn.getChild("super").getChild("type").getChild("class").getChild("name");
429       NameDescriptor nd=parseName(snn);
430       cn.setSuper(nd.toString());
431     } else {
432       if (!(cn.getSymbol().equals(TypeUtil.ObjectClass)||
433             cn.getSymbol().equals(TypeUtil.TagClass)))
434         cn.setSuper(TypeUtil.ObjectClass);
435     }
436     // check inherited interfaces
437     if (!isEmpty(pn.getChild("superIF").getTerminal())) {
438       /* parse inherited interface name */
439       ParseNode snlist=pn.getChild("superIF").getChild("interface_type_list");
440       ParseNodeVector pnv=snlist.getChildren();
441       for(int i=0; i<pnv.size(); i++) {
442         ParseNode decl=pnv.elementAt(i);
443         if (isNode(decl,"type")) {
444           NameDescriptor nd=parseName(decl.getChild("class").getChild("name"));
445           cn.addSuperInterface(nd.toString());
446         }
447       }
448     }
449     cn.setModifiers(parseModifiersList(pn.getChild("modifiers")));
450     parseClassBody(cn, pn.getChild("classbody"));
451     
452     boolean hasConstructor = false;
453     for(Iterator method_it=cn.getMethods(); method_it.hasNext();) {
454       MethodDescriptor md=(MethodDescriptor)method_it.next();
455       hasConstructor |= md.isConstructor();
456     }
457     if((!hasConstructor) && (!cn.isEnum())) {
458       // add a default constructor for this class
459       MethodDescriptor md = new MethodDescriptor(new Modifiers(Modifiers.PUBLIC),
460           cn.getSymbol(), false);
461       BlockNode bn=new BlockNode();
462       state.addTreeCode(md,bn);
463       md.setDefaultConstructor();
464       cn.addMethod(md);
465     }
466     return cn;
467   }
468
469   private void parseClassBody(ClassDescriptor cn, ParseNode pn) {
470     ParseNode decls=pn.getChild("class_body_declaration_list");
471     if (decls!=null) {
472       ParseNodeVector pnv=decls.getChildren();
473       for(int i=0; i<pnv.size(); i++) {
474         ParseNode decl=pnv.elementAt(i);
475         if (isNode(decl,"member")) {
476           parseClassMember(cn,decl);
477         } else if (isNode(decl,"constructor")) {
478           parseConstructorDecl(cn,decl.getChild("constructor_declaration"));
479         } else if (isNode(decl, "static_block")) {
480       if(state.MGC) {
481         // TODO add version for normal Java later
482       parseStaticBlockDecl(cn, decl.getChild("static_block_declaration"));
483       } else {
484         throw new Error("Static blocks not implemented");
485       }
486     } else if (isNode(decl,"block")) {
487         } else throw new Error();
488       }
489     }
490   }
491   
492   private void parseClassMember(ClassDescriptor cn, ParseNode pn) {
493     ParseNode fieldnode=pn.getChild("field");
494     if (fieldnode!=null) {
495       parseFieldDecl(cn,fieldnode.getChild("field_declaration"));
496       return;
497     }
498     ParseNode methodnode=pn.getChild("method");
499     if (methodnode!=null) {
500       parseMethodDecl(cn,methodnode.getChild("method_declaration"));
501       return;
502     }
503     ParseNode innerclassnode=pn.getChild("inner_class_declaration");
504     if (innerclassnode!=null) {
505       if(state.MGC){
506         parseInnerClassDecl(cn,innerclassnode);
507         return;
508       } else {
509         // TODO add version for noraml Java later
510         throw new Error("Error: inner class in Class " + cn.getSymbol() + " is not supported yet");
511       }
512     }
513     ParseNode enumnode=pn.getChild("enum_declaration");
514     if (enumnode!=null) {
515       if(state.MGC){
516         parseEnumDecl(cn,enumnode);
517         return;
518       } else {
519         // TODO add version for noraml Java later
520         throw new Error("Error: enumerated type in Class " + cn.getSymbol() + " is not supported yet");
521       }
522     }
523     ParseNode flagnode=pn.getChild("flag");
524     if (flagnode!=null) {
525       parseFlagDecl(cn, flagnode.getChild("flag_declaration"));
526       return;
527     }
528     // in case there are empty node
529     ParseNode emptynode=pn.getChild("empty");
530     if(emptynode != null) {
531       return;
532     }
533     throw new Error();
534   }
535   
536   private ClassDescriptor parseInnerClassDecl(ClassDescriptor cn, ParseNode pn) {
537     ClassDescriptor icn=new ClassDescriptor(pn.getChild("name").getTerminal(), false);
538     icn.setAsInnerClass();
539     icn.setSurroundingClass(cn.getSymbol());
540     icn.setSurrounding(cn);
541     cn.addInnerClass(icn);
542     if (!isEmpty(pn.getChild("super").getTerminal())) {
543       /* parse superclass name */
544       ParseNode snn=pn.getChild("super").getChild("type").getChild("class").getChild("name");
545       NameDescriptor nd=parseName(snn);
546       icn.setSuper(nd.toString());
547     } else {
548       if (!(icn.getSymbol().equals(TypeUtil.ObjectClass)||
549           icn.getSymbol().equals(TypeUtil.TagClass)))
550         icn.setSuper(TypeUtil.ObjectClass);
551     }
552     // check inherited interfaces
553     if (!isEmpty(pn.getChild("superIF").getTerminal())) {
554       /* parse inherited interface name */
555       ParseNode snlist=pn.getChild("superIF").getChild("interface_type_list");
556       ParseNodeVector pnv=snlist.getChildren();
557       for(int i=0; i<pnv.size(); i++) {
558         ParseNode decl=pnv.elementAt(i);
559         if (isNode(decl,"type")) {
560           NameDescriptor nd=parseName(decl.getChild("class").getChild("name"));
561           icn.addSuperInterface(nd.toString());
562         }
563       }
564     }
565     icn.setModifiers(parseModifiersList(pn.getChild("modifiers")));
566     if(!icn.isStatic()) {
567       throw new Error("Error: inner class " + icn.getSymbol() + " in Class " + 
568           cn.getSymbol() + " is not a nested class and is not supported yet!");
569     }
570     parseClassBody(icn, pn.getChild("classbody"));
571     return icn;
572   }
573
574   private TypeDescriptor parseTypeDescriptor(ParseNode pn) {
575     ParseNode tn=pn.getChild("type");
576     String type_st=tn.getTerminal();
577     if(type_st.equals("byte")) {
578       return state.getTypeDescriptor(TypeDescriptor.BYTE);
579     } else if(type_st.equals("short")) {
580       return state.getTypeDescriptor(TypeDescriptor.SHORT);
581     } else if(type_st.equals("boolean")) {
582       return state.getTypeDescriptor(TypeDescriptor.BOOLEAN);
583     } else if(type_st.equals("int")) {
584       return state.getTypeDescriptor(TypeDescriptor.INT);
585     } else if(type_st.equals("long")) {
586       return state.getTypeDescriptor(TypeDescriptor.LONG);
587     } else if(type_st.equals("char")) {
588       return state.getTypeDescriptor(TypeDescriptor.CHAR);
589     } else if(type_st.equals("float")) {
590       return state.getTypeDescriptor(TypeDescriptor.FLOAT);
591     } else if(type_st.equals("double")) {
592       return state.getTypeDescriptor(TypeDescriptor.DOUBLE);
593     } else if(type_st.equals("class")) {
594       ParseNode nn=tn.getChild("class");
595       return state.getTypeDescriptor(parseName(nn.getChild("name")));
596     } else if(type_st.equals("array")) {
597       ParseNode nn=tn.getChild("array");
598       TypeDescriptor td=parseTypeDescriptor(nn.getChild("basetype"));
599       Integer numdims=(Integer)nn.getChild("dims").getLiteral();
600       for(int i=0; i<numdims.intValue(); i++)
601         td=td.makeArray(state);
602       return td;
603     } else {
604       System.out.println(pn.PPrint(2, true));
605       throw new Error();
606     }
607   }
608
609   private NameDescriptor parseName(ParseNode nn) {
610     ParseNode base=nn.getChild("base");
611     ParseNode id=nn.getChild("identifier");
612     if (base==null)
613       return new NameDescriptor(id.getTerminal());
614     return new NameDescriptor(parseName(base.getChild("name")),id.getTerminal());
615
616   }
617
618   private void parseFlagDecl(ClassDescriptor cn,ParseNode pn) {
619     String name=pn.getChild("name").getTerminal();
620     FlagDescriptor flag=new FlagDescriptor(name);
621     if (pn.getChild("external")!=null)
622       flag.makeExternal();
623     cn.addFlag(flag);
624   }
625
626   private void parseFieldDecl(ClassDescriptor cn,ParseNode pn) {
627     ParseNode mn=pn.getChild("modifier");
628     Modifiers m=parseModifiersList(mn);
629     if((state.MGC) && cn.isInterface()) {
630       // TODO add version for normal Java later
631       // Can only be PUBLIC or STATIC or FINAL
632       if((m.isAbstract()) || (m.isAtomic()) || (m.isNative()) 
633           || (m.isSynchronized())) {
634         throw new Error("Error: field in Interface " + cn.getSymbol() + "can only be PUBLIC or STATIC or FINAL");
635       }
636       m.addModifier(Modifiers.PUBLIC);
637       m.addModifier(Modifiers.STATIC);
638       m.addModifier(Modifiers.FINAL);
639     }
640
641     ParseNode tn=pn.getChild("type");
642     TypeDescriptor t=parseTypeDescriptor(tn);
643     ParseNode vn=pn.getChild("variables").getChild("variable_declarators_list");
644     ParseNodeVector pnv=vn.getChildren();
645     boolean isglobal=pn.getChild("global")!=null;
646
647     for(int i=0; i<pnv.size(); i++) {
648       ParseNode vardecl=pnv.elementAt(i);
649       ParseNode tmp=vardecl;
650       TypeDescriptor arrayt=t;
651       while (tmp.getChild("single")==null) {
652         arrayt=arrayt.makeArray(state);
653         tmp=tmp.getChild("array");
654       }
655       String identifier=tmp.getChild("single").getTerminal();
656       ParseNode epn=vardecl.getChild("initializer");
657
658       ExpressionNode en=null;
659       if (epn!=null) {
660         en=parseExpression(epn.getFirstChild());
661         if(state.MGC && m.isStatic()) {
662           // for static field, the initializer should be considered as a 
663           // static block
664           boolean isfirst = false;
665           MethodDescriptor md = (MethodDescriptor)cn.getMethodTable().getFromSameScope("staticblocks");
666           if(md == null) {
667             // the first static block for this class
668             Modifiers m_i=new Modifiers();
669             m_i.addModifier(Modifiers.STATIC);
670             md = new MethodDescriptor(m_i, "staticblocks", false);
671             md.setAsStaticBlock();
672             isfirst = true;
673           }
674           if(isfirst) {
675             cn.addMethod(md);
676           }
677           cn.incStaticBlocks();
678           BlockNode bn=new BlockNode();
679           NameNode nn=new NameNode(new NameDescriptor(identifier));
680           AssignmentNode an=new AssignmentNode(nn,en,new AssignOperation(1));
681           bn.addBlockStatement(new BlockExpressionNode(an));
682           if(isfirst) {
683             state.addTreeCode(md,bn);
684           } else {
685             BlockNode obn = state.getMethodBody(md);
686             for(int ii = 0; ii < bn.size(); ii++) {
687               BlockStatementNode bsn = bn.get(ii);
688               obn.addBlockStatement(bsn);
689             }
690             state.addTreeCode(md, obn);
691             bn = null;
692           }
693           en = null;
694         }
695       }
696
697       cn.addField(new FieldDescriptor(m, arrayt, identifier, en, isglobal));
698     }
699   }
700
701   private ExpressionNode parseExpression(ParseNode pn) {
702     if (isNode(pn,"assignment"))
703       return parseAssignmentExpression(pn);
704     else if (isNode(pn,"logical_or")||isNode(pn,"logical_and")||
705              isNode(pn,"bitwise_or")||isNode(pn,"bitwise_xor")||
706              isNode(pn,"bitwise_and")||isNode(pn,"equal")||
707              isNode(pn,"not_equal")||isNode(pn,"comp_lt")||
708              isNode(pn,"comp_lte")||isNode(pn,"comp_gt")||
709              isNode(pn,"comp_gte")||isNode(pn,"leftshift")||
710              isNode(pn,"rightshift")||isNode(pn,"sub")||
711              isNode(pn,"urightshift")||isNode(pn,"sub")||
712              isNode(pn,"add")||isNode(pn,"mult")||
713              isNode(pn,"div")||isNode(pn,"mod")) {
714       ParseNodeVector pnv=pn.getChildren();
715       ParseNode left=pnv.elementAt(0);
716       ParseNode right=pnv.elementAt(1);
717       Operation op=new Operation(pn.getLabel());
718       return new OpNode(parseExpression(left),parseExpression(right),op);
719     } else if (isNode(pn,"unaryplus")||
720                isNode(pn,"unaryminus")||
721                isNode(pn,"not")||
722                isNode(pn,"comp")) {
723       ParseNode left=pn.getFirstChild();
724       Operation op=new Operation(pn.getLabel());
725       return new OpNode(parseExpression(left),op);
726     } else if (isNode(pn,"postinc")||
727                isNode(pn,"postdec")) {
728       ParseNode left=pn.getFirstChild();
729       AssignOperation op=new AssignOperation(pn.getLabel());
730       return new AssignmentNode(parseExpression(left),null,op);
731
732     } else if (isNode(pn,"preinc")||
733                isNode(pn,"predec")) {
734       ParseNode left=pn.getFirstChild();
735       AssignOperation op=isNode(pn,"preinc") ? new AssignOperation(AssignOperation.PLUSEQ) : new AssignOperation(AssignOperation.MINUSEQ);
736       return new AssignmentNode(parseExpression(left),
737                                 new LiteralNode("integer",new Integer(1)),op);
738     } else if (isNode(pn,"literal")) {
739       String literaltype=pn.getTerminal();
740       ParseNode literalnode=pn.getChild(literaltype);
741       Object literal_obj=literalnode.getLiteral();
742       return new LiteralNode(literaltype, literal_obj);
743     } else if (isNode(pn,"createobject")) {
744       TypeDescriptor td=parseTypeDescriptor(pn);
745       
746       Vector args=parseArgumentList(pn);
747       boolean isglobal=pn.getChild("global")!=null||
748         pn.getChild("scratch")!=null;
749       String disjointId=null;
750       if( pn.getChild("disjoint") != null) {
751         disjointId = pn.getChild("disjoint").getTerminal();
752       }
753       CreateObjectNode con=new CreateObjectNode(td, isglobal, disjointId);
754       for(int i=0; i<args.size(); i++) {
755         con.addArgument((ExpressionNode)args.get(i));
756       }
757       /* Could have flag set or tag added here */
758       if (pn.getChild("flag_list")!=null||pn.getChild("tag_list")!=null) {
759         FlagEffects fe=new FlagEffects(null);
760         if (pn.getChild("flag_list")!=null)
761           parseFlagEffect(fe, pn.getChild("flag_list"));
762
763         if (pn.getChild("tag_list")!=null)
764           parseTagEffect(fe, pn.getChild("tag_list"));
765         con.addFlagEffects(fe);
766       }
767
768       return con;
769     } else if (isNode(pn,"createarray")) {
770       //System.out.println(pn.PPrint(3,true));
771       boolean isglobal=pn.getChild("global")!=null||
772         pn.getChild("scratch")!=null;
773       String disjointId=null;
774       if( pn.getChild("disjoint") != null) {
775         disjointId = pn.getChild("disjoint").getTerminal();
776       }
777       TypeDescriptor td=parseTypeDescriptor(pn);
778       Vector args=parseDimExprs(pn);
779       int num=0;
780       if (pn.getChild("dims_opt").getLiteral()!=null)
781         num=((Integer)pn.getChild("dims_opt").getLiteral()).intValue();
782       for(int i=0; i<(args.size()+num); i++)
783         td=td.makeArray(state);
784       CreateObjectNode con=new CreateObjectNode(td, isglobal, disjointId);
785       for(int i=0; i<args.size(); i++) {
786         con.addArgument((ExpressionNode)args.get(i));
787       }
788       return con;
789     } if (isNode(pn,"createarray2") && state.MGC) {
790       TypeDescriptor td=parseTypeDescriptor(pn);
791       int num=0;
792       if (pn.getChild("dims_opt").getLiteral()!=null)
793     num=((Integer)pn.getChild("dims_opt").getLiteral()).intValue();
794       for(int i=0; i<num; i++)
795     td=td.makeArray(state);
796       CreateObjectNode con=new CreateObjectNode(td, false, null);
797       // TODO array initializers
798       ParseNode ipn = pn.getChild("initializer");     
799       Vector initializers=parseVariableInitializerList(ipn);
800       ArrayInitializerNode ain = new ArrayInitializerNode(initializers);
801       con.addArrayInitializer(ain);
802       return con;
803     } else if (isNode(pn,"name")) {
804       NameDescriptor nd=parseName(pn);
805       return new NameNode(nd);
806     } else if (isNode(pn,"this")) {
807       NameDescriptor nd=new NameDescriptor("this");
808       return new NameNode(nd);
809     } else if (isNode(pn,"isavailable")) {
810       NameDescriptor nd=new NameDescriptor(pn.getTerminal());
811       return new OpNode(new NameNode(nd),null,new Operation(Operation.ISAVAILABLE));
812     } else if (isNode(pn,"methodinvoke1")) {
813       NameDescriptor nd=parseName(pn.getChild("name"));
814       Vector args=parseArgumentList(pn);
815       MethodInvokeNode min=new MethodInvokeNode(nd);
816       for(int i=0; i<args.size(); i++) {
817         min.addArgument((ExpressionNode)args.get(i));
818       }
819       return min;
820     } else if (isNode(pn,"methodinvoke2")) {
821       String methodid=pn.getChild("id").getTerminal();
822       ExpressionNode exp=parseExpression(pn.getChild("base").getFirstChild());
823       Vector args=parseArgumentList(pn);
824       MethodInvokeNode min=new MethodInvokeNode(methodid,exp);
825       for(int i=0; i<args.size(); i++) {
826         min.addArgument((ExpressionNode)args.get(i));
827       }
828       return min;
829     } else if (isNode(pn,"fieldaccess")) {
830       ExpressionNode en=parseExpression(pn.getChild("base").getFirstChild());
831       String fieldname=pn.getChild("field").getTerminal();
832       return new FieldAccessNode(en,fieldname);
833     } else if (isNode(pn,"arrayaccess")) {
834       ExpressionNode en=parseExpression(pn.getChild("base").getFirstChild());
835       ExpressionNode index=parseExpression(pn.getChild("index").getFirstChild());
836       return new ArrayAccessNode(en,index);
837     } else if (isNode(pn,"cast1")) {
838       try {
839         return new CastNode(parseTypeDescriptor(pn.getChild("type")),parseExpression(pn.getChild("exp").getFirstChild()));
840       } catch (Exception e) {
841         System.out.println(pn.PPrint(1,true));
842         e.printStackTrace();
843         throw new Error();
844       }
845     } else if (isNode(pn,"cast2")) {
846       return new CastNode(parseExpression(pn.getChild("type").getFirstChild()),parseExpression(pn.getChild("exp").getFirstChild()));
847     } else if (isNode(pn, "getoffset")) {
848       TypeDescriptor td=parseTypeDescriptor(pn);
849       String fieldname = pn.getChild("field").getTerminal();
850       //System.out.println("Checking the values of: "+ " td.toString()= " + td.toString()+ "  fieldname= " + fieldname);
851       return new OffsetNode(td, fieldname);
852     } else if (isNode(pn, "tert")) {
853       return new TertiaryNode(parseExpression(pn.getChild("cond").getFirstChild()),
854                               parseExpression(pn.getChild("trueexpr").getFirstChild()),
855                               parseExpression(pn.getChild("falseexpr").getFirstChild()) );
856     } else if (isNode(pn, "instanceof")) {
857       ExpressionNode exp=parseExpression(pn.getChild("exp").getFirstChild());
858       TypeDescriptor t=parseTypeDescriptor(pn);
859       return new InstanceOfNode(exp,t);
860     } else if (isNode(pn, "array_initializer")) {  
861       Vector initializers=parseVariableInitializerList(pn);
862       return new ArrayInitializerNode(initializers);
863     } else if (isNode(pn, "class_type") && state.MGC) {
864       TypeDescriptor td=parseTypeDescriptor(pn);
865       return new ClassTypeNode(td);
866     } else if (isNode(pn, "empty") && state.MGC) {
867       return null;
868     } else {
869       System.out.println("---------------------");
870       System.out.println(pn.PPrint(3,true));
871       throw new Error();
872     }
873   }
874
875   private Vector parseDimExprs(ParseNode pn) {
876     Vector arglist=new Vector();
877     ParseNode an=pn.getChild("dim_exprs");
878     if (an==null)       /* No argument list */
879       return arglist;
880     ParseNodeVector anv=an.getChildren();
881     for(int i=0; i<anv.size(); i++) {
882       arglist.add(parseExpression(anv.elementAt(i)));
883     }
884     return arglist;
885   }
886
887   private Vector parseArgumentList(ParseNode pn) {
888     Vector arglist=new Vector();
889     ParseNode an=pn.getChild("argument_list");
890     if (an==null)       /* No argument list */
891       return arglist;
892     ParseNodeVector anv=an.getChildren();
893     for(int i=0; i<anv.size(); i++) {
894       arglist.add(parseExpression(anv.elementAt(i)));
895     }
896     return arglist;
897   }
898
899   private Vector[] parseConsArgumentList(ParseNode pn) {
900     Vector arglist=new Vector();
901     Vector varlist=new Vector();
902     ParseNode an=pn.getChild("cons_argument_list");
903     if (an==null)       /* No argument list */
904       return new Vector[] {varlist, arglist};
905     ParseNodeVector anv=an.getChildren();
906     for(int i=0; i<anv.size(); i++) {
907       ParseNode cpn=anv.elementAt(i);
908       ParseNode var=cpn.getChild("var");
909       ParseNode exp=cpn.getChild("exp").getFirstChild();
910       varlist.add(var.getTerminal());
911       arglist.add(parseExpression(exp));
912     }
913     return new Vector[] {varlist, arglist};
914   }
915
916   private Vector parseVariableInitializerList(ParseNode pn) {
917     Vector varInitList=new Vector();
918     ParseNode vin=pn.getChild("var_init_list");
919     if (vin==null)       /* No argument list */
920       return varInitList;
921     ParseNodeVector vinv=vin.getChildren();
922     for(int i=0; i<vinv.size(); i++) {
923       varInitList.add(parseExpression(vinv.elementAt(i)));
924     }
925     return varInitList;
926   }
927
928   private ExpressionNode parseAssignmentExpression(ParseNode pn) {
929     AssignOperation ao=new AssignOperation(pn.getChild("op").getTerminal());
930     ParseNodeVector pnv=pn.getChild("args").getChildren();
931
932     AssignmentNode an=new AssignmentNode(parseExpression(pnv.elementAt(0)),parseExpression(pnv.elementAt(1)),ao);
933     return an;
934   }
935
936
937   private void parseMethodDecl(ClassDescriptor cn, ParseNode pn) {
938     ParseNode headern=pn.getChild("method_header");
939     ParseNode bodyn=pn.getChild("body");
940     MethodDescriptor md=parseMethodHeader(headern);
941     try {
942       BlockNode bn=parseBlock(bodyn);
943       cn.addMethod(md);
944       state.addTreeCode(md,bn);
945
946       // this is a hack for investigating new language features
947       // at the AST level, someday should evolve into a nice compiler
948       // option *wink*
949       //if( cn.getSymbol().equals( ***put a class in here like:     "Test" ) &&
950       //    md.getSymbol().equals( ***put your method in here like: "main" ) 
951       //) {
952       //  bn.setStyle( BlockNode.NORMAL );
953       //  System.out.println( bn.printNode( 0 ) );
954       //}
955
956     } catch (Exception e) {
957       System.out.println("Error with method:"+md.getSymbol());
958       e.printStackTrace();
959       throw new Error();
960     } catch (Error e) {
961       System.out.println("Error with method:"+md.getSymbol());
962       e.printStackTrace();
963       throw new Error();
964     }
965   }
966
967   private void parseConstructorDecl(ClassDescriptor cn, ParseNode pn) {
968     ParseNode mn=pn.getChild("modifiers");
969     Modifiers m=parseModifiersList(mn);
970     ParseNode cdecl=pn.getChild("constructor_declarator");
971     boolean isglobal=cdecl.getChild("global")!=null;
972     String name=cdecl.getChild("name").getChild("identifier").getTerminal();
973     MethodDescriptor md=new MethodDescriptor(m, name, isglobal);
974     ParseNode paramnode=cdecl.getChild("parameters");
975     parseParameterList(md,paramnode);
976     ParseNode bodyn0=pn.getChild("body");
977     ParseNode bodyn=bodyn0.getChild("constructor_body");
978     cn.addMethod(md);
979     BlockNode bn=null;
980     if (bodyn!=null&&bodyn.getChild("block_statement_list")!=null)
981       bn=parseBlock(bodyn);
982     else
983       bn=new BlockNode();
984     if (bodyn!=null&&bodyn.getChild("superinvoke")!=null) {
985       ParseNode sin=bodyn.getChild("superinvoke");
986       NameDescriptor nd=new NameDescriptor("super");
987       Vector args=parseArgumentList(sin);
988       MethodInvokeNode min=new MethodInvokeNode(nd);
989       for(int i=0; i<args.size(); i++) {
990         min.addArgument((ExpressionNode)args.get(i));
991       }
992       BlockExpressionNode ben=new BlockExpressionNode(min);
993       bn.addFirstBlockStatement(ben);
994
995     } else if (bodyn!=null&&bodyn.getChild("explconstrinv")!=null) {
996       ParseNode eci=bodyn.getChild("explconstrinv");
997       NameDescriptor nd=new NameDescriptor(cn.getSymbol());
998       Vector args=parseArgumentList(eci);
999       MethodInvokeNode min=new MethodInvokeNode(nd);
1000       for(int i=0; i<args.size(); i++) {
1001         min.addArgument((ExpressionNode)args.get(i));
1002       }
1003       BlockExpressionNode ben=new BlockExpressionNode(min);
1004       bn.addFirstBlockStatement(ben);
1005     }
1006     state.addTreeCode(md,bn);
1007   }
1008   
1009   private void parseStaticBlockDecl(ClassDescriptor cn, ParseNode pn) {
1010     // Each class maintains one MethodDecscriptor which combines all its 
1011     // static blocks in their declaration order
1012     boolean isfirst = false;
1013     MethodDescriptor md = (MethodDescriptor)cn.getMethodTable().getFromSameScope("staticblocks");
1014     if(md == null) {
1015       // the first static block for this class
1016       Modifiers m_i=new Modifiers();
1017       m_i.addModifier(Modifiers.STATIC);
1018       md = new MethodDescriptor(m_i, "staticblocks", false);
1019       md.setAsStaticBlock();
1020       isfirst = true;
1021     }
1022     ParseNode bodyn=pn.getChild("body");
1023     if(isfirst) {
1024       cn.addMethod(md);
1025     }
1026     cn.incStaticBlocks();
1027     BlockNode bn=null;
1028     if (bodyn!=null&&bodyn.getChild("block_statement_list")!=null)
1029       bn=parseBlock(bodyn);
1030     else
1031       bn=new BlockNode();
1032     if(isfirst) {
1033       state.addTreeCode(md,bn);
1034     } else {
1035       BlockNode obn = state.getMethodBody(md);
1036       for(int i = 0; i < bn.size(); i++) {
1037         BlockStatementNode bsn = bn.get(i);
1038         obn.addBlockStatement(bsn);
1039       }
1040       state.addTreeCode(md, obn);
1041       bn = null;
1042     }
1043   }
1044
1045   public BlockNode parseBlock(ParseNode pn) {
1046     this.m_taskexitnum = 0;
1047     if (pn==null||isEmpty(pn.getTerminal()))
1048       return new BlockNode();
1049     ParseNode bsn=pn.getChild("block_statement_list");
1050     return parseBlockHelper(bsn);
1051   }
1052
1053   private BlockNode parseBlockHelper(ParseNode pn) {
1054     ParseNodeVector pnv=pn.getChildren();
1055     BlockNode bn=new BlockNode();
1056     for(int i=0; i<pnv.size(); i++) {
1057       Vector bsv=parseBlockStatement(pnv.elementAt(i));
1058       for(int j=0; j<bsv.size(); j++) {
1059         bn.addBlockStatement((BlockStatementNode)bsv.get(j));
1060       }
1061     }
1062     return bn;
1063   }
1064
1065   public BlockNode parseSingleBlock(ParseNode pn) {
1066     BlockNode bn=new BlockNode();
1067     Vector bsv=parseBlockStatement(pn);
1068     for(int j=0; j<bsv.size(); j++) {
1069       bn.addBlockStatement((BlockStatementNode)bsv.get(j));
1070     }
1071     bn.setStyle(BlockNode.NOBRACES);
1072     return bn;
1073   }
1074
1075   public Vector parseSESEBlock(Vector parentbs, ParseNode pn) {
1076     ParseNodeVector pnv=pn.getChildren();
1077     Vector bv=new Vector();
1078     for(int i=0; i<pnv.size(); i++) {
1079       bv.addAll(parseBlockStatement(pnv.elementAt(i)));
1080     }
1081     return bv;
1082   }
1083
1084   public Vector parseBlockStatement(ParseNode pn) {
1085     Vector blockstatements=new Vector();
1086     if (isNode(pn,"tag_declaration")) {
1087       String name=pn.getChild("single").getTerminal();
1088       String type=pn.getChild("type").getTerminal();
1089
1090       blockstatements.add(new TagDeclarationNode(name, type));
1091     } else if (isNode(pn,"local_variable_declaration")) {
1092       TypeDescriptor t=parseTypeDescriptor(pn);
1093       ParseNode vn=pn.getChild("variable_declarators_list");
1094       ParseNodeVector pnv=vn.getChildren();
1095       for(int i=0; i<pnv.size(); i++) {
1096         ParseNode vardecl=pnv.elementAt(i);
1097
1098
1099         ParseNode tmp=vardecl;
1100         TypeDescriptor arrayt=t;
1101         while (tmp.getChild("single")==null) {
1102           arrayt=arrayt.makeArray(state);
1103           tmp=tmp.getChild("array");
1104         }
1105         String identifier=tmp.getChild("single").getTerminal();
1106
1107         ParseNode epn=vardecl.getChild("initializer");
1108
1109
1110         ExpressionNode en=null;
1111         if (epn!=null)
1112           en=parseExpression(epn.getFirstChild());
1113
1114         blockstatements.add(new DeclarationNode(new VarDescriptor(arrayt, identifier),en));
1115       }
1116     } else if (isNode(pn,"nop")) {
1117       /* Do Nothing */
1118     } else if (isNode(pn,"expression")) {
1119       blockstatements.add(new BlockExpressionNode(parseExpression(pn.getFirstChild())));
1120     } else if (isNode(pn,"ifstatement")) {
1121       blockstatements.add(new IfStatementNode(parseExpression(pn.getChild("condition").getFirstChild()),
1122                                               parseSingleBlock(pn.getChild("statement").getFirstChild()),
1123                                               pn.getChild("else_statement")!=null ? parseSingleBlock(pn.getChild("else_statement").getFirstChild()) : null));
1124     } else if ((state.MGC) && (isNode(pn,"switch_statement"))) {
1125       // TODO add version for normal Java later
1126       blockstatements.add(new SwitchStatementNode(parseExpression(pn.getChild("condition").getFirstChild()),
1127           parseSingleBlock(pn.getChild("statement").getFirstChild())));
1128     } else if ((state.MGC) && (isNode(pn,"switch_block_list"))) {
1129       // TODO add version for normal Java later
1130       ParseNodeVector pnv=pn.getChildren();
1131       for(int i=0; i<pnv.size(); i++) {
1132         ParseNode sblockdecl=pnv.elementAt(i);
1133         
1134         if(isNode(sblockdecl, "switch_block")) {
1135           ParseNode lpn=sblockdecl.getChild("switch_labels").getChild("switch_label_list");
1136           ParseNodeVector labelv=lpn.getChildren();
1137           Vector<SwitchLabelNode> slv = new Vector<SwitchLabelNode>();
1138           for(int j=0; j<labelv.size(); j++) {
1139             ParseNode labeldecl=labelv.elementAt(j);
1140             if(isNode(labeldecl, "switch_label")) {
1141               slv.addElement(new SwitchLabelNode(parseExpression(labeldecl.getChild("constant_expression").getFirstChild()), false));
1142             } else if(isNode(labeldecl, "default_switch_label")) {
1143               slv.addElement(new SwitchLabelNode(null, true));
1144             }
1145           }
1146           
1147           blockstatements.add(new SwitchBlockNode(slv, 
1148               parseSingleBlock(sblockdecl.getChild("switch_statements").getFirstChild())));
1149           
1150         }
1151       }
1152     } else if (state.MGC && isNode(pn, "trycatchstatement")) {
1153       // TODO add version for normal Java later
1154       // Do not fully support exceptions now. Only make sure that if there are no
1155       // exceptions thrown, the execution is right
1156       ParseNode tpn = pn.getChild("tryblock").getFirstChild();
1157       BlockNode bn=parseBlockHelper(tpn);
1158       blockstatements.add(new SubBlockNode(bn));
1159       
1160       ParseNode fbk = pn.getChild("finallyblock");
1161       if(fbk != null) {
1162         ParseNode fpn = fbk.getFirstChild();
1163         BlockNode fbn=parseBlockHelper(fpn);
1164         blockstatements.add(new SubBlockNode(fbn));
1165       }
1166     } else if (isNode(pn, "throwstatement")) {
1167       // TODO Simply return here
1168       //blockstatements.add(new ReturnNode());
1169     } else if (isNode(pn,"taskexit")) {
1170       Vector vfe=null;
1171       if (pn.getChild("flag_effects_list")!=null)
1172         vfe=parseFlags(pn.getChild("flag_effects_list"));
1173       Vector ccs=null;
1174       if (pn.getChild("cons_checks")!=null)
1175         ccs=parseChecks(pn.getChild("cons_checks"));
1176
1177       blockstatements.add(new TaskExitNode(vfe, ccs, this.m_taskexitnum++));
1178     } else if (isNode(pn,"atomic")) {
1179       BlockNode bn=parseBlockHelper(pn);
1180       blockstatements.add(new AtomicNode(bn));
1181     } else if (isNode(pn,"synchronized")) {
1182       BlockNode bn=parseBlockHelper(pn.getChild("block"));
1183       ExpressionNode en=parseExpression(pn.getChild("expr").getFirstChild());
1184       blockstatements.add(new SynchronizedNode(en, bn));
1185     } else if (isNode(pn,"return")) {
1186       if (isEmpty(pn.getTerminal()))
1187         blockstatements.add(new ReturnNode());
1188       else {
1189         ExpressionNode en=parseExpression(pn.getFirstChild());
1190         blockstatements.add(new ReturnNode(en));
1191       }
1192     } else if (isNode(pn,"block_statement_list")) {
1193       BlockNode bn=parseBlockHelper(pn);
1194       blockstatements.add(new SubBlockNode(bn));
1195     } else if (isNode(pn,"empty")) {
1196       /* nop */
1197     } else if (isNode(pn,"statement_expression_list")) {
1198       ParseNodeVector pnv=pn.getChildren();
1199       BlockNode bn=new BlockNode();
1200       for(int i=0; i<pnv.size(); i++) {
1201         ExpressionNode en=parseExpression(pnv.elementAt(i));
1202         blockstatements.add(new BlockExpressionNode(en));
1203       }
1204       bn.setStyle(BlockNode.EXPRLIST);
1205     } else if (isNode(pn,"forstatement")) {
1206       BlockNode init=parseSingleBlock(pn.getChild("initializer").getFirstChild());
1207       BlockNode update=parseSingleBlock(pn.getChild("update").getFirstChild());
1208       ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild());
1209       BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild());
1210       if(condition == null) {
1211         // no condition clause, make a 'true' expression as the condition
1212         condition = (ExpressionNode)new LiteralNode("boolean", new Boolean(true));
1213       }
1214       blockstatements.add(new LoopNode(init,condition,update,body));
1215     } else if (isNode(pn,"whilestatement")) {
1216       ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild());
1217       BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild());
1218       if(condition == null) {
1219         // no condition clause, make a 'true' expression as the condition
1220         condition = (ExpressionNode)new LiteralNode("boolean", new Boolean(true));
1221       }
1222       blockstatements.add(new LoopNode(condition,body,LoopNode.WHILELOOP));
1223     } else if (isNode(pn,"dowhilestatement")) {
1224       ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild());
1225       BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild());
1226       if(condition == null) {
1227         // no condition clause, make a 'true' expression as the condition
1228         condition = (ExpressionNode)new LiteralNode("boolean", new Boolean(true));
1229       }
1230       blockstatements.add(new LoopNode(condition,body,LoopNode.DOWHILELOOP));
1231     } else if (isNode(pn,"sese")) {
1232       ParseNode pnID=pn.getChild("identifier");
1233       String stID=null;
1234       if( pnID != null ) { stID=pnID.getFirstChild().getTerminal(); }
1235       SESENode start=new SESENode(stID);
1236       SESENode end  =new SESENode(stID);
1237       start.setEnd( end   );
1238       end.setStart( start );
1239       blockstatements.add(start);
1240       blockstatements.addAll(parseSESEBlock(blockstatements,pn.getChild("body").getFirstChild()));
1241       blockstatements.add(end);
1242     } else if (isNode(pn,"continue")) {
1243       blockstatements.add(new ContinueBreakNode(false));
1244     } else if (isNode(pn,"break")) {
1245       blockstatements.add(new ContinueBreakNode(true));
1246
1247     } else if (isNode(pn,"genreach")) {
1248       String graphName = pn.getChild("graphName").getTerminal();
1249       blockstatements.add( new GenReachNode( graphName ) );
1250
1251     } else {
1252       System.out.println("---------------");
1253       System.out.println(pn.PPrint(3,true));
1254       throw new Error();
1255     }
1256     return blockstatements;
1257   }
1258
1259   public MethodDescriptor parseMethodHeader(ParseNode pn) {
1260     ParseNode mn=pn.getChild("modifiers");
1261     Modifiers m=parseModifiersList(mn);
1262
1263     ParseNode tn=pn.getChild("returntype");
1264     TypeDescriptor returntype;
1265     if (tn!=null)
1266       returntype=parseTypeDescriptor(tn);
1267     else
1268       returntype=new TypeDescriptor(TypeDescriptor.VOID);
1269
1270     ParseNode pmd=pn.getChild("method_declarator");
1271     String name=pmd.getChild("name").getTerminal();
1272     MethodDescriptor md=new MethodDescriptor(m, returntype, name);
1273
1274     ParseNode paramnode=pmd.getChild("parameters");
1275     parseParameterList(md,paramnode);
1276     return md;
1277   }
1278
1279   public void parseParameterList(MethodDescriptor md, ParseNode pn) {
1280     ParseNode paramlist=pn.getChild("formal_parameter_list");
1281     if (paramlist==null)
1282       return;
1283     ParseNodeVector pnv=paramlist.getChildren();
1284     for(int i=0; i<pnv.size(); i++) {
1285       ParseNode paramn=pnv.elementAt(i);
1286
1287       if (isNode(paramn, "tag_parameter")) {
1288         String paramname=paramn.getChild("single").getTerminal();
1289         TypeDescriptor type=new TypeDescriptor(TypeDescriptor.TAG);
1290         md.addTagParameter(type, paramname);
1291       } else {
1292         TypeDescriptor type=parseTypeDescriptor(paramn);
1293
1294         ParseNode tmp=paramn;
1295         while (tmp.getChild("single")==null) {
1296           type=type.makeArray(state);
1297           tmp=tmp.getChild("array");
1298         }
1299         String paramname=tmp.getChild("single").getTerminal();
1300
1301         md.addParameter(type, paramname);
1302       }
1303     }
1304   }
1305
1306   public Modifiers parseModifiersList(ParseNode pn) {
1307     Modifiers m=new Modifiers();
1308     ParseNode modlist=pn.getChild("modifier_list");
1309     if (modlist!=null) {
1310       ParseNodeVector pnv=modlist.getChildren();
1311       for(int i=0; i<pnv.size(); i++) {
1312         ParseNode modn=pnv.elementAt(i);
1313         if (isNode(modn,"public"))
1314           m.addModifier(Modifiers.PUBLIC);
1315         else if (isNode(modn,"protected"))
1316           m.addModifier(Modifiers.PROTECTED);
1317         else if (isNode(modn,"private"))
1318           m.addModifier(Modifiers.PRIVATE);
1319         else if (isNode(modn,"static"))
1320           m.addModifier(Modifiers.STATIC);
1321         else if (isNode(modn,"final"))
1322           m.addModifier(Modifiers.FINAL);
1323         else if (isNode(modn,"native"))
1324           m.addModifier(Modifiers.NATIVE);
1325         else if (isNode(modn,"synchronized"))
1326           m.addModifier(Modifiers.SYNCHRONIZED);
1327         else if (isNode(modn,"atomic"))
1328           m.addModifier(Modifiers.ATOMIC);
1329     else if (isNode(modn,"abstract"))
1330       m.addModifier(Modifiers.ABSTRACT);
1331     else if (isNode(modn,"volatile"))
1332       m.addModifier(Modifiers.VOLATILE);
1333     else if (isNode(modn,"transient"))
1334       m.addModifier(Modifiers.TRANSIENT);
1335         else throw new Error("Unrecognized Modifier");
1336       }
1337     }
1338     return m;
1339   }
1340
1341   private boolean isNode(ParseNode pn, String label) {
1342     if (pn.getLabel().equals(label))
1343       return true;
1344     else return false;
1345   }
1346
1347   private static boolean isEmpty(ParseNode pn) {
1348     if (pn.getLabel().equals("empty"))
1349       return true;
1350     else
1351       return false;
1352   }
1353
1354   private static boolean isEmpty(String s) {
1355     if (s.equals("empty"))
1356       return true;
1357     else
1358       return false;
1359   }
1360
1361   /** Throw an exception if something is unexpected */
1362   private void check(ParseNode pn, String label) {
1363     if (pn == null) {
1364       throw new Error(pn+ "IE: Expected '" + label + "', got null");
1365     }
1366     if (!pn.getLabel().equals(label)) {
1367       throw new Error(pn+ "IE: Expected '" + label + "', got '"+pn.getLabel()+"'");
1368     }
1369   }
1370 }