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:
|
public:
|
||||||
inline Error(SourceLocation sourceLocation, ErrorCategory errorCategory, ErrorType errorType) noexcept;
|
inline Error(SourceLocation sourceLocation, ErrorCategory errorCategory, ErrorType errorType) noexcept;
|
||||||
Error(const Error&) = delete;
|
Error(const Error&) = default;
|
||||||
Error(Error&&) noexcept = default;
|
Error(Error&&) noexcept = default;
|
||||||
~Error() = default;
|
~Error() = default;
|
||||||
|
|
||||||
|
|
@ -51,7 +51,7 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
const char* what() const noexcept override;
|
const char* what() const noexcept override;
|
||||||
|
|
||||||
Error& operator=(const Error&) = delete;
|
Error& operator=(const Error&) = default;
|
||||||
Error& operator=(Error&&) noexcept = default;
|
Error& operator=(Error&&) noexcept = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -118,14 +118,14 @@ namespace Nz::ShaderLang
|
||||||
sourceFile = *m_sourceLocation.file;
|
sourceFile = *m_sourceLocation.file;
|
||||||
|
|
||||||
if (m_sourceLocation.startLine != m_sourceLocation.endLine)
|
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)
|
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
|
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
|
else
|
||||||
m_errorMessage = fmt::format("?: {} error {}: {}", m_errorCategory, m_errorType, BuildErrorMessage());
|
m_errorMessage = fmt::format("?: {} error: {}", m_errorType, BuildErrorMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_errorMessage;
|
return m_errorMessage;
|
||||||
|
|
|
||||||
|
|
@ -224,6 +224,7 @@ namespace Nz::ShaderLang
|
||||||
}
|
}
|
||||||
|
|
||||||
token.location.endColumn = SafeCast<UInt32>(currentPos - lastLineFeed) + 1;
|
token.location.endColumn = SafeCast<UInt32>(currentPos - lastLineFeed) + 1;
|
||||||
|
token.location.endLine = currentLine;
|
||||||
|
|
||||||
if (floatingPoint)
|
if (floatingPoint)
|
||||||
{
|
{
|
||||||
|
|
@ -244,17 +245,18 @@ namespace Nz::ShaderLang
|
||||||
{
|
{
|
||||||
tokenType = TokenType::IntegerValue;
|
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;
|
long long value;
|
||||||
std::from_chars_result r = std::from_chars(&str[start], &str[currentPos + 1], value);
|
std::from_chars_result r = std::from_chars(first, last, value);
|
||||||
if (r.ptr != &str[currentPos + 1])
|
if (r.ptr == last && r.ec == std::errc{})
|
||||||
{
|
token.data = value;
|
||||||
if (r.ec == std::errc::result_out_of_range)
|
else if (r.ec == std::errc::result_out_of_range)
|
||||||
throw LexerNumberOutOfRangeError{ token.location };
|
throw LexerNumberOutOfRangeError{ token.location };
|
||||||
|
else
|
||||||
throw LexerBadNumberError{ token.location };
|
throw LexerBadNumberError{ token.location };
|
||||||
}
|
|
||||||
|
|
||||||
token.data = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -414,12 +416,13 @@ namespace Nz::ShaderLang
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
token.location.endColumn = SafeCast<UInt32>(currentPos - lastLineFeed) + 1;
|
token.location.endColumn = SafeCast<UInt32>(currentPos - lastLineFeed) + 1;
|
||||||
|
token.location.endLine = currentLine;
|
||||||
throw LexerUnfinishedStringError{ token.location };
|
throw LexerUnfinishedStringError{ token.location };
|
||||||
|
|
||||||
case '\\':
|
case '\\':
|
||||||
{
|
{
|
||||||
currentPos++;
|
currentPos++;
|
||||||
char next = Peek();
|
char next = Peek(0);
|
||||||
switch (next)
|
switch (next)
|
||||||
{
|
{
|
||||||
case 'n': character = '\n'; break;
|
case 'n': character = '\n'; break;
|
||||||
|
|
@ -429,6 +432,7 @@ namespace Nz::ShaderLang
|
||||||
case '\\': character = '\\'; break;
|
case '\\': character = '\\'; break;
|
||||||
default:
|
default:
|
||||||
token.location.endColumn = SafeCast<UInt32>(currentPos - lastLineFeed) + 1;
|
token.location.endColumn = SafeCast<UInt32>(currentPos - lastLineFeed) + 1;
|
||||||
|
token.location.endLine = currentLine;
|
||||||
throw LexerUnrecognizedCharError{ token.location };
|
throw LexerUnrecognizedCharError{ token.location };
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -469,7 +473,11 @@ namespace Nz::ShaderLang
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
token.location.endColumn = SafeCast<UInt32>(currentPos - lastLineFeed) + 1;
|
||||||
|
token.location.endLine = currentLine;
|
||||||
throw LexerUnrecognizedTokenError{ token.location };
|
throw LexerUnrecognizedTokenError{ token.location };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -285,7 +285,7 @@ namespace Nz::ShaderLang
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!moduleVersion.has_value())
|
if (!moduleVersion.has_value())
|
||||||
throw ParserMissingAttributeError{ moduleToken.location };
|
throw ParserMissingAttributeError{ moduleToken.location, ShaderAst::AttributeType::LangVersion };
|
||||||
|
|
||||||
if (!moduleId)
|
if (!moduleId)
|
||||||
moduleId = Uuid::Generate();
|
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