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