#include "icode.hpp" #include "parser.hpp" #include <cstdlib> #include <fstream> #include <iostream> #include <sstream> std::string removeComments(const std::string &text) { std::ostringstream stream; enum State { CODE, BRACE_COMMENT, PAREN_COMMENT, STRING }; State state = CODE; for (size_t i = 0; i < text.length(); ++i) { char c = text[i]; char next = (i + 1 < text.length()) ? text[i + 1] : '\0'; switch (state) { case CODE: if (c == '{') { state = BRACE_COMMENT; } else if (c == '(' && next == '*') { state = PAREN_COMMENT; i++; } else if (c == '\'') { stream << c; state = STRING; } else if (c == '/' && next == '/') { while (i < text.length() && text[i] != '\n') { i++; } if (i < text.length()) { stream << '\n'; } } else { stream << c; } break; case BRACE_COMMENT: if (c == '}') { state = CODE; } break; case PAREN_COMMENT: if (c == '*' && next == ')') { state = CODE; i++; } break; case STRING: stream << c; if (c == '\'') { if (next == '\'') { stream << next; i++; } else { state = CODE; } } break; } } return stream.str(); } int main(int argc, char **argv) { try { std::string source; if (argc != 3) { std::cerr << "Error: requires two arguments input/output.\n"; return EXIT_FAILURE; } std::ifstream file(argv[1]); if (!file.is_open()) { std::cerr << "Error: Cannot open file " << argv[1] << std::endl; return 1; } std::ostringstream buffer; buffer << file.rdbuf(); if (buffer.str().empty()) { std::cerr << "mxx: file is empty\n"; return EXIT_FAILURE; } source = buffer.str(); pascal::PascalParser parser(removeComments(source)); if (!parser.validator.validate(argv[1])) { std::cerr << "mxx: validation failed.\n"; return EXIT_FAILURE; } auto ast = parser.parseProgram(); if (ast) { pascal::CodeGenVisitor emiter; emiter.generate(ast.get()); std::fstream file; file.open(argv[2], std::ios::out); if (!file.is_open()) { std::cerr << "Error could not open file: " << argv[2] << "\n"; } std::ostringstream output; emiter.writeTo(output); std::string opt = pascal::mxvmOpt(output.str()); file << opt << "\n"; file.close(); } } catch (const pascal::ParseException &e) { std::cerr << "Parse Error: " << e.what() << std::endl; return EXIT_FAILURE; } catch (const std::exception &e) { std::cerr << "Error: " << e.what() << std::endl; return EXIT_FAILURE; } catch (const scan::ScanExcept &e) { std::cerr << "Syntax Error: " << e.why() << std::endl; return EXIT_FAILURE; } return 0; }