00001
00002
00003
00004
00005
00006
00007
00008 #include <iostream>
00009 #include <map>
00010 #include <list>
00011
00012
00013 #include "sourcereader.hh"
00014 #include "enrobage.hh"
00015 #include "ppbox.hh"
00016
00017 using namespace std;
00018
00019
00020
00021
00022
00023
00024 int yyparse();
00025
00026 extern int yyerr;
00027 extern int yydebug;
00028 extern FILE* yyin;
00029 extern int yylineno;
00030 extern const char * yyfilename;
00031
00032 extern Tree gResult;
00033 extern Tree gResult2;
00034
00035
00036
00037
00046 static bool standardArgList(Tree args)
00047 {
00048 map<Tree,int> L;
00049 while (isList(args)) {
00050 if (!isBoxIdent(hd(args))) return false;
00051 if (++L[hd(args)] > 1) return false;
00052 args = tl(args);
00053 }
00054 return true;
00055 }
00056
00057
00058 static void printPatternError(Tree lhs1, Tree rhs1, Tree lhs2, Tree rhs2)
00059 {
00060 cerr << "ERROR : inconsistent number of parameters in pattern-matching rule: "
00061 << boxpp(reverse(lhs2)) << " => " << boxpp(rhs2) << ";"
00062 << " previous rule was: "
00063 << boxpp(reverse(lhs1)) << " => " << boxpp(rhs1) << ";"
00064 << endl;
00065 }
00066
00067 Tree checkRulelist (Tree lr)
00068 {
00069 Tree lrules = lr;
00070 if (isNil(lrules)) { cerr << "ERROR : a case expression can't be empty" << endl; exit(1); }
00071
00072 Tree lhs1 = hd(hd(lrules));
00073 Tree rhs1 = tl(hd(lrules));
00074 int npat = len(lhs1);
00075 lrules = tl(lrules);
00076 while (! isNil(lrules)) {
00077 Tree lhs2 = hd(hd(lrules));
00078 Tree rhs2 = tl(hd(lrules));
00079 if (npat != len(lhs2)) {
00080 printPatternError(lhs1,rhs1,lhs2,rhs2);
00081 exit(1);
00082 }
00083
00084 lhs1 = lhs2;
00085 rhs1 = rhs2;
00086 lrules = tl(lrules);
00087 }
00088 return lr;
00089 }
00090
00091
00098 static Tree makeDefinition(list<Tree>& variants)
00099 {
00100 if (variants.size() == 1) {
00101 Tree rhs = *(variants.begin());
00102 Tree args= hd(rhs);
00103 Tree body= tl(rhs);
00104
00105 if (isNil(args)) {
00106 return body;
00107 } else if (standardArgList(args)) {
00108 return buildBoxAbstr(args, body);
00109 } else {
00110 return boxCase(cons(rhs,nil));
00111 }
00112 } else {
00113 list<Tree>::iterator p;
00114 Tree l = nil;
00115 Tree prev = *variants.begin();
00116 int npat = len(hd(prev));
00117 for (p=variants.begin(); p!=variants.end(); p++) {
00118 Tree cur = *p;
00119 if (npat != len(hd(cur))) {
00120 printPatternError(hd(prev), tl(prev), hd(cur), tl(cur));
00121 exit(1);
00122 }
00123 prev = cur;
00124 l = cons(*p,l);
00125 }
00126 return boxCase(l);
00127 }
00128 }
00129
00130
00131
00140 Tree formatDefinitions(Tree rldef)
00141 {
00142 map<Tree,list<Tree> > dic;
00143 map<Tree,list<Tree> >::iterator p;
00144 Tree ldef2 = nil;
00145 Tree file;
00146
00147
00148
00149 while (!isNil(rldef)) {
00150 Tree def = hd(rldef);
00151 rldef = tl(rldef);
00152 if (isImportFile(def, file)) {
00153 ldef2 = cons(def,ldef2);
00154 } else if (!isNil(def)) {
00155
00156 dic[hd(def)].push_front(tl(def));
00157 }
00158 }
00159
00160
00161
00162 for (p=dic.begin(); p!=dic.end(); p++) {
00163 ldef2 = cons (cons(p->first, makeDefinition(p->second)), ldef2);
00164 }
00165
00166
00167 return ldef2;
00168
00169 }
00170
00171
00180 Tree SourceReader::parse(string fname)
00181 {
00182 yyerr = 0;
00183
00184 yyfilename = fname.c_str();
00185 yyin = fopensearch(yyfilename);
00186 if (yyin == NULL) {
00187 fprintf(stderr, "ERROR : Unable to open file %s \n", yyfilename);
00188 exit(1);
00189 }
00190
00191 yylineno = 1;
00192 int r = yyparse();
00193 if (r) {
00194 fprintf(stderr, "Parse error : code = %d \n", r);
00195 }
00196 if (yyerr > 0) {
00197
00198 exit(1);
00199 }
00200
00201 return gResult;
00202 }
00203
00204
00212 bool SourceReader::cached(string fname)
00213 {
00214 return fFileCache.find(fname) != fFileCache.end();
00215 }
00216
00217
00225 Tree SourceReader::getlist(string fname)
00226 {
00227 if (!cached(fname)) {
00228 fFileCache[fname] = parse(fname);
00229 }
00230 if (fFileCache[fname] == 0) exit(1);
00231 return fFileCache[fname];
00232 }
00233
00234
00242 Tree SourceReader::expandlist(Tree ldef)
00243 {
00244 set<string> visited;
00245 return expandrec(ldef, visited, nil);
00246 }
00247
00248 Tree SourceReader::expandrec(Tree ldef, set<string>& visited, Tree lresult)
00249 {
00250 for (;!isNil(ldef); ldef = tl(ldef)) {
00251 Tree d = hd(ldef);
00252 Tree fname;
00253 if (isNil(d)) {
00254
00255 } else if (isImportFile(d,fname)) {
00256 string f = tree2str(fname);
00257
00258
00259
00260 if (visited.find(f) == visited.end()) {
00261 visited.insert(f);
00262
00263 lresult = expandrec(getlist(f), visited, lresult);
00264 }
00265
00266 } else {
00267 lresult = cons(d, lresult);
00268 }
00269 }
00270 return lresult;
00271 }
00272
00273