Shader: Fixes some errors and add unit tests
This commit is contained in:
parent
1c7a3a96e5
commit
aa43db956c
|
|
@ -40,7 +40,7 @@ namespace Nz::ShaderLang
|
|||
{
|
||||
public:
|
||||
inline Error(SourceLocation sourceLocation, ErrorCategory errorCategory, ErrorType errorType) noexcept;
|
||||
Error(const Error&) = delete;
|
||||
Error(const Error&) = default;
|
||||
Error(Error&&) noexcept = default;
|
||||
~Error() = default;
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ namespace Nz::ShaderLang
|
|||
|
||||
const char* what() const noexcept override;
|
||||
|
||||
Error& operator=(const Error&) = delete;
|
||||
Error& operator=(const Error&) = default;
|
||||
Error& operator=(Error&&) noexcept = default;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -118,14 +118,14 @@ namespace Nz::ShaderLang
|
|||
sourceFile = *m_sourceLocation.file;
|
||||
|
||||
if (m_sourceLocation.startLine != m_sourceLocation.endLine)
|
||||
m_errorMessage = fmt::format("{}({} -> {},{} -> {}): {} error {}: {}", sourceFile, m_sourceLocation.startLine, m_sourceLocation.endLine, m_sourceLocation.startColumn, m_sourceLocation.endColumn, m_errorCategory, m_errorType, BuildErrorMessage());
|
||||
m_errorMessage = fmt::format("{}({} -> {},{} -> {}): {} error: {}", sourceFile, m_sourceLocation.startLine, m_sourceLocation.endLine, m_sourceLocation.startColumn, m_sourceLocation.endColumn, m_errorType, BuildErrorMessage());
|
||||
else if (m_sourceLocation.startColumn != m_sourceLocation.endColumn)
|
||||
m_errorMessage = fmt::format("{}({},{} -> {}): {} error {}: {}", sourceFile, m_sourceLocation.startLine, m_sourceLocation.startColumn, m_sourceLocation.endColumn, m_errorCategory, m_errorType, BuildErrorMessage());
|
||||
m_errorMessage = fmt::format("{}({},{} -> {}): {} error: {}", sourceFile, m_sourceLocation.startLine, m_sourceLocation.startColumn, m_sourceLocation.endColumn, m_errorType, BuildErrorMessage());
|
||||
else
|
||||
m_errorMessage = fmt::format("{}({}, {}): {} error {}: {}", sourceFile, m_sourceLocation.startLine, m_sourceLocation.startColumn, m_errorCategory, m_errorType, BuildErrorMessage());
|
||||
m_errorMessage = fmt::format("{}({}, {}): {} error: {}", sourceFile, m_sourceLocation.startLine, m_sourceLocation.startColumn, m_errorType, BuildErrorMessage());
|
||||
}
|
||||
else
|
||||
m_errorMessage = fmt::format("?: {} error {}: {}", m_errorCategory, m_errorType, BuildErrorMessage());
|
||||
m_errorMessage = fmt::format("?: {} error: {}", m_errorType, BuildErrorMessage());
|
||||
}
|
||||
|
||||
return m_errorMessage;
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ namespace Nz::ShaderLang
|
|||
}
|
||||
|
||||
token.location.endColumn = SafeCast<UInt32>(currentPos - lastLineFeed) + 1;
|
||||
token.location.endLine = currentLine;
|
||||
|
||||
if (floatingPoint)
|
||||
{
|
||||
|
|
@ -244,17 +245,18 @@ namespace Nz::ShaderLang
|
|||
{
|
||||
tokenType = TokenType::IntegerValue;
|
||||
|
||||
// avoid std::string_view operator[] assertions (if &str[currentPos + 1] is out of the string)
|
||||
const char* first = &str[start];
|
||||
const char* last = first + (currentPos - start + 1);
|
||||
|
||||
long long value;
|
||||
std::from_chars_result r = std::from_chars(&str[start], &str[currentPos + 1], value);
|
||||
if (r.ptr != &str[currentPos + 1])
|
||||
{
|
||||
if (r.ec == std::errc::result_out_of_range)
|
||||
throw LexerNumberOutOfRangeError{ token.location };
|
||||
|
||||
std::from_chars_result r = std::from_chars(first, last, value);
|
||||
if (r.ptr == last && r.ec == std::errc{})
|
||||
token.data = value;
|
||||
else if (r.ec == std::errc::result_out_of_range)
|
||||
throw LexerNumberOutOfRangeError{ token.location };
|
||||
else
|
||||
throw LexerBadNumberError{ token.location };
|
||||
}
|
||||
|
||||
token.data = value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -414,12 +416,13 @@ namespace Nz::ShaderLang
|
|||
case '\n':
|
||||
case '\r':
|
||||
token.location.endColumn = SafeCast<UInt32>(currentPos - lastLineFeed) + 1;
|
||||
token.location.endLine = currentLine;
|
||||
throw LexerUnfinishedStringError{ token.location };
|
||||
|
||||
case '\\':
|
||||
{
|
||||
currentPos++;
|
||||
char next = Peek();
|
||||
char next = Peek(0);
|
||||
switch (next)
|
||||
{
|
||||
case 'n': character = '\n'; break;
|
||||
|
|
@ -429,6 +432,7 @@ namespace Nz::ShaderLang
|
|||
case '\\': character = '\\'; break;
|
||||
default:
|
||||
token.location.endColumn = SafeCast<UInt32>(currentPos - lastLineFeed) + 1;
|
||||
token.location.endLine = currentLine;
|
||||
throw LexerUnrecognizedCharError{ token.location };
|
||||
}
|
||||
break;
|
||||
|
|
@ -469,7 +473,11 @@ namespace Nz::ShaderLang
|
|||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
token.location.endColumn = SafeCast<UInt32>(currentPos - lastLineFeed) + 1;
|
||||
token.location.endLine = currentLine;
|
||||
throw LexerUnrecognizedTokenError{ token.location };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@ namespace Nz::ShaderLang
|
|||
}
|
||||
|
||||
if (!moduleVersion.has_value())
|
||||
throw ParserMissingAttributeError{ moduleToken.location };
|
||||
throw ParserMissingAttributeError{ moduleToken.location, ShaderAst::AttributeType::LangVersion };
|
||||
|
||||
if (!moduleId)
|
||||
moduleId = Uuid::Generate();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
#include <Engine/Shader/ShaderUtils.hpp>
|
||||
#include <Nazara/Shader/ShaderLangParser.hpp>
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
TEST_CASE("errors", "[Shader]")
|
||||
{
|
||||
SECTION("Checking lexer errors")
|
||||
{
|
||||
CHECK_THROWS_WITH(Nz::ShaderLang::Tokenize("1x42"), "(1,1 -> 4): LBadNumber error: bad number");
|
||||
CHECK_THROWS_WITH(Nz::ShaderLang::Tokenize("123456789876543210123456789"), "(1,1 -> 27): LNumberOutOfRange error: number is out of range");
|
||||
CHECK_THROWS_WITH(Nz::ShaderLang::Tokenize("\"Hello world"), "(1,1 -> 13): LUnfinishedString error: unfinished string");
|
||||
CHECK_THROWS_WITH(Nz::ShaderLang::Tokenize(R"("hello \p")"), "(1,1 -> 9): LUnrecognizedChar error: unrecognized character");
|
||||
CHECK_THROWS_WITH(Nz::ShaderLang::Tokenize("$"), "(1, 1): LUnrecognizedToken error: unrecognized token");
|
||||
}
|
||||
|
||||
SECTION("Checking parser errors")
|
||||
{
|
||||
CHECK_THROWS_WITH(Nz::ShaderLang::Parse("nazara"), "(1,1 -> 6): PUnexpectedToken error: unexpected token Identifier");
|
||||
CHECK_THROWS_WITH(Nz::ShaderLang::Parse("module;"), "(1,1 -> 6): PMissingAttribute error: missing attribute nzsl_version");
|
||||
CHECK_THROWS_WITH(Nz::ShaderLang::Parse("[nzsl_version] module;"), "(1,2 -> 13): PAttributeMissingParameter error: attribute nzsl_version requires a parameter");
|
||||
CHECK_THROWS_WITH(Nz::ShaderLang::Parse("[nzsl_version(\"1.0\"), nzsl_version(\"1.0\")] module;"), "(1,23 -> 41): PAttributeMultipleUnique error: attribute nzsl_version can only be present once");
|
||||
CHECK_THROWS_WITH(Nz::ShaderLang::Parse("[nzsl_version(\"1.0\"), uuid(\"Nazara\")] module;"), "(1,23 -> 36): PInvalidUuid error: \"Nazara\" is not a valid UUID");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue