|
FAUST compiler
0.9.9.6b8
|
00001 /* 00002 sourcereader : Faust source file reader 00003 00004 This component is in charge of mapping filenames to 00005 the list of faust definitions they contain. 00006 00007 */ 00008 #include <iostream> 00009 #include <map> 00010 #include <list> 00011 #include <string> 00012 00013 00014 #include "sourcereader.hh" 00015 #include "enrobage.hh" 00016 #include "ppbox.hh" 00017 00018 using namespace std; 00019 00020 extern map<Tree, set<Tree> > gMetaDataSet; 00021 extern string gMasterDocument; 00022 extern vector<Tree> gDocVector; 00023 extern bool gLatexDocSwitch; 00024 00025 /**************************************************************** 00026 Parser variables 00027 *****************************************************************/ 00028 00029 00030 int yyparse(); 00031 00032 extern int yyerr; 00033 extern int yydebug; 00034 extern FILE* yyin; 00035 extern int yylineno; 00036 extern const char * yyfilename; 00037 00038 extern Tree gResult; 00039 extern Tree gResult2; 00040 00041 00042 00043 00052 static bool standardArgList(Tree args) 00053 { 00054 map<Tree,int> L; 00055 while (isList(args)) { 00056 if (!isBoxIdent(hd(args))) return false; 00057 if (++L[hd(args)] > 1) return false; 00058 args = tl(args); 00059 } 00060 return true; 00061 } 00062 00063 00064 static void printPatternError(Tree lhs1, Tree rhs1, Tree lhs2, Tree rhs2) 00065 { 00066 cerr << "ERROR : inconsistent number of parameters in pattern-matching rule: " 00067 << boxpp(reverse(lhs2)) << " => " << boxpp(rhs2) << ";" 00068 << " previous rule was: " 00069 << boxpp(reverse(lhs1)) << " => " << boxpp(rhs1) << ";" 00070 << endl; 00071 } 00072 00073 Tree checkRulelist (Tree lr) 00074 { 00075 Tree lrules = lr; 00076 if (isNil(lrules)) { cerr << "ERROR : a case expression can't be empty" << endl; exit(1); } 00077 // first pattern used as a reference 00078 Tree lhs1 = hd(hd(lrules)); 00079 Tree rhs1 = tl(hd(lrules)); 00080 int npat = len(lhs1); 00081 lrules = tl(lrules); 00082 while (! isNil(lrules)) { 00083 Tree lhs2 = hd(hd(lrules)); 00084 Tree rhs2 = tl(hd(lrules)); 00085 if (npat != len(lhs2)) { 00086 printPatternError(lhs1,rhs1,lhs2,rhs2); 00087 exit(1); 00088 } 00089 00090 lhs1 = lhs2; 00091 rhs1 = rhs2; 00092 lrules = tl(lrules); 00093 } 00094 return lr; 00095 } 00096 00097 00104 static Tree makeDefinition(list<Tree>& variants) 00105 { 00106 if (variants.size() == 1) { 00107 Tree rhs = *(variants.begin()); 00108 Tree args= hd(rhs); 00109 Tree body= tl(rhs); 00110 00111 if (isNil(args)) { 00112 return body; 00113 } else if (standardArgList(args)) { 00114 return buildBoxAbstr(args, body); 00115 } else { 00116 return boxCase(cons(rhs,nil)); 00117 } 00118 } else { 00119 list<Tree>::iterator p; 00120 Tree l = nil; 00121 Tree prev = *variants.begin(); 00122 int npat = len(hd(prev)); 00123 for (p=variants.begin(); p!=variants.end(); p++) { 00124 Tree cur = *p; 00125 if (npat != len(hd(cur))) { 00126 printPatternError(hd(prev), tl(prev), hd(cur), tl(cur)); 00127 exit(1); 00128 } 00129 prev = cur; 00130 l = cons(*p,l); 00131 } 00132 return boxCase(l); 00133 } 00134 } 00135 00136 00137 00146 Tree formatDefinitions(Tree rldef) 00147 { 00148 map<Tree,list<Tree> > dic; 00149 map<Tree,list<Tree> >::iterator p; 00150 Tree ldef2 = nil; 00151 Tree file; 00152 00153 //cout << "Format definitions " << *rldef << endl; 00154 // collects the definitions in a dictionnary 00155 while (!isNil(rldef)) { 00156 Tree def = hd(rldef); 00157 rldef = tl(rldef); 00158 if (isImportFile(def, file)) { 00159 ldef2 = cons(def,ldef2); 00160 } else if (!isNil(def)) { 00161 //cout << " def : " << *def << endl; 00162 dic[hd(def)].push_front(tl(def)); 00163 } 00164 } 00165 00166 // produce the definitions 00167 00168 for (p=dic.begin(); p!=dic.end(); p++) { 00169 ldef2 = cons (cons(p->first, makeDefinition(p->second)), ldef2); 00170 } 00171 00172 //cout << "list of definitions : " << *ldef2 << endl; 00173 return ldef2; 00174 00175 } 00176 00177 00186 Tree SourceReader::parse(string fname) 00187 { 00188 string fullpath; 00189 00190 yyerr = 0; 00191 00192 yyfilename = fname.c_str(); 00193 yyin = fopensearch(yyfilename, fullpath); 00194 if (yyin == NULL) { 00195 fprintf(stderr, "ERROR : Unable to open file %s \n", yyfilename); 00196 exit(1); 00197 } 00198 00199 yylineno = 1; 00200 int r = yyparse(); 00201 if (r) { 00202 fprintf(stderr, "Parse error : code = %d \n", r); 00203 } 00204 if (yyerr > 0) { 00205 //fprintf(stderr, "Erreur de parsing 2, count = %d \n", yyerr); 00206 exit(1); 00207 } 00208 00209 // we have parsed a valid file 00210 fFilePathnames.push_back(fullpath); 00211 return gResult; 00212 } 00213 00214 00222 bool SourceReader::cached(string fname) 00223 { 00224 return fFileCache.find(fname) != fFileCache.end(); 00225 } 00226 00227 00235 Tree SourceReader::getlist(string fname) 00236 { 00237 if (!cached(fname)) { 00238 fFileCache[fname] = parse(fname); 00239 } 00240 if (fFileCache[fname] == 0) exit(1); 00241 return fFileCache[fname]; 00242 } 00243 00244 00251 vector<string> SourceReader::listSrcFiles() 00252 { 00253 // vector<string> srcfiles; 00254 00255 // for (map<string, Tree>::const_iterator p = fFileCache.begin(); p != fFileCache.end(); p++) { 00256 // srcfiles.push_back(p->first); 00257 // } 00258 00259 // return srcfiles; 00260 return fFilePathnames; 00261 } 00262 00263 00271 Tree SourceReader::expandlist(Tree ldef) 00272 { 00273 set<string> visited; 00274 return expandrec(ldef, visited, nil); 00275 } 00276 00277 Tree SourceReader::expandrec(Tree ldef, set<string>& visited, Tree lresult) 00278 { 00279 for (;!isNil(ldef); ldef = tl(ldef)) { 00280 Tree d = hd(ldef); 00281 Tree fname; 00282 if (isNil(d)) { 00283 // skill null definitions produced by declarations 00284 } else if (isImportFile(d,fname)) { 00285 string f = tree2str(fname); 00286 //cerr << "import(" << f << ")" << endl; 00287 00288 //string f = tree2str(fname); 00289 if (visited.find(f) == visited.end()) { 00290 visited.insert(f); 00291 //Tree l = getlist(f); 00292 lresult = expandrec(getlist(f), visited, lresult); 00293 } 00294 00295 } else { 00296 lresult = cons(d, lresult); 00297 } 00298 } 00299 return lresult; 00300 } 00301 00302 00303 void declareMetadata(Tree key, Tree value) 00304 { 00305 if (gMasterDocument == yyfilename) { 00306 // inside master document, no prefix needed to declare metadata 00307 gMetaDataSet[key].insert(value); 00308 } else { 00309 string fkey(yyfilename); 00310 fkey += "/"; 00311 fkey += tree2str(key); 00312 gMetaDataSet[tree(fkey.c_str())].insert(value); 00313 } 00314 //cout << "Master " << gMasterDocument << ", file " << yyfilename << " : declare " << *key << "," << *value << endl; 00315 } 00316 00317 00318 void declareDoc(Tree t) 00319 { 00320 //gLatexDocSwitch = true; 00321 gDocVector.push_back(t); 00322 }
1.8.0