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

View file

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