7b14d103ae23a3b77740012cd5399cba77eeb99e
[IRC.git] / Robust / src / IR / Tree / BuildIR.java
1 package IR.Tree;
2 import IR.*;
3 import Util.Lattice;
4 import Util.Pair;
5
6 import java.io.File;
7 import java.util.*;
8 import java.io.*;
9 import java.lang.Throwable;
10 public class BuildIR {
11   State state;
12   private boolean isRunningRecursiveInnerClass;
13   private int m_taskexitnum;
14
15   public BuildIR(State state) {
16     this.state=state;
17     this.m_taskexitnum = 0;
18     this.isRunningRecursiveInnerClass = false;
19   }
20
21   public void buildtree(ParseNode pn, Set toanalyze, String sourcefile) {
22     parseFile(pn, toanalyze, sourcefile);
23
24     // numering the interfaces
25     int if_num = 0;
26     Iterator it_classes = state.getClassSymbolTable().getValueSet().iterator();
27     while(it_classes.hasNext()) {
28       ClassDescriptor cd = (ClassDescriptor)it_classes.next();
29       if(cd.isInterface()) {
30         cd.setInterfaceId(if_num++);
31       }
32     }
33   }
34
35   //This is all single imports and a subset of the
36   //multi imports that have been resolved.
37   ChainHashMap mandatoryImports;
38   //maps class names in file to full name
39   //Note may map a name to an ERROR.
40   ChainHashMap multiimports;
41   String packageName;
42
43   String currsourcefile;
44   Set analyzeset;
45
46   void pushChainMaps() {
47     mandatoryImports=mandatoryImports.makeChild();
48     multiimports=multiimports.makeChild();
49   }
50   
51   void popChainMaps() {
52     mandatoryImports=mandatoryImports.getParent();
53     multiimports=multiimports.getParent();
54   }
55
56   /** Parse the classes in this file */
57   public void parseFile(ParseNode pn, Set toanalyze, String sourcefile) {
58     mandatoryImports = new ChainHashMap();
59     multiimports = new ChainHashMap();
60     currsourcefile=sourcefile;
61     analyzeset=toanalyze;
62
63     if(state.JNI) {
64       //add java.lang as our default multi-import
65       this.addMultiImport(sourcefile, "java.lang", false);
66     }
67
68     ParseNode ipn = pn.getChild("imports").getChild("import_decls_list");
69     if ((ipn != null) && !state.MGC) {
70       ParseNodeVector pnv = ipn.getChildren();
71       for (int i = 0; i < pnv.size(); i++) {
72         ParseNode pnimport = pnv.elementAt(i);
73         NameDescriptor nd = parseName(pnimport.getChild("name"));
74         if (isNode(pnimport, "import_single")) {
75           if (!mandatoryImports.containsKey(nd.getIdentifier())) {
76             // map name to full name (includes package/directory
77             mandatoryImports.put(nd.getIdentifier(), nd.getPathFromRootToHere());
78           } else {
79             throw new Error("An ambiguous class "+ nd.getIdentifier() +" has been found. It is included for " +
80                             ((String)mandatoryImports.get(nd.getIdentifier())) + " and " +
81                             nd.getPathFromRootToHere());
82           }
83         } else {
84           addMultiImport(sourcefile, nd.getPathFromRootToHere(), false);
85         }
86       }
87     }
88
89     ParseNode ppn=pn.getChild("packages").getChild("package");
90     packageName = null;
91     if ((ppn!=null) && !state.MGC){
92       NameDescriptor nd = parseClassName(ppn.getChild("name"));
93       packageName = nd.getPathFromRootToHere();
94       //Trick -> import the package directory as a multi-import and it'll
95       //automatically recognize files in the same directory.
96       addMultiImport(sourcefile, packageName, true);
97     }
98
99     ParseNode tpn=pn.getChild("type_declaration_list");
100     if (tpn != null) {
101       ParseNodeVector pnv = tpn.getChildren();
102       for (int i = 0; i < pnv.size(); i++) {
103         ParseNode type_pn = pnv.elementAt(i);
104         if (isEmpty(type_pn)) /* Skip the semicolon */
105           continue;
106         if (isNode(type_pn, "class_declaration")) {
107           ClassDescriptor cn = parseTypeDecl(type_pn);
108           parseInitializers(cn);
109
110           // for inner classes/enum
111           HashSet tovisit = new HashSet();
112           Iterator it_icds = cn.getInnerClasses();
113           while (it_icds.hasNext()) {
114             tovisit.add(it_icds.next());
115           }
116
117           while (!tovisit.isEmpty()) {
118             ClassDescriptor cd = (ClassDescriptor) tovisit.iterator().next();
119             tovisit.remove(cd);
120             parseInitializers(cd);
121
122             Iterator it_ics = cd.getInnerClasses();
123             while (it_ics.hasNext()) {
124               tovisit.add(it_ics.next());
125             }
126           }
127         } else if (isNode(type_pn, "task_declaration")) {
128           TaskDescriptor td = parseTaskDecl(type_pn);
129           if (toanalyze != null)
130             toanalyze.add(td);
131           state.addTask(td);
132         } else if (isNode(type_pn, "interface_declaration")) {
133           // TODO add version for normal Java later
134           ClassDescriptor cn = parseInterfaceDecl(type_pn, null);
135         } else if (isNode(type_pn, "enum_declaration")) {
136           // TODO add version for normal Java later
137           ClassDescriptor cn = parseEnumDecl(null, type_pn);
138
139         } else if(isNode(type_pn,"annotation_type_declaration")) {
140           ClassDescriptor cn=parseAnnotationTypeDecl(type_pn);
141         } else {
142           throw new Error(type_pn.getLabel());
143         }
144       }
145     }
146   }
147
148
149   //This kind of breaks away from tradition a little bit by doing the file checks here
150   // instead of in Semantic check, but doing it here is easier because we have a mapping early on
151   // if I wait until semantic check, I have to change ALL the type descriptors to match the new
152   // mapping and that's both ugly and tedious.
153   private void addMultiImport(String currentSource, String importPath, boolean isPackageDirectory) {
154     boolean found = false;
155     for (int j = 0; j < state.classpath.size(); j++) {
156       String path = (String) state.classpath.get(j);
157       File folder = new File(path, importPath.replace('.', '/'));
158       if (folder.exists()) {
159         found = true;
160         for (String file : folder.list()) {
161           // if the file is of type *.java add to multiImport list.
162           if (file.lastIndexOf('.') != -1 && file.substring(file.lastIndexOf('.')).equalsIgnoreCase(".java")) {
163             String classname = file.substring(0, file.length() - 5);
164             // single imports have precedence over multi-imports
165             if (!mandatoryImports.containsKey(classname)) {
166               //package files have precedence over multi-imports.
167               if (multiimports.containsKey(classname)  && !isPackageDirectory) {
168                 // put error in for later, in case we try to import
169                 multiimports.put(classname, new Error("Error: class " + classname + " is defined more than once in a multi-import in " + currentSource));
170               } else {
171                 multiimports.put(classname, importPath + "." + classname);
172               }
173             }
174           }
175         }
176       }
177     }
178
179     if(!found) {
180       throw new Error("Import package " + importPath + " in  " + currentSource
181                       + " cannot be resolved.");
182     }
183   }
184
185   public void parseInitializers(ClassDescriptor cn) {
186     Vector fv=cn.getFieldVec();
187     Iterator methodit = cn.getMethods();
188     HashMap<MethodDescriptor, Integer> md2pos = new HashMap<MethodDescriptor, Integer>();
189     while(methodit.hasNext()) {
190       MethodDescriptor currmd=(MethodDescriptor)methodit.next();
191       if(currmd.isConstructor()) {
192         BlockNode bn=state.getMethodBody(currmd);
193         // if there are super(...) invokation, the initializers should be invoked after that
194         int i = 0;
195         for(; i < bn.size(); i++) {
196           if(Kind.BlockExpressionNode==bn.get(i).kind()
197                   &&(((BlockExpressionNode)bn.get(i)).getExpression() instanceof MethodInvokeNode)
198                   &&((MethodInvokeNode)(((BlockExpressionNode)bn.get(i)).getExpression())).getMethodName().equals("super")) {
199             break;
200           }
201         }
202         if(i==bn.size()) {
203           md2pos.put(currmd, 0);
204         } else {
205           md2pos.put(currmd, i+1);
206         }
207       }
208     }
209     int pos = 0;
210     for(int i=0; i<fv.size(); i++) {
211       FieldDescriptor fd=(FieldDescriptor)fv.get(i);
212       if(fd.getExpressionNode()!=null) {
213         methodit = cn.getMethods();
214         while(methodit.hasNext()) {
215           MethodDescriptor currmd=(MethodDescriptor)methodit.next();
216           if(currmd.isConstructor()) {
217             int offset = md2pos.get(currmd);
218             BlockNode bn=state.getMethodBody(currmd);
219             NameNode nn=new NameNode(new NameDescriptor(fd.getSymbol()));
220             AssignmentNode an=new AssignmentNode(nn,fd.getExpressionNode(),new AssignOperation(1));
221             bn.addBlockStatementAt(new BlockExpressionNode(an), pos+offset);
222           }
223         }
224         pos++;
225       }
226     }
227   }
228   
229   private ClassDescriptor parseEnumDecl(ClassDescriptor cn, ParseNode pn) {    
230     String basename=pn.getChild("name").getTerminal();
231     String classname=(cn!=null)?cn.getClassName()+"$"+basename:basename;
232     ClassDescriptor ecd=new ClassDescriptor(cn!=null?cn.getPackage():null, classname, false);
233     
234     if (cn!=null) {
235       if (packageName==null)
236         cn.getSingleImportMappings().put(basename,classname);
237       else
238         cn.getSingleImportMappings().put(basename,packageName+"."+classname);
239     }
240
241     pushChainMaps();
242     ecd.setImports(mandatoryImports, multiimports);
243     ecd.setAsEnum();
244     if(cn != null) {
245       ecd.setSurroundingClass(cn.getSymbol());
246       ecd.setSurrounding(cn);
247       cn.addEnum(ecd);
248     }
249     if (!(ecd.getSymbol().equals(TypeUtil.ObjectClass)||
250           ecd.getSymbol().equals(TypeUtil.TagClass))) {
251       ecd.setSuper(TypeUtil.ObjectClass);
252     }
253     ecd.setModifiers(parseModifiersList(pn.getChild("modifiers")));
254     parseEnumBody(ecd, pn.getChild("enumbody"));
255
256     if (analyzeset != null)
257       analyzeset.add(ecd);
258     ecd.setSourceFileName(currsourcefile);
259     state.addClass(ecd);
260
261     popChainMaps();
262     return ecd;
263   }
264
265   private void parseEnumBody(ClassDescriptor cn, ParseNode pn) {
266     ParseNode decls=pn.getChild("enum_constants_list");
267     if (decls!=null) {
268       ParseNodeVector pnv=decls.getChildren();
269       for(int i=0; i<pnv.size(); i++) {
270         ParseNode decl=pnv.elementAt(i);
271         if (isNode(decl,"enum_constant")) {
272           parseEnumConstant(cn,decl);
273         } else throw new Error();
274       }
275     }
276   }
277
278   private void parseEnumConstant(ClassDescriptor cn, ParseNode pn) {
279     cn.addEnumConstant(pn.getChild("name").getTerminal());
280   }
281
282   private ClassDescriptor parseAnnotationTypeDecl(ParseNode pn) {
283     ClassDescriptor cn=new ClassDescriptor(pn.getChild("name").getTerminal(), true);
284     pushChainMaps();
285     cn.setImports(mandatoryImports, multiimports);
286     ParseNode modifiers=pn.getChild("modifiers");
287     if(modifiers!=null) {
288       cn.setModifiers(parseModifiersList(modifiers));
289     }
290     parseAnnotationTypeBody(cn,pn.getChild("body"));
291     popChainMaps();
292
293     if (analyzeset != null)
294       analyzeset.add(cn);
295     cn.setSourceFileName(currsourcefile);
296     state.addClass(cn);
297
298     return cn;
299   }
300
301   private void parseAnnotationTypeBody(ClassDescriptor cn, ParseNode pn) {
302     ParseNode list_node=pn.getChild("annotation_type_element_list");
303     if(list_node!=null) {
304       ParseNodeVector pnv = list_node.getChildren();
305       for (int i = 0; i < pnv.size(); i++) {
306         ParseNode element_node = pnv.elementAt(i);
307         if (isNode(element_node, "annotation_type_element_declaration")) {
308           ParseNodeVector elementProps = element_node.getChildren();
309           String identifier=null;
310           TypeDescriptor type=null;
311           Modifiers modifiers=new Modifiers();
312           for(int eidx=0; eidx<elementProps.size(); eidx++) {
313             ParseNode prop_node=elementProps.elementAt(eidx);
314             if(isNode(prop_node,"name")) {
315               identifier=prop_node.getTerminal();
316             } else if(isNode(prop_node,"type")) {
317               type=parseTypeDescriptor(prop_node);
318             } else if(isNode(prop_node,"modifier")) {
319               modifiers=parseModifiersList(prop_node);
320             }
321           }
322           cn.addField(new FieldDescriptor(modifiers, type, identifier, null, false));
323         }
324       }
325     }
326   }
327
328   public ClassDescriptor parseInterfaceDecl(ParseNode pn, ClassDescriptor outerclass) {
329     String basename=pn.getChild("name").getTerminal();
330     String classname=((outerclass==null)?"":(outerclass.getClassName()+"$"))+basename;
331     if (outerclass!=null) {
332       if (packageName==null)
333         outerclass.getSingleImportMappings().put(basename,classname);
334       else
335         outerclass.getSingleImportMappings().put(basename,packageName+"."+classname);
336     }
337     ClassDescriptor cn= new ClassDescriptor(packageName, classname, true);
338
339     pushChainMaps();
340     cn.setImports(mandatoryImports, multiimports);
341     //cn.setAsInterface();
342     if (!isEmpty(pn.getChild("superIF").getTerminal())) {
343       /* parse inherited interface name */
344       ParseNode snlist=pn.getChild("superIF").getChild("extend_interface_list");
345       ParseNodeVector pnv=snlist.getChildren();
346       for(int i=0; i<pnv.size(); i++) {
347         ParseNode decl=pnv.elementAt(i);
348         if (isNode(decl,"type")) {
349           NameDescriptor nd=parseClassName(decl.getChild("class").getChild("name"));
350           cn.addSuperInterface(nd.toString());
351         } else if (isNode(decl, "interface_declaration")) {
352           ClassDescriptor innercn = parseInterfaceDecl(decl, cn);
353         } else throw new Error();
354       }
355     }
356     cn.setModifiers(parseModifiersList(pn.getChild("modifiers")));
357     parseInterfaceBody(cn, pn.getChild("interfacebody"));
358     if (analyzeset != null)
359       analyzeset.add(cn);
360     cn.setSourceFileName(currsourcefile);
361     state.addClass(cn);
362     popChainMaps();
363     return cn;
364   }
365
366   private void parseInterfaceBody(ClassDescriptor cn, ParseNode pn) {
367     assert(cn.isInterface());
368     ParseNode decls=pn.getChild("interface_member_declaration_list");
369     if (decls!=null) {
370       ParseNodeVector pnv=decls.getChildren();
371       for(int i=0; i<pnv.size(); i++) {
372         ParseNode decl=pnv.elementAt(i);
373         if (isNode(decl,"constant")) {
374           parseInterfaceConstant(cn,decl);
375         } else if (isNode(decl,"method")) {
376           parseInterfaceMethod(cn,decl.getChild("method_declaration"));
377         } else if (isNode(decl, "interface_declaration")) {
378           parseInterfaceDecl(decl, cn);
379         } else throw new Error(decl.PPrint(2, true));
380       }
381     }
382   }
383
384
385
386   private void parseInterfaceConstant(ClassDescriptor cn, ParseNode pn) {
387     if (pn!=null) {
388       parseFieldDecl(cn,pn.getChild("field_declaration"));
389       return;
390     }
391     throw new Error();
392   }
393
394   private void parseInterfaceMethod(ClassDescriptor cn, ParseNode pn) {
395     ParseNode headern=pn.getChild("header");
396     ParseNode bodyn=pn.getChild("body");
397     MethodDescriptor md=parseMethodHeader(headern.getChild("method_header"));
398     md.getModifiers().addModifier(Modifiers.PUBLIC);
399     md.getModifiers().addModifier(Modifiers.ABSTRACT);
400     try {
401       BlockNode bn=parseBlock(cn, md, md.isStatic()||md.isStaticBlock(), bodyn);
402       cn.addMethod(md);
403       state.addTreeCode(md,bn);
404     } catch (Exception e) {
405       System.out.println("Error with method:"+md.getSymbol());
406       e.printStackTrace();
407       throw new Error();
408     } catch (Error e) {
409       System.out.println("Error with method:"+md.getSymbol());
410       e.printStackTrace();
411       throw new Error();
412     }
413   }
414
415   public TaskDescriptor parseTaskDecl(ParseNode pn) {
416     TaskDescriptor td=new TaskDescriptor(pn.getChild("name").getTerminal());
417     ParseNode bodyn=pn.getChild("body");
418     BlockNode bn=parseBlock(null, null, false, bodyn);
419     parseParameterList(td, pn);
420     state.addTreeCode(td,bn);
421     if (pn.getChild("flag_effects_list")!=null)
422       td.addFlagEffects(parseFlags(pn.getChild("flag_effects_list")));
423     return td;
424   }
425
426   public Vector parseFlags(ParseNode pn) {
427     Vector vfe=new Vector();
428     ParseNodeVector pnv=pn.getChildren();
429     for(int i=0; i<pnv.size(); i++) {
430       ParseNode fn=pnv.elementAt(i);
431       FlagEffects fe=parseFlagEffects(fn);
432       vfe.add(fe);
433     }
434     return vfe;
435   }
436
437   public FlagEffects parseFlagEffects(ParseNode pn) {
438     if (isNode(pn,"flag_effect")) {
439       String flagname=pn.getChild("name").getTerminal();
440       FlagEffects fe=new FlagEffects(flagname);
441       if (pn.getChild("flag_list")!=null)
442         parseFlagEffect(fe, pn.getChild("flag_list"));
443       if (pn.getChild("tag_list")!=null)
444         parseTagEffect(fe, pn.getChild("tag_list"));
445       return fe;
446     } else throw new Error();
447   }
448
449   public void parseTagEffect(FlagEffects fes, ParseNode pn) {
450     ParseNodeVector pnv=pn.getChildren();
451     for(int i=0; i<pnv.size(); i++) {
452       ParseNode pn2=pnv.elementAt(i);
453       boolean status=true;
454       if (isNode(pn2,"not")) {
455         status=false;
456         pn2=pn2.getChild("name");
457       }
458       String name=pn2.getTerminal();
459       fes.addTagEffect(new TagEffect(name,status));
460     }
461   }
462
463   public void parseFlagEffect(FlagEffects fes, ParseNode pn) {
464     ParseNodeVector pnv=pn.getChildren();
465     for(int i=0; i<pnv.size(); i++) {
466       ParseNode pn2=pnv.elementAt(i);
467       boolean status=true;
468       if (isNode(pn2,"not")) {
469         status=false;
470         pn2=pn2.getChild("name");
471       }
472       String name=pn2.getTerminal();
473       fes.addEffect(new FlagEffect(name,status));
474     }
475   }
476
477   public FlagExpressionNode parseFlagExpression(ParseNode pn) {
478     if (isNode(pn,"or")) {
479       ParseNodeVector pnv=pn.getChildren();
480       ParseNode left=pnv.elementAt(0);
481       ParseNode right=pnv.elementAt(1);
482       return new FlagOpNode(parseFlagExpression(left), parseFlagExpression(right), new Operation(Operation.LOGIC_OR));
483     } else if (isNode(pn,"and")) {
484       ParseNodeVector pnv=pn.getChildren();
485       ParseNode left=pnv.elementAt(0);
486       ParseNode right=pnv.elementAt(1);
487       return new FlagOpNode(parseFlagExpression(left), parseFlagExpression(right), new Operation(Operation.LOGIC_AND));
488     } else if (isNode(pn, "not")) {
489       ParseNodeVector pnv=pn.getChildren();
490       ParseNode left=pnv.elementAt(0);
491       return new FlagOpNode(parseFlagExpression(left), new Operation(Operation.LOGIC_NOT));
492
493     } else if (isNode(pn,"name")) {
494       return new FlagNode(pn.getTerminal());
495     } else {
496       throw new Error();
497     }
498   }
499
500   public Vector parseChecks(ParseNode pn) {
501     Vector ccs=new Vector();
502     ParseNodeVector pnv=pn.getChildren();
503     for(int i=0; i<pnv.size(); i++) {
504       ParseNode fn=pnv.elementAt(i);
505       ConstraintCheck cc=parseConstraintCheck(fn);
506       ccs.add(cc);
507     }
508     return ccs;
509   }
510
511   public ConstraintCheck parseConstraintCheck(ParseNode pn) {
512     if (isNode(pn,"cons_check")) {
513       String specname=pn.getChild("name").getChild("identifier").getTerminal();
514       Vector[] args=parseConsArgumentList(pn);
515       ConstraintCheck cc=new ConstraintCheck(specname);
516       for(int i=0; i<args[0].size(); i++) {
517         cc.addVariable((String)args[0].get(i));
518         cc.addArgument((ExpressionNode)args[1].get(i));
519       }
520       return cc;
521     } else throw new Error();
522   }
523
524   public void parseParameterList(TaskDescriptor td, ParseNode pn) {
525
526     boolean optional;
527     ParseNode paramlist=pn.getChild("task_parameter_list");
528     if (paramlist==null)
529       return;
530     ParseNodeVector pnv=paramlist.getChildren();
531     for(int i=0; i<pnv.size(); i++) {
532       ParseNode paramn=pnv.elementAt(i);
533       if(paramn.getChild("optional")!=null) {
534         optional = true;
535         paramn = paramn.getChild("optional").getFirstChild();
536         System.out.println("OPTIONAL FOUND!!!!!!!");
537       } else { optional = false;
538                System.out.println("NOT OPTIONAL"); }
539
540       TypeDescriptor type=parseTypeDescriptor(paramn);
541
542       String paramname=paramn.getChild("single").getTerminal();
543       FlagExpressionNode fen=null;
544       if (paramn.getChild("flag")!=null)
545         fen=parseFlagExpression(paramn.getChild("flag").getFirstChild());
546
547       ParseNode tagnode=paramn.getChild("tag");
548
549       TagExpressionList tel=null;
550       if (tagnode!=null) {
551         tel=parseTagExpressionList(tagnode);
552       }
553
554       td.addParameter(type,paramname,fen, tel, optional);
555     }
556   }
557
558   public TagExpressionList parseTagExpressionList(ParseNode pn) {
559     //BUG FIX: change pn.getChildren() to pn.getChild("tag_expression_list").getChildren()
560     //To test, feed in any input program that uses tags
561     ParseNodeVector pnv=pn.getChild("tag_expression_list").getChildren();
562     TagExpressionList tel=new TagExpressionList();
563     for(int i=0; i<pnv.size(); i++) {
564       ParseNode tn=pnv.elementAt(i);
565       String type=tn.getChild("type").getTerminal();
566       String name=tn.getChild("single").getTerminal();
567       tel.addTag(type, name);
568     }
569     return tel;
570   }
571
572   public ClassDescriptor parseTypeDecl(ParseNode pn) {
573     ClassDescriptor cn=new ClassDescriptor(packageName, pn.getChild("name").getTerminal(), false);
574     pushChainMaps();
575     cn.setImports(mandatoryImports, multiimports);
576     if (!isEmpty(pn.getChild("super").getTerminal())) {
577       /* parse superclass name */
578       ParseNode snn=pn.getChild("super").getChild("type").getChild("class").getChild("name");
579       NameDescriptor nd=parseClassName(snn);
580       cn.setSuper(nd.toString());
581     } else {
582       if (!(cn.getSymbol().equals(TypeUtil.ObjectClass)||
583             cn.getSymbol().equals(TypeUtil.TagClass)))
584         cn.setSuper(TypeUtil.ObjectClass);
585     }
586     // check inherited interfaces
587     if (!isEmpty(pn.getChild("superIF").getTerminal())) {
588       /* parse inherited interface name */
589       ParseNode snlist=pn.getChild("superIF").getChild("interface_type_list");
590       ParseNodeVector pnv=snlist.getChildren();
591       for(int i=0; i<pnv.size(); i++) {
592         ParseNode decl=pnv.elementAt(i);
593         if (isNode(decl,"type")) {
594           NameDescriptor nd=parseClassName(decl.getChild("class").getChild("name"));
595           cn.addSuperInterface(nd.toString());
596         }
597       }
598     }
599     cn.setModifiers(parseModifiersList(pn.getChild("modifiers")));
600     parseClassBody(cn, pn.getChild("classbody"));
601
602     boolean hasConstructor = false;
603     for(Iterator method_it=cn.getMethods(); method_it.hasNext(); ) {
604       MethodDescriptor md=(MethodDescriptor)method_it.next();
605       hasConstructor |= md.isConstructor();
606     }
607     if((!hasConstructor) && (!cn.isEnum())) {
608       // add a default constructor for this class
609       MethodDescriptor md = new MethodDescriptor(new Modifiers(Modifiers.PUBLIC),
610                                                  cn.getSymbol(), false);
611       BlockNode bn=new BlockNode();
612       state.addTreeCode(md,bn);
613       md.setDefaultConstructor();
614       cn.addMethod(md);
615     }
616
617
618     popChainMaps();
619
620     cn.setSourceFileName(currsourcefile);
621
622
623     
624     if (analyzeset != null)
625       analyzeset.add(cn);
626     state.addClass(cn);
627 //create this$n representing a final reference to the next surrounding class. each inner class should have whatever inner class
628 //pointers the surrounding class has + a pointer to the surrounding class.
629    if( true )
630    {
631         this.isRunningRecursiveInnerClass = true; //fOR dEBUGGING PURPOSES IN ORDER TO DUMP STRINGS WHILE IN THIS CODE PATH
632         addOuterClassReferences( cn, 0 );
633         addOuterClassParam( cn, 0 );
634         this.isRunningRecursiveInnerClass = false;
635     }
636     return cn;
637   }
638
639 private void initializeOuterMember( MethodDescriptor md, String fieldName, String formalParameter ) {
640          BlockNode obn = state.getMethodBody(md);
641          NameNode nn=new NameNode( new NameDescriptor( fieldName ) );
642          NameNode fn = new NameNode ( new NameDescriptor( formalParameter ) );
643           //nn.setNumLine(en.getNumLine())
644          AssignmentNode an=new AssignmentNode(nn,fn,new AssignOperation(1));
645          //an.setNumLine(pn.getLine());
646          obn.addFirstBlockStatement(new BlockExpressionNode(an));
647         // System.out.print( "The code inserted is : " + obn.printNode( 0 ) + "\n" );
648          state.addTreeCode(md, obn);
649 }
650
651 private void addOuterClassParam( ClassDescriptor cn, int depth )
652 {
653         Iterator nullCheckItr = cn.getInnerClasses();
654         if( false == nullCheckItr.hasNext() )
655                 return;
656
657         //create a typedescriptor of type cn
658         TypeDescriptor theTypeDesc = new TypeDescriptor( cn );
659         
660         for(Iterator it=cn.getInnerClasses(); it.hasNext(); ) {
661                 ClassDescriptor icd=(ClassDescriptor)it.next();
662                 if(icd.isStatic()||icd.getInStaticContext()) {
663                     continue;
664                 }
665                 
666                 //iterate over all ctors of I.Cs and add a new param
667                 for(Iterator method_it=icd.getMethods(); method_it.hasNext(); ) {
668                          MethodDescriptor md=(MethodDescriptor)method_it.next();
669                          if( md.isConstructor() ){
670                                 md.addParameter( theTypeDesc, "surrounding$" + String.valueOf(depth) ); 
671                                 initializeOuterMember( md, "this$" + String.valueOf( depth ), "surrounding$" + String.valueOf(depth) );
672                                 //System.out.println( "The added param is " + md.toString() + "\n" );
673                         }
674                 }
675                 addOuterClassParam( icd, depth + 1 );
676                 
677         }
678         
679 }
680 private void addOuterClassReferences( ClassDescriptor cn, int depth )
681 {
682         //SYMBOLTABLE does not have a length or empty method, hence could not define a hasInnerClasses method in classDescriptor
683         Iterator nullCheckItr = cn.getInnerClasses();
684         if( false == nullCheckItr.hasNext() )
685                 return;
686
687         String tempCopy = cn.getClassName();
688         //MESSY HACK FOLLOWS
689         int i = 0;
690
691         ParseNode theNode = new ParseNode( "field_declaration" );
692         theNode.addChild("modifier").addChild( new ParseNode( "modifier_list" ) ).addChild("final");
693         ParseNode theTypeNode = new ParseNode("type");
694         ParseNode tempChildNode = theTypeNode.addChild("class").addChild( "name" );
695                 //tempChildNode.addChild("base").addChild( new ParseNode("empty") );
696         tempChildNode.addChild("identifier").addChild ( tempCopy );
697         theNode.addChild("type").addChild( theTypeNode );
698         ParseNode variableDeclaratorID = new ParseNode("single");
699         String theStr = "this$" + String.valueOf( depth );
700         variableDeclaratorID.addChild( theStr );
701         ParseNode variableDeclarator = new ParseNode( "variable_declarator" );
702         variableDeclarator.addChild( variableDeclaratorID );
703         ParseNode variableDeclaratorList = new ParseNode("variable_declarators_list");
704         variableDeclaratorList.addChild( variableDeclarator );
705         theNode.addChild("variables").addChild( variableDeclaratorList );
706
707         for(Iterator it=cn.getInnerClasses(); it.hasNext(); ) {
708                 ClassDescriptor icd=(ClassDescriptor)it.next();
709                 if(icd.isStatic() || icd.getInStaticContext()) {
710                   continue;
711                 }
712                 parseFieldDecl( icd, theNode );         
713                 /*if( true ) {
714                         SymbolTable fieldTable = icd.getFieldTable();
715                         //System.out.println( fieldTable.toString() );
716                 }*/
717                 icd.setInnerDepth( depth + 1 );
718                 addOuterClassReferences( icd, depth + 1 );      
719         }
720 }
721
722   private void parseClassBody(ClassDescriptor cn, ParseNode pn) {
723     ParseNode decls=pn.getChild("class_body_declaration_list");
724     if (decls!=null) {
725       ParseNodeVector pnv=decls.getChildren();
726       for(int i=0; i<pnv.size(); i++) {
727         ParseNode decl=pnv.elementAt(i);
728         if (isNode(decl,"member")) {
729           parseClassMember(cn,decl);
730         } else if (isNode(decl,"constructor")) {
731           parseConstructorDecl(cn,decl.getChild("constructor_declaration"));
732         } else if (isNode(decl, "static_block")) {
733           parseStaticBlockDecl(cn, decl.getChild("static_block_declaration"));
734         } else if (isNode(decl,"block")) {
735         } else throw new Error();
736       }
737     }
738   }
739
740   private void parseClassMember(ClassDescriptor cn, ParseNode pn) {
741     ParseNode fieldnode=pn.getChild("field");
742     if (fieldnode!=null) {
743       //System.out.println( pn.PPrint( 0, true ) );
744       parseFieldDecl(cn,fieldnode.getChild("field_declaration"));
745       return;
746     }
747     ParseNode methodnode=pn.getChild("method");
748     if (methodnode!=null) {
749       parseMethodDecl(cn,methodnode.getChild("method_declaration"));
750       return;
751     }
752     ParseNode innerclassnode=pn.getChild("inner_class_declaration");
753     if (innerclassnode!=null) {
754       parseInnerClassDecl(cn,innerclassnode);
755       return;
756     }
757      ParseNode innerinterfacenode=pn.getChild("interface_declaration");
758     if (innerinterfacenode!=null) {
759       parseInterfaceDecl(innerinterfacenode, cn);
760       return;
761     }
762
763     ParseNode enumnode=pn.getChild("enum_declaration");
764     if (enumnode!=null) {
765       ClassDescriptor ecn=parseEnumDecl(cn,enumnode);
766       return;
767     }
768     ParseNode flagnode=pn.getChild("flag");
769     if (flagnode!=null) {
770       parseFlagDecl(cn, flagnode.getChild("flag_declaration"));
771       return;
772     }
773     // in case there are empty node
774     ParseNode emptynode=pn.getChild("empty");
775     if(emptynode != null) {
776       return;
777     }
778     System.out.println("Unrecognized node:"+pn.PPrint(2,true));
779     throw new Error();
780   }
781
782 //10/9/2011 changed this function to enable creation of default constructor for inner classes.
783 //the change was refactoring this function with the corresponding version for normal classes. sganapat
784   private ClassDescriptor parseInnerClassDecl(ClassDescriptor cn, ParseNode pn) {
785     String basename=pn.getChild("name").getTerminal();
786     String classname=cn.getClassName()+"$"+basename;
787
788     if (cn.getPackage()==null)
789       cn.getSingleImportMappings().put(basename,classname);
790     else
791       cn.getSingleImportMappings().put(basename,cn.getPackage()+"."+classname);
792     
793     ClassDescriptor icn=new ClassDescriptor(cn.getPackage(), classname, false);
794     pushChainMaps();
795     icn.setImports(mandatoryImports, multiimports);
796     icn.setSurroundingClass(cn.getSymbol());
797     icn.setSurrounding(cn);
798     cn.addInnerClass(icn);
799
800      if (!isEmpty(pn.getChild("super").getTerminal())) {
801       /* parse superclass name */
802       ParseNode snn=pn.getChild("super").getChild("type").getChild("class").getChild("name");
803       NameDescriptor nd=parseClassName(snn);
804       icn.setSuper(nd.toString());
805     } else {
806       if (!(icn.getSymbol().equals(TypeUtil.ObjectClass)||
807             icn.getSymbol().equals(TypeUtil.TagClass)))
808         icn.setSuper(TypeUtil.ObjectClass);
809     }
810     // check inherited interfaces
811     if (!isEmpty(pn.getChild("superIF").getTerminal())) {
812       /* parse inherited interface name */
813       ParseNode snlist=pn.getChild("superIF").getChild("interface_type_list");
814       ParseNodeVector pnv=snlist.getChildren();
815       for(int i=0; i<pnv.size(); i++) {
816         ParseNode decl=pnv.elementAt(i);
817         if (isNode(decl,"type")) {
818           NameDescriptor nd=parseClassName(decl.getChild("class").getChild("name"));
819           icn.addSuperInterface(nd.toString());
820         }
821       }
822     }
823     icn.setModifiers(parseModifiersList(pn.getChild("modifiers")));
824
825    if (!icn.isStatic())
826      icn.setAsInnerClass();
827
828     parseClassBody(icn, pn.getChild("classbody"));
829
830     boolean hasConstructor = false;
831     for(Iterator method_it=icn.getMethods(); method_it.hasNext(); ) {
832       MethodDescriptor md=(MethodDescriptor)method_it.next();
833       hasConstructor |= md.isConstructor();
834     }
835 //sganapat adding change to allow proper construction of inner class objects
836     if((!hasConstructor) && (!icn.isEnum())) {
837       // add a default constructor for this class
838       MethodDescriptor md = new MethodDescriptor(new Modifiers(Modifiers.PUBLIC),
839                                                  icn.getSymbol(), false);
840       BlockNode bn=new BlockNode();
841       state.addTreeCode(md,bn);
842       md.setDefaultConstructor();
843       icn.addMethod(md);
844    }
845     popChainMaps();
846
847      if (analyzeset != null)
848       analyzeset.add(icn);
849     icn.setSourceFileName(currsourcefile);
850     state.addClass(icn);
851
852     return icn;
853   }
854
855   private TypeDescriptor parseTypeDescriptor(ParseNode pn) {
856     ParseNode tn=pn.getChild("type");
857     String type_st=tn.getTerminal();
858     if(type_st.equals("byte")) {
859       return state.getTypeDescriptor(TypeDescriptor.BYTE);
860     } else if(type_st.equals("short")) {
861       return state.getTypeDescriptor(TypeDescriptor.SHORT);
862     } else if(type_st.equals("boolean")) {
863       return state.getTypeDescriptor(TypeDescriptor.BOOLEAN);
864     } else if(type_st.equals("int")) {
865       return state.getTypeDescriptor(TypeDescriptor.INT);
866     } else if(type_st.equals("long")) {
867       return state.getTypeDescriptor(TypeDescriptor.LONG);
868     } else if(type_st.equals("char")) {
869       return state.getTypeDescriptor(TypeDescriptor.CHAR);
870     } else if(type_st.equals("float")) {
871       return state.getTypeDescriptor(TypeDescriptor.FLOAT);
872     } else if(type_st.equals("double")) {
873       return state.getTypeDescriptor(TypeDescriptor.DOUBLE);
874     } else if(type_st.equals("class")) {
875       ParseNode nn=tn.getChild("class");
876       return state.getTypeDescriptor(parseClassName(nn.getChild("name")));
877     } else if(type_st.equals("array")) {
878       ParseNode nn=tn.getChild("array");
879       TypeDescriptor td=parseTypeDescriptor(nn.getChild("basetype"));
880       Integer numdims=(Integer)nn.getChild("dims").getLiteral();
881       for(int i=0; i<numdims.intValue(); i++)
882         td=td.makeArray(state);
883       return td;
884     } else {
885       System.out.println(pn.PPrint(2, true));
886       throw new Error();
887     }
888   }
889
890   //Needed to separate out top level call since if a base exists,
891   //we do not want to apply our resolveName function (i.e. deal with imports)
892   //otherwise, if base == null, we do just want to resolve name.
893   private NameDescriptor parseClassName(ParseNode nn) {
894     
895
896     ParseNode base=nn.getChild("base");
897     ParseNode id=nn.getChild("identifier");
898     String classname = id.getTerminal();
899     if (base==null) {
900       return new NameDescriptor(resolveName(classname));
901     }
902     return new NameDescriptor(parseClassNameRecursive(base.getChild("name")),classname);
903   }
904
905   private NameDescriptor parseClassNameRecursive(ParseNode nn) {
906     ParseNode base=nn.getChild("base");
907     ParseNode id=nn.getChild("identifier");
908     String classname = id.getTerminal();
909     if (base==null) {
910       return new NameDescriptor(classname);
911     }
912     return new NameDescriptor(parseClassNameRecursive(base.getChild("name")),classname);
913   }
914
915   //This will get the mapping of a terminal class name
916   //to a canonical classname (with imports/package locations in them)
917   private String resolveName(String terminal) {
918     
919     if(mandatoryImports.containsKey(terminal)) {
920       return (String) mandatoryImports.get(terminal);
921     } else {
922       if(multiimports.containsKey(terminal)) {
923         //Test for error
924         Object o = multiimports.get(terminal);
925         if(o instanceof Error) {
926           throw new Error("Class " + terminal + " is ambiguous. Cause: more than 1 package import contain the same class.");
927         } else {
928           //At this point, if we found a unique class
929           //we can treat it as a single, mandatory import.
930           mandatoryImports.put(terminal, o);
931           return (String) o;
932         }
933       }
934     }
935
936     return terminal;
937   }
938
939   //only function difference between this and parseName() is that this
940   //does not look for a import mapping.
941   private NameDescriptor parseName(ParseNode nn) {
942     ParseNode base=nn.getChild("base");
943     ParseNode id=nn.getChild("identifier");
944     if (base==null) {
945       return new NameDescriptor(id.getTerminal());
946     }
947     return new NameDescriptor(parseName(base.getChild("name")),id.getTerminal());
948   }
949
950   private void parseFlagDecl(ClassDescriptor cn,ParseNode pn) {
951     String name=pn.getChild("name").getTerminal();
952     FlagDescriptor flag=new FlagDescriptor(name);
953     if (pn.getChild("external")!=null)
954       flag.makeExternal();
955     cn.addFlag(flag);
956   }
957
958   private void parseFieldDecl(ClassDescriptor cn,ParseNode pn) {
959     ParseNode mn=pn.getChild("modifier");
960     Modifiers m=parseModifiersList(mn);
961     if(cn.isInterface()) {
962       // TODO add version for normal Java later
963       // Can only be PUBLIC or STATIC or FINAL
964       if((m.isAbstract()) || (m.isAtomic()) || (m.isNative())
965          || (m.isSynchronized())) {
966         throw new Error("Error: field in Interface " + cn.getSymbol() + "can only be PUBLIC or STATIC or FINAL");
967       }
968       m.addModifier(Modifiers.PUBLIC);
969       m.addModifier(Modifiers.STATIC);
970       m.addModifier(Modifiers.FINAL);
971     }
972
973     ParseNode tn=pn.getChild("type");
974     TypeDescriptor t=parseTypeDescriptor(tn);
975     ParseNode vn=pn.getChild("variables").getChild("variable_declarators_list");
976     ParseNodeVector pnv=vn.getChildren();
977     boolean isglobal=pn.getChild("global")!=null;
978
979     for(int i=0; i<pnv.size(); i++) {
980       ParseNode vardecl=pnv.elementAt(i);
981       ParseNode tmp=vardecl;
982       TypeDescriptor arrayt=t;
983        if( this.isRunningRecursiveInnerClass && false )
984         {       
985                 System.out.println( "the length of the list is " + String.valueOf( pnv.size() ) );
986                 System.out.println( "\n the parse node is \n" + tmp.PPrint( 0, true ) );
987         }
988       while (tmp.getChild("single")==null) {
989         arrayt=arrayt.makeArray(state);
990         tmp=tmp.getChild("array");
991       }
992       String identifier=tmp.getChild("single").getTerminal();
993       ParseNode epn=vardecl.getChild("initializer");
994
995       ExpressionNode en=null;
996       
997       if (epn!=null) {
998         en=parseExpression(cn, null, m.isStatic(), epn.getFirstChild());
999         en.setNumLine(epn.getFirstChild().getLine());
1000         if(m.isStatic()) {
1001           // for static field, the initializer should be considered as a
1002           // static block
1003           boolean isfirst = false;
1004           MethodDescriptor md = (MethodDescriptor)cn.getMethodTable().getFromSameScope("staticblocks");
1005           if(md == null) {
1006             // the first static block for this class
1007             Modifiers m_i=new Modifiers();
1008             m_i.addModifier(Modifiers.STATIC);
1009             md = new MethodDescriptor(m_i, "staticblocks", false);
1010             md.setAsStaticBlock();
1011             isfirst = true;
1012           }
1013           if(isfirst) {
1014             cn.addMethod(md);
1015           }
1016           cn.incStaticBlocks();
1017           BlockNode bn=new BlockNode();
1018           NameNode nn=new NameNode(new NameDescriptor(identifier));
1019           nn.setNumLine(en.getNumLine());
1020           AssignmentNode an=new AssignmentNode(nn,en,new AssignOperation(1));
1021           an.setNumLine(pn.getLine());
1022           bn.addBlockStatement(new BlockExpressionNode(an));
1023           if(isfirst) {
1024             state.addTreeCode(md,bn);
1025           } else {
1026             BlockNode obn = state.getMethodBody(md);
1027             for(int ii = 0; ii < bn.size(); ii++) {
1028               BlockStatementNode bsn = bn.get(ii);
1029               obn.addBlockStatement(bsn);
1030             }
1031             state.addTreeCode(md, obn);
1032             bn = null;
1033           }
1034           en = null;
1035         }
1036       }
1037
1038       cn.addField(new FieldDescriptor(m, arrayt, identifier, en, isglobal));
1039       assignAnnotationsToType(m,arrayt);
1040     }
1041   }
1042
1043   private void assignAnnotationsToType(Modifiers modifiers, TypeDescriptor type) {
1044     Vector<AnnotationDescriptor> annotations=modifiers.getAnnotations();
1045     for(int i=0; i<annotations.size(); i++) {
1046       // it only supports a marker annotation
1047       AnnotationDescriptor an=annotations.elementAt(i);
1048       type.addAnnotationMarker(an);
1049     }
1050   }
1051
1052   int innerCount=0;
1053
1054   private ExpressionNode parseExpression(ClassDescriptor cn, MethodDescriptor md, boolean isStaticContext, ParseNode pn) {
1055     if (isNode(pn,"assignment"))
1056         {
1057           //System.out.println( "parsing a field decl in my class that has assignment in initialization " + pn.PPrint( 0, true ) + "\n");
1058       return parseAssignmentExpression(cn, md, isStaticContext, pn);
1059         }
1060     else if (isNode(pn,"logical_or")||isNode(pn,"logical_and")||
1061              isNode(pn,"bitwise_or")||isNode(pn,"bitwise_xor")||
1062              isNode(pn,"bitwise_and")||isNode(pn,"equal")||
1063              isNode(pn,"not_equal")||isNode(pn,"comp_lt")||
1064              isNode(pn,"comp_lte")||isNode(pn,"comp_gt")||
1065              isNode(pn,"comp_gte")||isNode(pn,"leftshift")||
1066              isNode(pn,"rightshift")||isNode(pn,"sub")||
1067              isNode(pn,"urightshift")||isNode(pn,"sub")||
1068              isNode(pn,"add")||isNode(pn,"mult")||
1069              isNode(pn,"div")||isNode(pn,"mod")) {
1070       ParseNodeVector pnv=pn.getChildren();
1071       ParseNode left=pnv.elementAt(0);
1072       ParseNode right=pnv.elementAt(1);
1073       Operation op=new Operation(pn.getLabel());
1074       OpNode on=new OpNode(parseExpression(cn, md, isStaticContext, left),parseExpression(cn, md, isStaticContext,  right),op);
1075       on.setNumLine(pn.getLine());
1076       return on;
1077     } else if (isNode(pn,"unaryplus")||
1078                isNode(pn,"unaryminus")||
1079                isNode(pn,"not")||
1080                isNode(pn,"comp")) {
1081       ParseNode left=pn.getFirstChild();
1082       Operation op=new Operation(pn.getLabel());
1083       OpNode on=new OpNode(parseExpression(cn, md, isStaticContext, left),op);
1084       on.setNumLine(pn.getLine());
1085       return on;
1086     } else if (isNode(pn,"postinc")||
1087                isNode(pn,"postdec")) {
1088       ParseNode left=pn.getFirstChild();
1089       AssignOperation op=new AssignOperation(pn.getLabel());
1090       AssignmentNode an=new AssignmentNode(parseExpression(cn, md, isStaticContext, left),null,op);
1091       an.setNumLine(pn.getLine());
1092       return an;
1093
1094     } else if (isNode(pn,"preinc")||
1095                isNode(pn,"predec")) {
1096       ParseNode left=pn.getFirstChild();
1097       AssignOperation op=isNode(pn,"preinc")?new AssignOperation(AssignOperation.PLUSEQ):new AssignOperation(AssignOperation.MINUSEQ);
1098       AssignmentNode an=new AssignmentNode(parseExpression(cn, md, isStaticContext, left),
1099                                            new LiteralNode("integer",new Integer(1)),op);
1100       an.setNumLine(pn.getLine());
1101       return an;
1102     } else if (isNode(pn,"literal")) {
1103       String literaltype=pn.getTerminal();
1104       ParseNode literalnode=pn.getChild(literaltype);
1105       Object literal_obj=literalnode.getLiteral();
1106       LiteralNode ln=new LiteralNode(literaltype, literal_obj);
1107       ln.setNumLine(pn.getLine());
1108       return ln;
1109     } else if (isNode(pn, "createobject")) {
1110       TypeDescriptor td = parseTypeDescriptor(pn);
1111
1112       Vector args = parseArgumentList(cn, md, isStaticContext, pn);
1113       boolean isglobal = pn.getChild("global") != null || pn.getChild("scratch") != null;
1114       String disjointId = null;
1115       if (pn.getChild("disjoint") != null) {
1116         disjointId = pn.getChild("disjoint").getTerminal();
1117       }
1118       ParseNode idChild = (pn.getChild( "id" ));
1119       ParseNode baseChild = (pn.getChild( "base" ));
1120       
1121       CreateObjectNode con = new CreateObjectNode(td, isglobal, disjointId);
1122       if( null != idChild && null != idChild.getFirstChild() ) {
1123         idChild = idChild.getFirstChild();
1124         //System.out.println( "\nThe object passed has this expression " + idChild.PPrint( 0, true ) );
1125         ExpressionNode en = parseExpression(cn, md, isStaticContext, idChild ); 
1126         //System.out.println( "\nThe object passed has this expression " + en.printNode( 0 ) );
1127         con.setSurroundingExpression( en );
1128       }
1129       else if( null != baseChild  && null != baseChild.getFirstChild()  ) {
1130         baseChild = baseChild.getFirstChild();
1131         //System.out.println( "\nThe object passed has this expression " + baseChild.PPrint( 0, true ) );
1132         ExpressionNode en = parseExpression(cn, md, isStaticContext, baseChild ); 
1133         //System.out.println( "\nThe object passed has this expression " + en.printNode( 0 ) );
1134         con.setSurroundingExpression( en );     
1135       }
1136       con.setNumLine(pn.getLine());
1137       for (int i = 0; i < args.size(); i++) {
1138         con.addArgument((ExpressionNode) args.get(i));
1139       }
1140       /* Could have flag set or tag added here */
1141       if (pn.getChild("flag_list") != null || pn.getChild("tag_list") != null) {
1142         FlagEffects fe = new FlagEffects(null);
1143         if (pn.getChild("flag_list") != null)
1144           parseFlagEffect(fe, pn.getChild("flag_list"));
1145
1146         if (pn.getChild("tag_list") != null)
1147           parseTagEffect(fe, pn.getChild("tag_list"));
1148         con.addFlagEffects(fe);
1149       }
1150
1151       return con;
1152     } else if (isNode(pn,"createobjectcls")) {
1153       TypeDescriptor td=parseTypeDescriptor(pn);
1154       innerCount++;
1155       ClassDescriptor cnnew=new ClassDescriptor(packageName,td.getSymbol()+"$"+innerCount, false);
1156       pushChainMaps();
1157       cnnew.setImports(mandatoryImports, multiimports);
1158       cnnew.setSuper(td.getSymbol());
1159       cnnew.setInline();
1160       // the inline anonymous class does not have modifiers, it cannot be static 
1161       // it is always implicit final
1162       cnnew.setModifiers(new Modifiers(Modifiers.FINAL));
1163       cnnew.setAsInnerClass();
1164       cnnew.setSurroundingClass(cn.getSymbol());
1165       cnnew.setSurrounding(cn);
1166       cn.addInnerClass(cnnew);
1167       // Note that if the inner class is declared in a static context, it does NOT 
1168       // have lexically enclosing instances.
1169       if((null!=md)&&(md.isStatic()||md.isStaticBlock())) {
1170         cnnew.setSurroundingBlock(md);
1171         cnnew.setInStaticContext();
1172       } else if (isStaticContext) {
1173         cnnew.setInStaticContext();
1174       }
1175       parseClassBody(cnnew, pn.getChild("decl").getChild("classbody"));
1176       boolean hasConstructor = false;
1177       for(Iterator method_it=cnnew.getMethods(); method_it.hasNext(); ) {
1178           MethodDescriptor cmd=(MethodDescriptor)method_it.next();
1179           hasConstructor |= cmd.isConstructor();
1180       }
1181       if(hasConstructor) {
1182           // anonymous class should not have explicit constructors
1183           throw new Error("Error! Anonymous class " + cnnew.getSymbol() + " in " + cn.getSymbol() + " has explicit constructors!");
1184       } else if(!cnnew.isEnum()) {
1185           // add a default constructor for this class
1186           MethodDescriptor cmd = new MethodDescriptor(new Modifiers(Modifiers.PUBLIC|Modifiers.FINAL),cnnew.getSymbol(), false);
1187           BlockNode bn=new BlockNode();
1188           state.addTreeCode(cmd,bn);
1189           cmd.setDefaultConstructor();
1190           cnnew.addMethod(cmd);
1191       }
1192       TypeDescriptor tdnew=state.getTypeDescriptor(cnnew.getSymbol());
1193
1194       Vector args=parseArgumentList(cn, md, isStaticContext, pn);
1195       ParseNode idChild = pn.getChild( "id" );
1196       ParseNode baseChild = pn.getChild( "base" );
1197       //System.out.println("\n to print idchild and basechild for ");
1198       /*if( null != idChild )
1199         System.out.println( "\n trying to create an inner class and the id child passed is "  + idChild.PPrint( 0, true ) );
1200       if( null != baseChild )
1201         System.out.println( "\n trying to create an inner class and the base child passed is "  + baseChild.PPrint( 0, true ) );*/
1202       CreateObjectNode con=new CreateObjectNode(tdnew, false, null);
1203       con.setNumLine(pn.getLine());
1204       for(int i=0; i<args.size(); i++) {
1205         con.addArgument((ExpressionNode)args.get(i));
1206       }
1207       popChainMaps();
1208
1209       if (analyzeset != null)
1210         analyzeset.add(cnnew);
1211       cnnew.setSourceFileName(currsourcefile);
1212       state.addClass(cnnew);
1213
1214       return con;
1215     } else if (isNode(pn,"createarray")) {
1216       //System.out.println(pn.PPrint(3,true));
1217       boolean isglobal=pn.getChild("global")!=null||
1218                         pn.getChild("scratch")!=null;
1219       String disjointId=null;
1220       if( pn.getChild("disjoint") != null) {
1221         disjointId = pn.getChild("disjoint").getTerminal();
1222       }
1223       TypeDescriptor td=parseTypeDescriptor(pn);
1224       Vector args=parseDimExprs(cn, md, isStaticContext, pn);
1225       int num=0;
1226       if (pn.getChild("dims_opt").getLiteral()!=null)
1227         num=((Integer)pn.getChild("dims_opt").getLiteral()).intValue();
1228       for(int i=0; i<(args.size()+num); i++)
1229         td=td.makeArray(state);
1230       CreateObjectNode con=new CreateObjectNode(td, isglobal, disjointId);
1231       con.setNumLine(pn.getLine());
1232       for(int i=0; i<args.size(); i++) {
1233         con.addArgument((ExpressionNode)args.get(i));
1234       }
1235       return con;
1236     }
1237     if (isNode(pn,"createarray2")) {
1238       TypeDescriptor td=parseTypeDescriptor(pn);
1239       int num=0;
1240       if (pn.getChild("dims_opt").getLiteral()!=null)
1241         num=((Integer)pn.getChild("dims_opt").getLiteral()).intValue();
1242       for(int i=0; i<num; i++)
1243         td=td.makeArray(state);
1244       CreateObjectNode con=new CreateObjectNode(td, false, null);
1245       con.setNumLine(pn.getLine());
1246       ParseNode ipn = pn.getChild("initializer");
1247       Vector initializers=parseVariableInitializerList(cn, md, isStaticContext, ipn);
1248       ArrayInitializerNode ain = new ArrayInitializerNode(initializers);
1249       ain.setNumLine(pn.getLine());
1250       con.addArrayInitializer(ain);
1251       return con;
1252     } else if (isNode(pn,"name")) {
1253       NameDescriptor nd=parseName(pn);
1254       NameNode nn=new NameNode(nd);
1255       nn.setNumLine(pn.getLine());
1256       return nn;
1257     } else if (isNode(pn,"this")) {
1258       NameDescriptor nd=new NameDescriptor("this");
1259       NameNode nn=new NameNode(nd);
1260       nn.setNumLine(pn.getLine());
1261       return nn;
1262     } else if (isNode(pn,"parentclass")) {
1263       NameDescriptor nd=new NameDescriptor(pn.getChild("name").getFirstChild().getFirstChild().getTerminal());
1264       NameNode nn=new NameNode(nd);
1265       nn.setNumLine(pn.getLine());
1266         //because inner classes pass right thru......
1267       FieldAccessNode fan=new FieldAccessNode(nn,"this");
1268       fan.setNumLine(pn.getLine());
1269       return fan;
1270     } else if (isNode(pn,"isavailable")) {
1271       NameDescriptor nd=new NameDescriptor(pn.getTerminal());
1272       NameNode nn=new NameNode(nd);
1273       nn.setNumLine(pn.getLine());
1274       return new OpNode(nn,null,new Operation(Operation.ISAVAILABLE));
1275     } else if (isNode(pn,"methodinvoke1")) {
1276       NameDescriptor nd=parseName(pn.getChild("name"));
1277       Vector args=parseArgumentList(cn, md, isStaticContext, pn);
1278       MethodInvokeNode min=new MethodInvokeNode(nd);
1279       min.setNumLine(pn.getLine());
1280       for(int i=0; i<args.size(); i++) {
1281         min.addArgument((ExpressionNode)args.get(i));
1282       }
1283       return min;
1284     } else if (isNode(pn,"methodinvoke2")) {
1285       String methodid=pn.getChild("id").getTerminal();
1286       ExpressionNode exp=parseExpression(cn, md, isStaticContext, pn.getChild("base").getFirstChild());
1287       Vector args=parseArgumentList(cn, md, isStaticContext, pn);
1288       MethodInvokeNode min=new MethodInvokeNode(methodid,exp);
1289       min.setNumLine(pn.getLine());
1290       for(int i=0; i<args.size(); i++) {
1291         min.addArgument((ExpressionNode)args.get(i));
1292       }
1293       return min;
1294     } else if (isNode(pn,"fieldaccess")) {
1295       ExpressionNode en=parseExpression(cn, md, isStaticContext, pn.getChild("base").getFirstChild());
1296       String fieldname=pn.getChild("field").getTerminal();
1297
1298       FieldAccessNode fan=new FieldAccessNode(en,fieldname);
1299       fan.setNumLine(pn.getLine());
1300       return fan;
1301     } else if (isNode(pn,"superfieldaccess")) {
1302         ExpressionNode en=new NameNode(new NameDescriptor("super"));
1303         String fieldname=pn.getChild("field").getTerminal();
1304
1305         FieldAccessNode fan=new FieldAccessNode(en,fieldname);
1306         fan.setNumLine(pn.getLine());
1307         return fan;
1308     } else if (isNode(pn,"supernamefieldaccess")) {
1309         ExpressionNode en=parseExpression(cn, md, isStaticContext, pn.getChild("base").getFirstChild());
1310         ExpressionNode exp = new FieldAccessNode(en, "super");
1311         exp.setNumLine(pn.getLine());
1312         String fieldname=pn.getChild("field").getTerminal();
1313
1314         FieldAccessNode fan=new FieldAccessNode(exp,fieldname);
1315         fan.setNumLine(pn.getLine());
1316         return fan;
1317     } else if (isNode(pn,"arrayaccess")) {
1318       ExpressionNode en=parseExpression(cn, md, isStaticContext, pn.getChild("base").getFirstChild());
1319       ExpressionNode index=parseExpression(cn, md, isStaticContext, pn.getChild("index").getFirstChild());
1320       ArrayAccessNode aan=new ArrayAccessNode(en,index);
1321       aan.setNumLine(pn.getLine());
1322       return aan;
1323     } else if (isNode(pn,"cast1")) {
1324       try {
1325         CastNode castn=new CastNode(parseTypeDescriptor(pn.getChild("type")),parseExpression(cn, md, isStaticContext, pn.getChild("exp").getFirstChild()));
1326         castn.setNumLine(pn.getLine());
1327         return castn;
1328       } catch (Exception e) {
1329         System.out.println(pn.PPrint(1,true));
1330         e.printStackTrace();
1331         throw new Error();
1332       }
1333     } else if (isNode(pn,"cast2")) {
1334       CastNode castn=new CastNode(parseExpression(cn, md, isStaticContext, pn.getChild("type").getFirstChild()),parseExpression(cn, md, isStaticContext, pn.getChild("exp").getFirstChild()));
1335       castn.setNumLine(pn.getLine());
1336       return castn;
1337     } else if (isNode(pn, "getoffset")) {
1338       TypeDescriptor td=parseTypeDescriptor(pn);
1339       String fieldname = pn.getChild("field").getTerminal();
1340       //System.out.println("Checking the values of: "+ " td.toString()= " + td.toString()+ "  fieldname= " + fieldname);
1341       return new OffsetNode(td, fieldname);
1342     } else if (isNode(pn, "tert")) {
1343
1344       TertiaryNode tn=new TertiaryNode(parseExpression(cn, md, isStaticContext, pn.getChild("cond").getFirstChild()),
1345                                        parseExpression(cn, md, isStaticContext, pn.getChild("trueexpr").getFirstChild()),
1346                                        parseExpression(cn, md, isStaticContext, pn.getChild("falseexpr").getFirstChild()) );
1347       tn.setNumLine(pn.getLine());
1348
1349       return tn;
1350     } else if (isNode(pn, "instanceof")) {
1351       ExpressionNode exp=parseExpression(cn, md, isStaticContext, pn.getChild("exp").getFirstChild());
1352       TypeDescriptor t=parseTypeDescriptor(pn);
1353       InstanceOfNode ion=new InstanceOfNode(exp,t);
1354       ion.setNumLine(pn.getLine());
1355       return ion;
1356     } else if (isNode(pn, "array_initializer")) {
1357       Vector initializers=parseVariableInitializerList(cn, md, isStaticContext, pn);
1358       return new ArrayInitializerNode(initializers);
1359     } else if (isNode(pn, "class_type")) {
1360       TypeDescriptor td=parseTypeDescriptor(pn);
1361       ClassTypeNode ctn=new ClassTypeNode(td);
1362       ctn.setNumLine(pn.getLine());
1363       return ctn;
1364     } else if (isNode(pn, "empty")) {
1365       return null;
1366     } else {
1367       System.out.println("---------------------");
1368       System.out.println(pn.PPrint(3,true));
1369       throw new Error();
1370     }
1371   }
1372
1373   private Vector parseDimExprs(ClassDescriptor cn, MethodDescriptor md, boolean isStaticContext, ParseNode pn) {
1374     Vector arglist=new Vector();
1375     ParseNode an=pn.getChild("dim_exprs");
1376     if (an==null)       /* No argument list */
1377       return arglist;
1378     ParseNodeVector anv=an.getChildren();
1379     for(int i=0; i<anv.size(); i++) {
1380       arglist.add(parseExpression(cn, md, isStaticContext, anv.elementAt(i)));
1381     }
1382     return arglist;
1383   }
1384
1385   private Vector parseArgumentList(ClassDescriptor cn, MethodDescriptor md, boolean isStaticContext, ParseNode pn) {
1386     Vector arglist=new Vector();
1387     ParseNode an=pn.getChild("argument_list");
1388     if (an==null)       /* No argument list */
1389       return arglist;
1390     ParseNodeVector anv=an.getChildren();
1391     for(int i=0; i<anv.size(); i++) {
1392       arglist.add(parseExpression(cn, md, isStaticContext, anv.elementAt(i)));
1393     }
1394     return arglist;
1395   }
1396
1397   private Vector[] parseConsArgumentList(ParseNode pn) {
1398     Vector arglist=new Vector();
1399     Vector varlist=new Vector();
1400     ParseNode an=pn.getChild("cons_argument_list");
1401     if (an==null)       /* No argument list */
1402       return new Vector[] {varlist, arglist};
1403     ParseNodeVector anv=an.getChildren();
1404     for(int i=0; i<anv.size(); i++) {
1405       ParseNode cpn=anv.elementAt(i);
1406       ParseNode var=cpn.getChild("var");
1407       ParseNode exp=cpn.getChild("exp").getFirstChild();
1408       varlist.add(var.getTerminal());
1409       arglist.add(parseExpression(null, null, false, exp));
1410     }
1411     return new Vector[] {varlist, arglist};
1412   }
1413
1414   private Vector parseVariableInitializerList(ClassDescriptor cn, MethodDescriptor md, boolean isStaticContext, ParseNode pn) {
1415     Vector varInitList=new Vector();
1416     ParseNode vin=pn.getChild("var_init_list");
1417     if (vin==null)       /* No argument list */
1418       return varInitList;
1419     ParseNodeVector vinv=vin.getChildren();
1420     for(int i=0; i<vinv.size(); i++) {
1421       varInitList.add(parseExpression(cn, md, isStaticContext, vinv.elementAt(i)));
1422     }
1423     return varInitList;
1424   }
1425
1426   private ExpressionNode parseAssignmentExpression(ClassDescriptor cn, MethodDescriptor md, boolean isStaticContext, ParseNode pn) {
1427     AssignOperation ao=new AssignOperation(pn.getChild("op").getTerminal());
1428     ParseNodeVector pnv=pn.getChild("args").getChildren();
1429
1430     AssignmentNode an=new AssignmentNode(parseExpression(cn, md, isStaticContext, pnv.elementAt(0)),parseExpression(cn, md, isStaticContext, pnv.elementAt(1)),ao);
1431     an.setNumLine(pn.getLine());
1432     return an;
1433   }
1434
1435
1436   private void parseMethodDecl(ClassDescriptor cn, ParseNode pn) {
1437     ParseNode headern=pn.getChild("method_header");
1438     ParseNode bodyn=pn.getChild("body");
1439     MethodDescriptor md=parseMethodHeader(headern);
1440     try {
1441       BlockNode bn=parseBlock(cn, md, md.isStatic()||md.isStaticBlock(), bodyn);
1442       bn.setNumLine(pn.getLine()); // assume that method header is located at the beginning of method body
1443       cn.addMethod(md);
1444       state.addTreeCode(md,bn);
1445
1446       // this is a hack for investigating new language features
1447       // at the AST level, someday should evolve into a nice compiler
1448       // option *wink*
1449       //if( cn.getSymbol().equals( ***put a class in here like:     "Test" ) &&
1450       //    md.getSymbol().equals( ***put your method in here like: "main" )
1451       //) {
1452       //  bn.setStyle( BlockNode.NORMAL );
1453       //  System.out.println( bn.printNode( 0 ) );
1454       //}
1455
1456     } catch (Exception e) {
1457       System.out.println("Error with method:"+md.getSymbol());
1458       e.printStackTrace();
1459       throw new Error();
1460     } catch (Error e) {
1461       System.out.println("Error with method:"+md.getSymbol());
1462       e.printStackTrace();
1463       throw new Error();
1464     }
1465   }
1466
1467   private void parseConstructorDecl(ClassDescriptor cn, ParseNode pn) {
1468     ParseNode mn=pn.getChild("modifiers");
1469     Modifiers m=parseModifiersList(mn);
1470     ParseNode cdecl=pn.getChild("constructor_declarator");
1471     boolean isglobal=cdecl.getChild("global")!=null;
1472     String name=resolveName(cn.getSymbol());
1473     MethodDescriptor md=new MethodDescriptor(m, name, isglobal);
1474     ParseNode paramnode=cdecl.getChild("parameters");
1475     parseParameterList(md,paramnode);
1476     ParseNode bodyn0=pn.getChild("body");
1477     ParseNode bodyn=bodyn0.getChild("constructor_body");
1478     cn.addMethod(md);
1479     BlockNode bn=null;
1480     if (bodyn!=null&&bodyn.getChild("block_statement_list")!=null)
1481       bn=parseBlock(cn, md, md.isStatic()||md.isStaticBlock(), bodyn);
1482     else
1483       bn=new BlockNode();
1484     if (bodyn!=null&&bodyn.getChild("superinvoke")!=null) {
1485       ParseNode sin=bodyn.getChild("superinvoke");
1486       NameDescriptor nd=new NameDescriptor("super");
1487       Vector args=parseArgumentList(cn, md, true, sin);
1488       MethodInvokeNode min=new MethodInvokeNode(nd);
1489       min.setNumLine(sin.getLine());
1490       for(int i=0; i<args.size(); i++) {
1491         min.addArgument((ExpressionNode)args.get(i));
1492       }
1493       BlockExpressionNode ben=new BlockExpressionNode(min);
1494       bn.addFirstBlockStatement(ben);
1495
1496     } else if (bodyn!=null&&bodyn.getChild("explconstrinv")!=null) {
1497       ParseNode eci=bodyn.getChild("explconstrinv");
1498       NameDescriptor nd=new NameDescriptor(cn.getSymbol());
1499       Vector args=parseArgumentList(cn, md, true, eci);
1500       MethodInvokeNode min=new MethodInvokeNode(nd);
1501       min.setNumLine(eci.getLine());
1502       for(int i=0; i<args.size(); i++) {
1503         min.addArgument((ExpressionNode)args.get(i));
1504       }
1505       BlockExpressionNode ben=new BlockExpressionNode(min);
1506       ben.setNumLine(eci.getLine());
1507       bn.addFirstBlockStatement(ben);
1508     }
1509     state.addTreeCode(md,bn);
1510   }
1511
1512   private void parseStaticBlockDecl(ClassDescriptor cn, ParseNode pn) {
1513     // Each class maintains one MethodDecscriptor which combines all its
1514     // static blocks in their declaration order
1515     boolean isfirst = false;
1516     MethodDescriptor md = (MethodDescriptor)cn.getMethodTable().getFromSameScope("staticblocks");
1517     if(md == null) {
1518       // the first static block for this class
1519       Modifiers m_i=new Modifiers();
1520       m_i.addModifier(Modifiers.STATIC);
1521       md = new MethodDescriptor(m_i, "staticblocks", false);
1522       md.setAsStaticBlock();
1523       isfirst = true;
1524     }
1525     ParseNode bodyn=pn.getChild("body");
1526     if(isfirst) {
1527       cn.addMethod(md);
1528     }
1529     cn.incStaticBlocks();
1530     BlockNode bn=null;
1531     if (bodyn!=null&&bodyn.getChild("block_statement_list")!=null)
1532       bn=parseBlock(cn, md, true, bodyn);
1533     else
1534       bn=new BlockNode();
1535     if(isfirst) {
1536       state.addTreeCode(md,bn);
1537     } else {
1538       BlockNode obn = state.getMethodBody(md);
1539       for(int i = 0; i < bn.size(); i++) {
1540         BlockStatementNode bsn = bn.get(i);
1541         obn.addBlockStatement(bsn);
1542       }
1543       state.addTreeCode(md, obn);
1544       bn = null;
1545     }
1546   }
1547
1548   public BlockNode parseBlock(ClassDescriptor cn, MethodDescriptor md, boolean isStaticContext, ParseNode pn) {
1549     this.m_taskexitnum = 0;
1550     if (pn==null||isEmpty(pn.getTerminal()))
1551       return new BlockNode();
1552     ParseNode bsn=pn.getChild("block_statement_list");
1553     return parseBlockHelper(cn, md, isStaticContext, bsn);
1554   }
1555
1556   private BlockNode parseBlockHelper(ClassDescriptor cn, MethodDescriptor md, boolean isStaticContext, ParseNode pn) {
1557     ParseNodeVector pnv=pn.getChildren();
1558     BlockNode bn=new BlockNode();
1559     for(int i=0; i<pnv.size(); i++) {
1560       Vector bsv=parseBlockStatement(cn, md, isStaticContext, pnv.elementAt(i));
1561       for(int j=0; j<bsv.size(); j++) {
1562         bn.addBlockStatement((BlockStatementNode)bsv.get(j));
1563       }
1564     }
1565     return bn;
1566   }
1567
1568   public BlockNode parseSingleBlock(ClassDescriptor cn, MethodDescriptor md, boolean isStaticContext, ParseNode pn, String label){
1569     BlockNode bn=new BlockNode();
1570     Vector bsv=parseBlockStatement(cn, md, isStaticContext, pn,label);
1571     for(int j=0; j<bsv.size(); j++) {
1572       bn.addBlockStatement((BlockStatementNode)bsv.get(j));
1573     }
1574     bn.setStyle(BlockNode.NOBRACES);
1575     return bn;
1576   }
1577   
1578   public BlockNode parseSingleBlock(ClassDescriptor cn, MethodDescriptor md, boolean isStaticContext, ParseNode pn) {
1579     return parseSingleBlock(cn, md, isStaticContext, pn, null);
1580   }
1581
1582   public Vector parseSESEBlock(ClassDescriptor cn, MethodDescriptor md, boolean isStaticContext, Vector parentbs, ParseNode pn) {
1583     ParseNodeVector pnv=pn.getChildren();
1584     Vector bv=new Vector();
1585     for(int i=0; i<pnv.size(); i++) {
1586       bv.addAll(parseBlockStatement(cn, md, isStaticContext, pnv.elementAt(i)));
1587     }
1588     return bv;
1589   }
1590   
1591   public Vector parseBlockStatement(ClassDescriptor cn, MethodDescriptor md, boolean isStaticContext, ParseNode pn){
1592     return parseBlockStatement(cn, md, isStaticContext, pn,null);
1593   }
1594
1595   public Vector parseBlockStatement(ClassDescriptor cn, MethodDescriptor md, boolean isStaticContext, ParseNode pn, String label) {
1596     Vector blockstatements=new Vector();
1597     if (isNode(pn,"tag_declaration")) {
1598       String name=pn.getChild("single").getTerminal();
1599       String type=pn.getChild("type").getTerminal();
1600
1601       TagDeclarationNode tdn=new TagDeclarationNode(name, type);
1602       tdn.setNumLine(pn.getLine());
1603
1604       blockstatements.add(tdn);
1605     } else if (isNode(pn,"local_variable_declaration")) {
1606
1607       TypeDescriptor t=parseTypeDescriptor(pn);
1608       ParseNode vn=pn.getChild("variable_declarators_list");
1609       ParseNodeVector pnv=vn.getChildren();
1610       for(int i=0; i<pnv.size(); i++) {
1611         ParseNode vardecl=pnv.elementAt(i);
1612
1613
1614         ParseNode tmp=vardecl;
1615         TypeDescriptor arrayt=t;
1616
1617         while (tmp.getChild("single")==null) {
1618           arrayt=arrayt.makeArray(state);
1619           tmp=tmp.getChild("array");
1620         }
1621         String identifier=tmp.getChild("single").getTerminal();
1622
1623         ParseNode epn=vardecl.getChild("initializer");
1624
1625
1626         ExpressionNode en=null;
1627         if (epn!=null)
1628           en=parseExpression(cn, md, isStaticContext, epn.getFirstChild());
1629
1630         DeclarationNode dn=new DeclarationNode(new VarDescriptor(arrayt, identifier),en);
1631         dn.setNumLine(tmp.getLine());
1632         
1633         ParseNode mn=pn.getChild("modifiers");
1634         if(mn!=null) {
1635           // here, modifers parse node has the list of annotations
1636           Modifiers m=parseModifiersList(mn);
1637           assignAnnotationsToType(m, arrayt);
1638         }
1639
1640         blockstatements.add(dn);
1641       }
1642     } else if (isNode(pn,"nop")) {
1643       /* Do Nothing */
1644     } else if (isNode(pn,"expression")) {
1645       BlockExpressionNode ben=new BlockExpressionNode(parseExpression(cn, md, isStaticContext, pn.getFirstChild()));
1646       ben.setNumLine(pn.getLine());
1647       blockstatements.add(ben);
1648     } else if (isNode(pn,"ifstatement")) {
1649       IfStatementNode isn=new IfStatementNode(parseExpression(cn, md, isStaticContext, pn.getChild("condition").getFirstChild()),
1650                                               parseSingleBlock(cn, md, isStaticContext, pn.getChild("statement").getFirstChild()),
1651                                               pn.getChild("else_statement")!=null?parseSingleBlock(cn, md, isStaticContext, pn.getChild("else_statement").getFirstChild()):null);
1652       isn.setNumLine(pn.getLine());
1653
1654       blockstatements.add(isn);
1655     } else if (isNode(pn,"switch_statement")) {
1656       // TODO add version for normal Java later
1657       SwitchStatementNode ssn=new SwitchStatementNode(parseExpression(cn, md, isStaticContext, pn.getChild("condition").getFirstChild()),
1658                                                       parseSingleBlock(cn, md, isStaticContext, pn.getChild("statement").getFirstChild()));
1659       ssn.setNumLine(pn.getLine());
1660       blockstatements.add(ssn);
1661     } else if (isNode(pn,"switch_block_list")) {
1662       // TODO add version for normal Java later
1663       ParseNodeVector pnv=pn.getChildren();
1664       for(int i=0; i<pnv.size(); i++) {
1665         ParseNode sblockdecl=pnv.elementAt(i);
1666
1667         if(isNode(sblockdecl, "switch_block")) {
1668           ParseNode lpn=sblockdecl.getChild("switch_labels").getChild("switch_label_list");
1669           ParseNodeVector labelv=lpn.getChildren();
1670           Vector<SwitchLabelNode> slv = new Vector<SwitchLabelNode>();
1671           for(int j=0; j<labelv.size(); j++) {
1672             ParseNode labeldecl=labelv.elementAt(j);
1673             if(isNode(labeldecl, "switch_label")) {
1674               SwitchLabelNode sln=new SwitchLabelNode(parseExpression(cn, md, isStaticContext, labeldecl.getChild("constant_expression").getFirstChild()), false);
1675               sln.setNumLine(labeldecl.getLine());
1676               slv.addElement(sln);
1677             } else if(isNode(labeldecl, "default_switch_label")) {
1678               SwitchLabelNode sln=new SwitchLabelNode(null, true);
1679               sln.setNumLine(labeldecl.getLine());
1680               slv.addElement(sln);
1681             }
1682           }
1683
1684           SwitchBlockNode sbn=new SwitchBlockNode(slv,
1685                                                   parseSingleBlock(cn, md, isStaticContext, sblockdecl.getChild("switch_statements").getFirstChild()));
1686           sbn.setNumLine(sblockdecl.getLine());
1687
1688           blockstatements.add(sbn);
1689
1690         }
1691       }
1692     } else if (isNode(pn, "trycatchstatement")) {
1693       // TODO add version for normal Java later
1694       // Do not fully support exceptions now. Only make sure that if there are no
1695       // exceptions thrown, the execution is right
1696       ParseNode tpn = pn.getChild("tryblock").getFirstChild();
1697       BlockNode bn=parseBlockHelper(cn, md, isStaticContext, tpn);
1698       blockstatements.add(new SubBlockNode(bn));
1699
1700       ParseNode fbk = pn.getChild("finallyblock");
1701       if(fbk != null) {
1702         ParseNode fpn = fbk.getFirstChild();
1703         BlockNode fbn=parseBlockHelper(cn, md, isStaticContext, fpn);
1704         blockstatements.add(new SubBlockNode(fbn));
1705       }
1706     } else if (isNode(pn, "throwstatement")) {
1707       // TODO Simply return here
1708       //blockstatements.add(new ReturnNode());
1709     } else if (isNode(pn,"taskexit")) {
1710       Vector vfe=null;
1711       if (pn.getChild("flag_effects_list")!=null)
1712         vfe=parseFlags(pn.getChild("flag_effects_list"));
1713       Vector ccs=null;
1714       if (pn.getChild("cons_checks")!=null)
1715         ccs=parseChecks(pn.getChild("cons_checks"));
1716       TaskExitNode ten=new TaskExitNode(vfe, ccs, this.m_taskexitnum++);
1717       ten.setNumLine(pn.getLine());
1718       blockstatements.add(ten);
1719     } else if (isNode(pn,"atomic")) {
1720       BlockNode bn=parseBlockHelper(cn, md, isStaticContext, pn);
1721       AtomicNode an=new AtomicNode(bn);
1722       an.setNumLine(pn.getLine());
1723       blockstatements.add(an);
1724     } else if (isNode(pn,"synchronized")) {
1725       BlockNode bn=parseBlockHelper(cn, md, isStaticContext, pn.getChild("block"));
1726       ExpressionNode en=parseExpression(cn, md, isStaticContext, pn.getChild("expr").getFirstChild());
1727       SynchronizedNode sn=new SynchronizedNode(en, bn);
1728       sn.setNumLine(pn.getLine());
1729       blockstatements.add(sn);
1730     } else if (isNode(pn,"return")) {
1731       if (isEmpty(pn.getTerminal()))
1732         blockstatements.add(new ReturnNode());
1733       else {
1734         ExpressionNode en=parseExpression(cn, md, isStaticContext, pn.getFirstChild());
1735         ReturnNode rn=new ReturnNode(en);
1736         rn.setNumLine(pn.getLine());
1737         blockstatements.add(rn);
1738       }
1739     } else if (isNode(pn,"block_statement_list")) {
1740       BlockNode bn=parseBlockHelper(cn, md, isStaticContext, pn);
1741       blockstatements.add(new SubBlockNode(bn));
1742     } else if (isNode(pn,"empty")) {
1743       /* nop */
1744     } else if (isNode(pn,"statement_expression_list")) {
1745       ParseNodeVector pnv=pn.getChildren();
1746       BlockNode bn=new BlockNode();
1747       for(int i=0; i<pnv.size(); i++) {
1748         ExpressionNode en=parseExpression(cn, md, isStaticContext, pnv.elementAt(i));
1749         blockstatements.add(new BlockExpressionNode(en));
1750       }
1751       bn.setStyle(BlockNode.EXPRLIST);
1752     } else if (isNode(pn,"forstatement")) {
1753       BlockNode init=parseSingleBlock(cn, md, isStaticContext, pn.getChild("initializer").getFirstChild());
1754       BlockNode update=parseSingleBlock(cn, md, isStaticContext, pn.getChild("update").getFirstChild());
1755       ExpressionNode condition=parseExpression(cn, md, isStaticContext, pn.getChild("condition").getFirstChild());
1756       BlockNode body=parseSingleBlock(cn, md, isStaticContext, pn.getChild("statement").getFirstChild());
1757       if(condition == null) {
1758         // no condition clause, make a 'true' expression as the condition
1759         condition = (ExpressionNode) new LiteralNode("boolean", new Boolean(true));
1760       }
1761       LoopNode ln=new LoopNode(init,condition,update,body,label);
1762       ln.setNumLine(pn.getLine());
1763       blockstatements.add(ln);
1764     } else if (isNode(pn,"whilestatement")) {
1765       ExpressionNode condition=parseExpression(cn, md, isStaticContext, pn.getChild("condition").getFirstChild());
1766       BlockNode body=parseSingleBlock(cn, md, isStaticContext, pn.getChild("statement").getFirstChild());
1767       if(condition == null) {
1768         // no condition clause, make a 'true' expression as the condition
1769         condition = (ExpressionNode) new LiteralNode("boolean", new Boolean(true));
1770       }
1771       blockstatements.add(new LoopNode(condition,body,LoopNode.WHILELOOP,label));
1772     } else if (isNode(pn,"dowhilestatement")) {
1773       ExpressionNode condition=parseExpression(cn, md, isStaticContext, pn.getChild("condition").getFirstChild());
1774       BlockNode body=parseSingleBlock(cn, md, isStaticContext, pn.getChild("statement").getFirstChild());
1775       if(condition == null) {
1776         // no condition clause, make a 'true' expression as the condition
1777         condition = (ExpressionNode) new LiteralNode("boolean", new Boolean(true));
1778       }
1779       blockstatements.add(new LoopNode(condition,body,LoopNode.DOWHILELOOP,label));
1780     } else if (isNode(pn,"sese")) {
1781       ParseNode pnID=pn.getChild("identifier");
1782       String stID=null;
1783       if( pnID != null ) {
1784         stID=pnID.getFirstChild().getTerminal();
1785       }
1786       SESENode start=new SESENode(stID);
1787       start.setNumLine(pn.getLine());
1788       SESENode end  =new SESENode(stID);
1789       start.setEnd(end);
1790       end.setStart(start);
1791       blockstatements.add(start);
1792       blockstatements.addAll(parseSESEBlock(cn, md, isStaticContext, blockstatements,pn.getChild("body").getFirstChild()));
1793       blockstatements.add(end);
1794     } else if (isNode(pn,"continue")) {
1795       ContinueBreakNode cbn=new ContinueBreakNode(false);
1796       cbn.setNumLine(pn.getLine());
1797       blockstatements.add(cbn);
1798     } else if (isNode(pn,"break")) {
1799       ContinueBreakNode cbn=new ContinueBreakNode(true);
1800       cbn.setNumLine(pn.getLine());
1801       blockstatements.add(cbn);
1802       ParseNode idopt_pn=pn.getChild("identifier_opt");
1803       ParseNode name_pn=idopt_pn.getChild("name");
1804       // name_pn.getTerminal() gives you the label
1805
1806     } else if (isNode(pn,"genreach")) {
1807       String graphName = pn.getChild("graphName").getTerminal();
1808       blockstatements.add(new GenReachNode(graphName) );
1809
1810     } else if (isNode(pn,"gen_def_reach")) {
1811       String outputName = pn.getChild("outputName").getTerminal();
1812       blockstatements.add(new GenDefReachNode(outputName) );
1813
1814     } else if(isNode(pn,"labeledstatement")) {
1815       String labeledstatement = pn.getChild("name").getTerminal();
1816       BlockNode bn=parseSingleBlock(cn, md, isStaticContext, pn.getChild("statement").getFirstChild(),labeledstatement);
1817       blockstatements.add(new SubBlockNode(bn));
1818     } else {
1819       System.out.println("---------------");
1820       System.out.println(pn.PPrint(3,true));
1821       throw new Error();
1822     }
1823     return blockstatements;
1824   }
1825
1826   public MethodDescriptor parseMethodHeader(ParseNode pn) {
1827     ParseNode mn=pn.getChild("modifiers");
1828     Modifiers m=parseModifiersList(mn);
1829
1830     ParseNode tn=pn.getChild("returntype");
1831     TypeDescriptor returntype;
1832     if (tn!=null)
1833       returntype=parseTypeDescriptor(tn);
1834     else
1835       returntype=new TypeDescriptor(TypeDescriptor.VOID);
1836
1837     ParseNode pmd=pn.getChild("method_declarator");
1838     String name=pmd.getChild("name").getTerminal();
1839     MethodDescriptor md=new MethodDescriptor(m, returntype, name);
1840
1841     ParseNode paramnode=pmd.getChild("parameters");
1842     parseParameterList(md,paramnode);
1843     return md;
1844   }
1845
1846   public void parseParameterList(MethodDescriptor md, ParseNode pn) {
1847     ParseNode paramlist=pn.getChild("formal_parameter_list");
1848     if (paramlist==null)
1849       return;
1850     ParseNodeVector pnv=paramlist.getChildren();
1851     for(int i=0; i<pnv.size(); i++) {
1852       ParseNode paramn=pnv.elementAt(i);
1853
1854       if (isNode(paramn, "tag_parameter")) {
1855         String paramname=paramn.getChild("single").getTerminal();
1856         TypeDescriptor type=new TypeDescriptor(TypeDescriptor.TAG);
1857         md.addTagParameter(type, paramname);
1858       } else  {
1859
1860         TypeDescriptor type=parseTypeDescriptor(paramn);
1861
1862         ParseNode tmp=paramn;
1863         while (tmp.getChild("single")==null) {
1864           type=type.makeArray(state);
1865           tmp=tmp.getChild("array");
1866         }
1867         String paramname=tmp.getChild("single").getTerminal();
1868
1869         md.addParameter(type, paramname);
1870         if(isNode(paramn, "annotation_parameter")) {
1871           ParseNode listnode=paramn.getChild("annotation_list");
1872           parseParameterAnnotation(listnode,type);
1873         }
1874
1875       }
1876     }
1877   }
1878
1879   public Modifiers parseModifiersList(ParseNode pn) {
1880     Modifiers m=new Modifiers();
1881     ParseNode modlist=pn.getChild("modifier_list");
1882     if (modlist!=null) {
1883       ParseNodeVector pnv=modlist.getChildren();
1884       for(int i=0; i<pnv.size(); i++) {
1885         ParseNode modn=pnv.elementAt(i);
1886         if (isNode(modn,"public"))
1887           m.addModifier(Modifiers.PUBLIC);
1888         else if (isNode(modn,"protected"))
1889           m.addModifier(Modifiers.PROTECTED);
1890         else if (isNode(modn,"private"))
1891           m.addModifier(Modifiers.PRIVATE);
1892         else if (isNode(modn,"static"))
1893           m.addModifier(Modifiers.STATIC);
1894         else if (isNode(modn,"final"))
1895           m.addModifier(Modifiers.FINAL);
1896         else if (isNode(modn,"native"))
1897           m.addModifier(Modifiers.NATIVE);
1898         else if (isNode(modn,"synchronized"))
1899           m.addModifier(Modifiers.SYNCHRONIZED);
1900         else if (isNode(modn,"atomic"))
1901           m.addModifier(Modifiers.ATOMIC);
1902         else if (isNode(modn,"abstract"))
1903           m.addModifier(Modifiers.ABSTRACT);
1904         else if (isNode(modn,"volatile"))
1905           m.addModifier(Modifiers.VOLATILE);
1906         else if (isNode(modn,"transient"))
1907           m.addModifier(Modifiers.TRANSIENT);
1908         else if(isNode(modn,"annotation_list"))
1909           parseAnnotationList(modn,m);
1910         else {
1911           throw new Error("Unrecognized Modifier:"+modn.getLabel());
1912         }
1913       }
1914     }
1915     return m;
1916   }
1917
1918   private void parseAnnotationList(ParseNode pn, Modifiers m) {
1919     ParseNodeVector pnv = pn.getChildren();
1920     for (int i = 0; i < pnv.size(); i++) {
1921       ParseNode body_list = pnv.elementAt(i);
1922       if (isNode(body_list, "annotation_body")) {
1923         ParseNode body_node = body_list.getFirstChild();
1924         if (isNode(body_node, "marker_annotation")) {
1925           m.addAnnotation(new AnnotationDescriptor(body_node.getChild("name").getTerminal()));
1926         } else if (isNode(body_node, "single_annotation")) {
1927           m.addAnnotation(new AnnotationDescriptor(body_node.getChild("name").getTerminal(),
1928                                                    body_node.getChild("element_value").getTerminal()));
1929         } else if (isNode(body_node, "normal_annotation")) {
1930           throw new Error("Annotation with multiple data members is not supported yet.");
1931         }
1932       }
1933     }
1934   }
1935
1936   private void parseParameterAnnotation(ParseNode pn,TypeDescriptor type) {
1937     ParseNodeVector pnv = pn.getChildren();
1938     for (int i = 0; i < pnv.size(); i++) {
1939       ParseNode body_list = pnv.elementAt(i);
1940       if (isNode(body_list, "annotation_body")) {
1941         ParseNode body_node = body_list.getFirstChild();
1942         if (isNode(body_node, "marker_annotation")) {
1943           type.addAnnotationMarker(new AnnotationDescriptor(body_node.getChild("name").getTerminal()));
1944         } else if (isNode(body_node, "single_annotation")) {
1945           type.addAnnotationMarker(new AnnotationDescriptor(body_node.getChild("name").getTerminal(),
1946                                                    body_node.getChild("element_value").getTerminal()));
1947         } else if (isNode(body_node, "normal_annotation")) {
1948           throw new Error("Annotation with multiple data members is not supported yet.");
1949         }
1950       }
1951     }
1952   }
1953
1954   private boolean isNode(ParseNode pn, String label) {
1955     if (pn.getLabel().equals(label))
1956       return true;
1957     else return false;
1958   }
1959
1960   private static boolean isEmpty(ParseNode pn) {
1961     if (pn.getLabel().equals("empty"))
1962       return true;
1963     else
1964       return false;
1965   }
1966
1967   private static boolean isEmpty(String s) {
1968     if (s.equals("empty"))
1969       return true;
1970     else
1971       return false;
1972   }
1973
1974   /** Throw an exception if something is unexpected */
1975   private void check(ParseNode pn, String label) {
1976     if (pn == null) {
1977       throw new Error(pn+ "IE: Expected '" + label + "', got null");
1978     }
1979     if (!pn.getLabel().equals(label)) {
1980       throw new Error(pn+ "IE: Expected '" + label + "', got '"+pn.getLabel()+"'");
1981     }
1982   }
1983 }