package edu.neu.ccs.demeterf.demfgen; import edu.neu.ccs.demeterf.*; import edu.neu.ccs.demeterf.demfgen.classes.*; import edu.neu.ccs.demeterf.lib.List; import java.io.*; /** Resolve the Included CD/BEH files recursively. Cycles are not broken, and * repeate includes result in multiple definitions. */ public class IncludeCDs{ public static List resolveCDs(IncludeList l, String par){ return resolveCDs(l, par, new YesGen()); } public static List resolveCDs(IncludeList l, String par, DoGen g){ return Factory.newTraversal(new ReadCDs(par,g)).traverseIncludeList(l); } public static List resolveBEHs(IncludeList l, String par){ return resolveBEHs(l, par, new YesGen()); } public static List resolveBEHs(IncludeList l, String par, DoGen g){ return Factory.newTraversal(new ReadBEHs(par,g)).traverseIncludeList(l); } /** Resolve relative include paths based on the containing CD file (name) */ public static String localFile(String name, String inc){ if(inc.charAt(0) == File.separatorChar)return inc; return name.substring(0, name.lastIndexOf(File.separatorChar)+1)+inc; } /** Collect all the types in a CD */ public static List allTypes(List l){ return l.fold(new List.Fold>(){ public List fold(CDFile f, List r){ return r.append(f.getTypes().toList()); }},List.create()); } /** Calculate the maximum look ahead from all transitive included CDs */ public static LookDef maxLookAhead(List l){ return l.fold(new List.Fold(){ public LookDef fold(CDFile f, LookDef r){ if(!f.getLook().isLook())return r; if(!r.isLook())return f.getLook(); return (f.getLook().look() > r.look())?f.getLook():r; }}, new NoLook()); } /** Collect all the imports from all transitive included CDs */ public static ImportList allImports(List l){ return l.fold(new List.Fold(){ public ImportList fold(CDFile f, ImportList r){ return f.getImports().append(r); }}, new ImportEmpty()); } public static abstract class Read extends ID{ String parFile; DoGen gen; protected Read(String p, DoGen g){ parFile = p; gen = g; } protected abstract List read(InputStream in, DoGen g, String par) throws Exception; protected abstract String type(); protected DoGen combine(DoGen g){ return g; } protected List combine(Include inc, DoGen g, String file){ String loc = IncludeCDs.localFile(parFile,file); try{ FileInputStream in = new FileInputStream(loc); return read(in,g.merge(gen), loc); }catch(FileNotFoundException fe){ throw new RTFileNotFound(" ** In \""+parFile+"\"\n Included "+type()+" File Not Found : \""+loc+"\""); }catch(Exception e){ throw new RTParseException(" ** "+type()+" File: \""+loc+"\"\n"+e.getMessage()); } } protected List combine(ConsList c, List f, List r){ return r.push(f); } protected List combine(EmptyList e){ return List.create(); } } static class ReadCDs extends Read{ ReadCDs(String p, DoGen g){ super(p,g); } protected String type(){ return "CD"; } protected List read(InputStream in, DoGen g, String file) throws Exception{ CDFile m = mergeGen(CDFile.parse(in),g); List incl = IncludeCDs.resolveCDs(m.getIncl(),file,g); ImportList imp = IncludeCDs.allImports(incl); return incl.push(m.updateImports(imp.append(m.getImports()))); } static CDFile mergeGen(CDFile m, final DoGen g){ if(g.doGen() && g.doParse())return m; return Factory.newTraversal(new TP(){ DoGen combine(DoGen gen){ return gen.merge(g); } }).>traverseList_CDFile_(List.create(m)).top(); } } static class ReadBEHs extends Read{ ReadBEHs(String p, DoGen g){ super(p,g); } protected String type(){ return "BEH"; } protected List read(InputStream in, DoGen g, String file) throws Exception{ BehFile b = BehFile.parse(in); return IncludeCDs.resolveBEHs(b.getIncl(),file,g).push(b.getBehs().toList()); } } }