00001
00002
00003
00004
00005
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
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
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
00154
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
00162 dic[hd(def)].push_front(tl(def));
00163 }
00164 }
00165
00166
00167
00168 for (p=dic.begin(); p!=dic.end(); p++) {
00169 ldef2 = cons (cons(p->first, makeDefinition(p->second)), ldef2);
00170 }
00171
00172
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
00206 exit(1);
00207 }
00208
00209
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
00254
00255
00256
00257
00258
00259
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
00284 } else if (isImportFile(d,fname)) {
00285 string f = tree2str(fname);
00286
00287
00288
00289 if (visited.find(f) == visited.end()) {
00290 visited.insert(f);
00291
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
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
00315 }
00316
00317
00318 void declareDoc(Tree t)
00319 {
00320
00321 gDocVector.push_back(t);
00322 }