Shader: Fill SourceLocation info to AST when parsing
This commit is contained in:
parent
8429411755
commit
78f4751967
|
|
@ -198,7 +198,7 @@ namespace Nz::ShaderBuilder
|
||||||
{
|
{
|
||||||
inline ShaderAst::WhileStatementPtr operator()(ShaderAst::ExpressionPtr condition, ShaderAst::StatementPtr body) const;
|
inline ShaderAst::WhileStatementPtr operator()(ShaderAst::ExpressionPtr condition, ShaderAst::StatementPtr body) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Impl::AccessIndex AccessIndex;
|
constexpr Impl::AccessIndex AccessIndex;
|
||||||
constexpr Impl::AccessMember AccessMember;
|
constexpr Impl::AccessMember AccessMember;
|
||||||
|
|
|
||||||
|
|
@ -315,6 +315,7 @@ namespace Nz::ShaderBuilder
|
||||||
inline ShaderAst::ExpressionStatementPtr Impl::ExpressionStatement::operator()(ShaderAst::ExpressionPtr expression) const
|
inline ShaderAst::ExpressionStatementPtr Impl::ExpressionStatement::operator()(ShaderAst::ExpressionPtr expression) const
|
||||||
{
|
{
|
||||||
auto expressionStatementNode = std::make_unique<ShaderAst::ExpressionStatement>();
|
auto expressionStatementNode = std::make_unique<ShaderAst::ExpressionStatement>();
|
||||||
|
expressionStatementNode->sourceLocation = expression->sourceLocation;
|
||||||
expressionStatementNode->expression = std::move(expression);
|
expressionStatementNode->expression = std::move(expression);
|
||||||
|
|
||||||
return expressionStatementNode;
|
return expressionStatementNode;
|
||||||
|
|
@ -421,6 +422,7 @@ namespace Nz::ShaderBuilder
|
||||||
inline ShaderAst::ScopedStatementPtr Impl::Scoped::operator()(ShaderAst::StatementPtr statement) const
|
inline ShaderAst::ScopedStatementPtr Impl::Scoped::operator()(ShaderAst::StatementPtr statement) const
|
||||||
{
|
{
|
||||||
auto scopedNode = std::make_unique<ShaderAst::ScopedStatement>();
|
auto scopedNode = std::make_unique<ShaderAst::ScopedStatement>();
|
||||||
|
scopedNode->sourceLocation = statement->sourceLocation;
|
||||||
scopedNode->statement = std::move(statement);
|
scopedNode->statement = std::move(statement);
|
||||||
|
|
||||||
return scopedNode;
|
return scopedNode;
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ namespace Nz::ShaderLang
|
||||||
public:
|
public:
|
||||||
inline Error(SourceLocation sourceLocation, ErrorCategory errorCategory, unsigned int errorType) noexcept;
|
inline Error(SourceLocation sourceLocation, ErrorCategory errorCategory, unsigned int errorType) noexcept;
|
||||||
Error(const Error&) = delete;
|
Error(const Error&) = delete;
|
||||||
Error(Error&&) = delete;
|
Error(Error&&) noexcept = default;
|
||||||
~Error() = default;
|
~Error() = default;
|
||||||
|
|
||||||
inline ErrorCategory GetErrorCategory() const;
|
inline ErrorCategory GetErrorCategory() const;
|
||||||
|
|
@ -45,7 +45,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&) = delete;
|
||||||
Error& operator=(Error&&) = delete;
|
Error& operator=(Error&&) noexcept = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual std::string BuildErrorMessage() const = 0;
|
virtual std::string BuildErrorMessage() const = 0;
|
||||||
|
|
@ -82,7 +82,7 @@ namespace Nz::ShaderLang
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NAZARA_SHADERLANG_NEWERRORTYPE(Prefix, BaseClass, ErrorType, ErrorName, ErrorString, ...) \
|
#define NAZARA_SHADERLANG_NEWERRORTYPE(Prefix, BaseClass, ErrorType, ErrorName, ErrorString, ...) \
|
||||||
class Prefix ## ErrorName ## Error : public BaseClass \
|
class Prefix ## ErrorName ## Error final : public BaseClass \
|
||||||
{ \
|
{ \
|
||||||
public: \
|
public: \
|
||||||
template<typename... Args> Prefix ## ErrorName ## Error(SourceLocation sourceLocation, Args&&... args) : \
|
template<typename... Args> Prefix ## ErrorName ## Error(SourceLocation sourceLocation, Args&&... args) : \
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
#include <Nazara/Shader/Config.hpp>
|
#include <Nazara/Shader/Config.hpp>
|
||||||
|
#include <Nazara/Shader/ShaderLangSourceLocation.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -26,10 +27,8 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
struct Token
|
struct Token
|
||||||
{
|
{
|
||||||
unsigned int column;
|
SourceLocation location;
|
||||||
unsigned int line;
|
|
||||||
TokenType type;
|
TokenType type;
|
||||||
std::shared_ptr<const std::string> file;
|
|
||||||
std::variant<double, long long, std::string> data;
|
std::variant<double, long long, std::string> data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,13 @@ namespace Nz::ShaderLang
|
||||||
ShaderAst::ModulePtr Parse(const std::vector<Token>& tokens);
|
ShaderAst::ModulePtr Parse(const std::vector<Token>& tokens);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct Attribute
|
||||||
|
{
|
||||||
|
ShaderAst::AttributeType type;
|
||||||
|
ShaderAst::ExpressionPtr args;
|
||||||
|
SourceLocation sourceLocation;
|
||||||
|
};
|
||||||
|
|
||||||
// Flow control
|
// Flow control
|
||||||
const Token& Advance();
|
const Token& Advance();
|
||||||
void Consume(std::size_t count = 1);
|
void Consume(std::size_t count = 1);
|
||||||
|
|
@ -33,9 +40,9 @@ namespace Nz::ShaderLang
|
||||||
const Token& Expect(TokenType type);
|
const Token& Expect(TokenType type);
|
||||||
const Token& Peek(std::size_t advance = 0);
|
const Token& Peek(std::size_t advance = 0);
|
||||||
|
|
||||||
std::vector<ShaderAst::ExprValue> ParseAttributes();
|
std::vector<Attribute> ParseAttributes();
|
||||||
void ParseModuleStatement(std::vector<ShaderAst::ExprValue> attributes);
|
void ParseModuleStatement(std::vector<Attribute> attributes);
|
||||||
void ParseVariableDeclaration(std::string& name, ShaderAst::ExpressionValue<ShaderAst::ExpressionType>& type, ShaderAst::ExpressionPtr& initialValue);
|
void ParseVariableDeclaration(std::string& name, ShaderAst::ExpressionValue<ShaderAst::ExpressionType>& type, ShaderAst::ExpressionPtr& initialValue, SourceLocation& sourceLocation);
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr BuildIdentifierAccess(ShaderAst::ExpressionPtr lhs, ShaderAst::ExpressionPtr rhs);
|
ShaderAst::ExpressionPtr BuildIdentifierAccess(ShaderAst::ExpressionPtr lhs, ShaderAst::ExpressionPtr rhs);
|
||||||
ShaderAst::ExpressionPtr BuildIndexAccess(ShaderAst::ExpressionPtr lhs, ShaderAst::ExpressionPtr rhs);
|
ShaderAst::ExpressionPtr BuildIndexAccess(ShaderAst::ExpressionPtr lhs, ShaderAst::ExpressionPtr rhs);
|
||||||
|
|
@ -46,27 +53,26 @@ namespace Nz::ShaderLang
|
||||||
ShaderAst::StatementPtr ParseBranchStatement();
|
ShaderAst::StatementPtr ParseBranchStatement();
|
||||||
ShaderAst::StatementPtr ParseConstStatement();
|
ShaderAst::StatementPtr ParseConstStatement();
|
||||||
ShaderAst::StatementPtr ParseDiscardStatement();
|
ShaderAst::StatementPtr ParseDiscardStatement();
|
||||||
ShaderAst::StatementPtr ParseExternalBlock(std::vector<ShaderAst::ExprValue> attributes = {});
|
ShaderAst::StatementPtr ParseExternalBlock(std::vector<Attribute> attributes = {});
|
||||||
ShaderAst::StatementPtr ParseForDeclaration(std::vector<ShaderAst::ExprValue> attributes = {});
|
ShaderAst::StatementPtr ParseForDeclaration(std::vector<Attribute> attributes = {});
|
||||||
std::vector<ShaderAst::StatementPtr> ParseFunctionBody();
|
ShaderAst::StatementPtr ParseFunctionDeclaration(std::vector<Attribute> attributes = {});
|
||||||
ShaderAst::StatementPtr ParseFunctionDeclaration(std::vector<ShaderAst::ExprValue> attributes = {});
|
|
||||||
ShaderAst::DeclareFunctionStatement::Parameter ParseFunctionParameter();
|
ShaderAst::DeclareFunctionStatement::Parameter ParseFunctionParameter();
|
||||||
ShaderAst::StatementPtr ParseImportStatement();
|
ShaderAst::StatementPtr ParseImportStatement();
|
||||||
ShaderAst::StatementPtr ParseOptionDeclaration();
|
ShaderAst::StatementPtr ParseOptionDeclaration();
|
||||||
ShaderAst::StatementPtr ParseReturnStatement();
|
ShaderAst::StatementPtr ParseReturnStatement();
|
||||||
ShaderAst::StatementPtr ParseRootStatement(std::vector<ShaderAst::ExprValue> attributes = {});
|
ShaderAst::StatementPtr ParseRootStatement(std::vector<Attribute> attributes = {});
|
||||||
ShaderAst::StatementPtr ParseSingleStatement();
|
ShaderAst::StatementPtr ParseSingleStatement();
|
||||||
ShaderAst::StatementPtr ParseStatement();
|
ShaderAst::StatementPtr ParseStatement();
|
||||||
std::vector<ShaderAst::StatementPtr> ParseStatementList();
|
std::vector<ShaderAst::StatementPtr> ParseStatementList(SourceLocation* sourceLocation);
|
||||||
ShaderAst::StatementPtr ParseStructDeclaration(std::vector<ShaderAst::ExprValue> attributes = {});
|
ShaderAst::StatementPtr ParseStructDeclaration(std::vector<Attribute> attributes = {});
|
||||||
ShaderAst::StatementPtr ParseVariableDeclaration();
|
ShaderAst::StatementPtr ParseVariableDeclaration();
|
||||||
ShaderAst::StatementPtr ParseWhileStatement(std::vector<ShaderAst::ExprValue> attributes);
|
ShaderAst::StatementPtr ParseWhileStatement(std::vector<Attribute> attributes);
|
||||||
|
|
||||||
// Expressions
|
// Expressions
|
||||||
ShaderAst::ExpressionPtr ParseBinOpRhs(int exprPrecedence, ShaderAst::ExpressionPtr lhs);
|
ShaderAst::ExpressionPtr ParseBinOpRhs(int exprPrecedence, ShaderAst::ExpressionPtr lhs);
|
||||||
ShaderAst::ExpressionPtr ParseConstSelectExpression();
|
ShaderAst::ExpressionPtr ParseConstSelectExpression();
|
||||||
ShaderAst::ExpressionPtr ParseExpression();
|
ShaderAst::ExpressionPtr ParseExpression();
|
||||||
std::vector<ShaderAst::ExpressionPtr> ParseExpressionList(TokenType terminationToken);
|
std::vector<ShaderAst::ExpressionPtr> ParseExpressionList(TokenType terminationToken, SourceLocation* terminationLocation);
|
||||||
ShaderAst::ExpressionPtr ParseFloatingPointExpression();
|
ShaderAst::ExpressionPtr ParseFloatingPointExpression();
|
||||||
ShaderAst::ExpressionPtr ParseIdentifier();
|
ShaderAst::ExpressionPtr ParseIdentifier();
|
||||||
ShaderAst::ExpressionPtr ParseIntegerExpression();
|
ShaderAst::ExpressionPtr ParseIntegerExpression();
|
||||||
|
|
@ -75,8 +81,7 @@ namespace Nz::ShaderLang
|
||||||
ShaderAst::ExpressionPtr ParseStringExpression();
|
ShaderAst::ExpressionPtr ParseStringExpression();
|
||||||
ShaderAst::ExpressionPtr ParseVariableAssignation();
|
ShaderAst::ExpressionPtr ParseVariableAssignation();
|
||||||
|
|
||||||
ShaderAst::AttributeType ParseIdentifierAsAttributeType();
|
const std::string& ParseIdentifierAsName(SourceLocation* sourceLocation);
|
||||||
const std::string& ParseIdentifierAsName();
|
|
||||||
std::string ParseModuleName();
|
std::string ParseModuleName();
|
||||||
ShaderAst::ExpressionPtr ParseType();
|
ShaderAst::ExpressionPtr ParseType();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,13 @@ namespace Nz::ShaderLang
|
||||||
inline SourceLocation(unsigned int line, unsigned int startColumn, unsigned int endColumn, std::shared_ptr<const std::string> file);
|
inline SourceLocation(unsigned int line, unsigned int startColumn, unsigned int endColumn, std::shared_ptr<const std::string> file);
|
||||||
inline SourceLocation(unsigned int startLine, unsigned int endLine, unsigned int startColumn, unsigned int endColumn, std::shared_ptr<const std::string> file);
|
inline SourceLocation(unsigned int startLine, unsigned int endLine, unsigned int startColumn, unsigned int endColumn, std::shared_ptr<const std::string> file);
|
||||||
|
|
||||||
|
inline void ExtendToLeft(const SourceLocation& leftLocation);
|
||||||
|
inline void ExtendToRight(const SourceLocation& rightLocation);
|
||||||
|
|
||||||
inline bool IsValid() const;
|
inline bool IsValid() const;
|
||||||
|
|
||||||
|
static inline SourceLocation BuildFromTo(const SourceLocation& leftSource, const SourceLocation& rightSource);
|
||||||
|
|
||||||
std::shared_ptr<const std::string> file; //< Since the same file will be used for every node, prevent holding X time the same path
|
std::shared_ptr<const std::string> file; //< Since the same file will be used for every node, prevent holding X time the same path
|
||||||
UInt32 endColumn;
|
UInt32 endColumn;
|
||||||
UInt32 endLine;
|
UInt32 endLine;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Shader/ShaderLangSourceLocation.hpp>
|
#include <Nazara/Shader/ShaderLangSourceLocation.hpp>
|
||||||
|
#include <cassert>
|
||||||
#include <Nazara/Shader/Debug.hpp>
|
#include <Nazara/Shader/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz::ShaderLang
|
namespace Nz::ShaderLang
|
||||||
|
|
@ -42,6 +43,40 @@ namespace Nz::ShaderLang
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void SourceLocation::ExtendToLeft(const SourceLocation& leftLocation)
|
||||||
|
{
|
||||||
|
assert(file == leftLocation.file);
|
||||||
|
assert(leftLocation.startLine <= endLine);
|
||||||
|
startLine = leftLocation.startLine;
|
||||||
|
assert(leftLocation.startLine < endLine || leftLocation.startColumn <= endColumn);
|
||||||
|
startColumn = leftLocation.startColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SourceLocation::ExtendToRight(const SourceLocation& rightLocation)
|
||||||
|
{
|
||||||
|
assert(file == rightLocation.file);
|
||||||
|
assert(rightLocation.endLine >= startLine);
|
||||||
|
endLine = rightLocation.endLine;
|
||||||
|
assert(rightLocation.endLine > startLine || rightLocation.endColumn >= startColumn);
|
||||||
|
endColumn = endColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline SourceLocation SourceLocation::BuildFromTo(const SourceLocation& leftSource, const SourceLocation& rightSource)
|
||||||
|
{
|
||||||
|
assert(leftSource.file == rightSource.file);
|
||||||
|
assert(leftSource.startLine <= rightSource.endLine);
|
||||||
|
assert(leftSource.startLine < rightSource.endLine || leftSource.startColumn <= rightSource.endColumn);
|
||||||
|
|
||||||
|
SourceLocation sourceLoc;
|
||||||
|
sourceLoc.file = leftSource.file;
|
||||||
|
sourceLoc.startLine = leftSource.startLine;
|
||||||
|
sourceLoc.startColumn = leftSource.startColumn;
|
||||||
|
sourceLoc.endLine = rightSource.endLine;
|
||||||
|
sourceLoc.endColumn = rightSource.endColumn;
|
||||||
|
|
||||||
|
return sourceLoc;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool SourceLocation::IsValid() const
|
inline bool SourceLocation::IsValid() const
|
||||||
{
|
{
|
||||||
return startLine != 0 && endLine != 0 && endColumn != 0 && startColumn != 0;
|
return startLine != 0 && endLine != 0 && endColumn != 0 && startColumn != 0;
|
||||||
|
|
|
||||||
|
|
@ -460,7 +460,7 @@ namespace Nz::ShaderAst
|
||||||
if (newString)
|
if (newString)
|
||||||
{
|
{
|
||||||
Value(const_cast<std::string&>(*val)); //< won't be used for writing
|
Value(const_cast<std::string&>(*val)); //< won't be used for writing
|
||||||
m_stringIndices.emplace(*val, m_stringIndices.size());
|
m_stringIndices.emplace(*val, SafeCast<UInt32>(m_stringIndices.size()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Value(it->second); //< string index
|
Value(it->second); //< string index
|
||||||
|
|
|
||||||
|
|
@ -91,9 +91,9 @@ namespace Nz::ShaderLang
|
||||||
char c = Peek(0);
|
char c = Peek(0);
|
||||||
|
|
||||||
Token token;
|
Token token;
|
||||||
token.column = static_cast<unsigned int>(currentPos - lastLineFeed);
|
token.location.startColumn = static_cast<unsigned int>(currentPos - lastLineFeed);
|
||||||
token.file = currentFile;
|
token.location.startLine = lineNumber;
|
||||||
token.line = lineNumber;
|
token.location.file = currentFile;
|
||||||
|
|
||||||
if (c == '\0')
|
if (c == '\0')
|
||||||
{
|
{
|
||||||
|
|
@ -223,6 +223,8 @@ namespace Nz::ShaderLang
|
||||||
currentPos++;
|
currentPos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
token.location.endColumn = static_cast<unsigned int>(currentPos - lastLineFeed);
|
||||||
|
|
||||||
if (floatingPoint)
|
if (floatingPoint)
|
||||||
{
|
{
|
||||||
tokenType = TokenType::FloatingPointValue;
|
tokenType = TokenType::FloatingPointValue;
|
||||||
|
|
@ -234,10 +236,7 @@ namespace Nz::ShaderLang
|
||||||
char* end;
|
char* end;
|
||||||
double value = std::strtod(ptr, &end);
|
double value = std::strtod(ptr, &end);
|
||||||
if (end != &ptr[valueStr.size()])
|
if (end != &ptr[valueStr.size()])
|
||||||
{
|
throw LexerBadNumberError{ token.location };
|
||||||
unsigned int columnOffset = SafeCast<unsigned int>(end - ptr);
|
|
||||||
throw LexerBadNumberError{ SourceLocation{ token.line, token.column + columnOffset, token.file } };
|
|
||||||
}
|
|
||||||
|
|
||||||
token.data = value;
|
token.data = value;
|
||||||
}
|
}
|
||||||
|
|
@ -249,11 +248,10 @@ namespace Nz::ShaderLang
|
||||||
std::from_chars_result r = std::from_chars(&str[start], &str[currentPos + 1], value);
|
std::from_chars_result r = std::from_chars(&str[start], &str[currentPos + 1], value);
|
||||||
if (r.ptr != &str[currentPos + 1])
|
if (r.ptr != &str[currentPos + 1])
|
||||||
{
|
{
|
||||||
unsigned int columnOffset = SafeCast<unsigned int>(r.ptr - &str[start]);
|
|
||||||
if (r.ec == std::errc::result_out_of_range)
|
if (r.ec == std::errc::result_out_of_range)
|
||||||
throw LexerNumberOutOfRangeError{ SourceLocation{ token.line, token.column, token.column + columnOffset, token.file } };
|
throw LexerNumberOutOfRangeError{ token.location };
|
||||||
|
|
||||||
throw LexerBadNumberError{ SourceLocation{ token.line, token.column, token.column + columnOffset, token.file } };
|
throw LexerBadNumberError{ token.location };
|
||||||
}
|
}
|
||||||
|
|
||||||
token.data = value;
|
token.data = value;
|
||||||
|
|
@ -292,7 +290,7 @@ namespace Nz::ShaderLang
|
||||||
tokenType = TokenType::LogicalOr;
|
tokenType = TokenType::LogicalOr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw LexerUnrecognizedTokenError{ SourceLocation{ token.line, token.column, token.file } }; //< TODO: Add BOR (a | b)
|
throw LexerUnrecognizedTokenError{ token.location }; //< TODO: Add BOR (a | b)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -313,7 +311,7 @@ namespace Nz::ShaderLang
|
||||||
tokenType = TokenType::LogicalAnd;
|
tokenType = TokenType::LogicalAnd;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw LexerUnrecognizedTokenError{ SourceLocation{ token.line, token.column, token.file } }; //< TODO: Add BAND (a & b)
|
throw LexerUnrecognizedTokenError{ token.location }; //< TODO: Add BAND (a & b)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -415,7 +413,8 @@ namespace Nz::ShaderLang
|
||||||
case '\0':
|
case '\0':
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
throw LexerUnfinishedStringError{ SourceLocation{ token.line, SafeCast<unsigned int>(currentPos - lastLineFeed), token.file } };
|
token.location.endColumn = static_cast<unsigned int>(currentPos - lastLineFeed);
|
||||||
|
throw LexerUnfinishedStringError{ token.location };
|
||||||
|
|
||||||
case '\\':
|
case '\\':
|
||||||
{
|
{
|
||||||
|
|
@ -429,7 +428,8 @@ namespace Nz::ShaderLang
|
||||||
case '"': character = '"'; break;
|
case '"': character = '"'; break;
|
||||||
case '\\': character = '\\'; break;
|
case '\\': character = '\\'; break;
|
||||||
default:
|
default:
|
||||||
throw LexerUnrecognizedCharError{ SourceLocation{ token.line, SafeCast<unsigned int>(currentPos - lastLineFeed), token.file } };
|
token.location.endColumn = static_cast<unsigned int>(currentPos - lastLineFeed);
|
||||||
|
throw LexerUnrecognizedCharError{ token.location };
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -469,12 +469,14 @@ namespace Nz::ShaderLang
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw LexerUnrecognizedTokenError{ SourceLocation{ token.line, token.column, token.file } };
|
throw LexerUnrecognizedTokenError{ token.location };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokenType)
|
if (tokenType)
|
||||||
{
|
{
|
||||||
|
token.location.endColumn = static_cast<unsigned int>(currentPos - lastLineFeed);
|
||||||
|
token.location.endLine = lineNumber;
|
||||||
token.type = *tokenType;
|
token.type = *tokenType;
|
||||||
|
|
||||||
tokens.push_back(std::move(token));
|
tokens.push_back(std::move(token));
|
||||||
|
|
@ -503,16 +505,16 @@ namespace Nz::ShaderLang
|
||||||
if (tokens.empty())
|
if (tokens.empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
unsigned int lastLineNumber = tokens.front().line;
|
unsigned int lastLineNumber = tokens.front().location.startLine;
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
bool empty = true;
|
bool empty = true;
|
||||||
|
|
||||||
for (const Token& token : tokens)
|
for (const Token& token : tokens)
|
||||||
{
|
{
|
||||||
if (token.line != lastLineNumber && pretty)
|
if (token.location.startLine != lastLineNumber && pretty)
|
||||||
{
|
{
|
||||||
lastLineNumber = token.line;
|
lastLineNumber = token.location.startLine;
|
||||||
if (!empty)
|
if (!empty)
|
||||||
ss << '\n';
|
ss << '\n';
|
||||||
}
|
}
|
||||||
|
|
@ -534,6 +536,10 @@ namespace Nz::ShaderLang
|
||||||
ss << "(" << std::get<long long>(token.data) << ")";
|
ss << "(" << std::get<long long>(token.data) << ")";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TokenType::StringValue:
|
||||||
|
ss << "(\"" << std::get<std::string>(token.data) << "\")";
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,25 +59,6 @@ namespace Nz::ShaderLang
|
||||||
{ "never", ShaderAst::LoopUnroll::Never }
|
{ "never", ShaderAst::LoopUnroll::Never }
|
||||||
};
|
};
|
||||||
|
|
||||||
SourceLocation TokenLocation(const Token& token)
|
|
||||||
{
|
|
||||||
SourceLocation sourceLoc;
|
|
||||||
sourceLoc.file = token.file;
|
|
||||||
sourceLoc.startColumn = sourceLoc.endColumn = token.column;
|
|
||||||
sourceLoc.startLine = sourceLoc.endLine = token.line;
|
|
||||||
|
|
||||||
return sourceLoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExtendLocationToToken(SourceLocation& location, const Token& token)
|
|
||||||
{
|
|
||||||
assert(location.file == token.file);
|
|
||||||
assert(token.line >= location.startLine);
|
|
||||||
location.endLine = token.line;
|
|
||||||
assert(token.column >= location.startColumn);
|
|
||||||
location.endColumn = location.endColumn;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void HandleUniqueAttribute(ShaderAst::ExpressionValue<T>& targetAttribute, Parser::Attribute&& attribute)
|
void HandleUniqueAttribute(ShaderAst::ExpressionValue<T>& targetAttribute, Parser::Attribute&& attribute)
|
||||||
{
|
{
|
||||||
|
|
@ -148,7 +129,7 @@ namespace Nz::ShaderLang
|
||||||
if (!m_context->module)
|
if (!m_context->module)
|
||||||
{
|
{
|
||||||
const Token& nextToken = Peek();
|
const Token& nextToken = Peek();
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(nextToken) };
|
throw ParserUnexpectedTokenError{ nextToken.location };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!statement)
|
if (!statement)
|
||||||
|
|
@ -177,7 +158,7 @@ namespace Nz::ShaderLang
|
||||||
const Token& Parser::Expect(const Token& token, TokenType type)
|
const Token& Parser::Expect(const Token& token, TokenType type)
|
||||||
{
|
{
|
||||||
if (token.type != type)
|
if (token.type != type)
|
||||||
throw ParserExpectedTokenError{ TokenLocation(token), type, token.type };
|
throw ParserExpectedTokenError{ token.location, type, token.type };
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
@ -185,7 +166,7 @@ namespace Nz::ShaderLang
|
||||||
const Token& Parser::ExpectNot(const Token& token, TokenType type)
|
const Token& Parser::ExpectNot(const Token& token, TokenType type)
|
||||||
{
|
{
|
||||||
if (token.type == type)
|
if (token.type == type)
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token), type };
|
throw ParserUnexpectedTokenError{ token.location, type };
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
@ -235,11 +216,11 @@ namespace Nz::ShaderLang
|
||||||
const Token& identifierToken = Expect(Advance(), TokenType::Identifier);
|
const Token& identifierToken = Expect(Advance(), TokenType::Identifier);
|
||||||
const std::string& identifier = std::get<std::string>(identifierToken.data);
|
const std::string& identifier = std::get<std::string>(identifierToken.data);
|
||||||
|
|
||||||
SourceLocation attributeLocation = TokenLocation(identifierToken);
|
SourceLocation attributeLocation = identifierToken.location;
|
||||||
|
|
||||||
auto it = s_identifierToAttributeType.find(identifier);
|
auto it = s_identifierToAttributeType.find(identifier);
|
||||||
if (it == s_identifierToAttributeType.end())
|
if (it == s_identifierToAttributeType.end())
|
||||||
throw ParserUnknownAttributeError{ attributeLocation };
|
throw ParserUnknownAttributeError{ identifierToken.location };
|
||||||
|
|
||||||
ShaderAst::AttributeType attributeType = it->second;
|
ShaderAst::AttributeType attributeType = it->second;
|
||||||
|
|
||||||
|
|
@ -251,7 +232,7 @@ namespace Nz::ShaderLang
|
||||||
arg = ParseExpression();
|
arg = ParseExpression();
|
||||||
|
|
||||||
const Token& closeToken = Expect(Advance(), TokenType::ClosingParenthesis);
|
const Token& closeToken = Expect(Advance(), TokenType::ClosingParenthesis);
|
||||||
ExtendLocationToToken(attributeLocation, closeToken);
|
attributeLocation.ExtendToRight(closeToken.location);
|
||||||
}
|
}
|
||||||
|
|
||||||
expectComma = true;
|
expectComma = true;
|
||||||
|
|
@ -273,7 +254,7 @@ namespace Nz::ShaderLang
|
||||||
if (m_context->parsingImportedModule)
|
if (m_context->parsingImportedModule)
|
||||||
{
|
{
|
||||||
const Token& token = Peek();
|
const Token& token = Peek();
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token), token.type };
|
throw ParserUnexpectedTokenError{ token.location, token.type };
|
||||||
}
|
}
|
||||||
|
|
||||||
const Token& moduleToken = Expect(Advance(), TokenType::Module);
|
const Token& moduleToken = Expect(Advance(), TokenType::Module);
|
||||||
|
|
@ -355,7 +336,7 @@ namespace Nz::ShaderLang
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!moduleVersion.has_value())
|
if (!moduleVersion.has_value())
|
||||||
throw ParserMissingAttributeError{ TokenLocation(moduleToken) };
|
throw ParserMissingAttributeError{ moduleToken.location };
|
||||||
|
|
||||||
if (!moduleId)
|
if (!moduleId)
|
||||||
moduleId = Uuid::Generate();
|
moduleId = Uuid::Generate();
|
||||||
|
|
@ -376,7 +357,7 @@ namespace Nz::ShaderLang
|
||||||
if (!statement)
|
if (!statement)
|
||||||
{
|
{
|
||||||
const Token& token = Peek();
|
const Token& token = Peek();
|
||||||
throw ParserUnexpectedEndOfFileError{ TokenLocation(token) };
|
throw ParserUnexpectedEndOfFileError{ token.location };
|
||||||
}
|
}
|
||||||
|
|
||||||
module->rootNode->statements.push_back(std::move(statement));
|
module->rootNode->statements.push_back(std::move(statement));
|
||||||
|
|
@ -401,15 +382,15 @@ namespace Nz::ShaderLang
|
||||||
Expect(Advance(), TokenType::Semicolon);
|
Expect(Advance(), TokenType::Semicolon);
|
||||||
|
|
||||||
if (m_context->module)
|
if (m_context->module)
|
||||||
throw ParserDuplicateModuleError{ TokenLocation(moduleToken) };
|
throw ParserDuplicateModuleError{ moduleToken.location };
|
||||||
|
|
||||||
m_context->module = std::move(module);
|
m_context->module = std::move(module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::ParseVariableDeclaration(std::string& name, ShaderAst::ExpressionValue<ShaderAst::ExpressionType>& type, ShaderAst::ExpressionPtr& initialValue)
|
void Parser::ParseVariableDeclaration(std::string& name, ShaderAst::ExpressionValue<ShaderAst::ExpressionType>& type, ShaderAst::ExpressionPtr& initialValue, SourceLocation& sourceLocation)
|
||||||
{
|
{
|
||||||
name = ParseIdentifierAsName();
|
name = ParseIdentifierAsName(nullptr);
|
||||||
|
|
||||||
if (Peek().type == TokenType::Colon)
|
if (Peek().type == TokenType::Colon)
|
||||||
{
|
{
|
||||||
|
|
@ -424,40 +405,61 @@ namespace Nz::ShaderLang
|
||||||
initialValue = ParseExpression();
|
initialValue = ParseExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
Expect(Advance(), TokenType::Semicolon);
|
const Token& endToken = Expect(Advance(), TokenType::Semicolon);
|
||||||
|
sourceLocation.ExtendToRight(endToken.location);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::BuildIdentifierAccess(ShaderAst::ExpressionPtr lhs, ShaderAst::ExpressionPtr rhs)
|
ShaderAst::ExpressionPtr Parser::BuildIdentifierAccess(ShaderAst::ExpressionPtr lhs, ShaderAst::ExpressionPtr rhs)
|
||||||
{
|
{
|
||||||
if (rhs->GetType() == ShaderAst::NodeType::IdentifierExpression)
|
if (rhs->GetType() == ShaderAst::NodeType::IdentifierExpression)
|
||||||
return ShaderBuilder::AccessMember(std::move(lhs), { std::move(SafeCast<ShaderAst::IdentifierExpression&>(*rhs).identifier) });
|
{
|
||||||
|
SourceLocation location = SourceLocation::BuildFromTo(lhs->sourceLocation, rhs->sourceLocation);
|
||||||
|
|
||||||
|
auto accessMemberExpr = ShaderBuilder::AccessMember(std::move(lhs), { std::move(SafeCast<ShaderAst::IdentifierExpression&>(*rhs).identifier) });
|
||||||
|
accessMemberExpr->sourceLocation = std::move(location);
|
||||||
|
|
||||||
|
return accessMemberExpr;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return BuildIndexAccess(std::move(lhs), std::move(rhs));
|
return BuildIndexAccess(std::move(lhs), std::move(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::BuildIndexAccess(ShaderAst::ExpressionPtr lhs, ShaderAst::ExpressionPtr rhs)
|
ShaderAst::ExpressionPtr Parser::BuildIndexAccess(ShaderAst::ExpressionPtr lhs, ShaderAst::ExpressionPtr rhs)
|
||||||
{
|
{
|
||||||
return ShaderBuilder::AccessIndex(std::move(lhs), std::move(rhs));
|
SourceLocation location = SourceLocation::BuildFromTo(lhs->sourceLocation, rhs->sourceLocation);
|
||||||
|
|
||||||
|
auto accessIndexExpr = ShaderBuilder::AccessIndex(std::move(lhs), std::move(rhs));
|
||||||
|
accessIndexExpr->sourceLocation = std::move(location);
|
||||||
|
|
||||||
|
return accessIndexExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::BuildBinary(ShaderAst::BinaryType binaryType, ShaderAst::ExpressionPtr lhs, ShaderAst::ExpressionPtr rhs)
|
ShaderAst::ExpressionPtr Parser::BuildBinary(ShaderAst::BinaryType binaryType, ShaderAst::ExpressionPtr lhs, ShaderAst::ExpressionPtr rhs)
|
||||||
{
|
{
|
||||||
return ShaderBuilder::Binary(binaryType, std::move(lhs), std::move(rhs));
|
SourceLocation location = SourceLocation::BuildFromTo(lhs->sourceLocation, rhs->sourceLocation);
|
||||||
|
|
||||||
|
auto accessIndexExpr = ShaderBuilder::Binary(binaryType, std::move(lhs), std::move(rhs));
|
||||||
|
accessIndexExpr->sourceLocation = std::move(location);
|
||||||
|
|
||||||
|
return accessIndexExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseAliasDeclaration()
|
ShaderAst::StatementPtr Parser::ParseAliasDeclaration()
|
||||||
{
|
{
|
||||||
Expect(Advance(), TokenType::Alias);
|
const Token& aliasToken = Expect(Advance(), TokenType::Alias);
|
||||||
|
|
||||||
std::string name = ParseIdentifierAsName();
|
std::string name = ParseIdentifierAsName(nullptr);
|
||||||
|
|
||||||
Expect(Advance(), TokenType::Assign);
|
Expect(Advance(), TokenType::Assign);
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr expr = ParseExpression();
|
ShaderAst::ExpressionPtr expr = ParseExpression();
|
||||||
|
|
||||||
Expect(Advance(), TokenType::Semicolon);
|
const Token& endToken = Expect(Advance(), TokenType::Semicolon);
|
||||||
|
|
||||||
return ShaderBuilder::DeclareAlias(std::move(name), std::move(expr));
|
auto aliasStatement = ShaderBuilder::DeclareAlias(std::move(name), std::move(expr));
|
||||||
|
aliasStatement->sourceLocation = SourceLocation::BuildFromTo(aliasToken.location, endToken.location);
|
||||||
|
|
||||||
|
return aliasStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseBranchStatement()
|
ShaderAst::StatementPtr Parser::ParseBranchStatement()
|
||||||
|
|
@ -470,9 +472,11 @@ namespace Nz::ShaderLang
|
||||||
if (!first)
|
if (!first)
|
||||||
Expect(Advance(), TokenType::Else);
|
Expect(Advance(), TokenType::Else);
|
||||||
|
|
||||||
first = false;
|
const Token& ifToken = Expect(Advance(), TokenType::If);
|
||||||
|
if (first)
|
||||||
|
branch->sourceLocation = ifToken.location;
|
||||||
|
|
||||||
Expect(Advance(), TokenType::If);
|
first = false;
|
||||||
|
|
||||||
auto& condStatement = branch->condStatements.emplace_back();
|
auto& condStatement = branch->condStatements.emplace_back();
|
||||||
|
|
||||||
|
|
@ -483,6 +487,7 @@ namespace Nz::ShaderLang
|
||||||
Expect(Advance(), TokenType::ClosingParenthesis);
|
Expect(Advance(), TokenType::ClosingParenthesis);
|
||||||
|
|
||||||
condStatement.statement = ParseStatement();
|
condStatement.statement = ParseStatement();
|
||||||
|
branch->sourceLocation.ExtendToRight(condStatement.statement->sourceLocation);
|
||||||
|
|
||||||
if (Peek().type != TokenType::Else || Peek(1).type != TokenType::If)
|
if (Peek().type != TokenType::Else || Peek(1).type != TokenType::If)
|
||||||
break;
|
break;
|
||||||
|
|
@ -492,6 +497,7 @@ namespace Nz::ShaderLang
|
||||||
{
|
{
|
||||||
Consume();
|
Consume();
|
||||||
branch->elseStatement = ParseStatement();
|
branch->elseStatement = ParseStatement();
|
||||||
|
branch->sourceLocation.ExtendToRight(branch->elseStatement->sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
return branch;
|
return branch;
|
||||||
|
|
@ -499,7 +505,9 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseConstStatement()
|
ShaderAst::StatementPtr Parser::ParseConstStatement()
|
||||||
{
|
{
|
||||||
Expect(Advance(), TokenType::Const);
|
const Token& constToken = Expect(Advance(), TokenType::Const);
|
||||||
|
|
||||||
|
SourceLocation constLocation = constToken.location;
|
||||||
|
|
||||||
const Token& token = Peek();
|
const Token& token = Peek();
|
||||||
switch (token.type)
|
switch (token.type)
|
||||||
|
|
@ -510,30 +518,37 @@ namespace Nz::ShaderLang
|
||||||
ShaderAst::ExpressionValue<ShaderAst::ExpressionType> constType;
|
ShaderAst::ExpressionValue<ShaderAst::ExpressionType> constType;
|
||||||
ShaderAst::ExpressionPtr initialValue;
|
ShaderAst::ExpressionPtr initialValue;
|
||||||
|
|
||||||
ParseVariableDeclaration(constName, constType, initialValue);
|
ParseVariableDeclaration(constName, constType, initialValue, constLocation);
|
||||||
|
|
||||||
return ShaderBuilder::DeclareConst(std::move(constName), std::move(constType), std::move(initialValue));
|
auto constDeclaration = ShaderBuilder::DeclareConst(std::move(constName), std::move(constType), std::move(initialValue));
|
||||||
|
constDeclaration->sourceLocation = std::move(constLocation);
|
||||||
|
|
||||||
|
return constDeclaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TokenType::If:
|
case TokenType::If:
|
||||||
{
|
{
|
||||||
auto branch = ParseBranchStatement();
|
auto branch = ParseBranchStatement();
|
||||||
SafeCast<ShaderAst::BranchStatement&>(*branch).isConst = true;
|
SafeCast<ShaderAst::BranchStatement&>(*branch).isConst = true;
|
||||||
|
branch->sourceLocation.ExtendToLeft(constLocation);
|
||||||
|
|
||||||
return branch;
|
return branch;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token), token.type };
|
throw ParserUnexpectedTokenError{ token.location, token.type };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseDiscardStatement()
|
ShaderAst::StatementPtr Parser::ParseDiscardStatement()
|
||||||
{
|
{
|
||||||
Expect(Advance(), TokenType::Discard);
|
const Token& discardToken = Expect(Advance(), TokenType::Discard);
|
||||||
Expect(Advance(), TokenType::Semicolon);
|
const Token& endToken = Expect(Advance(), TokenType::Semicolon);
|
||||||
|
|
||||||
return ShaderBuilder::Discard();
|
auto discardStatement = ShaderBuilder::Discard();
|
||||||
|
discardStatement->sourceLocation = SourceLocation::BuildFromTo(discardToken.location, endToken.location);
|
||||||
|
|
||||||
|
return discardStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseExternalBlock(std::vector<Attribute> attributes)
|
ShaderAst::StatementPtr Parser::ParseExternalBlock(std::vector<Attribute> attributes)
|
||||||
|
|
@ -544,9 +559,7 @@ namespace Nz::ShaderLang
|
||||||
Expect(Advance(), TokenType::OpenCurlyBracket);
|
Expect(Advance(), TokenType::OpenCurlyBracket);
|
||||||
|
|
||||||
std::unique_ptr<ShaderAst::DeclareExternalStatement> externalStatement = std::make_unique<ShaderAst::DeclareExternalStatement>();
|
std::unique_ptr<ShaderAst::DeclareExternalStatement> externalStatement = std::make_unique<ShaderAst::DeclareExternalStatement>();
|
||||||
externalStatement->sourceLocation.startColumn = externalToken.column;
|
externalStatement->sourceLocation = externalToken.location;
|
||||||
externalStatement->sourceLocation.startLine = externalToken.line;
|
|
||||||
externalStatement->sourceLocation.file = externalToken.file;
|
|
||||||
|
|
||||||
ShaderAst::ExpressionValue<bool> condition;
|
ShaderAst::ExpressionValue<bool> condition;
|
||||||
|
|
||||||
|
|
@ -610,9 +623,13 @@ namespace Nz::ShaderLang
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extVar.name = ParseIdentifierAsName();
|
extVar.name = ParseIdentifierAsName(&extVar.sourceLocation);
|
||||||
Expect(Advance(), TokenType::Colon);
|
Expect(Advance(), TokenType::Colon);
|
||||||
extVar.type = ParseType();
|
|
||||||
|
auto typeExpr = ParseType();
|
||||||
|
extVar.sourceLocation.ExtendToRight(typeExpr->sourceLocation);
|
||||||
|
|
||||||
|
extVar.type = std::move(typeExpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expect(Advance(), TokenType::ClosingCurlyBracket);
|
Expect(Advance(), TokenType::ClosingCurlyBracket);
|
||||||
|
|
@ -629,7 +646,7 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
const Token& forToken = Expect(Advance(), TokenType::For);
|
const Token& forToken = Expect(Advance(), TokenType::For);
|
||||||
|
|
||||||
std::string varName = ParseIdentifierAsName();
|
std::string varName = ParseIdentifierAsName(nullptr);
|
||||||
|
|
||||||
Expect(Advance(), TokenType::In);
|
Expect(Advance(), TokenType::In);
|
||||||
|
|
||||||
|
|
@ -652,6 +669,7 @@ namespace Nz::ShaderLang
|
||||||
ShaderAst::StatementPtr statement = ParseStatement();
|
ShaderAst::StatementPtr statement = ParseStatement();
|
||||||
|
|
||||||
auto forNode = ShaderBuilder::For(std::move(varName), std::move(expr), std::move(toExpr), std::move(stepExpr), std::move(statement));
|
auto forNode = ShaderBuilder::For(std::move(varName), std::move(expr), std::move(toExpr), std::move(stepExpr), std::move(statement));
|
||||||
|
forNode->sourceLocation = SourceLocation::BuildFromTo(forToken.location, forNode->statement->sourceLocation);
|
||||||
|
|
||||||
// TODO: Deduplicate code
|
// TODO: Deduplicate code
|
||||||
for (auto&& attribute : attributes)
|
for (auto&& attribute : attributes)
|
||||||
|
|
@ -675,6 +693,7 @@ namespace Nz::ShaderLang
|
||||||
ShaderAst::StatementPtr statement = ParseStatement();
|
ShaderAst::StatementPtr statement = ParseStatement();
|
||||||
|
|
||||||
auto forEachNode = ShaderBuilder::ForEach(std::move(varName), std::move(expr), std::move(statement));
|
auto forEachNode = ShaderBuilder::ForEach(std::move(varName), std::move(expr), std::move(statement));
|
||||||
|
forEachNode->sourceLocation = SourceLocation::BuildFromTo(forToken.location, forEachNode->statement->sourceLocation);
|
||||||
|
|
||||||
// TODO: Deduplicate code
|
// TODO: Deduplicate code
|
||||||
for (auto&& attribute : attributes)
|
for (auto&& attribute : attributes)
|
||||||
|
|
@ -694,18 +713,13 @@ namespace Nz::ShaderLang
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ShaderAst::StatementPtr> Parser::ParseFunctionBody()
|
|
||||||
{
|
|
||||||
return ParseStatementList();
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseFunctionDeclaration(std::vector<Attribute> attributes)
|
ShaderAst::StatementPtr Parser::ParseFunctionDeclaration(std::vector<Attribute> attributes)
|
||||||
{
|
{
|
||||||
NAZARA_USE_ANONYMOUS_NAMESPACE
|
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||||
|
|
||||||
const auto& funcToken = Expect(Advance(), TokenType::FunctionDeclaration);
|
const auto& funcToken = Expect(Advance(), TokenType::FunctionDeclaration);
|
||||||
|
|
||||||
std::string functionName = ParseIdentifierAsName();
|
std::string functionName = ParseIdentifierAsName(nullptr);
|
||||||
|
|
||||||
Expect(Advance(), TokenType::OpenParenthesis);
|
Expect(Advance(), TokenType::OpenParenthesis);
|
||||||
|
|
||||||
|
|
@ -736,9 +750,13 @@ namespace Nz::ShaderLang
|
||||||
returnType = ParseType();
|
returnType = ParseType();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ShaderAst::StatementPtr> functionBody = ParseFunctionBody();
|
SourceLocation functionLocation;
|
||||||
|
std::vector<ShaderAst::StatementPtr> functionBody = ParseStatementList(&functionLocation);
|
||||||
|
|
||||||
|
functionLocation.ExtendToLeft(funcToken.location);
|
||||||
|
|
||||||
auto func = ShaderBuilder::DeclareFunction(std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType));
|
auto func = ShaderBuilder::DeclareFunction(std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType));
|
||||||
|
func->sourceLocation = std::move(functionLocation);
|
||||||
|
|
||||||
ShaderAst::ExpressionValue<bool> condition;
|
ShaderAst::ExpressionValue<bool> condition;
|
||||||
|
|
||||||
|
|
@ -781,31 +799,37 @@ namespace Nz::ShaderLang
|
||||||
{
|
{
|
||||||
ShaderAst::DeclareFunctionStatement::Parameter parameter;
|
ShaderAst::DeclareFunctionStatement::Parameter parameter;
|
||||||
|
|
||||||
parameter.name = ParseIdentifierAsName();
|
parameter.name = ParseIdentifierAsName(¶meter.sourceLocation);
|
||||||
|
|
||||||
Expect(Advance(), TokenType::Colon);
|
Expect(Advance(), TokenType::Colon);
|
||||||
|
|
||||||
parameter.type = ParseType();
|
auto typeExpr = ParseType();
|
||||||
|
parameter.sourceLocation.ExtendToRight(typeExpr->sourceLocation);
|
||||||
|
|
||||||
|
parameter.type = std::move(typeExpr);
|
||||||
|
|
||||||
return parameter;
|
return parameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseImportStatement()
|
ShaderAst::StatementPtr Parser::ParseImportStatement()
|
||||||
{
|
{
|
||||||
Expect(Advance(), TokenType::Import);
|
const Token& importToken = Expect(Advance(), TokenType::Import);
|
||||||
|
|
||||||
std::string moduleName = ParseModuleName();
|
std::string moduleName = ParseModuleName();
|
||||||
|
|
||||||
Expect(Advance(), TokenType::Semicolon);
|
const Token& endtoken = Expect(Advance(), TokenType::Semicolon);
|
||||||
|
|
||||||
return ShaderBuilder::Import(std::move(moduleName));
|
auto importStatement = ShaderBuilder::Import(std::move(moduleName));
|
||||||
|
importStatement->sourceLocation = SourceLocation::BuildFromTo(importToken.location, endtoken.location);
|
||||||
|
|
||||||
|
return importStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseOptionDeclaration()
|
ShaderAst::StatementPtr Parser::ParseOptionDeclaration()
|
||||||
{
|
{
|
||||||
Expect(Advance(), TokenType::Option);
|
const Token& optionToken = Expect(Advance(), TokenType::Option);
|
||||||
|
|
||||||
std::string optionName = ParseIdentifierAsName();
|
std::string optionName = ParseIdentifierAsName(nullptr);
|
||||||
|
|
||||||
Expect(Advance(), TokenType::Colon);
|
Expect(Advance(), TokenType::Colon);
|
||||||
|
|
||||||
|
|
@ -819,22 +843,28 @@ namespace Nz::ShaderLang
|
||||||
initialValue = ParseExpression();
|
initialValue = ParseExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
Expect(Advance(), TokenType::Semicolon);
|
const Token& endToken = Expect(Advance(), TokenType::Semicolon);
|
||||||
|
|
||||||
return ShaderBuilder::DeclareOption(std::move(optionName), std::move(optionType), std::move(initialValue));
|
auto optionDeclarationStatement = ShaderBuilder::DeclareOption(std::move(optionName), std::move(optionType), std::move(initialValue));
|
||||||
|
optionDeclarationStatement->sourceLocation = SourceLocation::BuildFromTo(optionToken.location, endToken.location);
|
||||||
|
|
||||||
|
return optionDeclarationStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseReturnStatement()
|
ShaderAst::StatementPtr Parser::ParseReturnStatement()
|
||||||
{
|
{
|
||||||
Expect(Advance(), TokenType::Return);
|
const Token& returnToken = Expect(Advance(), TokenType::Return);
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr expr;
|
ShaderAst::ExpressionPtr expr;
|
||||||
if (Peek().type != TokenType::Semicolon)
|
if (Peek().type != TokenType::Semicolon)
|
||||||
expr = ParseExpression();
|
expr = ParseExpression();
|
||||||
|
|
||||||
Expect(Advance(), TokenType::Semicolon);
|
const Token& endToken = Expect(Advance(), TokenType::Semicolon);
|
||||||
|
|
||||||
return ShaderBuilder::Return(std::move(expr));
|
auto returnStatement = ShaderBuilder::Return(std::move(expr));
|
||||||
|
returnStatement->sourceLocation = SourceLocation::BuildFromTo(returnToken.location, endToken.location);
|
||||||
|
|
||||||
|
return returnStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseRootStatement(std::vector<Attribute> attributes)
|
ShaderAst::StatementPtr Parser::ParseRootStatement(std::vector<Attribute> attributes)
|
||||||
|
|
@ -844,19 +874,19 @@ namespace Nz::ShaderLang
|
||||||
{
|
{
|
||||||
case TokenType::Alias:
|
case TokenType::Alias:
|
||||||
if (!attributes.empty())
|
if (!attributes.empty())
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(nextToken), nextToken.type };
|
throw ParserUnexpectedTokenError{ nextToken.location, nextToken.type };
|
||||||
|
|
||||||
return ParseAliasDeclaration();
|
return ParseAliasDeclaration();
|
||||||
|
|
||||||
case TokenType::Const:
|
case TokenType::Const:
|
||||||
if (!attributes.empty())
|
if (!attributes.empty())
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(nextToken), nextToken.type };
|
throw ParserUnexpectedTokenError{ nextToken.location, nextToken.type };
|
||||||
|
|
||||||
return ParseConstStatement();
|
return ParseConstStatement();
|
||||||
|
|
||||||
case TokenType::EndOfStream:
|
case TokenType::EndOfStream:
|
||||||
if (!attributes.empty())
|
if (!attributes.empty())
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(nextToken), nextToken.type };
|
throw ParserUnexpectedTokenError{ nextToken.location, nextToken.type };
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
|
@ -865,7 +895,7 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
case TokenType::Import:
|
case TokenType::Import:
|
||||||
if (!attributes.empty())
|
if (!attributes.empty())
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(nextToken), nextToken.type };
|
throw ParserUnexpectedTokenError{ nextToken.location, nextToken.type };
|
||||||
|
|
||||||
return ParseImportStatement();
|
return ParseImportStatement();
|
||||||
|
|
||||||
|
|
@ -880,7 +910,7 @@ namespace Nz::ShaderLang
|
||||||
case TokenType::Option:
|
case TokenType::Option:
|
||||||
{
|
{
|
||||||
if (!attributes.empty())
|
if (!attributes.empty())
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(nextToken), nextToken.type };
|
throw ParserUnexpectedTokenError{ nextToken.location, nextToken.type };
|
||||||
|
|
||||||
return ParseOptionDeclaration();
|
return ParseOptionDeclaration();
|
||||||
}
|
}
|
||||||
|
|
@ -892,7 +922,7 @@ namespace Nz::ShaderLang
|
||||||
return ParseStructDeclaration(std::move(attributes));
|
return ParseStructDeclaration(std::move(attributes));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(nextToken), nextToken.type };
|
throw ParserUnexpectedTokenError{ nextToken.location, nextToken.type };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -907,14 +937,14 @@ namespace Nz::ShaderLang
|
||||||
{
|
{
|
||||||
case TokenType::Const:
|
case TokenType::Const:
|
||||||
if (!attributes.empty())
|
if (!attributes.empty())
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token), token.type };
|
throw ParserUnexpectedTokenError{ token.location, token.type };
|
||||||
|
|
||||||
statement = ParseConstStatement();
|
statement = ParseConstStatement();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TokenType::Discard:
|
case TokenType::Discard:
|
||||||
if (!attributes.empty())
|
if (!attributes.empty())
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token), token.type };
|
throw ParserUnexpectedTokenError{ token.location, token.type };
|
||||||
|
|
||||||
statement = ParseDiscardStatement();
|
statement = ParseDiscardStatement();
|
||||||
break;
|
break;
|
||||||
|
|
@ -926,14 +956,14 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
case TokenType::Let:
|
case TokenType::Let:
|
||||||
if (!attributes.empty())
|
if (!attributes.empty())
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token), token.type };
|
throw ParserUnexpectedTokenError{ token.location, token.type };
|
||||||
|
|
||||||
statement = ParseVariableDeclaration();
|
statement = ParseVariableDeclaration();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TokenType::Identifier:
|
case TokenType::Identifier:
|
||||||
if (!attributes.empty())
|
if (!attributes.empty())
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token), token.type };
|
throw ParserUnexpectedTokenError{ token.location, token.type };
|
||||||
|
|
||||||
statement = ShaderBuilder::ExpressionStatement(ParseVariableAssignation());
|
statement = ShaderBuilder::ExpressionStatement(ParseVariableAssignation());
|
||||||
Expect(Advance(), TokenType::Semicolon);
|
Expect(Advance(), TokenType::Semicolon);
|
||||||
|
|
@ -941,7 +971,7 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
case TokenType::If:
|
case TokenType::If:
|
||||||
if (!attributes.empty())
|
if (!attributes.empty())
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token), token.type };
|
throw ParserUnexpectedTokenError{ token.location, token.type };
|
||||||
|
|
||||||
statement = ParseBranchStatement();
|
statement = ParseBranchStatement();
|
||||||
break;
|
break;
|
||||||
|
|
@ -953,7 +983,7 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
case TokenType::Return:
|
case TokenType::Return:
|
||||||
if (!attributes.empty())
|
if (!attributes.empty())
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token), token.type };
|
throw ParserUnexpectedTokenError{ token.location, token.type };
|
||||||
|
|
||||||
statement = ParseReturnStatement();
|
statement = ParseReturnStatement();
|
||||||
break;
|
break;
|
||||||
|
|
@ -964,7 +994,7 @@ namespace Nz::ShaderLang
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token), token.type };
|
throw ParserUnexpectedTokenError{ token.location, token.type };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!statement); //< small trick to repeat parsing once we got attributes
|
while (!statement); //< small trick to repeat parsing once we got attributes
|
||||||
|
|
@ -975,14 +1005,19 @@ namespace Nz::ShaderLang
|
||||||
ShaderAst::StatementPtr Parser::ParseStatement()
|
ShaderAst::StatementPtr Parser::ParseStatement()
|
||||||
{
|
{
|
||||||
if (Peek().type == TokenType::OpenCurlyBracket)
|
if (Peek().type == TokenType::OpenCurlyBracket)
|
||||||
return ShaderBuilder::Scoped(ShaderBuilder::MultiStatement(ParseStatementList()));
|
{
|
||||||
|
auto multiStatement = ShaderBuilder::MultiStatement();
|
||||||
|
multiStatement->statements = ParseStatementList(&multiStatement->sourceLocation);
|
||||||
|
|
||||||
|
return ShaderBuilder::Scoped(std::move(multiStatement));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return ParseSingleStatement();
|
return ParseSingleStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ShaderAst::StatementPtr> Parser::ParseStatementList()
|
std::vector<ShaderAst::StatementPtr> Parser::ParseStatementList(SourceLocation* sourceLocation)
|
||||||
{
|
{
|
||||||
Expect(Advance(), TokenType::OpenCurlyBracket);
|
const Token& openToken = Expect(Advance(), TokenType::OpenCurlyBracket);
|
||||||
|
|
||||||
std::vector<ShaderAst::StatementPtr> statements;
|
std::vector<ShaderAst::StatementPtr> statements;
|
||||||
while (Peek().type != TokenType::ClosingCurlyBracket)
|
while (Peek().type != TokenType::ClosingCurlyBracket)
|
||||||
|
|
@ -990,7 +1025,10 @@ namespace Nz::ShaderLang
|
||||||
ExpectNot(Peek(), TokenType::EndOfStream);
|
ExpectNot(Peek(), TokenType::EndOfStream);
|
||||||
statements.push_back(ParseStatement());
|
statements.push_back(ParseStatement());
|
||||||
}
|
}
|
||||||
Consume(); //< Consume closing curly bracket
|
const Token& closeToken = Expect(Advance(), TokenType::ClosingCurlyBracket);
|
||||||
|
|
||||||
|
if (sourceLocation)
|
||||||
|
*sourceLocation = SourceLocation::BuildFromTo(openToken.location, closeToken.location);
|
||||||
|
|
||||||
return statements;
|
return statements;
|
||||||
}
|
}
|
||||||
|
|
@ -1002,7 +1040,7 @@ namespace Nz::ShaderLang
|
||||||
const auto& structToken = Expect(Advance(), TokenType::Struct);
|
const auto& structToken = Expect(Advance(), TokenType::Struct);
|
||||||
|
|
||||||
ShaderAst::StructDescription description;
|
ShaderAst::StructDescription description;
|
||||||
description.name = ParseIdentifierAsName();
|
description.name = ParseIdentifierAsName(nullptr);
|
||||||
|
|
||||||
ShaderAst::ExpressionValue<bool> condition;
|
ShaderAst::ExpressionValue<bool> condition;
|
||||||
ShaderAst::ExpressionValue<bool> exported;
|
ShaderAst::ExpressionValue<bool> exported;
|
||||||
|
|
@ -1078,19 +1116,27 @@ namespace Nz::ShaderLang
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
structField.name = ParseIdentifierAsName();
|
structField.name = ParseIdentifierAsName(&structField.sourceLocation);
|
||||||
|
|
||||||
Expect(Advance(), TokenType::Colon);
|
Expect(Advance(), TokenType::Colon);
|
||||||
|
|
||||||
structField.type = ParseType();
|
structField.type = ParseType();
|
||||||
}
|
}
|
||||||
|
|
||||||
Expect(Advance(), TokenType::ClosingCurlyBracket);
|
const Token& endToken = Expect(Advance(), TokenType::ClosingCurlyBracket);
|
||||||
|
|
||||||
|
auto structDeclStatement = ShaderBuilder::DeclareStruct(std::move(description), std::move(exported));
|
||||||
|
structDeclStatement->sourceLocation = SourceLocation::BuildFromTo(structToken.location, endToken.location);
|
||||||
|
|
||||||
if (condition.HasValue())
|
if (condition.HasValue())
|
||||||
return ShaderBuilder::ConditionalStatement(std::move(condition).GetExpression(), ShaderBuilder::DeclareStruct(std::move(description), std::move(exported)));
|
{
|
||||||
|
auto condStatement = ShaderBuilder::ConditionalStatement(std::move(condition).GetExpression(), std::move(structDeclStatement));
|
||||||
|
condStatement->sourceLocation = condStatement->statement->sourceLocation;
|
||||||
|
|
||||||
|
return condStatement;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return ShaderBuilder::DeclareStruct(std::move(description), std::move(exported));
|
return structDeclStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::ParseVariableAssignation()
|
ShaderAst::ExpressionPtr Parser::ParseVariableAssignation()
|
||||||
|
|
@ -1113,7 +1159,7 @@ namespace Nz::ShaderLang
|
||||||
case TokenType::PlusAssign: assignType = ShaderAst::AssignType::CompoundAdd; break;
|
case TokenType::PlusAssign: assignType = ShaderAst::AssignType::CompoundAdd; break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token) };
|
throw ParserUnexpectedTokenError{ token.location };
|
||||||
}
|
}
|
||||||
|
|
||||||
Consume();
|
Consume();
|
||||||
|
|
@ -1121,20 +1167,28 @@ namespace Nz::ShaderLang
|
||||||
// Value expression
|
// Value expression
|
||||||
ShaderAst::ExpressionPtr right = ParseExpression();
|
ShaderAst::ExpressionPtr right = ParseExpression();
|
||||||
|
|
||||||
return ShaderBuilder::Assign(assignType, std::move(left), std::move(right));
|
auto assignExpr = ShaderBuilder::Assign(assignType, std::move(left), std::move(right));
|
||||||
|
assignExpr->sourceLocation = SourceLocation::BuildFromTo(assignExpr->left->sourceLocation, assignExpr->right->sourceLocation);
|
||||||
|
|
||||||
|
return assignExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseVariableDeclaration()
|
ShaderAst::StatementPtr Parser::ParseVariableDeclaration()
|
||||||
{
|
{
|
||||||
Expect(Advance(), TokenType::Let);
|
const auto& letToken = Expect(Advance(), TokenType::Let);
|
||||||
|
|
||||||
|
SourceLocation letLocation = letToken.location;
|
||||||
|
|
||||||
std::string variableName;
|
std::string variableName;
|
||||||
ShaderAst::ExpressionValue<ShaderAst::ExpressionType> variableType;
|
ShaderAst::ExpressionValue<ShaderAst::ExpressionType> variableType;
|
||||||
ShaderAst::ExpressionPtr expression;
|
ShaderAst::ExpressionPtr expression;
|
||||||
|
|
||||||
ParseVariableDeclaration(variableName, variableType, expression);
|
ParseVariableDeclaration(variableName, variableType, expression, letLocation);
|
||||||
|
|
||||||
return ShaderBuilder::DeclareVariable(std::move(variableName), std::move(variableType), std::move(expression));
|
auto variableDeclStatement = ShaderBuilder::DeclareVariable(std::move(variableName), std::move(variableType), std::move(expression));
|
||||||
|
variableDeclStatement->sourceLocation = std::move(letLocation);
|
||||||
|
|
||||||
|
return variableDeclStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseWhileStatement(std::vector<Attribute> attributes)
|
ShaderAst::StatementPtr Parser::ParseWhileStatement(std::vector<Attribute> attributes)
|
||||||
|
|
@ -1152,6 +1206,7 @@ namespace Nz::ShaderLang
|
||||||
ShaderAst::StatementPtr body = ParseStatement();
|
ShaderAst::StatementPtr body = ParseStatement();
|
||||||
|
|
||||||
auto whileStatement = ShaderBuilder::While(std::move(condition), std::move(body));
|
auto whileStatement = ShaderBuilder::While(std::move(condition), std::move(body));
|
||||||
|
whileStatement->sourceLocation = SourceLocation::BuildFromTo(whileToken.location, whileStatement->body->sourceLocation);
|
||||||
|
|
||||||
for (auto&& attribute : attributes)
|
for (auto&& attribute : attributes)
|
||||||
{
|
{
|
||||||
|
|
@ -1176,7 +1231,7 @@ namespace Nz::ShaderLang
|
||||||
const Token& token = Peek();
|
const Token& token = Peek();
|
||||||
TokenType currentTokenType = token.type;
|
TokenType currentTokenType = token.type;
|
||||||
if (currentTokenType == TokenType::EndOfStream)
|
if (currentTokenType == TokenType::EndOfStream)
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token), token.type };
|
throw ParserUnexpectedTokenError{ token.location, token.type };
|
||||||
|
|
||||||
int tokenPrecedence = GetTokenPrecedence(currentTokenType);
|
int tokenPrecedence = GetTokenPrecedence(currentTokenType);
|
||||||
if (tokenPrecedence < exprPrecedence)
|
if (tokenPrecedence < exprPrecedence)
|
||||||
|
|
@ -1187,8 +1242,10 @@ namespace Nz::ShaderLang
|
||||||
Consume();
|
Consume();
|
||||||
|
|
||||||
// Function call
|
// Function call
|
||||||
auto parameters = ParseExpressionList(TokenType::ClosingParenthesis);
|
SourceLocation closingLocation;
|
||||||
|
auto parameters = ParseExpressionList(TokenType::ClosingParenthesis, &closingLocation);
|
||||||
lhs = ShaderBuilder::CallFunction(std::move(lhs), std::move(parameters));
|
lhs = ShaderBuilder::CallFunction(std::move(lhs), std::move(parameters));
|
||||||
|
lhs->sourceLocation = SourceLocation::BuildFromTo(token.location, closingLocation);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1197,8 +1254,11 @@ namespace Nz::ShaderLang
|
||||||
Consume();
|
Consume();
|
||||||
|
|
||||||
// Indices
|
// Indices
|
||||||
auto parameters = ParseExpressionList(TokenType::ClosingSquareBracket);
|
SourceLocation closingLocation;
|
||||||
|
auto parameters = ParseExpressionList(TokenType::ClosingSquareBracket, &closingLocation);
|
||||||
|
|
||||||
lhs = ShaderBuilder::AccessIndex(std::move(lhs), std::move(parameters));
|
lhs = ShaderBuilder::AccessIndex(std::move(lhs), std::move(parameters));
|
||||||
|
lhs->sourceLocation = SourceLocation::BuildFromTo(token.location, closingLocation);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1231,7 +1291,7 @@ namespace Nz::ShaderLang
|
||||||
case TokenType::NotEqual: return BuildBinary(ShaderAst::BinaryType::CompNe, std::move(lhs), std::move(rhs));
|
case TokenType::NotEqual: return BuildBinary(ShaderAst::BinaryType::CompNe, std::move(lhs), std::move(rhs));
|
||||||
case TokenType::Plus: return BuildBinary(ShaderAst::BinaryType::Add, std::move(lhs), std::move(rhs));
|
case TokenType::Plus: return BuildBinary(ShaderAst::BinaryType::Add, std::move(lhs), std::move(rhs));
|
||||||
default:
|
default:
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token), token.type };
|
throw ParserUnexpectedTokenError{ token.location, token.type };
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
|
|
@ -1239,7 +1299,7 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::ParseConstSelectExpression()
|
ShaderAst::ExpressionPtr Parser::ParseConstSelectExpression()
|
||||||
{
|
{
|
||||||
Expect(Advance(), TokenType::ConstSelect);
|
const Token& constSelectToken = Expect(Advance(), TokenType::ConstSelect);
|
||||||
Expect(Advance(), TokenType::OpenParenthesis);
|
Expect(Advance(), TokenType::OpenParenthesis);
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr cond = ParseExpression();
|
ShaderAst::ExpressionPtr cond = ParseExpression();
|
||||||
|
|
@ -1252,9 +1312,12 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr falseExpr = ParseExpression();
|
ShaderAst::ExpressionPtr falseExpr = ParseExpression();
|
||||||
|
|
||||||
Expect(Advance(), TokenType::ClosingParenthesis);
|
const Token& closeToken = Expect(Advance(), TokenType::ClosingParenthesis);
|
||||||
|
|
||||||
return ShaderBuilder::ConditionalExpression(std::move(cond), std::move(trueExpr), std::move(falseExpr));
|
auto condExpr = ShaderBuilder::ConditionalExpression(std::move(cond), std::move(trueExpr), std::move(falseExpr));
|
||||||
|
condExpr->sourceLocation = SourceLocation::BuildFromTo(constSelectToken.location, closeToken.location);
|
||||||
|
|
||||||
|
return condExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::ParseExpression()
|
ShaderAst::ExpressionPtr Parser::ParseExpression()
|
||||||
|
|
@ -1262,7 +1325,7 @@ namespace Nz::ShaderLang
|
||||||
return ParseBinOpRhs(0, ParsePrimaryExpression());
|
return ParseBinOpRhs(0, ParsePrimaryExpression());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ShaderAst::ExpressionPtr> Parser::ParseExpressionList(TokenType terminationToken)
|
std::vector<ShaderAst::ExpressionPtr> Parser::ParseExpressionList(TokenType terminationToken, SourceLocation* terminationLocation)
|
||||||
{
|
{
|
||||||
std::vector<ShaderAst::ExpressionPtr> parameters;
|
std::vector<ShaderAst::ExpressionPtr> parameters;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
@ -1275,7 +1338,9 @@ namespace Nz::ShaderLang
|
||||||
parameters.push_back(ParseExpression());
|
parameters.push_back(ParseExpression());
|
||||||
}
|
}
|
||||||
|
|
||||||
Expect(Advance(), terminationToken);
|
const Token& endToken = Expect(Advance(), terminationToken);
|
||||||
|
if (terminationLocation)
|
||||||
|
*terminationLocation = endToken.location;
|
||||||
|
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
@ -1283,7 +1348,10 @@ namespace Nz::ShaderLang
|
||||||
ShaderAst::ExpressionPtr Parser::ParseFloatingPointExpression()
|
ShaderAst::ExpressionPtr Parser::ParseFloatingPointExpression()
|
||||||
{
|
{
|
||||||
const Token& floatingPointToken = Expect(Advance(), TokenType::FloatingPointValue);
|
const Token& floatingPointToken = Expect(Advance(), TokenType::FloatingPointValue);
|
||||||
return ShaderBuilder::Constant(float(std::get<double>(floatingPointToken.data))); //< FIXME
|
auto constantExpr = ShaderBuilder::Constant(float(std::get<double>(floatingPointToken.data))); //< FIXME
|
||||||
|
constantExpr->sourceLocation = floatingPointToken.location;
|
||||||
|
|
||||||
|
return constantExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::ParseIdentifier()
|
ShaderAst::ExpressionPtr Parser::ParseIdentifier()
|
||||||
|
|
@ -1291,20 +1359,28 @@ namespace Nz::ShaderLang
|
||||||
const Token& identifierToken = Expect(Advance(), TokenType::Identifier);
|
const Token& identifierToken = Expect(Advance(), TokenType::Identifier);
|
||||||
const std::string& identifier = std::get<std::string>(identifierToken.data);
|
const std::string& identifier = std::get<std::string>(identifierToken.data);
|
||||||
|
|
||||||
return ShaderBuilder::Identifier(identifier);
|
auto identifierExpr = ShaderBuilder::Identifier(identifier);
|
||||||
|
identifierExpr->sourceLocation = identifierToken.location;
|
||||||
|
|
||||||
|
return identifierExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::ParseIntegerExpression()
|
ShaderAst::ExpressionPtr Parser::ParseIntegerExpression()
|
||||||
{
|
{
|
||||||
const Token& integerToken = Expect(Advance(), TokenType::IntegerValue);
|
const Token& integerToken = Expect(Advance(), TokenType::IntegerValue);
|
||||||
return ShaderBuilder::Constant(SafeCast<Int32>(std::get<long long>(integerToken.data))); //< FIXME
|
auto constantExpr = ShaderBuilder::Constant(SafeCast<Int32>(std::get<long long>(integerToken.data))); //< FIXME
|
||||||
|
constantExpr->sourceLocation = integerToken.location;
|
||||||
|
|
||||||
|
return constantExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::ParseParenthesisExpression()
|
ShaderAst::ExpressionPtr Parser::ParseParenthesisExpression()
|
||||||
{
|
{
|
||||||
Expect(Advance(), TokenType::OpenParenthesis);
|
const Token& openToken = Expect(Advance(), TokenType::OpenParenthesis);
|
||||||
ShaderAst::ExpressionPtr expression = ParseExpression();
|
ShaderAst::ExpressionPtr expression = ParseExpression();
|
||||||
Expect(Advance(), TokenType::ClosingParenthesis);
|
const Token& closeToken = Expect(Advance(), TokenType::ClosingParenthesis);
|
||||||
|
|
||||||
|
expression->sourceLocation = SourceLocation::BuildFromTo(openToken.location, closeToken.location);
|
||||||
|
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
@ -1312,34 +1388,48 @@ namespace Nz::ShaderLang
|
||||||
ShaderAst::ExpressionPtr Parser::ParsePrimaryExpression()
|
ShaderAst::ExpressionPtr Parser::ParsePrimaryExpression()
|
||||||
{
|
{
|
||||||
const Token& token = Peek();
|
const Token& token = Peek();
|
||||||
|
|
||||||
|
ShaderAst::ExpressionPtr primaryExpr;
|
||||||
switch (token.type)
|
switch (token.type)
|
||||||
{
|
{
|
||||||
case TokenType::BoolFalse:
|
case TokenType::BoolFalse:
|
||||||
Consume();
|
Consume();
|
||||||
return ShaderBuilder::Constant(false);
|
primaryExpr = ShaderBuilder::Constant(false);
|
||||||
|
primaryExpr->sourceLocation = token.location;
|
||||||
|
break;
|
||||||
|
|
||||||
case TokenType::BoolTrue:
|
case TokenType::BoolTrue:
|
||||||
Consume();
|
Consume();
|
||||||
return ShaderBuilder::Constant(true);
|
primaryExpr = ShaderBuilder::Constant(true);
|
||||||
|
primaryExpr->sourceLocation = token.location;
|
||||||
|
break;
|
||||||
|
|
||||||
case TokenType::ConstSelect:
|
case TokenType::ConstSelect:
|
||||||
return ParseConstSelectExpression();
|
primaryExpr = ParseConstSelectExpression();
|
||||||
|
break;
|
||||||
|
|
||||||
case TokenType::FloatingPointValue:
|
case TokenType::FloatingPointValue:
|
||||||
return ParseFloatingPointExpression();
|
primaryExpr = ParseFloatingPointExpression();
|
||||||
|
break;
|
||||||
|
|
||||||
case TokenType::Identifier:
|
case TokenType::Identifier:
|
||||||
return ParseIdentifier();
|
primaryExpr = ParseIdentifier();
|
||||||
|
break;
|
||||||
|
|
||||||
case TokenType::IntegerValue:
|
case TokenType::IntegerValue:
|
||||||
return ParseIntegerExpression();
|
primaryExpr = ParseIntegerExpression();
|
||||||
|
break;
|
||||||
|
|
||||||
case TokenType::Minus:
|
case TokenType::Minus:
|
||||||
{
|
{
|
||||||
Consume();
|
Consume();
|
||||||
ShaderAst::ExpressionPtr expr = ParseExpression();
|
ShaderAst::ExpressionPtr expr = ParseExpression();
|
||||||
|
|
||||||
return ShaderBuilder::Unary(ShaderAst::UnaryType::Minus, std::move(expr));
|
auto minusExpr = ShaderBuilder::Unary(ShaderAst::UnaryType::Minus, std::move(expr));
|
||||||
|
minusExpr->sourceLocation = SourceLocation::BuildFromTo(token.location, minusExpr->expression->sourceLocation);
|
||||||
|
|
||||||
|
primaryExpr = std::move(minusExpr);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TokenType::Plus:
|
case TokenType::Plus:
|
||||||
|
|
@ -1347,7 +1437,11 @@ namespace Nz::ShaderLang
|
||||||
Consume();
|
Consume();
|
||||||
ShaderAst::ExpressionPtr expr = ParseExpression();
|
ShaderAst::ExpressionPtr expr = ParseExpression();
|
||||||
|
|
||||||
return ShaderBuilder::Unary(ShaderAst::UnaryType::Plus, std::move(expr));
|
auto plusExpr = ShaderBuilder::Unary(ShaderAst::UnaryType::Plus, std::move(expr));
|
||||||
|
plusExpr->sourceLocation = SourceLocation::BuildFromTo(token.location, plusExpr->expression->sourceLocation);
|
||||||
|
|
||||||
|
primaryExpr = std::move(plusExpr);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TokenType::Not:
|
case TokenType::Not:
|
||||||
|
|
@ -1355,40 +1449,56 @@ namespace Nz::ShaderLang
|
||||||
Consume();
|
Consume();
|
||||||
ShaderAst::ExpressionPtr expr = ParseExpression();
|
ShaderAst::ExpressionPtr expr = ParseExpression();
|
||||||
|
|
||||||
return ShaderBuilder::Unary(ShaderAst::UnaryType::LogicalNot, std::move(expr));
|
auto notExpr = ShaderBuilder::Unary(ShaderAst::UnaryType::LogicalNot, std::move(expr));
|
||||||
|
notExpr->sourceLocation = SourceLocation::BuildFromTo(token.location, notExpr->expression->sourceLocation);
|
||||||
|
|
||||||
|
primaryExpr = std::move(notExpr);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TokenType::OpenParenthesis:
|
case TokenType::OpenParenthesis:
|
||||||
return ParseParenthesisExpression();
|
primaryExpr = ParseParenthesisExpression();
|
||||||
|
break;
|
||||||
|
|
||||||
case TokenType::StringValue:
|
case TokenType::StringValue:
|
||||||
return ParseStringExpression();
|
primaryExpr = ParseStringExpression();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw ParserUnexpectedTokenError{ TokenLocation(token), token.type };
|
throw ParserUnexpectedTokenError{ token.location, token.type };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
primaryExpr->sourceLocation.ExtendToLeft(token.location);
|
||||||
|
|
||||||
|
return primaryExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::ParseStringExpression()
|
ShaderAst::ExpressionPtr Parser::ParseStringExpression()
|
||||||
{
|
{
|
||||||
const Token& litteralToken = Expect(Advance(), TokenType::StringValue);
|
const Token& litteralToken = Expect(Advance(), TokenType::StringValue);
|
||||||
return ShaderBuilder::Constant(std::get<std::string>(litteralToken.data));
|
auto constantExpr = ShaderBuilder::Constant(std::get<std::string>(litteralToken.data));
|
||||||
|
constantExpr->sourceLocation = litteralToken.location;
|
||||||
|
|
||||||
|
return constantExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& Parser::ParseIdentifierAsName()
|
const std::string& Parser::ParseIdentifierAsName(SourceLocation* sourceLocation)
|
||||||
{
|
{
|
||||||
const Token& identifierToken = Expect(Advance(), TokenType::Identifier);
|
const Token& identifierToken = Expect(Advance(), TokenType::Identifier);
|
||||||
|
if (sourceLocation)
|
||||||
|
*sourceLocation = identifierToken.location;
|
||||||
|
|
||||||
return std::get<std::string>(identifierToken.data);
|
return std::get<std::string>(identifierToken.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Parser::ParseModuleName()
|
std::string Parser::ParseModuleName()
|
||||||
{
|
{
|
||||||
std::string moduleName = ParseIdentifierAsName();
|
std::string moduleName = ParseIdentifierAsName(nullptr);
|
||||||
while (Peek().type == TokenType::Dot)
|
while (Peek().type == TokenType::Dot)
|
||||||
{
|
{
|
||||||
Consume();
|
Consume();
|
||||||
moduleName += '.';
|
moduleName += '.';
|
||||||
moduleName += ParseIdentifierAsName();
|
moduleName += ParseIdentifierAsName(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return moduleName;
|
return moduleName;
|
||||||
|
|
@ -1397,12 +1507,16 @@ namespace Nz::ShaderLang
|
||||||
ShaderAst::ExpressionPtr Parser::ParseType()
|
ShaderAst::ExpressionPtr Parser::ParseType()
|
||||||
{
|
{
|
||||||
// Handle () as no type
|
// Handle () as no type
|
||||||
if (Peek().type == TokenType::OpenParenthesis)
|
const Token& openToken = Peek();
|
||||||
|
if (openToken.type == TokenType::OpenParenthesis)
|
||||||
{
|
{
|
||||||
Consume();
|
Consume();
|
||||||
Expect(Advance(), TokenType::ClosingParenthesis);
|
const Token& closeToken = Expect(Advance(), TokenType::ClosingParenthesis);
|
||||||
|
|
||||||
return ShaderBuilder::Constant(ShaderAst::NoValue{});
|
auto constantExpr = ShaderBuilder::Constant(ShaderAst::NoValue{});
|
||||||
|
constantExpr->sourceLocation = closeToken.location;
|
||||||
|
|
||||||
|
return constantExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ParseExpression();
|
return ParseExpression();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue