From 84294117555c13278f5df35ed181ed9e2003f388 Mon Sep 17 00:00:00 2001 From: SirLynix Date: Mon, 28 Mar 2022 08:52:57 +0200 Subject: [PATCH] Shader: Improve attribute source location --- include/Nazara/Shader/Ast/AstCloner.hpp | 2 +- include/Nazara/Shader/Ast/AstCompare.hpp | 2 +- include/Nazara/Shader/Ast/ExpressionType.hpp | 2 +- .../{Attribute.hpp => ExpressionValue.hpp} | 18 +- .../{Attribute.inl => ExpressionValue.inl} | 2 +- include/Nazara/Shader/Ast/Nodes.hpp | 2 +- src/Nazara/Shader/ShaderLangParser.cpp | 282 +++++++++--------- 7 files changed, 158 insertions(+), 152 deletions(-) rename include/Nazara/Shader/Ast/{Attribute.hpp => ExpressionValue.hpp} (79%) rename include/Nazara/Shader/Ast/{Attribute.inl => ExpressionValue.inl} (97%) diff --git a/include/Nazara/Shader/Ast/AstCloner.hpp b/include/Nazara/Shader/Ast/AstCloner.hpp index 445eba834..e9a5aa6f8 100644 --- a/include/Nazara/Shader/Ast/AstCloner.hpp +++ b/include/Nazara/Shader/Ast/AstCloner.hpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include namespace Nz::ShaderAst diff --git a/include/Nazara/Shader/Ast/AstCompare.hpp b/include/Nazara/Shader/Ast/AstCompare.hpp index 74fef5a08..06d4fc307 100644 --- a/include/Nazara/Shader/Ast/AstCompare.hpp +++ b/include/Nazara/Shader/Ast/AstCompare.hpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/Nazara/Shader/Ast/ExpressionType.hpp b/include/Nazara/Shader/Ast/ExpressionType.hpp index 499da2578..be7b5f41f 100644 --- a/include/Nazara/Shader/Ast/ExpressionType.hpp +++ b/include/Nazara/Shader/Ast/ExpressionType.hpp @@ -9,8 +9,8 @@ #include #include -#include #include +#include #include #include #include diff --git a/include/Nazara/Shader/Ast/Attribute.hpp b/include/Nazara/Shader/Ast/ExpressionValue.hpp similarity index 79% rename from include/Nazara/Shader/Ast/Attribute.hpp rename to include/Nazara/Shader/Ast/ExpressionValue.hpp index 3394e64bc..38c087dd1 100644 --- a/include/Nazara/Shader/Ast/Attribute.hpp +++ b/include/Nazara/Shader/Ast/ExpressionValue.hpp @@ -4,13 +4,11 @@ #pragma once -#ifndef NAZARA_SHADER_AST_ATTRIBUTE_HPP -#define NAZARA_SHADER_AST_ATTRIBUTE_HPP +#ifndef NAZARA_SHADER_AST_EXPRESSIONVALUE_HPP +#define NAZARA_SHADER_AST_EXPRESSIONVALUE_HPP #include #include -#include -#include #include namespace Nz::ShaderAst @@ -47,16 +45,8 @@ namespace Nz::ShaderAst private: std::variant m_value; }; - - struct ExprValue - { - using Param = std::optional; - - AttributeType type; - Param args; - }; } -#include +#include -#endif // NAZARA_SHADER_AST_ATTRIBUTE_HPP +#endif // NAZARA_SHADER_AST_EXPRESSIONVALUE_HPP diff --git a/include/Nazara/Shader/Ast/Attribute.inl b/include/Nazara/Shader/Ast/ExpressionValue.inl similarity index 97% rename from include/Nazara/Shader/Ast/Attribute.inl rename to include/Nazara/Shader/Ast/ExpressionValue.inl index 0b5793e0f..672905611 100644 --- a/include/Nazara/Shader/Ast/Attribute.inl +++ b/include/Nazara/Shader/Ast/ExpressionValue.inl @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Shader module" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include #include #include diff --git a/include/Nazara/Shader/Ast/Nodes.hpp b/include/Nazara/Shader/Ast/Nodes.hpp index d5119ccae..115dd5501 100644 --- a/include/Nazara/Shader/Ast/Nodes.hpp +++ b/include/Nazara/Shader/Ast/Nodes.hpp @@ -13,10 +13,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index 50f154415..02f13fe12 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -59,55 +59,73 @@ namespace Nz::ShaderLang { "never", ShaderAst::LoopUnroll::Never } }; - template - void HandleUniqueAttribute(const Token& token, ShaderAst::AttributeType attributeType, ShaderAst::ExpressionValue& targetAttribute, ShaderAst::ExprValue::Param&& param) + SourceLocation TokenLocation(const Token& token) { - if (targetAttribute.HasValue()) - throw ParserAttributeMultipleUniqueError{ SourceLocation{ token.line, token.column, token.file }, attributeType }; //< TODO: Improve source location for attributes + SourceLocation sourceLoc; + sourceLoc.file = token.file; + sourceLoc.startColumn = sourceLoc.endColumn = token.column; + sourceLoc.startLine = sourceLoc.endLine = token.line; - if (param) - targetAttribute = std::move(*param); - else - throw ParserAttributeMissingParameterError{ SourceLocation{ token.line, token.column, token.file }, attributeType }; //< TODO: Improve source location for attributes + 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 - void HandleUniqueAttribute(const Token& token, ShaderAst::AttributeType attributeType, ShaderAst::ExpressionValue& targetAttribute, ShaderAst::ExprValue::Param&& param, T defaultValue) + void HandleUniqueAttribute(ShaderAst::ExpressionValue& targetAttribute, Parser::Attribute&& attribute) { if (targetAttribute.HasValue()) - throw ParserAttributeMultipleUniqueError{ SourceLocation{ token.line, token.column, token.file }, attributeType }; //< TODO: Improve source location for attributes + throw ParserAttributeMultipleUniqueError{ attribute.sourceLocation, attribute.type }; - if (param) - targetAttribute = std::move(*param); + if (!attribute.args) + throw ParserAttributeMissingParameterError{ attribute.sourceLocation, attribute.type }; + + targetAttribute = std::move(attribute.args); + } + + template + void HandleUniqueAttribute(ShaderAst::ExpressionValue& targetAttribute, Parser::Attribute&& attribute, T defaultValue) + { + if (targetAttribute.HasValue()) + throw ParserAttributeMultipleUniqueError{ attribute.sourceLocation, attribute.type }; + + if (attribute.args) + targetAttribute = std::move(attribute.args); else targetAttribute = std::move(defaultValue); } template - void HandleUniqueStringAttribute(const Token& token, ShaderAst::AttributeType attributeType, const std::unordered_map& map, ShaderAst::ExpressionValue& targetAttribute, ShaderAst::ExprValue::Param&& param, std::optional defaultValue = {}) + void HandleUniqueStringAttribute(ShaderAst::ExpressionValue& targetAttribute, Parser::Attribute&& attribute, const std::unordered_map& map, std::optional defaultValue = {}) { if (targetAttribute.HasValue()) - throw ParserAttributeMultipleUniqueError{ SourceLocation{ token.line, token.column, token.file }, attributeType }; //< TODO: Improve source location for attributes + throw ParserAttributeMultipleUniqueError{ attribute.sourceLocation, attribute.type }; //FIXME: This should be handled with global values at sanitization stage - if (param) + if (attribute.args) { - const ShaderAst::ExpressionPtr& expr = *param; - if (expr->GetType() != ShaderAst::NodeType::IdentifierExpression) - throw ParserAttributeParameterIdentifierError{ SourceLocation{ token.line, token.column, token.file }, attributeType }; + if (attribute.args->GetType() != ShaderAst::NodeType::IdentifierExpression) + throw ParserAttributeParameterIdentifierError{ attribute.args->sourceLocation, attribute.type }; - const std::string& exprStr = static_cast(*expr).identifier; + const std::string& exprStr = static_cast(*attribute.args).identifier; auto it = map.find(exprStr); if (it == map.end()) - throw ParserAttributeInvalidParameterError{ SourceLocation{ token.line, token.column, token.file }, exprStr, attributeType }; + throw ParserAttributeInvalidParameterError{ attribute.args->sourceLocation, exprStr, attribute.type }; targetAttribute = it->second; } else { if (!defaultValue) - throw ParserAttributeMissingParameterError{ SourceLocation{ token.line, token.column, token.file }, attributeType }; //< TODO: Improve source location for attributes + throw ParserAttributeMissingParameterError{ attribute.sourceLocation, attribute.type }; targetAttribute = defaultValue.value(); } @@ -122,7 +140,7 @@ namespace Nz::ShaderLang m_context = &context; - std::vector attributes; + std::vector attributes; for (;;) { @@ -130,7 +148,7 @@ namespace Nz::ShaderLang if (!m_context->module) { const Token& nextToken = Peek(); - throw ParserUnexpectedTokenError{ SourceLocation{ nextToken.line, nextToken.column, nextToken.file } }; + throw ParserUnexpectedTokenError{ TokenLocation(nextToken) }; } if (!statement) @@ -159,7 +177,7 @@ namespace Nz::ShaderLang const Token& Parser::Expect(const Token& token, TokenType type) { if (token.type != type) - throw ParserExpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, type, token.type }; + throw ParserExpectedTokenError{ TokenLocation(token), type, token.type }; return token; } @@ -167,7 +185,7 @@ namespace Nz::ShaderLang const Token& Parser::ExpectNot(const Token& token, TokenType type) { if (token.type == type) - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, type }; + throw ParserUnexpectedTokenError{ TokenLocation(token), type }; return token; } @@ -186,9 +204,9 @@ namespace Nz::ShaderLang return m_context->tokens[m_context->tokenIndex + advance]; } - std::vector Parser::ParseAttributes() + std::vector Parser::ParseAttributes() { - std::vector attributes; + std::vector attributes; Expect(Advance(), TokenType::OpenSquareBracket); @@ -214,23 +232,34 @@ namespace Nz::ShaderLang if (expectComma) Expect(Advance(), TokenType::Comma); - ShaderAst::AttributeType attributeType = ParseIdentifierAsAttributeType(); + const Token& identifierToken = Expect(Advance(), TokenType::Identifier); + const std::string& identifier = std::get(identifierToken.data); - ShaderAst::ExprValue::Param arg; + SourceLocation attributeLocation = TokenLocation(identifierToken); + + auto it = s_identifierToAttributeType.find(identifier); + if (it == s_identifierToAttributeType.end()) + throw ParserUnknownAttributeError{ attributeLocation }; + + ShaderAst::AttributeType attributeType = it->second; + + ShaderAst::ExpressionPtr arg; if (Peek().type == TokenType::OpenParenthesis) { Consume(); arg = ParseExpression(); - Expect(Advance(), TokenType::ClosingParenthesis); + const Token& closeToken = Expect(Advance(), TokenType::ClosingParenthesis); + ExtendLocationToToken(attributeLocation, closeToken); } expectComma = true; attributes.push_back({ attributeType, - std::move(arg) + std::move(arg), + attributeLocation }); } @@ -239,12 +268,12 @@ namespace Nz::ShaderLang return attributes; } - void Parser::ParseModuleStatement(std::vector attributes) + void Parser::ParseModuleStatement(std::vector attributes) { if (m_context->parsingImportedModule) { const Token& token = Peek(); - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, token.type }; + throw ParserUnexpectedTokenError{ TokenLocation(token), token.type }; } const Token& moduleToken = Expect(Advance(), TokenType::Module); @@ -252,7 +281,7 @@ namespace Nz::ShaderLang std::optional moduleVersion; std::optional moduleId; - for (auto&& [attributeType, arg] : attributes) + for (auto&& [attributeType, expr, location] : attributes) { switch (attributeType) { @@ -260,18 +289,17 @@ namespace Nz::ShaderLang { // Version parsing if (moduleVersion.has_value()) - throw ParserAttributeMultipleUniqueError{ SourceLocation{ moduleToken.line, moduleToken.column, moduleToken.file }, attributeType }; //< TODO: Improve source location for attributes + throw ParserAttributeMultipleUniqueError{ location, attributeType }; - if (!arg) - throw ParserAttributeMissingParameterError{ SourceLocation{ moduleToken.line, moduleToken.column, moduleToken.file }, attributeType }; //< TODO: Improve source location for attributes + if (!expr) + throw ParserAttributeMissingParameterError{ location, attributeType }; - const ShaderAst::ExpressionPtr& expr = *arg; if (expr->GetType() != ShaderAst::NodeType::ConstantValueExpression) - throw ParserAttributeExpectStringError{ SourceLocation{ moduleToken.line, moduleToken.column, moduleToken.file }, attributeType }; + throw ParserAttributeExpectStringError{ location, attributeType }; auto& constantValue = SafeCast(*expr); if (ShaderAst::GetConstantType(constantValue.value) != ShaderAst::ExpressionType{ ShaderAst::PrimitiveType::String }) - throw ParserAttributeExpectStringError{ SourceLocation{ moduleToken.line, moduleToken.column, moduleToken.file }, attributeType }; + throw ParserAttributeExpectStringError{ location, attributeType }; const std::string& versionStr = std::get(constantValue.value); @@ -279,7 +307,7 @@ namespace Nz::ShaderLang std::smatch versionMatch; if (!std::regex_match(versionStr, versionMatch, versionRegex)) - throw ParserInvalidVersionError{ SourceLocation{ moduleToken.line, moduleToken.column, moduleToken.file }, versionStr }; + throw ParserInvalidVersionError{ location, versionStr }; assert(versionMatch.size() == 6); @@ -299,36 +327,35 @@ namespace Nz::ShaderLang case ShaderAst::AttributeType::Uuid: { if (moduleId.has_value()) - throw ParserAttributeMultipleUniqueError{ SourceLocation{ moduleToken.line, moduleToken.column, moduleToken.file }, attributeType }; //< TODO: Improve source location for attributes + throw ParserAttributeMultipleUniqueError{ location, attributeType }; - if (!arg) - throw ParserAttributeMissingParameterError{ SourceLocation{ moduleToken.line, moduleToken.column, moduleToken.file }, attributeType }; //< TODO: Improve source location for attributes + if (!expr) + throw ParserAttributeMissingParameterError{ location, attributeType }; - const ShaderAst::ExpressionPtr& expr = *arg; if (expr->GetType() != ShaderAst::NodeType::ConstantValueExpression) - throw ParserAttributeExpectStringError{ SourceLocation{ moduleToken.line, moduleToken.column, moduleToken.file }, attributeType }; + throw ParserAttributeExpectStringError{ location, attributeType }; auto& constantValue = SafeCast(*expr); if (ShaderAst::GetConstantType(constantValue.value) != ShaderAst::ExpressionType{ ShaderAst::PrimitiveType::String }) - throw ParserAttributeExpectStringError{ SourceLocation{ moduleToken.line, moduleToken.column, moduleToken.file }, attributeType }; + throw ParserAttributeExpectStringError{ location, attributeType }; const std::string& uuidStr = std::get(constantValue.value); Uuid uuid = Uuid::FromString(uuidStr); if (uuid.IsNull()) - throw ParserInvalidUuidError{ SourceLocation{ moduleToken.line, moduleToken.column, moduleToken.file }, uuidStr }; + throw ParserInvalidUuidError{ location, uuidStr }; moduleId = uuid; break; } default: - throw ParserUnexpectedAttributeError{ SourceLocation{ moduleToken.line, moduleToken.column, moduleToken.file }, attributeType }; + throw ParserUnexpectedAttributeError{ location, attributeType }; } } if (!moduleVersion.has_value()) - throw ParserMissingAttributeError{ SourceLocation{ moduleToken.line, moduleToken.column, moduleToken.file } }; + throw ParserMissingAttributeError{ TokenLocation(moduleToken) }; if (!moduleId) moduleId = Uuid::Generate(); @@ -349,7 +376,7 @@ namespace Nz::ShaderLang if (!statement) { const Token& token = Peek(); - throw ParserUnexpectedEndOfFileError{ SourceLocation{ token.line, token.column, token.file } }; + throw ParserUnexpectedEndOfFileError{ TokenLocation(token) }; } module->rootNode->statements.push_back(std::move(statement)); @@ -374,7 +401,7 @@ namespace Nz::ShaderLang Expect(Advance(), TokenType::Semicolon); if (m_context->module) - throw ParserDuplicateModuleError{ SourceLocation{ moduleToken.line, moduleToken.column, moduleToken.file } }; + throw ParserDuplicateModuleError{ TokenLocation(moduleToken) }; m_context->module = std::move(module); } @@ -497,7 +524,7 @@ namespace Nz::ShaderLang } default: - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, token.type }; + throw ParserUnexpectedTokenError{ TokenLocation(token), token.type }; } } @@ -509,7 +536,7 @@ namespace Nz::ShaderLang return ShaderBuilder::Discard(); } - ShaderAst::StatementPtr Parser::ParseExternalBlock(std::vector attributes) + ShaderAst::StatementPtr Parser::ParseExternalBlock(std::vector attributes) { NAZARA_USE_ANONYMOUS_NAMESPACE @@ -517,23 +544,26 @@ namespace Nz::ShaderLang Expect(Advance(), TokenType::OpenCurlyBracket); std::unique_ptr externalStatement = std::make_unique(); + externalStatement->sourceLocation.startColumn = externalToken.column; + externalStatement->sourceLocation.startLine = externalToken.line; + externalStatement->sourceLocation.file = externalToken.file; ShaderAst::ExpressionValue condition; - for (auto&& [attributeType, arg] : attributes) + for (auto&& attribute : attributes) { - switch (attributeType) + switch (attribute.type) { case ShaderAst::AttributeType::Cond: - HandleUniqueAttribute(externalToken, attributeType, condition, std::move(arg)); + HandleUniqueAttribute(condition, std::move(attribute)); break; case ShaderAst::AttributeType::Set: - HandleUniqueAttribute(externalToken, attributeType, externalStatement->bindingSet, std::move(arg)); + HandleUniqueAttribute(externalStatement->bindingSet, std::move(attribute)); break; default: - throw ParserUnexpectedAttributeError{ SourceLocation{ externalToken.line, externalToken.column, externalToken.file }, attributeType }; + throw ParserUnexpectedAttributeError{ attribute.sourceLocation, attribute.type }; } } @@ -562,20 +592,20 @@ namespace Nz::ShaderLang if (token.type == TokenType::OpenSquareBracket) { - for (auto&& [attributeType, arg] : ParseAttributes()) + for (auto&& attribute : ParseAttributes()) { - switch (attributeType) + switch (attribute.type) { case ShaderAst::AttributeType::Binding: - HandleUniqueAttribute(externalToken, attributeType, extVar.bindingIndex, std::move(arg)); + HandleUniqueAttribute(extVar.bindingIndex, std::move(attribute)); break; case ShaderAst::AttributeType::Set: - HandleUniqueAttribute(externalToken, attributeType, extVar.bindingSet, std::move(arg)); + HandleUniqueAttribute(extVar.bindingSet, std::move(attribute)); break; default: - throw ParserUnexpectedAttributeError{ SourceLocation{ token.line, token.column, token.file }, attributeType }; + throw ParserUnexpectedAttributeError{ attribute.sourceLocation, attribute.type }; } } } @@ -593,7 +623,7 @@ namespace Nz::ShaderLang return externalStatement; } - ShaderAst::StatementPtr Parser::ParseForDeclaration(std::vector attributes) + ShaderAst::StatementPtr Parser::ParseForDeclaration(std::vector attributes) { NAZARA_USE_ANONYMOUS_NAMESPACE @@ -624,16 +654,16 @@ namespace Nz::ShaderLang auto forNode = ShaderBuilder::For(std::move(varName), std::move(expr), std::move(toExpr), std::move(stepExpr), std::move(statement)); // TODO: Deduplicate code - for (auto&& [attributeType, arg] : attributes) + for (auto&& attribute : attributes) { - switch (attributeType) + switch (attribute.type) { case ShaderAst::AttributeType::Unroll: - HandleUniqueStringAttribute(forToken, attributeType, s_unrollModes, forNode->unroll, std::move(arg), std::make_optional(ShaderAst::LoopUnroll::Always)); + HandleUniqueStringAttribute(forNode->unroll, std::move(attribute), s_unrollModes, std::make_optional(ShaderAst::LoopUnroll::Always)); break; default: - throw ParserUnexpectedAttributeError{ SourceLocation{ forToken.line, forToken.column, forToken.file }, attributeType }; + throw ParserUnexpectedAttributeError{ attribute.sourceLocation, attribute.type }; } } @@ -647,16 +677,16 @@ namespace Nz::ShaderLang auto forEachNode = ShaderBuilder::ForEach(std::move(varName), std::move(expr), std::move(statement)); // TODO: Deduplicate code - for (auto&& [attributeType, arg] : attributes) + for (auto&& attribute : attributes) { - switch (attributeType) + switch (attribute.type) { case ShaderAst::AttributeType::Unroll: - HandleUniqueStringAttribute(forToken, attributeType, s_unrollModes, forEachNode->unroll, std::move(arg), std::make_optional(ShaderAst::LoopUnroll::Always)); + HandleUniqueStringAttribute(forEachNode->unroll, std::move(attribute), s_unrollModes, std::make_optional(ShaderAst::LoopUnroll::Always)); break; default: - throw ParserUnexpectedAttributeError{ SourceLocation{ forToken.line, forToken.column, forToken.file }, attributeType }; + throw ParserUnexpectedAttributeError{ attribute.sourceLocation, attribute.type }; } } @@ -669,7 +699,7 @@ namespace Nz::ShaderLang return ParseStatementList(); } - ShaderAst::StatementPtr Parser::ParseFunctionDeclaration(std::vector attributes) + ShaderAst::StatementPtr Parser::ParseFunctionDeclaration(std::vector attributes) { NAZARA_USE_ANONYMOUS_NAMESPACE @@ -712,32 +742,32 @@ namespace Nz::ShaderLang ShaderAst::ExpressionValue condition; - for (auto&& [attributeType, attributeParam] : attributes) + for (auto&& attribute : attributes) { - switch (attributeType) + switch (attribute.type) { case ShaderAst::AttributeType::Cond: - HandleUniqueAttribute(funcToken, attributeType, condition, std::move(attributeParam)); + HandleUniqueAttribute(condition, std::move(attribute)); break; case ShaderAst::AttributeType::Entry: - HandleUniqueStringAttribute(funcToken, attributeType, s_entryPoints, func->entryStage, std::move(attributeParam)); + HandleUniqueStringAttribute(func->entryStage, std::move(attribute), s_entryPoints); break; case ShaderAst::AttributeType::Export: - HandleUniqueAttribute(funcToken, attributeType, func->isExported, std::move(attributeParam), true); + HandleUniqueAttribute(func->isExported, std::move(attribute), true); break; case ShaderAst::AttributeType::DepthWrite: - HandleUniqueStringAttribute(funcToken, attributeType, s_depthWriteModes, func->depthWrite, std::move(attributeParam)); + HandleUniqueStringAttribute(func->depthWrite, std::move(attribute), s_depthWriteModes); break; case ShaderAst::AttributeType::EarlyFragmentTests: - HandleUniqueAttribute(funcToken, attributeType, func->earlyFragmentTests, std::move(attributeParam), true); + HandleUniqueAttribute(func->earlyFragmentTests, std::move(attribute)); break; default: - throw ParserUnexpectedAttributeError{ SourceLocation{ funcToken.line, funcToken.column, funcToken.file }, attributeType }; + throw ParserUnexpectedAttributeError{ attribute.sourceLocation, attribute.type }; } } @@ -807,26 +837,26 @@ namespace Nz::ShaderLang return ShaderBuilder::Return(std::move(expr)); } - ShaderAst::StatementPtr Parser::ParseRootStatement(std::vector attributes) + ShaderAst::StatementPtr Parser::ParseRootStatement(std::vector attributes) { const Token& nextToken = Peek(); switch (nextToken.type) { case TokenType::Alias: if (!attributes.empty()) - throw ParserUnexpectedTokenError{ SourceLocation{ nextToken.line, nextToken.column, nextToken.file }, nextToken.type }; + throw ParserUnexpectedTokenError{ TokenLocation(nextToken), nextToken.type }; return ParseAliasDeclaration(); case TokenType::Const: if (!attributes.empty()) - throw ParserUnexpectedTokenError{ SourceLocation{ nextToken.line, nextToken.column, nextToken.file }, nextToken.type }; + throw ParserUnexpectedTokenError{ TokenLocation(nextToken), nextToken.type }; return ParseConstStatement(); case TokenType::EndOfStream: if (!attributes.empty()) - throw ParserUnexpectedTokenError{ SourceLocation{ nextToken.line, nextToken.column, nextToken.file }, nextToken.type }; + throw ParserUnexpectedTokenError{ TokenLocation(nextToken), nextToken.type }; return {}; @@ -835,7 +865,7 @@ namespace Nz::ShaderLang case TokenType::Import: if (!attributes.empty()) - throw ParserUnexpectedTokenError{ SourceLocation{ nextToken.line, nextToken.column, nextToken.file }, nextToken.type }; + throw ParserUnexpectedTokenError{ TokenLocation(nextToken), nextToken.type }; return ParseImportStatement(); @@ -850,7 +880,7 @@ namespace Nz::ShaderLang case TokenType::Option: { if (!attributes.empty()) - throw ParserUnexpectedTokenError{ SourceLocation{ nextToken.line, nextToken.column, nextToken.file }, nextToken.type }; + throw ParserUnexpectedTokenError{ TokenLocation(nextToken), nextToken.type }; return ParseOptionDeclaration(); } @@ -862,13 +892,13 @@ namespace Nz::ShaderLang return ParseStructDeclaration(std::move(attributes)); default: - throw ParserUnexpectedTokenError{ SourceLocation{ nextToken.line, nextToken.column, nextToken.file }, nextToken.type }; + throw ParserUnexpectedTokenError{ TokenLocation(nextToken), nextToken.type }; } } ShaderAst::StatementPtr Parser::ParseSingleStatement() { - std::vector attributes; + std::vector attributes; ShaderAst::StatementPtr statement; do { @@ -877,14 +907,14 @@ namespace Nz::ShaderLang { case TokenType::Const: if (!attributes.empty()) - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, token.type }; + throw ParserUnexpectedTokenError{ TokenLocation(token), token.type }; statement = ParseConstStatement(); break; case TokenType::Discard: if (!attributes.empty()) - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, token.type }; + throw ParserUnexpectedTokenError{ TokenLocation(token), token.type }; statement = ParseDiscardStatement(); break; @@ -896,14 +926,14 @@ namespace Nz::ShaderLang case TokenType::Let: if (!attributes.empty()) - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, token.type }; + throw ParserUnexpectedTokenError{ TokenLocation(token), token.type }; statement = ParseVariableDeclaration(); break; case TokenType::Identifier: if (!attributes.empty()) - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, token.type }; + throw ParserUnexpectedTokenError{ TokenLocation(token), token.type }; statement = ShaderBuilder::ExpressionStatement(ParseVariableAssignation()); Expect(Advance(), TokenType::Semicolon); @@ -911,7 +941,7 @@ namespace Nz::ShaderLang case TokenType::If: if (!attributes.empty()) - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, token.type }; + throw ParserUnexpectedTokenError{ TokenLocation(token), token.type }; statement = ParseBranchStatement(); break; @@ -923,7 +953,7 @@ namespace Nz::ShaderLang case TokenType::Return: if (!attributes.empty()) - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, token.type }; + throw ParserUnexpectedTokenError{ TokenLocation(token), token.type }; statement = ParseReturnStatement(); break; @@ -934,7 +964,7 @@ namespace Nz::ShaderLang break; default: - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, token.type }; + throw ParserUnexpectedTokenError{ TokenLocation(token), token.type }; } } while (!statement); //< small trick to repeat parsing once we got attributes @@ -965,7 +995,7 @@ namespace Nz::ShaderLang return statements; } - ShaderAst::StatementPtr Parser::ParseStructDeclaration(std::vector attributes) + ShaderAst::StatementPtr Parser::ParseStructDeclaration(std::vector attributes) { NAZARA_USE_ANONYMOUS_NAMESPACE @@ -977,24 +1007,24 @@ namespace Nz::ShaderLang ShaderAst::ExpressionValue condition; ShaderAst::ExpressionValue exported; - for (auto&& [attributeType, attributeParam] : attributes) + for (auto&& attribute : attributes) { - switch (attributeType) + switch (attribute.type) { case ShaderAst::AttributeType::Cond: - HandleUniqueAttribute(structToken, attributeType, condition, std::move(attributeParam)); + HandleUniqueAttribute(condition, std::move(attribute)); break; case ShaderAst::AttributeType::Export: - HandleUniqueAttribute(structToken, attributeType, exported, std::move(attributeParam), true); + HandleUniqueAttribute(exported, std::move(attribute), true); break; case ShaderAst::AttributeType::Layout: - HandleUniqueStringAttribute(structToken, attributeType, s_layoutMapping, description.layout, std::move(attributeParam)); + HandleUniqueStringAttribute(description.layout, std::move(attribute), s_layoutMapping); break; default: - throw ParserUnexpectedAttributeError{ SourceLocation{ structToken.line, structToken.column, structToken.file }, attributeType }; + throw ParserUnexpectedAttributeError{ attribute.sourceLocation, attribute.type }; } } @@ -1026,24 +1056,24 @@ namespace Nz::ShaderLang if (token.type == TokenType::OpenSquareBracket) { - for (auto&& [attributeType, arg] : ParseAttributes()) + for (auto&& attribute : ParseAttributes()) { - switch (attributeType) + switch (attribute.type) { case ShaderAst::AttributeType::Builtin: - HandleUniqueStringAttribute(token, attributeType, s_builtinMapping, structField.builtin, std::move(arg)); + HandleUniqueStringAttribute(structField.builtin, std::move(attribute), s_builtinMapping); break; case ShaderAst::AttributeType::Cond: - HandleUniqueAttribute(token, attributeType, structField.cond, std::move(arg)); + HandleUniqueAttribute(structField.cond, std::move(attribute)); break; case ShaderAst::AttributeType::Location: - HandleUniqueAttribute(token, attributeType, structField.locationIndex, std::move(arg)); + HandleUniqueAttribute(structField.locationIndex, std::move(attribute)); break; default: - throw ParserUnexpectedAttributeError{ SourceLocation{ token.line, token.column, token.file }, attributeType }; + throw ParserUnexpectedAttributeError{ attribute.sourceLocation, attribute.type }; } } } @@ -1083,7 +1113,7 @@ namespace Nz::ShaderLang case TokenType::PlusAssign: assignType = ShaderAst::AssignType::CompoundAdd; break; default: - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file } }; + throw ParserUnexpectedTokenError{ TokenLocation(token) }; } Consume(); @@ -1107,7 +1137,7 @@ namespace Nz::ShaderLang return ShaderBuilder::DeclareVariable(std::move(variableName), std::move(variableType), std::move(expression)); } - ShaderAst::StatementPtr Parser::ParseWhileStatement(std::vector attributes) + ShaderAst::StatementPtr Parser::ParseWhileStatement(std::vector attributes) { NAZARA_USE_ANONYMOUS_NAMESPACE @@ -1123,16 +1153,16 @@ namespace Nz::ShaderLang auto whileStatement = ShaderBuilder::While(std::move(condition), std::move(body)); - for (auto&& [attributeType, arg] : attributes) + for (auto&& attribute : attributes) { - switch (attributeType) + switch (attribute.type) { case ShaderAst::AttributeType::Unroll: - HandleUniqueStringAttribute(whileToken, attributeType, s_unrollModes, whileStatement->unroll, std::move(arg), std::make_optional(ShaderAst::LoopUnroll::Always)); + HandleUniqueStringAttribute(whileStatement->unroll, std::move(attribute), s_unrollModes, std::make_optional(ShaderAst::LoopUnroll::Always)); break; default: - throw ParserUnexpectedAttributeError{ SourceLocation{ whileToken.line, whileToken.column, whileToken.file }, attributeType }; + throw ParserUnexpectedAttributeError{ attribute.sourceLocation, attribute.type }; } } @@ -1146,7 +1176,7 @@ namespace Nz::ShaderLang const Token& token = Peek(); TokenType currentTokenType = token.type; if (currentTokenType == TokenType::EndOfStream) - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, token.type }; + throw ParserUnexpectedTokenError{ TokenLocation(token), token.type }; int tokenPrecedence = GetTokenPrecedence(currentTokenType); if (tokenPrecedence < exprPrecedence) @@ -1201,7 +1231,7 @@ namespace Nz::ShaderLang 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)); default: - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, token.type }; + throw ParserUnexpectedTokenError{ TokenLocation(token), token.type }; } }(); } @@ -1335,7 +1365,7 @@ namespace Nz::ShaderLang return ParseStringExpression(); default: - throw ParserUnexpectedTokenError{ SourceLocation{ token.line, token.column, token.file }, token.type }; + throw ParserUnexpectedTokenError{ TokenLocation(token), token.type }; } } @@ -1345,20 +1375,6 @@ namespace Nz::ShaderLang return ShaderBuilder::Constant(std::get(litteralToken.data)); } - ShaderAst::AttributeType Parser::ParseIdentifierAsAttributeType() - { - NAZARA_USE_ANONYMOUS_NAMESPACE - - const Token& identifierToken = Expect(Advance(), TokenType::Identifier); - const std::string& identifier = std::get(identifierToken.data); - - auto it = s_identifierToAttributeType.find(identifier); - if (it == s_identifierToAttributeType.end()) - throw ParserUnknownAttributeError{ SourceLocation{ identifierToken.line, identifierToken.column, identifierToken.file } }; - - return it->second; - } - const std::string& Parser::ParseIdentifierAsName() { const Token& identifierToken = Expect(Advance(), TokenType::Identifier);