~ubuntu-branches/ubuntu/wily/aspectc++/wily

« back to all changes in this revision

Viewing changes to Puma/examples/parser/parser.cc

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2009-06-15 10:17:02 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090615101702-qsr30iptwbxylmo2
Tags: 1.0pre4~svn.20090615-1
* New upstream release.
* don't ignore errors in the postrm script
* avoid spurious creation of empty dir ./usr/sbin/
* improve short descriptions of libpuma-doc and libpuma-dev
* bump Standards-Version to 3.8.1
* bump debhelper compat level to level 7 (latest in stable)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// This file is part of PUMA.
 
2
// Copyright (C) 1999-2003  The PUMA developer team.
 
3
//                                                                
 
4
// This program is free software;  you can redistribute it and/or 
 
5
// modify it under the terms of the GNU General Public License as 
 
6
// published by the Free Software Foundation; either version 2 of 
 
7
// the License, or (at your option) any later version.            
 
8
//                                                                
 
9
// This program is distributed in the hope that it will be useful,
 
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
 
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
 
12
// GNU General Public License for more details.                   
 
13
//                                                                
 
14
// You should have received a copy of the GNU General Public      
 
15
// License along with this program; if not, write to the Free     
 
16
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
 
17
// MA  02111-1307  USA                                            
 
18
 
 
19
#include <Puma/CParser.h>
 
20
#include <Puma/CCParser.h>
 
21
#include <Puma/ErrorStream.h>
 
22
#include <Puma/CSemVisitor.h>
 
23
#include <Puma/CCSemVisitor.h>
 
24
#include <Puma/CPrintVisitor.h>
 
25
#include <Puma/PrePrintVisitor.h>
 
26
#include <Puma/CTranslationUnit.h>
 
27
#include <Puma/RegComp.h>
 
28
#include <Puma/PreTree.h>
 
29
#include <Puma/CTree.h>
 
30
#include <Puma/version.h>
 
31
#include <iostream>
 
32
#include <string>
 
33
#include <list>
 
34
#include <fstream>
 
35
#include <sstream>
 
36
#include <stdlib.h>
 
37
#include <unistd.h>
 
38
#include <time.h>
 
39
#ifdef WIN32
 
40
#include <sys/timeb.h>
 
41
#else
 
42
#include <sys/time.h>
 
43
#endif
 
44
 
 
45
 
 
46
namespace Puma {
 
47
  extern int TRACE_TYPE;            // trace created types
 
48
  extern int TRACE_UNDO;            // trace discarded subtrees
 
49
  extern int TRACE_OBJS;            // trace created and discarded semantic objects
 
50
  extern int TRACE_SCOPES;          // trace entered/leaved scopes
 
51
  extern int TRACE_INSTANCE_CODE;   // trace instance units
 
52
  extern int TRACE_PARSE_INSTANCE;  // trace parse instance units
 
53
}
 
54
 
 
55
 
 
56
static bool verify_tree = false;
 
57
static bool lang_c = false;
 
58
static bool lang_cc = false;
 
59
static std::string input_file = "";
 
60
static bool verbose = false;
 
61
static bool dump_cpp = false;
 
62
static std::string dump_cpp_file;
 
63
static int dump_db = 0;
 
64
static std::string dump_db_file;
 
65
static bool dump_unit = false;
 
66
static std::string dump_unit_file;
 
67
static bool dump_tree = false;
 
68
static std::string dump_tree_file;
 
69
static bool dump_cpp_tree = false;
 
70
static std::string dump_cpp_tree_file;
 
71
static bool trace_parse = false;
 
72
static std::string trace_parse_file;
 
73
 
 
74
 
 
75
void log(const std::string& message) {
 
76
  if (verbose) {
 
77
    time_t ltime;
 
78
    time(&ltime);
 
79
    struct tm *today = localtime(&ltime);
 
80
    char buffer[128];
 
81
    strftime(buffer,127,"%b %d %H:%M:%S",today);
 
82
    std::cout << "-- " << buffer << ".";
 
83
#ifdef WIN32
 
84
    timeb btime;
 
85
    ftime(&btime);
 
86
    std::cout << btime.millitm;
 
87
#else
 
88
    struct timeval tv;
 
89
    gettimeofday(&tv,0);
 
90
    std::cout << tv.tv_usec/1000;
 
91
#endif
 
92
    std::cout << ": " << message << std::endl;
 
93
  }
 
94
}
 
