schema_editor/comdel/parser/parsecontext.cpp

129 lines
3.2 KiB
C++
Raw Permalink Normal View History

2022-03-29 19:31:45 +00:00
#include "parsecontext.h"
#include "assert.h"
#include <iostream>
#include <iomanip>
#include <cmath>
ParseContext::ParseContext()
{
applicationDir = std::string();
}
unsigned ParseContext::addFile(const std::string& fileName,
const std::string& source)
{
fileMap.push_back(SourceFile(fileName, source));
return fileMap.size();
}
SourceFile& ParseContext::getFile(unsigned fileId)
{
return fileMap[fileId-1];
}
struct pad {
char ch; int count;
pad(char ch, int count) : ch(ch), count(count) {}
};
std::ostream& operator<<(std::ostream& stream, const pad& p) {
for (int i = 0; i < p.count; i++) {
stream << p.ch;
}
return stream;
}
#define ATLAS_ASSERT(x) \
do {} while(0)
void ParseContext::formatError(const SourceError& sourceError,
std::ostream& stream,
const std::string& ErrorOrWarning)
{
ATLAS_ASSERT(sourceError.span.lo.col != 0
&& sourceError.span.hi.col != 0);
SourceFile sourceFile = getFile(sourceError.span.lo.fileId);
stream << ErrorOrWarning << sourceError.message << std::endl;
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)
: fileName(std::move(fileName)), source(std::move(source))
{
lineOffsets.push_back(0);
}
const std::string& SourceFile::getFileName() const
{
return fileName;
}
const std::string SourceFile::getLine(unsigned line) const
{
auto lineOffset = lineOffsets[line-1];
auto nextLF = source.find('\n', lineOffset);
auto nextCR = source.find('\r', lineOffset);
auto nl = std::min(nextCR, nextLF);
return source.substr(lineOffset, nl - lineOffset);
}
void SourceFile::addLineOffset(unsigned offset)
{
lineOffsets.push_back(offset);
}