Let the parser identify the origin of a failed #include

This commit is contained in:
Jean Pierre Cimalando 2020-03-28 02:11:20 +01:00
parent ba23ed810a
commit 3871d9c9b2
2 changed files with 19 additions and 9 deletions

View file

@ -49,7 +49,7 @@ void Parser::parseVirtualFile(const fs::path& path, std::unique_ptr<Reader> read
if (_listener)
_listener->onParseBegin();
includeNewFile(path, std::move(reader));
includeNewFile(path, std::move(reader), {});
processTopLevel();
flushCurrentHeader();
@ -57,7 +57,7 @@ void Parser::parseVirtualFile(const fs::path& path, std::unique_ptr<Reader> read
_listener->onParseEnd();
}
void Parser::includeNewFile(const fs::path& path, std::unique_ptr<Reader> reader)
void Parser::includeNewFile(const fs::path& path, std::unique_ptr<Reader> reader, const SourceRange& includeStmtRange)
{
fs::path fullPath =
(path.empty() || path.is_absolute()) ? path : _originalDirectory / path;
@ -69,10 +69,17 @@ void Parser::includeNewFile(const fs::path& path, std::unique_ptr<Reader> reader
return;
}
auto makeErrorRange = [&]() -> SourceRange {
if (!includeStmtRange) {
SourceLocation loc;
loc.filePath = std::make_shared<fs::path>(fullPath);
return {loc, loc};
}
return includeStmtRange;
};
if (_included.size() == _maxIncludeDepth) {
SourceLocation loc;
loc.filePath = std::make_shared<fs::path>(fullPath);
emitError({ loc, loc }, "Exceeded maximum include depth (" + std::to_string(_maxIncludeDepth) + ")");
emitError(makeErrorRange(), "Exceeded maximum include depth (" + std::to_string(_maxIncludeDepth) + ")");
return;
}
@ -80,7 +87,7 @@ void Parser::includeNewFile(const fs::path& path, std::unique_ptr<Reader> reader
auto fileReader = absl::make_unique<FileReader>(fullPath);
if (fileReader->hasError()) {
SourceLocation loc = fileReader->location();
emitError({ loc, loc }, "Cannot open file for reading: " + fullPath.string());
emitError(makeErrorRange(), "Cannot open file for reading: " + fullPath.string());
return;
}
reader = std::move(fileReader);
@ -159,15 +166,16 @@ void Parser::processDirective()
valid = reader.extractExactChar('"');
}
SourceLocation end = reader.location();
if (!valid) {
SourceLocation end = reader.location();
emitError({ start, end }, "Expected \"file.sfz\" after #include.");
recover();
return;
}
std::replace(path.begin(), path.end(), '\\', '/');
includeNewFile(path);
includeNewFile(path, nullptr, { start, end });
}
else {
SourceLocation end = reader.location();

View file

@ -63,7 +63,7 @@ public:
void setListener(Listener* listener) noexcept { _listener = listener; }
private:
void includeNewFile(const fs::path& path, std::unique_ptr<Reader> reader = nullptr);
void includeNewFile(const fs::path& path, std::unique_ptr<Reader> reader, const SourceRange& includeStmtRange);
void processTopLevel();
void processDirective();
void processHeader();
@ -122,6 +122,7 @@ struct SourceLocation {
std::shared_ptr<fs::path> filePath;
size_t lineNumber = 0;
size_t columnNumber = 0;
explicit operator bool() const noexcept { return filePath != nullptr; }
};
/**
@ -130,6 +131,7 @@ struct SourceLocation {
struct SourceRange {
SourceLocation start;
SourceLocation end;
explicit operator bool() const noexcept { return bool(start) && bool(end); }
};
} // namespace sfz