95
 
 
96
 
 
97
void printError(Puma::ErrorStream& err, Puma::CTree* node, const std::string& message) {
 
98
  if (node) {
 
99
    Puma::Token* t = node->token();
 
100
    if (t) {
 
101
      err << t->location();
 
102
    }
 
103
  }
 
104
  err << Puma::sev_error << message.c_str() << Puma::endMessage;
 
105
}
 
106
 
 
107
 
 
108
void printError(Puma::ErrorStream& err, const std::string& message) {
 
109
  printError(err, 0, message);
 
110
}
 
111
 
 
112
 
 
113
std::ostream* openStream(const std::string& file) {
 
114
  return file.empty() ? &std::cout : new std::ofstream(file.c_str());
 
115
}
 
116
 
 
117
 
 
118
void closeStream(const std::string& file, std::ostream* os) {
 
119
  if (! file.empty()) {
 
120
    delete os;
 
121
  }
 
122
}
 
123
 
 
124
 
 
125
void addCompilerConfig(Puma::ErrorStream& err, Puma::Config& config) {
 
126
  // always set when Puma parses something, can be used
 
127
  // to hide code from Puma's view
 
128
  config.Add("-D", "__puma");
 
129
  // signal that Puma prefers standard C code
 
130
  config.Add("-D", "__STDC__");
 
131
 
 
132
  // command to get the configuration options from the compiler
 
133
  std::string tmpfile = ".tmp_config";
 
134
  std::string cmd;
 
135
  if (lang_c) {
 
136
    cmd = "gcc -E -dM -v -x c /dev/null > "+tmpfile+" 2>&1";
 
137
  }
 
138
  else {
 
139
    cmd = "g++ -E -dM -v -x c++ /dev/null > "+tmpfile+" 2>&1";
 
140
  }
 
141
  // execute command to get the compiler config
 
142
  system(cmd.c_str());
 
143
 
 
144
  // parse the compiler config
 
145
  std::ifstream in(tmpfile.c_str());
 
146
  if (! in) {
 
147
    printError(err, "unable to open file "+tmpfile);
 
148
    printError(err, "command '"+cmd+"' failed");
 
149
    return;
 
150
  }
 
151
 
 
152
  // regular expressions for matching includes and macros
 
153
  Puma::RegComp regincl("#include [<\"].*:.*");
 
154
  Puma::RegComp reginlist("^ .*");
 
155
  Puma::RegComp regdef("#define .*");
 
156
 
 
157
  // read file line by line
 
158
  bool in_include_list = false;
 
159
  std::list<std::string> includes;
 
160
  std::string line;
 
161
  while (std::getline(in, line)) {
 
162
    // start of list of include paths
 
163
    if (regincl.match(line.c_str())) {
 
164
      in_include_list = true;
 
165
    // within a list of include paths
 
166
    } else if (in_include_list && reginlist.match(line.c_str())) {
 
167
      // strip leading white space
 
168
      unsigned int pos = line.find_first_not_of(" ");
 
169
      line = line.substr(pos);
 
170
 
 
171
      // convert '//*' to '/'
 
172
      char lastchar = '0';
 
173
      for (std::string::iterator c = line.begin(); c != line.end(); ++c) {
 
174
        if (lastchar == *c && *c == '/') {
 
175
          c = line.erase(c);
 
176
          --c;
 
177
        }
 
178
        lastchar = *c;
 
179
      }
 
180
 
 
181
      // add the include path
 
182
      includes.push_back(line);
 
183
    // end of list of include paths
 
184
    } else if (in_include_list) {
 
185
      in_include_list = false;
 
186
    // match a '#define ...'
 
187
    } else if (regdef.match(line.c_str())) {
 
188
      // remove '#define ' (8 characters)
 
189
      line = line.substr(8);
 
190
 
 
191
      // split name and argument of macro
 
192
 
 
193
      // find name, split at first whitespace
 
194
      std::string::size_type pos = line.find(" ");
 
195
      std::string name = line.substr(0, pos);
 
196
 
 
197
      // set '1' as default argument if no argument is defined
 
198
      std::string value = "1";
 
199
 
 
200
      // find value, i.e. the string behind the macro name
 
201
      if ((pos != string::npos) && (line.find_first_not_of(" ", pos) != std::string::npos)) {
 
202
        value = line.substr(pos+1);
 
203
      }
 
204
 
 
205
      // add the macro definition to the configuration
 
206
      config.Add("-D", name.c_str(), value.c_str());
 
207
 
 
208
      // check for gcc support
 
209
      if (name == "__GNUC__") {
 
210
        // get the compiler version
 
211
        int gcc_version = 0;
 
212
        std::istringstream convert(value);
 
213
        convert >> gcc_version;
 
214
 
 
215
        // enable correct gcc support
 
216
        if (gcc_version > 2) {
 
217
          config.Add("--gnu");
 
218
        } else {
 
219
          config.Add("--gnu-2.95");
 
220
        }
 
221
      // check for the size_t
 
222
      } else if (name == "__SIZE_TYPE__") {
 
223
        config.Add("--size-type", value.c_str());
 
224
      // check for the ptrdiff_t
 
225
      } else if (name == "__PTRDIFF_TYPE__") {
 
226
        config.Add("--ptrdiff-type", value.c_str());
 
227
      }
 
228
    }
 
229
  }
 
230
  in.close();
 
231
 
 
232
  // now add the include directories in the correct order
 
233
  std::list<std::string>::reverse_iterator i = includes.rbegin();
 
234
  for (; i != includes.rend(); ++i)
 
235
    config.Add("-I", i->c_str());
 
236
 
 
237
  unlink(tmpfile.c_str());
 
238
}
 
