changes.
[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       //checking if location is actually defined in the hierarchy
526       for (Iterator iterator = spinLocSet.iterator(); iterator.hasNext();) {
527         String locID = (String) iterator.next();
528         if(!locOrder.containsKey(locID)){
529           throw new Error("Error: The spinning location '"+
530               locID + "' is not defined in the hierarchy of the class '"+cd +"'.");
531         }
532       }
533       state.addLocationPropertySet(cd, spinLocSet);
534     }
535     state.addLocationOrder(cd, locOrder);
536   }
537   
538   private void parseClassMember(ClassDescriptor cn, ParseNode pn) {
539     ParseNode fieldnode=pn.getChild("field");
540     if (fieldnode!=null) {
541       parseFieldDecl(cn,fieldnode.getChild("field_declaration"));
542       return;
543     }
544     ParseNode methodnode=pn.getChild("method");
545     if (methodnode!=null) {
546       parseMethodDecl(cn,methodnode.getChild("method_declaration"));
547       return;
548     }
549     ParseNode innerclassnode=pn.getChild("inner_class_declaration");
550     if (innerclassnode!=null) {
551       parseInnerClassDecl(cn,innerclassnode);
552       return;
553     }
554     ParseNode enumnode=pn.getChild("enum_declaration");
555     if (enumnode!=null) {
556       parseEnumDecl(cn,enumnode);
557       return;
558     }
559     ParseNode flagnode=pn.getChild("flag");
560     if (flagnode!=null) {
561       parseFlagDecl(cn, flagnode.getChild("flag_declaration"));
562       return;
563     }
564     // in case there are empty node
565     ParseNode emptynode=pn.getChild("empty");
566     if(emptynode != null) {
567       return;
568     }
569     throw new Error();
570   }
571   
572   private ClassDescriptor parseInnerClassDecl(ClassDescriptor cn, ParseNode pn) {
573     ClassDescriptor icn=new ClassDescriptor(pn.getChild("name").getTerminal(), false);
574     icn.setAsInnerClass();
575     icn.setSurroundingClass(cn.getSymbol());
576     icn.setSurrounding(cn);
577     cn.addInnerClass(icn);
578     if (!isEmpty(pn.getChild("super").getTerminal())) {
579       /* parse superclass name */
580       ParseNode snn=pn.getChild("super").getChild("type").getChild("class").getChild("name");
581       NameDescriptor nd=parseName(snn);
582       icn.setSuper(nd.toString());
583     } else {
584       if (!(icn.getSymbol().equals(TypeUtil.ObjectClass)||
585           icn.getSymbol().equals(TypeUtil.TagClass)))
586         icn.setSuper(TypeUtil.ObjectClass);
587     }
588     // check inherited interfaces
589     if (!isEmpty(pn.getChild("superIF").getTerminal())) {
590       /* parse inherited interface name */
591       ParseNode snlist=pn.getChild("superIF").getChild("interface_type_list");
592       ParseNodeVector pnv=snlist.getChildren();
593       for(int i=0; i<pnv.size(); i++) {
594         ParseNode decl=pnv.elementAt(i);
595         if (isNode(decl,"type")) {
596           NameDescriptor nd=parseName(decl.getChild("class").getChild("name"));
597           icn.addSuperInterface(nd.toString());
598         }
599       }
600     }
601     icn.setModifiers(parseModifiersList(pn.getChild("modifiers")));
602     if(!icn.isStatic()) {
603       throw new Error("Error: inner class " + icn.getSymbol() + " in Class " + 
604           cn.getSymbol() + " is not a nested class and is not supported yet!");
605     }
606     parseClassBody(icn, pn.getChild("classbody"));
607     return icn;
608   }
609
610   private TypeDescriptor parseTypeDescriptor(ParseNode pn) {
611     ParseNode tn=pn.getChild("type");
612     String type_st=tn.getTerminal();
613     if(type_st.equals("byte")) {
614       return state.getTypeDescriptor(TypeDescriptor.BYTE);
615     } else if(type_st.equals("short")) {
616       return state.getTypeDescriptor(TypeDescriptor.SHORT);
617     } else if(type_st.equals("boolean")) {
618       return state.getTypeDescriptor(TypeDescriptor.BOOLEAN);
619     } else if(type_st.equals("int")) {
620       return state.getTypeDescriptor(TypeDescriptor.INT);
621     } else if(type_st.equals("long")) {
622       return state.getTypeDescriptor(TypeDescriptor.LONG);
623     } else if(type_st.equals("char")) {
624       return state.getTypeDescriptor(TypeDescriptor.CHAR);
625     } else if(type_st.equals("float")) {
626       return state.getTypeDescriptor(TypeDescriptor.FLOAT);
627     } else if(type_st.equals("double")) {
628       return state.getTypeDescriptor(TypeDescriptor.DOUBLE);
629     } else if(type_st.equals("class")) {
630       ParseNode nn=tn.getChild("class");
631       return state.getTypeDescriptor(parseName(nn.getChild("name")));
632     } else if(type_st.equals("array")) {
633       ParseNode nn=tn.getChild("array");
634       TypeDescriptor td=parseTypeDescriptor(nn.getChild("basetype"));
635       Integer numdims=(Integer)nn.getChild("dims").getLiteral();
636       for(int i=0; i<numdims.intValue(); i++)
637         td=td.makeArray(state);
638       return td;
639     } else {
640       System.out.println(pn.PPrint(2, true));
641       throw new Error();
642     }
643   }
644
645   private NameDescriptor parseName(ParseNode nn) {
646     ParseNode base=nn.getChild("base");
647     ParseNode id=nn.getChild("identifier");
648     if (base==null)
649       return new NameDescriptor(id.getTerminal());
650     return new NameDescriptor(parseName(base.getChild("name")),id.getTerminal());
651
652   }
653
654   private void parseFlagDecl(ClassDescriptor cn,ParseNode pn) {
655     String name=pn.getChild("name").getTerminal();
656     FlagDescriptor flag=new FlagDescriptor(name);
657     if (pn.getChild("external")!=null)
658       flag.makeExternal();
659     cn.addFlag(flag);
660   }
661
662   private void parseFieldDecl(ClassDescriptor cn,ParseNode pn) {
663     ParseNode mn=pn.getChild("modifier");
664     Modifiers m=parseModifiersList(mn);
665     if(cn.isInterface()) {
666       // TODO add version for normal Java later
667       // Can only be PUBLIC or STATIC or FINAL
668       if((m.isAbstract()) || (m.isAtomic()) || (m.isNative()) 
669           || (m.isSynchronized())) {
670         throw new Error("Error: field in Interface " + cn.getSymbol() + "can only be PUBLIC or STATIC or FINAL");
671       }
672       m.addModifier(Modifiers.PUBLIC);
673       m.addModifier(Modifiers.STATIC);
674       m.addModifier(Modifiers.FINAL);
675     }
676
677     ParseNode tn=pn.getChild("type");
678     TypeDescriptor t=parseTypeDescriptor(tn);
679     assignAnnotationsToType(m,t);
680     ParseNode vn=pn.getChild("variables").getChild("variable_declarators_list");
681     ParseNodeVector pnv=vn.getChildren();
682     boolean isglobal=pn.getChild("global")!=null;
683
684     for(int i=0; i<pnv.size(); i++) {
685       ParseNode vardecl=pnv.elementAt(i);
686       ParseNode tmp=vardecl;
687       TypeDescriptor arrayt=t;
688       while (tmp.getChild("single")==null) {
689         arrayt=arrayt.makeArray(state);
690         tmp=tmp.getChild("array");
691       }
692       String identifier=tmp.getChild("single").getTerminal();
693       ParseNode epn=vardecl.getChild("initializer");
694
695       ExpressionNode en=null;
696       if (epn!=null) {
697         en=parseExpression(epn.getFirstChild());
698         en.setNumLine(epn.getFirstChild().getLine());
699         if(m.isStatic()) {
700           // for static field, the initializer should be considered as a 
701           // static block
702           boolean isfirst = false;
703           MethodDescriptor md = (MethodDescriptor)cn.getMethodTable().getFromSameScope("staticblocks");
704           if(md == null) {
705             // the first static block for this class
706             Modifiers m_i=new Modifiers();
707             m_i.addModifier(Modifiers.STATIC);
708             md = new MethodDescriptor(m_i, "staticblocks", false);
709             md.setAsStaticBlock();
710             isfirst = true;
711           }
712           if(isfirst) {
713             cn.addMethod(md);
714           }
715           cn.incStaticBlocks();
716           BlockNode bn=new BlockNode();
717           NameNode nn=new NameNode(new NameDescriptor(identifier));
718           nn.setNumLine(en.getNumLine());
719           AssignmentNode an=new AssignmentNode(nn,en,new AssignOperation(1));
720           an.setNumLine(pn.getLine());
721           bn.addBlockStatement(new BlockExpressionNode(an));
722           if(isfirst) {
723             state.addTreeCode(md,bn);
724           } else {
725             BlockNode obn = state.getMethodBody(md);
726             for(int ii = 0; ii < bn.size(); ii++) {
727               BlockStatementNode bsn = bn.get(ii);
728               obn.addBlockStatement(bsn);
729             }
730             state.addTreeCode(md, obn);
731             bn = null;
732           }
733           en = null;
734         }
735       }
736
737       cn.addField(new FieldDescriptor(m, arrayt, identifier, en, isglobal));
738     }
739   }
740   
741   private void assignAnnotationsToType(Modifiers modifiers, TypeDescriptor type){
742     Vector<AnnotationDescriptor> annotations=modifiers.getAnnotations();
743     for(int i=0; i<annotations.size(); i++) {
744       // it only supports a marker annotation
745       AnnotationDescriptor an=annotations.elementAt(i);
746       type.addAnnotationMarker(an);           
747     }    
748   }
749
750   private ExpressionNode parseExpression(ParseNode pn) {
751     if (isNode(pn,"assignment"))
752       return parseAssignmentExpression(pn);
753     else if (isNode(pn,"logical_or")||isNode(pn,"logical_and")||
754              isNode(pn,"bitwise_or")||isNode(pn,"bitwise_xor")||
755              isNode(pn,"bitwise_and")||isNode(pn,"equal")||
756              isNode(pn,"not_equal")||isNode(pn,"comp_lt")||
757              isNode(pn,"comp_lte")||isNode(pn,"comp_gt")||
758              isNode(pn,"comp_gte")||isNode(pn,"leftshift")||
759              isNode(pn,"rightshift")||isNode(pn,"sub")||
760              isNode(pn,"urightshift")||isNode(pn,"sub")||
761              isNode(pn,"add")||isNode(pn,"mult")||
762              isNode(pn,"div")||isNode(pn,"mod")) {
763       ParseNodeVector pnv=pn.getChildren();
764       ParseNode left=pnv.elementAt(0);
765       ParseNode right=pnv.elementAt(1);
766       Operation op=new Operation(pn.getLabel());
767       OpNode on=new OpNode(parseExpression(left),parseExpression(right),op);
768       on.setNumLine(pn.getLine());
769       return on;
770     } else if (isNode(pn,"unaryplus")||
771                isNode(pn,"unaryminus")||
772                isNode(pn,"not")||
773                isNode(pn,"comp")) {
774       ParseNode left=pn.getFirstChild();
775       Operation op=new Operation(pn.getLabel());
776       OpNode on=new OpNode(parseExpression(left),op);
777       on.setNumLine(pn.getLine());
778       return on;
779     } else if (isNode(pn,"postinc")||
780                isNode(pn,"postdec")) {
781       ParseNode left=pn.getFirstChild();
782       AssignOperation op=new AssignOperation(pn.getLabel());
783       AssignmentNode an=new AssignmentNode(parseExpression(left),null,op);
784       an.setNumLine(pn.getLine());
785       return an;
786
787     } else if (isNode(pn,"preinc")||
788                isNode(pn,"predec")) {
789       ParseNode left=pn.getFirstChild();
790       AssignOperation op=isNode(pn,"preinc") ? new AssignOperation(AssignOperation.PLUSEQ) : new AssignOperation(AssignOperation.MINUSEQ);
791       AssignmentNode an=new AssignmentNode(parseExpression(left),
792           new LiteralNode("integer",new Integer(1)),op);
793       an.setNumLine(pn.getLine());
794       return an;
795     } else if (isNode(pn,"literal")) {
796       String literaltype=pn.getTerminal();
797       ParseNode literalnode=pn.getChild(literaltype);
798       Object literal_obj=literalnode.getLiteral();      
799       LiteralNode ln=new LiteralNode(literaltype, literal_obj);
800       ln.setNumLine(pn.getLine());
801       return ln;
802     } else if (isNode(pn,"createobject")) {
803       TypeDescriptor td=parseTypeDescriptor(pn);
804       
805       Vector args=parseArgumentList(pn);
806       boolean isglobal=pn.getChild("global")!=null||
807         pn.getChild("scratch")!=null;
808       String disjointId=null;
809       if( pn.getChild("disjoint") != null) {
810         disjointId = pn.getChild("disjoint").getTerminal();
811       }
812       CreateObjectNode con=new CreateObjectNode(td, isglobal, disjointId);
813       con.setNumLine(pn.getLine());
814       for(int i=0; i<args.size(); i++) {
815         con.addArgument((ExpressionNode)args.get(i));
816       }
817       /* Could have flag set or tag added here */
818       if (pn.getChild("flag_list")!=null||pn.getChild("tag_list")!=null) {
819         FlagEffects fe=new FlagEffects(null);
820         if (pn.getChild("flag_list")!=null)
821           parseFlagEffect(fe, pn.getChild("flag_list"));
822
823         if (pn.getChild("tag_list")!=null)
824           parseTagEffect(fe, pn.getChild("tag_list"));
825         con.addFlagEffects(fe);
826       }
827
828       return con;
829     } else if (isNode(pn,"createarray")) {
830       //System.out.println(pn.PPrint(3,true));
831       boolean isglobal=pn.getChild("global")!=null||
832         pn.getChild("scratch")!=null;
833       String disjointId=null;
834       if( pn.getChild("disjoint") != null) {
835         disjointId = pn.getChild("disjoint").getTerminal();
836       }
837       TypeDescriptor td=parseTypeDescriptor(pn);
838       Vector args=parseDimExprs(pn);
839       int num=0;
840       if (pn.getChild("dims_opt").getLiteral()!=null)
841         num=((Integer)pn.getChild("dims_opt").getLiteral()).intValue();
842       for(int i=0; i<(args.size()+num); i++)
843         td=td.makeArray(state);
844       CreateObjectNode con=new CreateObjectNode(td, isglobal, disjointId);
845       con.setNumLine(pn.getLine());
846       for(int i=0; i<args.size(); i++) {
847         con.addArgument((ExpressionNode)args.get(i));
848       }
849       return con;
850     } if (isNode(pn,"createarray2")) {
851       TypeDescriptor td=parseTypeDescriptor(pn);
852       int num=0;
853       if (pn.getChild("dims_opt").getLiteral()!=null)
854     num=((Integer)pn.getChild("dims_opt").getLiteral()).intValue();
855       for(int i=0; i<num; i++)
856     td=td.makeArray(state);
857       CreateObjectNode con=new CreateObjectNode(td, false, null);
858       con.setNumLine(pn.getLine());
859       ParseNode ipn = pn.getChild("initializer");     
860       Vector initializers=parseVariableInitializerList(ipn);
861       ArrayInitializerNode ain = new ArrayInitializerNode(initializers);
862       ain.setNumLine(pn.getLine());
863       con.addArrayInitializer(ain);
864       return con;
865     } else if (isNode(pn,"name")) {
866       NameDescriptor nd=parseName(pn);
867       NameNode nn=new NameNode(nd);
868       nn.setNumLine(pn.getLine());
869       return nn;
870     } else if (isNode(pn,"this")) {
871       NameDescriptor nd=new NameDescriptor("this");
872       NameNode nn=new NameNode(nd);
873       nn.setNumLine(pn.getLine());
874       return nn;
875     } else if (isNode(pn,"isavailable")) {
876       NameDescriptor nd=new NameDescriptor(pn.getTerminal());
877       NameNode nn=new NameNode(nd);
878       nn.setNumLine(pn.getLine());
879       return new OpNode(nn,null,new Operation(Operation.ISAVAILABLE));
880     } else if (isNode(pn,"methodinvoke1")) {
881       NameDescriptor nd=parseName(pn.getChild("name"));
882       Vector args=parseArgumentList(pn);
883       MethodInvokeNode min=new MethodInvokeNode(nd);
884       min.setNumLine(pn.getLine());
885       for(int i=0; i<args.size(); i++) {
886         min.addArgument((ExpressionNode)args.get(i));
887       }
888       return min;
889     } else if (isNode(pn,"methodinvoke2")) {
890       String methodid=pn.getChild("id").getTerminal();
891       ExpressionNode exp=parseExpression(pn.getChild("base").getFirstChild());
892       Vector args=parseArgumentList(pn);
893       MethodInvokeNode min=new MethodInvokeNode(methodid,exp);
894       min.setNumLine(pn.getLine());
895       for(int i=0; i<args.size(); i++) {
896         min.addArgument((ExpressionNode)args.get(i));
897       }
898       return min;
899     } else if (isNode(pn,"fieldaccess")) {
900       ExpressionNode en=parseExpression(pn.getChild("base").getFirstChild());
901       String fieldname=pn.getChild("field").getTerminal();
902       
903       FieldAccessNode fan=new FieldAccessNode(en,fieldname);
904       fan.setNumLine(pn.getLine());
905       return fan;
906     } else if (isNode(pn,"arrayaccess")) {
907       ExpressionNode en=parseExpression(pn.getChild("base").getFirstChild());
908       ExpressionNode index=parseExpression(pn.getChild("index").getFirstChild());
909       ArrayAccessNode aan=new ArrayAccessNode(en,index);
910       aan.setNumLine(pn.getLine());
911       return aan;
912     } else if (isNode(pn,"cast1")) {
913       try {
914   CastNode cn=new CastNode(parseTypeDescriptor(pn.getChild("type")),parseExpression(pn.getChild("exp").getFirstChild()));
915   cn.setNumLine(pn.getLine());      
916         return cn;
917       } catch (Exception e) {
918         System.out.println(pn.PPrint(1,true));
919         e.printStackTrace();
920         throw new Error();
921       }
922     } else if (isNode(pn,"cast2")) {
923       CastNode cn=new CastNode(parseExpression(pn.getChild("type").getFirstChild()),parseExpression(pn.getChild("exp").getFirstChild()));
924       cn.setNumLine(pn.getLine());
925       return cn;
926     } else if (isNode(pn, "getoffset")) {
927       TypeDescriptor td=parseTypeDescriptor(pn);
928       String fieldname = pn.getChild("field").getTerminal();
929       //System.out.println("Checking the values of: "+ " td.toString()= " + td.toString()+ "  fieldname= " + fieldname);
930       return new OffsetNode(td, fieldname);
931     } else if (isNode(pn, "tert")) {
932       
933       TertiaryNode tn=new TertiaryNode(parseExpression(pn.getChild("cond").getFirstChild()),
934           parseExpression(pn.getChild("trueexpr").getFirstChild()),
935           parseExpression(pn.getChild("falseexpr").getFirstChild()) );
936       tn.setNumLine(pn.getLine());
937       
938       return tn;
939     } else if (isNode(pn, "instanceof")) {
940       ExpressionNode exp=parseExpression(pn.getChild("exp").getFirstChild());
941       TypeDescriptor t=parseTypeDescriptor(pn);
942       InstanceOfNode ion=new InstanceOfNode(exp,t);
943       ion.setNumLine(pn.getLine());
944       return ion;
945     } else if (isNode(pn, "array_initializer")) {  
946       Vector initializers=parseVariableInitializerList(pn);
947       return new ArrayInitializerNode(initializers);
948     } else if (isNode(pn, "class_type")) {
949       TypeDescriptor td=parseTypeDescriptor(pn);
950       ClassTypeNode ctn=new ClassTypeNode(td);
951       ctn.setNumLine(pn.getLine());
952       return ctn;
953     } else if (isNode(pn, "empty")) {
954       return null;
955     } else {
956       System.out.println("---------------------");
957       System.out.println(pn.PPrint(3,true));
958       throw new Error();
959     }
960   }
961
962   private Vector parseDimExprs(ParseNode pn) {
963     Vector arglist=new Vector();
964     ParseNode an=pn.getChild("dim_exprs");
965     if (an==null)       /* No argument list */
966       return arglist;
967     ParseNodeVector anv=an.getChildren();
968     for(int i=0; i<anv.size(); i++) {
969       arglist.add(parseExpression(anv.elementAt(i)));
970     }
971     return arglist;
972   }
973
974   private Vector parseArgumentList(ParseNode pn) {
975     Vector arglist=new Vector();
976     ParseNode an=pn.getChild("argument_list");
977     if (an==null)       /* No argument list */
978       return arglist;
979     ParseNodeVector anv=an.getChildren();
980     for(int i=0; i<anv.size(); i++) {
981       arglist.add(parseExpression(anv.elementAt(i)));
982     }
983     return arglist;
984   }
985
986   private Vector[] parseConsArgumentList(ParseNode pn) {
987     Vector arglist=new Vector();
988     Vector varlist=new Vector();
989     ParseNode an=pn.getChild("cons_argument_list");
990     if (an==null)       /* No argument list */
991       return new Vector[] {varlist, arglist};
992     ParseNodeVector anv=an.getChildren();
993     for(int i=0; i<anv.size(); i++) {
994       ParseNode cpn=anv.elementAt(i);
995       ParseNode var=cpn.getChild("var");
996       ParseNode exp=cpn.getChild("exp").getFirstChild();
997       varlist.add(var.getTerminal());
998       arglist.add(parseExpression(exp));
999     }
1000     return new Vector[] {varlist, arglist};
1001   }
1002
1003   private Vector parseVariableInitializerList(ParseNode pn) {
1004     Vector varInitList=new Vector();
1005     ParseNode vin=pn.getChild("var_init_list");
1006     if (vin==null)       /* No argument list */
1007       return varInitList;
1008     ParseNodeVector vinv=vin.getChildren();
1009     for(int i=0; i<vinv.size(); i++) {
1010       varInitList.add(parseExpression(vinv.elementAt(i)));
1011     }
1012     return varInitList;
1013   }
1014
1015   private ExpressionNode parseAssignmentExpression(ParseNode pn) {
1016     AssignOperation ao=new AssignOperation(pn.getChild("op").getTerminal());
1017     ParseNodeVector pnv=pn.getChild("args").getChildren();
1018
1019     AssignmentNode an=new AssignmentNode(parseExpression(pnv.elementAt(0)),parseExpression(pnv.elementAt(1)),ao);
1020     an.setNumLine(pn.getLine());
1021     return an;
1022   }
1023
1024
1025   private void parseMethodDecl(ClassDescriptor cn, ParseNode pn) {
1026     ParseNode headern=pn.getChild("method_header");
1027     ParseNode bodyn=pn.getChild("body");
1028     MethodDescriptor md=parseMethodHeader(headern);
1029     try {
1030       BlockNode bn=parseBlock(bodyn);
1031       bn.setNumLine(pn.getLine()); // assume that method header is located at the beginning of method body
1032       cn.addMethod(md);
1033       state.addTreeCode(md,bn);
1034
1035       // this is a hack for investigating new language features
1036       // at the AST level, someday should evolve into a nice compiler
1037       // option *wink*
1038       //if( cn.getSymbol().equals( ***put a class in here like:     "Test" ) &&
1039       //    md.getSymbol().equals( ***put your method in here like: "main" ) 
1040       //) {
1041       //  bn.setStyle( BlockNode.NORMAL );
1042       //  System.out.println( bn.printNode( 0 ) );
1043       //}
1044
1045     } catch (Exception e) {
1046       System.out.println("Error with method:"+md.getSymbol());
1047       e.printStackTrace();
1048       throw new Error();
1049     } catch (Error e) {
1050       System.out.println("Error with method:"+md.getSymbol());
1051       e.printStackTrace();
1052       throw new Error();
1053     }
1054   }
1055
1056   private void parseConstructorDecl(ClassDescriptor cn, ParseNode pn) {
1057     ParseNode mn=pn.getChild("modifiers");
1058     Modifiers m=parseModifiersList(mn);
1059     ParseNode cdecl=pn.getChild("constructor_declarator");
1060     boolean isglobal=cdecl.getChild("global")!=null;
1061     String name=cdecl.getChild("name").getChild("identifier").getTerminal();
1062     MethodDescriptor md=new MethodDescriptor(m, name, isglobal);
1063     ParseNode paramnode=cdecl.getChild("parameters");
1064     parseParameterList(md,paramnode);
1065     ParseNode bodyn0=pn.getChild("body");
1066     ParseNode bodyn=bodyn0.getChild("constructor_body");
1067     cn.addMethod(md);
1068     BlockNode bn=null;
1069     if (bodyn!=null&&bodyn.getChild("block_statement_list")!=null)
1070       bn=parseBlock(bodyn);
1071     else
1072       bn=new BlockNode();
1073     if (bodyn!=null&&bodyn.getChild("superinvoke")!=null) {
1074       ParseNode sin=bodyn.getChild("superinvoke");
1075       NameDescriptor nd=new NameDescriptor("super");
1076       Vector args=parseArgumentList(sin);
1077       MethodInvokeNode min=new MethodInvokeNode(nd);
1078       min.setNumLine(sin.getLine());
1079       for(int i=0; i<args.size(); i++) {
1080         min.addArgument((ExpressionNode)args.get(i));
1081       }
1082       BlockExpressionNode ben=new BlockExpressionNode(min);
1083       bn.addFirstBlockStatement(ben);
1084
1085     } else if (bodyn!=null&&bodyn.getChild("explconstrinv")!=null) {
1086       ParseNode eci=bodyn.getChild("explconstrinv");
1087       NameDescriptor nd=new NameDescriptor(cn.getSymbol());
1088       Vector args=parseArgumentList(eci);
1089       MethodInvokeNode min=new MethodInvokeNode(nd);
1090       min.setNumLine(eci.getLine());
1091       for(int i=0; i<args.size(); i++) {
1092         min.addArgument((ExpressionNode)args.get(i));
1093       }
1094       BlockExpressionNode ben=new BlockExpressionNode(min);
1095       ben.setNumLine(eci.getLine());
1096       bn.addFirstBlockStatement(ben);
1097     }
1098     state.addTreeCode(md,bn);
1099   }
1100   
1101   private void parseStaticBlockDecl(ClassDescriptor cn, ParseNode pn) {
1102     // Each class maintains one MethodDecscriptor which combines all its 
1103     // static blocks in their declaration order
1104     boolean isfirst = false;
1105     MethodDescriptor md = (MethodDescriptor)cn.getMethodTable().getFromSameScope("staticblocks");
1106     if(md == null) {
1107       // the first static block for this class
1108       Modifiers m_i=new Modifiers();
1109       m_i.addModifier(Modifiers.STATIC);
1110       md = new MethodDescriptor(m_i, "staticblocks", false);
1111       md.setAsStaticBlock();
1112       isfirst = true;
1113     }
1114     ParseNode bodyn=pn.getChild("body");
1115     if(isfirst) {
1116       cn.addMethod(md);
1117     }
1118     cn.incStaticBlocks();
1119     BlockNode bn=null;
1120     if (bodyn!=null&&bodyn.getChild("block_statement_list")!=null)
1121       bn=parseBlock(bodyn);
1122     else
1123       bn=new BlockNode();
1124     if(isfirst) {
1125       state.addTreeCode(md,bn);
1126     } else {
1127       BlockNode obn = state.getMethodBody(md);
1128       for(int i = 0; i < bn.size(); i++) {
1129         BlockStatementNode bsn = bn.get(i);
1130         obn.addBlockStatement(bsn);
1131       }
1132       state.addTreeCode(md, obn);
1133       bn = null;
1134     }
1135   }
1136
1137   public BlockNode parseBlock(ParseNode pn) {
1138     this.m_taskexitnum = 0;
1139     if (pn==null||isEmpty(pn.getTerminal()))
1140       return new BlockNode();
1141     ParseNode bsn=pn.getChild("block_statement_list");
1142     return parseBlockHelper(bsn);
1143   }
1144
1145   private BlockNode parseBlockHelper(ParseNode pn) {
1146     ParseNodeVector pnv=pn.getChildren();
1147     BlockNode bn=new BlockNode();
1148     for(int i=0; i<pnv.size(); i++) {
1149       Vector bsv=parseBlockStatement(pnv.elementAt(i));
1150       for(int j=0; j<bsv.size(); j++) {
1151         bn.addBlockStatement((BlockStatementNode)bsv.get(j));
1152       }
1153     }
1154     return bn;
1155   }
1156
1157   public BlockNode parseSingleBlock(ParseNode pn) {
1158     BlockNode bn=new BlockNode();
1159     Vector bsv=parseBlockStatement(pn);
1160     for(int j=0; j<bsv.size(); j++) {
1161       bn.addBlockStatement((BlockStatementNode)bsv.get(j));
1162     }
1163     bn.setStyle(BlockNode.NOBRACES);
1164     return bn;
1165   }
1166
1167   public Vector parseSESEBlock(Vector parentbs, ParseNode pn) {
1168     ParseNodeVector pnv=pn.getChildren();
1169     Vector bv=new Vector();
1170     for(int i=0; i<pnv.size(); i++) {
1171       bv.addAll(parseBlockStatement(pnv.elementAt(i)));
1172     }
1173     return bv;
1174   }
1175
1176   public Vector parseBlockStatement(ParseNode pn) {
1177     Vector blockstatements=new Vector();
1178     if (isNode(pn,"tag_declaration")) {
1179       String name=pn.getChild("single").getTerminal();
1180       String type=pn.getChild("type").getTerminal();
1181
1182       TagDeclarationNode tdn=new TagDeclarationNode(name, type);
1183       tdn.setNumLine(pn.getLine());
1184       
1185       blockstatements.add(tdn);
1186     } else if (isNode(pn,"local_variable_declaration")) {
1187       
1188       ParseNode mn=pn.getChild("modifiers");         
1189       TypeDescriptor t=parseTypeDescriptor(pn);
1190       if(mn!=null){
1191         Modifiers m=parseModifiersList(mn);
1192         assignAnnotationsToType(m, t);        
1193       }   
1194       ParseNode vn=pn.getChild("variable_declarators_list");
1195       ParseNodeVector pnv=vn.getChildren();
1196       for(int i=0; i<pnv.size(); i++) {
1197         ParseNode vardecl=pnv.elementAt(i);
1198
1199
1200         ParseNode tmp=vardecl;
1201         TypeDescriptor arrayt=t;
1202
1203         while (tmp.getChild("single")==null) {
1204           arrayt=arrayt.makeArray(state);
1205           tmp=tmp.getChild("array");
1206         }
1207         String identifier=tmp.getChild("single").getTerminal();
1208
1209         ParseNode epn=vardecl.getChild("initializer");
1210
1211
1212         ExpressionNode en=null;
1213         if (epn!=null)
1214           en=parseExpression(epn.getFirstChild());
1215         
1216         DeclarationNode dn=new DeclarationNode(new VarDescriptor(arrayt, identifier),en);
1217         dn.setNumLine(tmp.getLine());
1218
1219         blockstatements.add(dn);
1220       }
1221     } else if (isNode(pn,"nop")) {
1222       /* Do Nothing */
1223     } else if (isNode(pn,"expression")) {
1224       BlockExpressionNode ben=new BlockExpressionNode(parseExpression(pn.getFirstChild()));
1225       ben.setNumLine(pn.getLine());
1226       blockstatements.add(ben);
1227     } else if (isNode(pn,"ifstatement")) {
1228       IfStatementNode isn=new IfStatementNode(parseExpression(pn.getChild("condition").getFirstChild()),
1229           parseSingleBlock(pn.getChild("statement").getFirstChild()),
1230           pn.getChild("else_statement")!=null ? parseSingleBlock(pn.getChild("else_statement").getFirstChild()) : null);
1231       isn.setNumLine(pn.getLine());
1232       
1233       blockstatements.add(isn);
1234     } else if (isNode(pn,"switch_statement")) {
1235       // TODO add version for normal Java later
1236       SwitchStatementNode ssn=new SwitchStatementNode(parseExpression(pn.getChild("condition").getFirstChild()),
1237           parseSingleBlock(pn.getChild("statement").getFirstChild()));
1238       ssn.setNumLine(pn.getLine());
1239       blockstatements.add(ssn);
1240     } else if (isNode(pn,"switch_block_list")) {
1241       // TODO add version for normal Java later
1242       ParseNodeVector pnv=pn.getChildren();
1243       for(int i=0; i<pnv.size(); i++) {
1244         ParseNode sblockdecl=pnv.elementAt(i);
1245         
1246         if(isNode(sblockdecl, "switch_block")) {
1247           ParseNode lpn=sblockdecl.getChild("switch_labels").getChild("switch_label_list");
1248           ParseNodeVector labelv=lpn.getChildren();
1249           Vector<SwitchLabelNode> slv = new Vector<SwitchLabelNode>();
1250           for(int j=0; j<labelv.size(); j++) {
1251             ParseNode labeldecl=labelv.elementAt(j);
1252             if(isNode(labeldecl, "switch_label")) {
1253               SwitchLabelNode sln=new SwitchLabelNode(parseExpression(labeldecl.getChild("constant_expression").getFirstChild()), false);
1254               sln.setNumLine(labeldecl.getLine());
1255               slv.addElement(sln);
1256             } else if(isNode(labeldecl, "default_switch_label")) {
1257               SwitchLabelNode sln=new SwitchLabelNode(null, true);
1258               sln.setNumLine(labeldecl.getLine());
1259               slv.addElement(sln);
1260             }
1261           }
1262           
1263           SwitchBlockNode sbn=new SwitchBlockNode(slv, 
1264               parseSingleBlock(sblockdecl.getChild("switch_statements").getFirstChild()));
1265           sbn.setNumLine(sblockdecl.getLine());
1266           
1267           blockstatements.add(sbn);
1268           
1269         }
1270       }
1271     } else if (isNode(pn, "trycatchstatement")) {
1272       // TODO add version for normal Java later
1273       // Do not fully support exceptions now. Only make sure that if there are no
1274       // exceptions thrown, the execution is right
1275       ParseNode tpn = pn.getChild("tryblock").getFirstChild();
1276       BlockNode bn=parseBlockHelper(tpn);
1277       blockstatements.add(new SubBlockNode(bn));
1278       
1279       ParseNode fbk = pn.getChild("finallyblock");
1280       if(fbk != null) {
1281         ParseNode fpn = fbk.getFirstChild();
1282         BlockNode fbn=parseBlockHelper(fpn);
1283         blockstatements.add(new SubBlockNode(fbn));
1284       }
1285     } else if (isNode(pn, "throwstatement")) {
1286       // TODO Simply return here
1287       //blockstatements.add(new ReturnNode());
1288     } else if (isNode(pn,"taskexit")) {
1289       Vector vfe=null;
1290       if (pn.getChild("flag_effects_list")!=null)
1291         vfe=parseFlags(pn.getChild("flag_effects_list"));
1292       Vector ccs=null;
1293       if (pn.getChild("cons_checks")!=null)
1294         ccs=parseChecks(pn.getChild("cons_checks"));
1295       TaskExitNode ten=new TaskExitNode(vfe, ccs, this.m_taskexitnum++);
1296       ten.setNumLine(pn.getLine());
1297       blockstatements.add(ten);
1298     } else if (isNode(pn,"atomic")) {
1299       BlockNode bn=parseBlockHelper(pn);
1300       AtomicNode an=new AtomicNode(bn);
1301       an.setNumLine(pn.getLine());
1302       blockstatements.add(an);
1303     } else if (isNode(pn,"synchronized")) {
1304       BlockNode bn=parseBlockHelper(pn.getChild("block"));
1305       ExpressionNode en=parseExpression(pn.getChild("expr").getFirstChild());
1306       SynchronizedNode sn=new SynchronizedNode(en, bn);
1307       sn.setNumLine(pn.getLine());
1308       blockstatements.add(sn);
1309     } else if (isNode(pn,"return")) {
1310       if (isEmpty(pn.getTerminal()))
1311         blockstatements.add(new ReturnNode());
1312       else {
1313         ExpressionNode en=parseExpression(pn.getFirstChild());
1314         ReturnNode rn=new ReturnNode(en);
1315         rn.setNumLine(pn.getLine());
1316         blockstatements.add(rn);
1317       }
1318     } else if (isNode(pn,"block_statement_list")) {
1319       BlockNode bn=parseBlockHelper(pn);
1320       blockstatements.add(new SubBlockNode(bn));
1321     } else if (isNode(pn,"empty")) {
1322       /* nop */
1323     } else if (isNode(pn,"statement_expression_list")) {
1324       ParseNodeVector pnv=pn.getChildren();
1325       BlockNode bn=new BlockNode();
1326       for(int i=0; i<pnv.size(); i++) {
1327         ExpressionNode en=parseExpression(pnv.elementAt(i));
1328         blockstatements.add(new BlockExpressionNode(en));
1329       }
1330       bn.setStyle(BlockNode.EXPRLIST);
1331     } else if (isNode(pn,"forstatement")) {
1332       BlockNode init=parseSingleBlock(pn.getChild("initializer").getFirstChild());
1333       BlockNode update=parseSingleBlock(pn.getChild("update").getFirstChild());
1334       ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild());
1335       BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild());
1336       if(condition == null) {
1337         // no condition clause, make a 'true' expression as the condition
1338         condition = (ExpressionNode)new LiteralNode("boolean", new Boolean(true));
1339       }
1340       LoopNode ln=new LoopNode(init,condition,update,body);
1341       ln.setNumLine(pn.getLine());
1342       blockstatements.add(ln);
1343     } else if (isNode(pn,"whilestatement")) {
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.WHILELOOP));
1351     } else if (isNode(pn,"dowhilestatement")) {
1352       ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild());
1353       BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild());
1354       if(condition == null) {
1355         // no condition clause, make a 'true' expression as the condition
1356         condition = (ExpressionNode)new LiteralNode("boolean", new Boolean(true));
1357       }
1358       blockstatements.add(new LoopNode(condition,body,LoopNode.DOWHILELOOP));
1359     } else if (isNode(pn,"sese")) {
1360       ParseNode pnID=pn.getChild("identifier");
1361       String stID=null;
1362       if( pnID != null ) { stID=pnID.getFirstChild().getTerminal(); }
1363       SESENode start=new SESENode(stID);
1364       start.setNumLine(pn.getLine());
1365       SESENode end  =new SESENode(stID);
1366       start.setEnd( end   );
1367       end.setStart( start );
1368       blockstatements.add(start);
1369       blockstatements.addAll(parseSESEBlock(blockstatements,pn.getChild("body").getFirstChild()));
1370       blockstatements.add(end);
1371     } else if (isNode(pn,"continue")) {
1372       ContinueBreakNode cbn=new ContinueBreakNode(false);
1373       cbn.setNumLine(pn.getLine());
1374       blockstatements.add(cbn);
1375     } else if (isNode(pn,"break")) {
1376       ContinueBreakNode cbn=new ContinueBreakNode(true);
1377       cbn.setNumLine(pn.getLine());
1378       blockstatements.add(cbn);
1379
1380     } else if (isNode(pn,"genreach")) {
1381       String graphName = pn.getChild("graphName").getTerminal();
1382       blockstatements.add( new GenReachNode( graphName ) );
1383
1384     } else {
1385       System.out.println("---------------");
1386       System.out.println(pn.PPrint(3,true));
1387       throw new Error();
1388     }
1389     return blockstatements;
1390   }
1391
1392   public MethodDescriptor parseMethodHeader(ParseNode pn) {
1393     ParseNode mn=pn.getChild("modifiers");
1394     Modifiers m=parseModifiersList(mn);
1395
1396     ParseNode tn=pn.getChild("returntype");
1397     TypeDescriptor returntype;
1398     if (tn!=null)
1399       returntype=parseTypeDescriptor(tn);
1400     else
1401       returntype=new TypeDescriptor(TypeDescriptor.VOID);
1402
1403     ParseNode pmd=pn.getChild("method_declarator");
1404     String name=pmd.getChild("name").getTerminal();
1405     MethodDescriptor md=new MethodDescriptor(m, returntype, name);
1406
1407     ParseNode paramnode=pmd.getChild("parameters");
1408     parseParameterList(md,paramnode);
1409     return md;
1410   }
1411
1412   public void parseParameterList(MethodDescriptor md, ParseNode pn) {
1413     ParseNode paramlist=pn.getChild("formal_parameter_list");
1414     if (paramlist==null)
1415       return;
1416     ParseNodeVector pnv=paramlist.getChildren();
1417     for(int i=0; i<pnv.size(); i++) {
1418       ParseNode paramn=pnv.elementAt(i);
1419
1420       if (isNode(paramn, "tag_parameter")) {
1421         String paramname=paramn.getChild("single").getTerminal();
1422         TypeDescriptor type=new TypeDescriptor(TypeDescriptor.TAG);
1423         md.addTagParameter(type, paramname);
1424       } else {
1425         TypeDescriptor type=parseTypeDescriptor(paramn);
1426
1427         ParseNode tmp=paramn;
1428         while (tmp.getChild("single")==null) {
1429           type=type.makeArray(state);
1430           tmp=tmp.getChild("array");
1431         }
1432         String paramname=tmp.getChild("single").getTerminal();
1433
1434         md.addParameter(type, paramname);
1435       }
1436     }
1437   }
1438
1439   public Modifiers parseModifiersList(ParseNode pn) {
1440     Modifiers m=new Modifiers();
1441     ParseNode modlist=pn.getChild("modifier_list");
1442     if (modlist!=null) {
1443       ParseNodeVector pnv=modlist.getChildren();
1444       for(int i=0; i<pnv.size(); i++) {
1445         ParseNode modn=pnv.elementAt(i);        
1446         if (isNode(modn,"public"))
1447           m.addModifier(Modifiers.PUBLIC);
1448         else if (isNode(modn,"protected"))
1449           m.addModifier(Modifiers.PROTECTED);
1450         else if (isNode(modn,"private"))
1451           m.addModifier(Modifiers.PRIVATE);
1452         else if (isNode(modn,"static"))
1453           m.addModifier(Modifiers.STATIC);
1454         else if (isNode(modn,"final"))
1455           m.addModifier(Modifiers.FINAL);
1456         else if (isNode(modn,"native"))
1457           m.addModifier(Modifiers.NATIVE);
1458         else if (isNode(modn,"synchronized"))
1459           m.addModifier(Modifiers.SYNCHRONIZED);
1460         else if (isNode(modn,"atomic"))
1461           m.addModifier(Modifiers.ATOMIC);
1462     else if (isNode(modn,"abstract"))
1463       m.addModifier(Modifiers.ABSTRACT);
1464     else if (isNode(modn,"volatile"))
1465       m.addModifier(Modifiers.VOLATILE);
1466     else if (isNode(modn,"transient"))
1467       m.addModifier(Modifiers.TRANSIENT);
1468     else if(isNode(modn,"annotation_list"))
1469       parseAnnotationList(modn,m);    
1470         else{     
1471           throw new Error("Unrecognized Modifier:"+modn.getLabel());}
1472       }
1473     }
1474     return m;
1475   }
1476   
1477   private void parseAnnotationList(ParseNode pn, Modifiers m) {
1478     ParseNodeVector pnv = pn.getChildren();
1479     for (int i = 0; i < pnv.size(); i++) {
1480       ParseNode body_list = pnv.elementAt(i);
1481       if (isNode(body_list, "annotation_body")) {
1482         ParseNode body_node = body_list.getFirstChild();
1483         if (isNode(body_node, "marker_annotation")) {
1484           m.addAnnotation(new AnnotationDescriptor(body_node.getChild("name").getTerminal()));
1485         } else if (isNode(body_node, "single_annotation")) {
1486           m.addAnnotation(new AnnotationDescriptor(body_node.getChild("name").getTerminal(),
1487               body_node.getChild("element_value").getTerminal()));
1488         } else if (isNode(body_node, "normal_annotation")) {
1489           throw new Error("Annotation with multiple data members is not supported yet.");
1490         }
1491       }
1492     }
1493   }
1494
1495   private boolean isNode(ParseNode pn, String label) {
1496     if (pn.getLabel().equals(label))
1497       return true;
1498     else return false;
1499   }
1500
1501   private static boolean isEmpty(ParseNode pn) {
1502     if (pn.getLabel().equals("empty"))
1503       return true;
1504     else
1505       return false;
1506   }
1507
1508   private static boolean isEmpty(String s) {
1509     if (s.equals("empty"))
1510       return true;
1511     else
1512       return false;
1513   }
1514
1515   /** Throw an exception if something is unexpected */
1516   private void check(ParseNode pn, String label) {
1517     if (pn == null) {
1518       throw new Error(pn+ "IE: Expected '" + label + "', got null");
1519     }
1520     if (!pn.getLabel().equals(label)) {
1521       throw new Error(pn+ "IE: Expected '" + label + "', got '"+pn.getLabel()+"'");
1522     }
1523   }
1524 }