Program Listing for File quack_compiler.h¶
↰ Return to documentation for file (src/quack_compiler.h)
#ifndef PROJECT01_QUACKCOMPILER_H
#define PROJECT01_QUACKCOMPILER_H
#include <string>
#include <fstream>
#include <iostream>
#include "lex.yy.h"
#include "quack_program.h"
#include "quack_class.h"
#include "code_generator.h"
#include "type_checker.h"
#include "keywords.h"
#include "compiler_utils.h"
#include "messages.h"
namespace Quack {
class Compiler {
public:
Compiler() {
initialize();
}
~Compiler() {
for (const auto &prog : progs_)
delete prog;
}
void parse_args(unsigned int argc, char *argv[]) {
if (argc == 1) {
std::cerr << "Insufficient input arguments. At least one parameter required."
<< std::flush;
exit(EXIT_FAILURE);
}
int c;
while ((c = getopt(argc, argv, "t")) != -1) {
if (c == 't') {
std::cerr << "Warning: Running in debugging mode" << std::endl;
debug_ = true;
}
}
// Verify that there is at least one file to parse
unsigned int num_files = argc - optind;
if (num_files == 0) {
std::cerr << "No source files specified for parsing. At least one is required."
<< std::flush;
exit(EXIT_FAILURE);
}
input_files_.reserve(num_files);
progs_.reserve(num_files);
for (unsigned int i = 0; i < num_files; i++)
input_files_.emplace_back(argv[i + optind]);
}
void run() {
num_errs_ = 0;
for (const std::string &file_path : input_files_) {
Quack::Class::Container::reset();
std::ifstream f_in(file_path);
// If specified file does not exist, report an error then continue
if (!f_in) {
std::cerr << "Unable to locate input file: " << file_path << std::endl;
num_errs_++;
continue;
}
report::reset_error_count();
Quack::Program *prog = nullptr;
try {
prog = parse(f_in, file_path);
} catch (ScannerException &e) {
Quack::Utils::print_exception_info_and_exit(e, EXIT_SCANNER);
} catch (ParserException &e) {
Quack::Utils::print_exception_info_and_exit(e, EXIT_PARSER);
}
f_in.close();
if (report::ok()) {
progs_.emplace_back(prog);
}
auto type_checker = Quack::TypeChecker();
type_checker.run(prog);
CodeGen::Gen gen(prog, file_path);
gen.run();
}
}
void initialize() {
Class::Container *classes = Class::Container::singleton();
if (classes->empty()) {
classes->add(new ObjectClass());
classes->add(new IntClass());
classes->add(new StringClass());
classes->add(new BooleanClass());
}
}
private:
Quack::Program* parse(std::istream &f_in, const std::string &file_path) {
yy::Lexer lexer(f_in);
Quack::Program *prog;
auto * parser = new yy::parser(lexer, &prog);
if (parser->parse() != 0 || !report::ok()) {
report::bail();
} else {
std::cout << "Parse successful for file: " << file_path << std::endl;
if (debug_)
prog->print_original_src();
}
delete parser;
return prog;
}
bool debug_ = false;
std::vector<std::string> input_files_;
std::vector<Quack::Program *> progs_;
unsigned int num_errs_ = 0;
};
}
#endif //PROJECT01_QUACKCOMPILER_H