239
 
 
240
 
 
241
void readOptionArg(int argc, char** argv, int& i, std::string& file) {
 
242
  if (argc > (i+2) && argv[i+1][0] != '-') {
 
243
    file = argv[++i];
 
244
  }
 
245
}
 
246
 
 
247
 
 
248
void printUsage(Puma::CProject& project) {
 
249
  std::cout << "PUMA C/C++ Parser, v" << Puma::puma_version() << std::endl;
 
250
  std::cout << "usage: parser [options] <FILE>" << std::endl;
 
251
  std::cout << "options:" << std::endl;
 
252
  project.config().PrintOptions(std::cout);
 
253
  std::cout << "  --dump-db [FILE]                Dump the semantic database to file or stdout" << std::endl;
 
254
  std::cout << "  --dump-db-all [FILE]            Dump the semantic database incl. builtins to file or stdout" << std::endl;
 
255
  std::cout << "  --dump-tree [FILE]              Dump the syntax tree to file or stdout" << std::endl;
 
256
  std::cout << "  --dump-unit [FILE]              Dump the primary token unit to file or stdout" << std::endl;
 
257
  std::cout << "  --dump-cpp [FILE]               Dump the C preprocessor output to file or stdout" << std::endl;
 
258
  std::cout << "  --dump-cpp-tree [FILE]          Dump the C preprocessor syntax tree to file or stdout" << std::endl;
 
259
  std::cout << "  --dump-instances                Dump the created template instances to stdout [debug]" << std::endl;
 
260
  std::cout << "  --trace-parse [FILE]            Trace the parse process and write it to file or stdout [debug]" << std::endl;
 
261
  std::cout << "  --trace-instances               Trace parsing template instances and write it to stdout [debug]" << std::endl;
 
262
  std::cout << "  --trace-types                   Trace the created types and write it to stdout [debug]" << std::endl;
 
263
  std::cout << "  --trace-scopes                  Trace the entered scopes and write it to stdout [debug]" << std::endl;
 
264
  std::cout << "  --trace-objects                 Trace the created semantic opjects and write it to stdout [debug]" << std::endl;
 
265
  std::cout << "  --trace-undo-tree               Trace the backtracking and write it to stdout [debug]" << std::endl;
 
266
  std::cout << "  --verify-tree                   Verify the syntax tree" << std::endl;
 
267
  std::cout << "  --default-path                  Add the path to the input file as source path" << std::endl;
 
268
  std::cout << "  --no-default-config             Don't add the default configuration of the target compiler" << std::endl;
 
269
  std::cout << "  --help                          Show the usage information and exit" << std::endl;
 
270
  std::cout << "  -v                              Enable verbose logging" << std::endl;
 
271
  exit(1);
 
272
}
 
