FAUST compiler  0.9.9.6b8
sourcereader.cpp
Go to the documentation of this file.
1 /*
2  sourcereader : Faust source file reader
3 
4  This component is in charge of mapping filenames to
5  the list of faust definitions they contain.
6 
7 */
8 #include <iostream>
9 #include <map>
10 #include <list>
11 #include <string>
12 
13 
14 #include "sourcereader.hh"
15 #include "sourcefetcher.hh"
16 #include "enrobage.hh"
17 #include "ppbox.hh"
18 
19 using namespace std;
20 
21 extern map<Tree, set<Tree> > gMetaDataSet;
22 extern string gMasterDocument;
23 extern vector<Tree> gDocVector;
24 extern bool gLatexDocSwitch;
25 
26 /****************************************************************
27  Parser variables
28 *****************************************************************/
29 
30 
31 int yyparse();
32 void yyrestart( FILE *new_file );
33 struct yy_buffer_state* yy_scan_string (const char *yy_str ); // In principle YY_BUFFER_STATE
34 
35 extern int yyerr;
36 extern int yydebug;
37 extern FILE* yyin;
38 extern int yylineno;
39 extern const char * yyfilename;
40 
41 extern Tree gResult;
42 extern Tree gResult2;
43 
44 
45 
46 
55 static bool standardArgList(Tree args)
56 {
57  map<Tree,int> L;
58  while (isList(args)) {
59  if (!isBoxIdent(hd(args))) return false;
60  if (++L[hd(args)] > 1) return false;
61  args = tl(args);
62  }
63  return true;
64 }
65 
66 
67 static void printPatternError(Tree lhs1, Tree rhs1, Tree lhs2, Tree rhs2)
68 {
69  cerr << "ERROR : inconsistent number of parameters in pattern-matching rule: "
70  << boxpp(reverse(lhs2)) << " => " << boxpp(rhs2) << ";"
71  << " previous rule was: "
72  << boxpp(reverse(lhs1)) << " => " << boxpp(rhs1) << ";"
73  << endl;
74 }
75 
77 {
78  Tree lrules = lr;
79  if (isNil(lrules)) { cerr << "ERROR : a case expression can't be empty" << endl; exit(1); }
80  // first pattern used as a reference
81  Tree lhs1 = hd(hd(lrules));
82  Tree rhs1 = tl(hd(lrules));
83  int npat = len(lhs1);
84  lrules = tl(lrules);
85  while (! isNil(lrules)) {
86  Tree lhs2 = hd(hd(lrules));
87  Tree rhs2 = tl(hd(lrules));
88  if (npat != len(lhs2)) {
89  printPatternError(lhs1,rhs1,lhs2,rhs2);
90  exit(1);
91  }
92 
93  lhs1 = lhs2;
94  rhs1 = rhs2;
95  lrules = tl(lrules);
96  }
97  return lr;
98 }
99 
100 
107 static Tree makeDefinition(list<Tree>& variants)
108 {
109  if (variants.size() == 1) {
110  Tree rhs = *(variants.begin());
111  Tree args= hd(rhs);
112  Tree body= tl(rhs);
113 
114  if (isNil(args)) {
115  return body;
116  } else if (standardArgList(args)) {
117  return buildBoxAbstr(args, body);
118  } else {
119  return boxCase(cons(rhs,nil));
120  }
121  } else {
122  list<Tree>::iterator p;
123  Tree l = nil;
124  Tree prev = *variants.begin();
125  int npat = len(hd(prev));
126  for (p=variants.begin(); p!=variants.end(); p++) {
127  Tree cur = *p;
128  if (npat != len(hd(cur))) {
129  printPatternError(hd(prev), tl(prev), hd(cur), tl(cur));
130  exit(1);
131  }
132  prev = cur;
133  l = cons(*p,l);
134  }
135  return boxCase(l);
136  }
137 }
138 
139 
140 
150 {
151  map<Tree,list<Tree> > dic;
152  map<Tree,list<Tree> >::iterator p;
153  Tree ldef2 = nil;
154  Tree file;
155 
156  //cout << "Format definitions " << *rldef << endl;
157  // collects the definitions in a dictionnary
158  while (!isNil(rldef)) {
159  Tree def = hd(rldef);
160  rldef = tl(rldef);
161  if (isImportFile(def, file)) {
162  ldef2 = cons(def,ldef2);
163  } else if (!isNil(def)) {
164  //cout << " def : " << *def << endl;
165  dic[hd(def)].push_front(tl(def));
166  }
167  }
168 
169  // produce the definitions
170 
171  for (p=dic.begin(); p!=dic.end(); p++) {
172  ldef2 = cons (cons(p->first, makeDefinition(p->second)), ldef2);
173  }
174 
175  //cout << "list of definitions : " << *ldef2 << endl;
176  return ldef2;
177 
178 }
179 
180 
190 {
191  string fullpath;
192  char* fileBuf = 0;
193 
194  yyerr = 0;
195 
196  yyfilename = fname.c_str();
197  if (strstr(yyfilename,"http://") != 0) {
198  // We are requested to parse an URL file
199  int ret = http_fetch(yyfilename, &fileBuf);
200  if (ret == -1) {
201  http_perror("http fetch");
202  exit(1);
203  }
204  yy_scan_string(fileBuf);
205  yylineno = 1;
206  int r = yyparse();
207  if (r) {
208  fprintf(stderr, "Parse error : code = %d \n", r);
209  }
210  if (yyerr > 0) {
211  //fprintf(stderr, "Erreur de parsing 2, count = %d \n", yyerr);
212  exit(1);
213  }
214 
215  // we have parsed a valid file
216  fFilePathnames.push_back(fullpath);
217  free(fileBuf);
218  return gResult;
219 
220  } else {
221  // test for local url
222  if (strstr(yyfilename,"file://") != 0) {
223  yyfilename = &yyfilename[7]; // skip 'file://'
224  }
225 
226  // We are requested to parse a regular file
227  yyin = fopensearch(yyfilename, fullpath);
228  if (yyin == NULL) {
229  fprintf(stderr, "ERROR : Unable to open file %s \n", yyfilename);
230  exit(1);
231  }
232  yyrestart(yyin); // make sure we scan from file again (in case we scanned a string just before)
233  yylineno = 1;
234  int r = yyparse();
235  if (r) {
236  fprintf(stderr, "Parse error : code = %d \n", r);
237  }
238  if (yyerr > 0) {
239  //fprintf(stderr, "Erreur de parsing 2, count = %d \n", yyerr);
240  exit(1);
241  }
242 
243  // we have parsed a valid file
244  fFilePathnames.push_back(fullpath);
245  return gResult;
246  }
247 }
248 
249 
257 bool SourceReader::cached(string fname)
258 {
259  return fFileCache.find(fname) != fFileCache.end();
260 }
261 
262 
271 {
272  if (!cached(fname)) {
273  fFileCache[fname] = parse(fname);
274  }
275  if (fFileCache[fname] == 0) exit(1);
276  return fFileCache[fname];
277 }
278 
279 
287 {
288 // vector<string> srcfiles;
289 
290 // for (map<string, Tree>::const_iterator p = fFileCache.begin(); p != fFileCache.end(); p++) {
291 // srcfiles.push_back(p->first);
292 // }
293 
294 // return srcfiles;
295  return fFilePathnames;
296 }
297 
298 
307 {
308  set<string> visited;
309  return expandrec(ldef, visited, nil);
310 }
311 
312 Tree SourceReader::expandrec(Tree ldef, set<string>& visited, Tree lresult)
313 {
314  for (;!isNil(ldef); ldef = tl(ldef)) {
315  Tree d = hd(ldef);
316  Tree fname;
317  if (isNil(d)) {
318  // skill null definitions produced by declarations
319  } else if (isImportFile(d,fname)) {
320  string f = tree2str(fname);
321  //cerr << "import(" << f << ")" << endl;
322 
323  //string f = tree2str(fname);
324  if (visited.find(f) == visited.end()) {
325  visited.insert(f);
326  //Tree l = getlist(f);
327  lresult = expandrec(getlist(f), visited, lresult);
328  }
329 
330  } else {
331  lresult = cons(d, lresult);
332  }
333  }
334  return lresult;
335 }
336 
337 
338 void declareMetadata(Tree key, Tree value)
339 {
340  if (gMasterDocument == yyfilename) {
341  // inside master document, no prefix needed to declare metadata
342  gMetaDataSet[key].insert(value);
343  } else {
344  string fkey(yyfilename);
345  fkey += "/";
346  fkey += tree2str(key);
347  gMetaDataSet[tree(fkey.c_str())].insert(value);
348  }
349  //cout << "Master " << gMasterDocument << ", file " << yyfilename << " : declare " << *key << "," << *value << endl;
350 }
351 
352 
354 {
355  //gLatexDocSwitch = true;
356  gDocVector.push_back(t);
357 }
bool cached(string fname)
Check if a file as been read and is in the "cache".
bool isImportFile(Tree s, Tree &filename)
Definition: boxes.cpp:301
const char * yyfilename
Definition: errormsg.cpp:30
void yyrestart(FILE *new_file)
Immediately switch to a different input stream.
void declareMetadata(Tree key, Tree value)
Tree parse(string fname)
Parse a single faust source file.
void http_perror(const char *string)
Tree reverse(Tree l)
Definition: list.cpp:240
Tree formatDefinitions(Tree rldef)
Formats a list of raw definitions represented by triplets into abstractions or pa...
vector< Tree > gDocVector
Contains parsed trees: DOCTXT, DOCEQN, DOCDGM.
Definition: doc.cpp:109
bool isBoxIdent(Tree t)
Definition: boxes.cpp:58
Tree cons(Tree a, Tree b)
Definition: list.hh:124
void declareDoc(Tree t)
Tree expandrec(Tree ldef, set< string > &visited, Tree lresult)
int yydebug
A CTree = (Node x [CTree]) is a Node associated with a list of subtrees called branches.
Definition: tree.hh:109
Tree hd(Tree l)
Definition: list.hh:133
Tree gResult
Definition: main.cpp:86
bool gLatexDocSwitch
Definition: main.cpp:123
bool isNil(Tree l)
Definition: list.hh:137
int yyparse()
static Tree makeDefinition(list< Tree > &variants)
Transforms a list of variants (arglist.body) into an abstraction or a boxCase.
vector< string > listSrcFiles()
Return a vector of pathnames representing the list of all the source files that have been required to...
bool isList(Tree l)
Definition: list.hh:138
FILE * fopensearch(const char *filename, string &fullpath)
Try to open the file searching in various directories.
Definition: enrobage.cpp:458
int http_fetch(const char *url_tmp, char **fileBuf)
Tree expandlist(Tree ldef)
Return the list of definitions where all imports have been expanded.
Tree checkRulelist(Tree lr)
FILE * yyin
Tree gResult2
Definition: main.cpp:87
string gMasterDocument
Definition: main.cpp:104
static bool standardArgList(Tree args)
Checks an argument list for containing only standard identifiers, no patterns and is linear...
Tree tree(const Node &n)
Definition: tree.hh:186
Definition: ppbox.hh:58
static void printPatternError(Tree lhs1, Tree rhs1, Tree lhs2, Tree rhs2)
Tree nil
Definition: list.cpp:116
Tree getlist(string fname)
Return the list of definitions file contains.
Tree buildBoxAbstr(Tree largs, Tree body)
Definition: boxes.cpp:208
int yyerr
Definition: main.cpp:83
map< Tree, set< Tree > > gMetaDataSet
Definition: main.cpp:91
int yylineno
struct yy_buffer_state * yy_scan_string(const char *yy_str)
Tree boxCase(Tree rules)
Definition: boxes.cpp:615
int len(Tree l)
Definition: list.cpp:198
Tree tl(Tree l)
Definition: list.hh:134
const char * tree2str(Tree t)
if t has a node of type symbol, return its name otherwise error
Definition: tree.cpp:278