schema_editor/comdel/parser/parse_context.cpp

119 lines
3.2 KiB
C++
Raw Normal View History

2022-05-27 06:18:17 +00:00
#include "parse_context.h"
2022-03-29 19:31:45 +00:00
#include "assert.h"
#include <iostream>
#include <iomanip>
#include <cmath>
2022-05-27 06:18:17 +00:00
ParseContext::ParseContext() {
2022-03-29 19:31:45 +00:00
applicationDir = std::string();
}
2022-05-27 06:18:17 +00:00
unsigned ParseContext::addFile(const std::string &fileName,
const std::string &source) {
fileMap.emplace_back(fileName, source);
2022-03-29 19:31:45 +00:00
return fileMap.size();
}
2022-05-27 06:18:17 +00:00
SourceFile &ParseContext::getFile(unsigned fileId) {
return fileMap[fileId - 1];
2022-03-29 19:31:45 +00:00
}
struct pad {
2022-05-27 06:18:17 +00:00
char ch;
int count;
2022-03-29 19:31:45 +00:00
pad(char ch, int count) : ch(ch), count(count) {}
};
2022-05-27 06:18:17 +00:00
std::ostream &operator<<(std::ostream &stream, const pad &p) {
2022-03-29 19:31:45 +00:00
for (int i = 0; i < p.count; i++) {
stream << p.ch;
}
return stream;
}
#define ATLAS_ASSERT(x) \
do {} while(0)
2022-05-27 06:18:17 +00:00
void ParseContext::formatError(const SourceError &sourceError,
std::ostream &stream,
const std::string &errorOrWarning) {
2022-03-29 19:31:45 +00:00
ATLAS_ASSERT(sourceError.span.lo.col != 0
&& sourceError.span.hi.col != 0);
2022-05-27 06:18:17 +00:00
stream << errorOrWarning << sourceError.message << std::endl;
2022-03-29 19:31:45 +00:00
Span span = sourceError.span;
// figure out how much padding is required for line numbers in front of
// printed source code
int numberPad = 0;
while (true) {
numberPad = std::max(numberPad,
static_cast<int>(ceil(log10(span.hi.line))) + 1);
break;
}
span = sourceError.span;
// print all spans
while (true) {
SourceFile sourceFile = getFile(span.lo.fileId);
// check if the span spans across multiple lines or even files
bool complex = span.lo.fileId != span.hi.fileId
|| span.lo.line != span.hi.line;
stream << pad(' ', numberPad) << " -> " << sourceFile.getFileName()
<< ":" << span.lo.line << ":" << span.lo.col << std::endl;
stream << pad(' ', numberPad) << " |" << std::endl
<< std::right << std::setw(numberPad) << span.lo.line << " | "
<< sourceFile.getLine(span.lo.line) << std::endl
<< pad(' ', numberPad) << " | ";
for (unsigned i = 0; i < span.lo.col - 1; i++) {
stream << ' ';
}
if (complex) {
// just point to the beginning of the span
stream << '^';
} else {
// underline the entire span
for (unsigned i = 0; i < span.hi.col - span.lo.col; i++) {
stream << '^';
}
}
stream << std::endl;
break;
}
stream << std::endl;
}
SourceFile::SourceFile(std::string fileName, std::string source)
2022-05-27 06:18:17 +00:00
: fileName(std::move(fileName)), source(std::move(source)) {
2022-03-29 19:31:45 +00:00
lineOffsets.push_back(0);
}
2022-05-27 06:18:17 +00:00
const std::string &SourceFile::getFileName() const {
2022-03-29 19:31:45 +00:00
return fileName;
}
2022-05-27 06:18:17 +00:00
std::string SourceFile::getLine(unsigned line) const {
auto lineOffset = lineOffsets[line - 1];
2022-03-29 19:31:45 +00:00
auto nextLF = source.find('\n', lineOffset);
auto nextCR = source.find('\r', lineOffset);
auto nl = std::min(nextCR, nextLF);
return source.substr(lineOffset, nl - lineOffset);
}
2022-05-27 06:18:17 +00:00
void SourceFile::addLineOffset(unsigned offset) {
2022-03-29 19:31:45 +00:00
lineOffsets.push_back(offset);
}