273
 
 
274
 
 
275
void evalOptions(Puma::CProject& project, int argc, char **argv) {
 
276
  // need usage information?
 
277
  if (argc < 2) {
 
278
    printUsage(project);
 
279
  }
 
280
 
 
281
  // read additional command line options
 
282
  bool default_path = false;
 
283
  bool default_config = true;
 
284
  for (int i = 1; i < argc; i++) {
 
285
    std::string o = argv[i];
 
286
    if (o == "--help") {
 
287
      printUsage(project);
 
288
    } else if (o == "-v") {
 
289
      verbose = true;
 
290
    } else if (o == "--verify-tree") {
 
291
      verify_tree = true;
 
292
    } else if (o == "--default-path") {
 
293
      default_path = true;
 
294
    } else if (o == "--no-default-config") {
 
295
      default_config = false;
 
296
    } else if (o == "--dump-db") {
 
297
      dump_db = 1;
 
298
      readOptionArg(argc, argv, i, dump_db_file);
 
299
    } else if (o == "--dump-db-all") {
 
300
      dump_db = 2;
 
301
      readOptionArg(argc, argv, i, dump_db_file);
 
302
    } else if (o == "--dump-tree") {
 
303
      dump_tree = true;
 
304
      readOptionArg(argc, argv, i, dump_tree_file);
 
305
    } else if (o == "--dump-unit") {
 
306
      dump_unit = true;
 
307
      readOptionArg(argc, argv, i, dump_unit_file);
 
308
    } else if (o == "--dump-cpp") {
 
309
      dump_cpp = true;
 
310
      readOptionArg(argc, argv, i, dump_cpp_file);
 
311
    } else if (o == "--dump-cpp-tree") {
 
312
      dump_cpp_tree = true;
 
313
      readOptionArg(argc, argv, i, dump_cpp_tree_file);
 
314
    } else if (o == "--trace-parse") {
 
315
      trace_parse = true;
 
316
      readOptionArg(argc, argv, i, trace_parse_file);
 
317
    } else if (o == "--trace-types") {
 
318
      Puma::TRACE_TYPE = 1;
 
319
    } else if (o == "--trace-scopes") {
 
320
      Puma::TRACE_SCOPES = 1;
 
321
    } else if (o == "--dump-instances") {
 
322
      Puma::TRACE_INSTANCE_CODE = 1;
 
323
    } else if (o == "--trace-instances") {
 
324
      Puma::TRACE_PARSE_INSTANCE = 1;
 
325
    } else if (o == "--trace-objects") {
 
326
      Puma::TRACE_OBJS = 1;
 
327
    } else if (o == "--trace-undo-tree") {
 
328
      Puma::TRACE_UNDO = 1;
 
329
    }
 
330
  }
 
331
 
 
332
  // add compiler configuration
 
333
  if (default_config) {
 
334
    addCompilerConfig(project.err(),project.config());
 
335
  }
 
336
 
 
337
  // add command line options
 
338
  project.config().Read(argc,argv);
 
339
 
 
340
  // evaluate options
 
341
  lang_c = project.config().Option("--lang-c");
 
342
  lang_cc = project.config().Option("--lang-c++") ||
 
343
            project.config().Option("--lang-ac++");
 
344
  input_file = argv[argc-1];
 
345
 
 
346
  // get input language
 
347
  if (! lang_c && ! lang_cc) {
 
348
    std::string::size_type pos = input_file.rfind('.');
 
349
    if (pos != input_file.npos) {
 
350
      std::string suffix = input_file.substr(pos+1);
 
351
      if (suffix == "cc" || suffix == "cpp") {
 
352
        lang_cc = true;
 
353
      }
 
354
      else if (suffix == "c") {
 
355
        lang_c = true;
 
356
      }
 
357
    }
 
358
 
 
359
    // set input language
 
360
    if (lang_c) {
 
361
      project.config().Add("--lang-c");
 
362
    }
 
363
    else {
 
364
      lang_cc = true;
 
365
      project.config().Add("--lang-c++");
 
366
    }
 
367
  }
 
368
 
 
369
  if (default_path) {
 
370
    // add the directory containing the current input file
 
371
    // as source directory
 
372
    std::string path = ".";
 
373
    std::string::size_type pos = input_file.rfind("/");
 
374
    if (pos != std::string::npos) {
 
375
      path = "/";
 
376
      if (pos != 0) {
 
377
        path = input_file.substr(0, pos);
 
378
      }
 
379
    }
 
380
    project.config().Add("-p", path.c_str());
 
381
  }
 
382
 
 
383
  // propagate the configuration
 
384
  project.configure(project.config());
 
385
}
 
