ErrorReporting.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #include "ErrorReporting.h"
  2. #include <map>
  3. #include <fstream>
  4. #include <sstream>
  5. using qlow::InternalError;
  6. using qlow::CompileError;
  7. using qlow::SyntaxError;
  8. using qlow::SemanticError;
  9. namespace qlow
  10. {
  11. void reportError(const CompileError& ce) noexcept
  12. {
  13. Printer& printer = Printer::getInstance();
  14. ce.print(printer);
  15. }
  16. void reportError(const std::string& msg) noexcept
  17. {
  18. Printer& printer = Printer::getInstance();
  19. printError(printer, msg);
  20. }
  21. void printError(Printer& printer, const std::string& msg) noexcept
  22. {
  23. printer.bold();
  24. printer.foreground(Printer::RED, true);
  25. printer << "error: ";
  26. printer.removeFormatting();
  27. printer << msg << std::endl;
  28. }
  29. void printError(Printer& printer, const std::string& msg, const CodePosition& cp) noexcept
  30. {
  31. printer.bold();
  32. printer << cp.getReportFormat() << ": "; //cp.filename << ":" << cp.first_line << ":" << cp.first_column << ": ";
  33. printer.foreground(Printer::RED, true);
  34. printer << "error: ";
  35. printer.removeFormatting();
  36. printer << msg << std::endl;
  37. }
  38. }
  39. std::string qlow::CodePosition::getReportFormat(void) const noexcept
  40. {
  41. std::ostringstream s;
  42. s << filename << ":" << first_line << ":" << first_column;
  43. return s.str();
  44. }
  45. void InternalError::print(Printer& printer) const noexcept
  46. {
  47. printError(printer, getMessage());
  48. printer <<
  49. "\n"
  50. "This kind of error isn't supposed to happen.\n\n"
  51. "Please submit a bug report to nicolas.winkler@gmx.ch\n"
  52. ;
  53. }
  54. const std::string& InternalError::getMessage(void) const noexcept
  55. {
  56. static std::map<ErrorCode, std::string> errors = {
  57. {ErrorCode::OUT_OF_MEMORY, "out of memory"},
  58. {ErrorCode::PARSER_INIT_FAILED, "parser initialization failed"},
  59. {ErrorCode::PARSER_DEST_FAILED, "parser destruction failed"},
  60. {ErrorCode::PARSER_FAILED, "parser failed"},
  61. {ErrorCode::PARSER_FAILED, "invalid type encountered"},
  62. };
  63. return errors.at(errorCode);
  64. }
  65. CompileError::~CompileError(void)
  66. {
  67. }
  68. // TODO rewrite more compact and more readable
  69. void CompileError::underlineError(Printer& printer) const noexcept
  70. {
  71. std::ifstream file(where.filename);
  72. if (!file)
  73. return;
  74. if (where.isMultiline()) {
  75. int lineNr = 1;
  76. while (lineNr < where.first_line) {
  77. if (file.get() == '\n') {
  78. lineNr++;
  79. }
  80. }
  81. std::string line;
  82. std::getline(file, line);
  83. int lineNrLength = std::to_string(lineNr).size();
  84. printer << "from here:" << std::endl;
  85. printer.foreground(Printer::Color::YELLOW, true);
  86. printer << lineNr;
  87. printer.removeFormatting();
  88. printer << ": " << line << std::endl;
  89. for (int i = 0; i < where.first_column + lineNrLength + 2; i++) {
  90. printer << ' ';
  91. }
  92. printer.foreground(Printer::Color::RED, true);
  93. for (size_t i = where.first_column; i < line.size(); i++) {
  94. printer << '^';
  95. }
  96. printer.removeFormatting();
  97. lineNr++;
  98. while (lineNr < where.last_line) {
  99. if (file.get() == '\n') {
  100. lineNr++;
  101. }
  102. }
  103. std::getline(file, line);
  104. lineNrLength = std::to_string(lineNr).size();
  105. printer << std::endl << "to here:" << std::endl;
  106. printer.foreground(Printer::Color::YELLOW, true);
  107. printer << lineNr;
  108. printer.removeFormatting();
  109. printer << ": " << line << std::endl;
  110. for (int i = 0; i < lineNrLength + 2; i++) {
  111. printer << ' ';
  112. }
  113. printer.foreground(Printer::Color::RED, true);
  114. for (int i = 0; i < where.last_column; i++) {
  115. printer << '^';
  116. }
  117. printer.removeFormatting();
  118. printer << std::endl;
  119. }
  120. else {
  121. int lineNr = 1;
  122. while (lineNr < where.first_line) {
  123. if (file.get() == '\n') {
  124. lineNr++;
  125. }
  126. }
  127. std::string line;
  128. std::getline(file, line);
  129. printer << line << std::endl;
  130. for (int i = 0; i < where.first_column; i++) {
  131. printer << ' ';
  132. }
  133. printer.foreground(Printer::Color::RED, true);
  134. for (int i = where.first_column; i < where.last_column; i++) {
  135. printer << '^';
  136. }
  137. printer.removeFormatting();
  138. printer << std::endl;
  139. }
  140. }
  141. void SyntaxError::print(Printer& printer) const noexcept
  142. {
  143. using namespace std::literals;
  144. if (message == "")
  145. printError(printer, "Syntax error", where);
  146. else
  147. printError(printer, "Syntax error: "s + message, where);
  148. underlineError(printer);
  149. }
  150. void SemanticError::print(Printer& printer) const noexcept
  151. {
  152. std::string errMsg = getMessage();
  153. printError(printer, errMsg + (errMsg != "" ? ": " : "") + message, where);
  154. underlineError(printer);
  155. }
  156. std::string SemanticError::getMessage(void) const noexcept
  157. {
  158. static const std::map<ErrorCode, std::string> error = {
  159. {UNKNOWN_TYPE, "unknown type"},
  160. {FEATURE_NOT_FOUND, "method or variable not found"},
  161. {DUPLICATE_CLASS_DEFINITION, "duplicate class definition"},
  162. {DUPLICATE_FIELD_DECLARATION, "duplicate field declaration"},
  163. {DUPLICATE_METHOD_DEFINITION, "duplicate method definition"},
  164. {OPERATOR_NOT_FOUND, ""},
  165. {WRONG_NUMBER_OF_ARGUMENTS, "wrong number of arguments passed"},
  166. };
  167. return error.at(errorCode);
  168. }
  169. SemanticError SemanticError::invalidReturnType(const std::string& should,
  170. const std::string& is, const CodePosition& where)
  171. {
  172. return SemanticError{ INVALID_RETURN_TYPE, "invalid return type: return type should be " +
  173. should + ", but " + is + " is given.", where };
  174. }