386
 
 
387
 
 
388
Puma::CTranslationUnit* parseCFile(Puma::ErrorStream& err, Puma::CProject& project) {
 
389
  // lexical analysis
 
390
  log("lexical analysis");
 
391
  Puma::Unit *unit = project.scanFile(input_file.c_str());
 
392
  if (! unit) {
 
393
    printError(err, "lexical analysis of input file failed");
 
394
    return 0;
 
395
  }
 
396
 
 
397
  // dump unit
 
398
  if (dump_unit) {
 
399
    std::ostream* unit_os = openStream(dump_unit_file);
 
400
    unit->print(*unit_os);
 
401
    closeStream(dump_unit_file, unit_os);
 
402
  }
 
403
 
 
404
  // syntactic analysis
 
405
  log("syntactic analysis");
 
406
  Puma::CParser parser;
 
407
  std::ostream* trace_os = openStream(trace_parse_file);
 
408
  std::ostream* cpp_os = openStream(dump_cpp_file);
 
409
  if (trace_parse) {
 
410
#ifdef __PUMA_TRACING__
 
411
    parser.trace(*trace_os, verbose);
 
412
#endif
 
413
  }
 
414
  Puma::CTranslationUnit* file = parser.parse(*unit, project, dump_cpp, *cpp_os);
 
415
  closeStream(dump_cpp_file, cpp_os);
 
416
  closeStream(trace_parse_file, trace_os);
 
417
 
 
418
  // semantic analysis
 
419
  if (file && file->tree()) {
 
420
    log("semantic analysis");
 
421
    Puma::CSemVisitor semantics(err);
 
422
    semantics.run(file->tree());
 
423
  }
 
424
 
 
425
  return file;
 
426
}
 
427
 
 
428
 
 
429
Puma::CTranslationUnit* parseCCFile(Puma::ErrorStream& err, Puma::CProject& project) {
 
430
  // lexical analysis
 
431
  log("lexical analysis");
 
432
  Puma::Unit *unit = project.scanFile(input_file.c_str());
 
433
  if (! unit) {
 
434
    return 0;
 
435
  }
 
436
 
 
437
  // dump unit
 
438
  if (dump_unit) {
 
439
    std::ostream* unit_os = openStream(dump_unit_file);
 
440
    unit->print(*unit_os);
 
441
    closeStream(dump_unit_file, unit_os);
 
442
  }
 
443
 
 
444
  // syntactic analysis
 
445
  log("syntactic analysis");
 
446
  Puma::CCParser parser;
 
447
  std::ostream* trace_os = openStream(trace_parse_file);
 
448
  std::ostream* cpp_os = openStream(dump_cpp_file);
 
449
  if (trace_parse) {
 
450
#ifdef __PUMA_TRACING__
 
451
    parser.trace(*trace_os, verbose);
 
452
#endif
 
453
  }
 
454
  Puma::CTranslationUnit* file = parser.parse(*unit, project, dump_cpp, *cpp_os);
 
455
  closeStream(dump_cpp_file, cpp_os);
 
456
  closeStream(trace_parse_file, trace_os);
 
457
 
 
458
  // semantic analysis
 
459
  if (file && file->tree()) {
 
460
    log("semantic analysis");
 
461
    Puma::CCSemVisitor semantics(err);
 
462
    semantics.run(file->tree());
 
463
  }
 
464
 
 
465
  return file;
 
466
}
 
467
 
 
468
 
 
469
bool isDependent(Puma::CTree* node) {
 
470
  // check if any sub expression of a given expression
 
471
  // depends on a template parameter
 
472
  if (node->Type() && node->Type()->isDependent()) {
 
473
    return true;
 
474
  }
 
475
  // check the child nodes
 
476
  unsigned sons = node->Sons();
 
477
  for (unsigned i = 0; i < sons; ++i) {
 
478
    if (isDependent(node->Son(i))) {
 
479
      return true;
 
480
    }
 
481
  }
 
482
  return false;
 
483
}
 
484
 
 
485
 
 
486
std::string printTree(Puma::CTree* node) {
 
487
  // print the tokens of a sub-tree
 
488
  std::ostringstream s;
 
489
  Puma::Token* token = node->token();
 
490
  Puma::Token* end = node->end_token();
 
491
  if (token && end) {
 
492
    Puma::Unit* file = token->unit();
 
493
    while (token) {
 
494
      s << token->text();
 
495
      if (token == end) {
 
496
        break;
 
497
      }
 
498
      token = file->next(token);
 
499
    }
 
500
  }
 
501
  return s.str();
 
502
}
 
503
 
 
504
 
 
505
void walk(Puma::ErrorStream& err, Puma::CTree* node) {
 
506
  if (! node) {
 
507
    return;
 
508
  }
 
509
  // node indicating an error in the input file
 
510
  if (! node->Parent() && node->NodeName() != Puma::CT_Program::NodeId()) {
 
511
    printError(err, node, node->NodeName()+std::string(" node has no parent"));
 
512
  }
 
513
  // node indicating an error in the input file
 
514
  if (node->NodeName() == Puma::CT_Error::NodeId()) {
 
515
    printError(err, node, "error node found in tree");
 
516
  }
 
517
  // all expressions shall have a type
 
518
  else if (node->IsExpression() && ! node->Type()) {
 
519
    if (! isDependent(node)) {
 
520
      printError(err, node, "expression without type");
 
521
    }
 
522
  }
 
523
  // all expressions shall have a defined type
 
524
  else if (node->IsExpression() && node->Type()->is_undefined()) {
 
525
    if (! isDependent(node)) {
 
526
      printError(err, node, "expression with undefined type");
 
527
    }
 
528
  }
 
529
  // all symbols shall be resolved
 
530
  else if (node->IsSimpleName() && node->SemObject() && ! node->SemObject()->Object()) {
 
531
    if (! isDependent(node)) {
 
532
      printError(err, node, std::string("unresolved symbol "+printTree(node)));
 
533
    }
 
534
  }
 
535
  // walk over the child nodes
 
536
  else {
 
537
    unsigned int sons = node->Sons();
 
538
    for (unsigned i = 0; i < sons; ++i) {
 
539
      walk(err, node->Son(i));
 
540
    }
 
541
  }
 
542
}
 
543
 
 
544
 
 
545
int main(int argc, char **argv) {
 
546
  Puma::ErrorStream err;
 
547
  Puma::CProject project(err);
 
548
 
 
549
  evalOptions(project,argc,argv);
 
550
 
 
551
  // parse input file
 
552
  Puma::CTranslationUnit* file = 0;
 
553
  if (lang_c) {
 
554
    file = parseCFile(err,project);
 
555
  }
 
556
  else if (lang_cc) {
 
557
    file = parseCCFile(err,project);
 
558
  }
 
559
 
 
560
  // dump the syntax tree
 
561
  if (dump_tree && file && file->tree()) {
 
562
    log("dump syntax tree");
 
563
    std::ostream* tree_os = openStream(dump_tree_file);
 
564
    Puma::CPrintVisitor printer;
 
565
    printer.print(file->tree(), *tree_os);
 
566
    closeStream(dump_tree_file, tree_os);
 
567
  }
 
568
 
 
569
  // dump the preprocessor syntax tree
 
570
  if (dump_cpp_tree && file && file->cpp_tree()) {
 
571
    log("dump preprocessor syntax tree");
 
572
    std::ostream* tree_os = openStream(dump_cpp_tree_file);
 
573
    Puma::PrePrintVisitor printer(*tree_os);
 
574
    file->cpp_tree()->accept(printer);
 
575
    closeStream(dump_cpp_tree_file, tree_os);
 
576
  }
 
577
 
 
578
  // dump the semantic database
 
579
  if (dump_db && file) {
 
580
    log("dump semantic information database");
 
581
    std::ostream* db_os = openStream(dump_db_file);
 
582
    file->db().Dump(*db_os, 10, dump_db == 2);
 
583
    closeStream(dump_db_file, db_os);
 
584
  }
 
585
 
 
586
  // walk over the tree
 
587
  if (verify_tree && file && file->tree()) {
 
588
    log("verify syntax tree");
 
589
    walk(err, file->tree());
 
590
  }
 
591
 
 
592
  log("cleanup");
 
593
  if (file) {
 
594
    delete file;
 
595
  }
 
596
  return err.severity() > Puma::sev_warning;
 
597
}