Shader: Rework Parser internals
This commit is contained in:
parent
48b93a9dea
commit
3f74ee4d66
|
|
@ -49,9 +49,9 @@ namespace Nz::ShaderLang
|
||||||
private:
|
private:
|
||||||
// Flow control
|
// Flow control
|
||||||
const Token& Advance();
|
const Token& Advance();
|
||||||
void Expect(const Token& token, TokenType type);
|
const Token& Expect(const Token& token, TokenType type);
|
||||||
const Token& ExpectNext(TokenType type);
|
const Token& Expect(TokenType type);
|
||||||
const Token& PeekNext();
|
const Token& Peek(std::size_t advance = 0);
|
||||||
|
|
||||||
// Statements
|
// Statements
|
||||||
std::vector<ShaderAst::StatementPtr> ParseFunctionBody();
|
std::vector<ShaderAst::StatementPtr> ParseFunctionBody();
|
||||||
|
|
@ -70,7 +70,7 @@ namespace Nz::ShaderLang
|
||||||
ShaderAst::ExpressionPtr ParseParenthesisExpression();
|
ShaderAst::ExpressionPtr ParseParenthesisExpression();
|
||||||
ShaderAst::ExpressionPtr ParsePrimaryExpression();
|
ShaderAst::ExpressionPtr ParsePrimaryExpression();
|
||||||
|
|
||||||
std::string ParseIdentifierAsName();
|
const std::string& ParseIdentifierAsName();
|
||||||
ShaderAst::ShaderExpressionType ParseIdentifierAsType();
|
ShaderAst::ShaderExpressionType ParseIdentifierAsType();
|
||||||
|
|
||||||
static int GetTokenPrecedence(TokenType token);
|
static int GetTokenPrecedence(TokenType token);
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
std::vector<Token> Tokenize(const std::string_view& str)
|
std::vector<Token> Tokenize(const std::string_view& str)
|
||||||
{
|
{
|
||||||
// Can't use std::from_chars for double thanks to libc++ and libstdc++ developers being lazy
|
// Can't use std::from_chars for double thanks to libc++ and libstdc++ developers for being lazy
|
||||||
ForceCLocale forceCLocale;
|
ForceCLocale forceCLocale;
|
||||||
|
|
||||||
std::unordered_map<std::string, TokenType> reservedKeywords = {
|
std::unordered_map<std::string, TokenType> reservedKeywords = {
|
||||||
|
|
|
||||||
|
|
@ -45,12 +45,10 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
m_context = &context;
|
m_context = &context;
|
||||||
|
|
||||||
m_context->tokenIndex = -1;
|
|
||||||
|
|
||||||
bool reachedEndOfStream = false;
|
bool reachedEndOfStream = false;
|
||||||
while (!reachedEndOfStream)
|
while (!reachedEndOfStream)
|
||||||
{
|
{
|
||||||
const Token& nextToken = PeekNext();
|
const Token& nextToken = Peek();
|
||||||
switch (nextToken.type)
|
switch (nextToken.type)
|
||||||
{
|
{
|
||||||
case TokenType::FunctionDeclaration:
|
case TokenType::FunctionDeclaration:
|
||||||
|
|
@ -71,28 +69,32 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
const Token& Parser::Advance()
|
const Token& Parser::Advance()
|
||||||
{
|
{
|
||||||
assert(m_context->tokenIndex + 1 < m_context->tokenCount);
|
const Token& token = Peek();
|
||||||
return m_context->tokens[++m_context->tokenIndex];
|
m_context->tokenIndex++;
|
||||||
|
|
||||||
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
void 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 ExpectedToken{};
|
throw ExpectedToken{};
|
||||||
|
|
||||||
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Token& Parser::ExpectNext(TokenType type)
|
const Token& Parser::Expect(TokenType type)
|
||||||
{
|
{
|
||||||
const Token& token = Advance();
|
const Token& token = Peek();
|
||||||
Expect(token, type);
|
Expect(token, type);
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Token& Parser::PeekNext()
|
const Token& Parser::Peek(std::size_t advance)
|
||||||
{
|
{
|
||||||
assert(m_context->tokenIndex + 1 < m_context->tokenCount);
|
assert(m_context->tokenIndex + advance < m_context->tokenCount);
|
||||||
return m_context->tokens[m_context->tokenIndex + 1];
|
return m_context->tokens[m_context->tokenIndex + advance];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ShaderAst::StatementPtr> Parser::ParseFunctionBody()
|
std::vector<ShaderAst::StatementPtr> Parser::ParseFunctionBody()
|
||||||
|
|
@ -102,18 +104,18 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseFunctionDeclaration()
|
ShaderAst::StatementPtr Parser::ParseFunctionDeclaration()
|
||||||
{
|
{
|
||||||
ExpectNext(TokenType::FunctionDeclaration);
|
Expect(Advance(), TokenType::FunctionDeclaration);
|
||||||
|
|
||||||
std::string functionName = ParseIdentifierAsName();
|
std::string functionName = ParseIdentifierAsName();
|
||||||
|
|
||||||
ExpectNext(TokenType::OpenParenthesis);
|
Expect(Advance(), TokenType::OpenParenthesis);
|
||||||
|
|
||||||
std::vector<ShaderAst::DeclareFunctionStatement::Parameter> parameters;
|
std::vector<ShaderAst::DeclareFunctionStatement::Parameter> parameters;
|
||||||
|
|
||||||
bool firstParameter = true;
|
bool firstParameter = true;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
const Token& t = PeekNext();
|
const Token& t = Peek();
|
||||||
if (t.type == TokenType::ClosingParenthesis)
|
if (t.type == TokenType::ClosingParenthesis)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -127,21 +129,21 @@ namespace Nz::ShaderLang
|
||||||
firstParameter = false;
|
firstParameter = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpectNext(TokenType::ClosingParenthesis);
|
Expect(Advance(), TokenType::ClosingParenthesis);
|
||||||
|
|
||||||
ShaderAst::ShaderExpressionType returnType = ShaderAst::BasicType::Void;
|
ShaderAst::ShaderExpressionType returnType = ShaderAst::BasicType::Void;
|
||||||
if (PeekNext().type == TokenType::FunctionReturn)
|
if (Peek().type == TokenType::FunctionReturn)
|
||||||
{
|
{
|
||||||
Advance(); //< Consume ->
|
Advance(); //< Consume ->
|
||||||
|
|
||||||
returnType = ParseIdentifierAsType();
|
returnType = ParseIdentifierAsType();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpectNext(TokenType::OpenCurlyBracket);
|
Expect(Advance(), TokenType::OpenCurlyBracket);
|
||||||
|
|
||||||
std::vector<ShaderAst::StatementPtr> functionBody = ParseFunctionBody();
|
std::vector<ShaderAst::StatementPtr> functionBody = ParseFunctionBody();
|
||||||
|
|
||||||
ExpectNext(TokenType::ClosingCurlyBracket);
|
Expect(Advance(), TokenType::ClosingCurlyBracket);
|
||||||
|
|
||||||
return ShaderBuilder::DeclareFunction(std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType));
|
return ShaderBuilder::DeclareFunction(std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType));
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +152,7 @@ namespace Nz::ShaderLang
|
||||||
{
|
{
|
||||||
std::string parameterName = ParseIdentifierAsName();
|
std::string parameterName = ParseIdentifierAsName();
|
||||||
|
|
||||||
ExpectNext(TokenType::Colon);
|
Expect(Advance(), TokenType::Colon);
|
||||||
|
|
||||||
ShaderAst::ShaderExpressionType parameterType = ParseIdentifierAsType();
|
ShaderAst::ShaderExpressionType parameterType = ParseIdentifierAsType();
|
||||||
|
|
||||||
|
|
@ -159,10 +161,10 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseReturnStatement()
|
ShaderAst::StatementPtr Parser::ParseReturnStatement()
|
||||||
{
|
{
|
||||||
ExpectNext(TokenType::Return);
|
Expect(Advance(), TokenType::Return);
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr expr;
|
ShaderAst::ExpressionPtr expr;
|
||||||
if (PeekNext().type != TokenType::Semicolon)
|
if (Peek().type != TokenType::Semicolon)
|
||||||
expr = ParseExpression();
|
expr = ParseExpression();
|
||||||
|
|
||||||
return ShaderBuilder::Return(std::move(expr));
|
return ShaderBuilder::Return(std::move(expr));
|
||||||
|
|
@ -170,7 +172,7 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseStatement()
|
ShaderAst::StatementPtr Parser::ParseStatement()
|
||||||
{
|
{
|
||||||
const Token& token = PeekNext();
|
const Token& token = Peek();
|
||||||
|
|
||||||
ShaderAst::StatementPtr statement;
|
ShaderAst::StatementPtr statement;
|
||||||
switch (token.type)
|
switch (token.type)
|
||||||
|
|
@ -187,7 +189,7 @@ namespace Nz::ShaderLang
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpectNext(TokenType::Semicolon);
|
Expect(Advance(), TokenType::Semicolon);
|
||||||
|
|
||||||
return statement;
|
return statement;
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +197,7 @@ namespace Nz::ShaderLang
|
||||||
std::vector<ShaderAst::StatementPtr> Parser::ParseStatementList()
|
std::vector<ShaderAst::StatementPtr> Parser::ParseStatementList()
|
||||||
{
|
{
|
||||||
std::vector<ShaderAst::StatementPtr> statements;
|
std::vector<ShaderAst::StatementPtr> statements;
|
||||||
while (PeekNext().type != TokenType::ClosingCurlyBracket)
|
while (Peek().type != TokenType::ClosingCurlyBracket)
|
||||||
{
|
{
|
||||||
statements.push_back(ParseStatement());
|
statements.push_back(ParseStatement());
|
||||||
}
|
}
|
||||||
|
|
@ -205,16 +207,16 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
ShaderAst::StatementPtr Parser::ParseVariableDeclaration()
|
ShaderAst::StatementPtr Parser::ParseVariableDeclaration()
|
||||||
{
|
{
|
||||||
ExpectNext(TokenType::Let);
|
Expect(Advance(), TokenType::Let);
|
||||||
|
|
||||||
std::string variableName = ParseIdentifierAsName();
|
std::string variableName = ParseIdentifierAsName();
|
||||||
|
|
||||||
ExpectNext(TokenType::Colon);
|
Expect(Advance(), TokenType::Colon);
|
||||||
|
|
||||||
ShaderAst::ShaderExpressionType variableType = ParseIdentifierAsType();
|
ShaderAst::ShaderExpressionType variableType = ParseIdentifierAsType();
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr expression;
|
ShaderAst::ExpressionPtr expression;
|
||||||
if (PeekNext().type == TokenType::Assign)
|
if (Peek().type == TokenType::Assign)
|
||||||
{
|
{
|
||||||
Advance();
|
Advance();
|
||||||
expression = ParseExpression();
|
expression = ParseExpression();
|
||||||
|
|
@ -227,7 +229,7 @@ namespace Nz::ShaderLang
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
const Token& currentOp = PeekNext();
|
const Token& currentOp = Peek();
|
||||||
|
|
||||||
int tokenPrecedence = GetTokenPrecedence(currentOp.type);
|
int tokenPrecedence = GetTokenPrecedence(currentOp.type);
|
||||||
if (tokenPrecedence < exprPrecedence)
|
if (tokenPrecedence < exprPrecedence)
|
||||||
|
|
@ -236,7 +238,7 @@ namespace Nz::ShaderLang
|
||||||
Advance();
|
Advance();
|
||||||
ShaderAst::ExpressionPtr rhs = ParsePrimaryExpression();
|
ShaderAst::ExpressionPtr rhs = ParsePrimaryExpression();
|
||||||
|
|
||||||
const Token& nextOp = PeekNext();
|
const Token& nextOp = Peek();
|
||||||
|
|
||||||
int nextTokenPrecedence = GetTokenPrecedence(nextOp.type);
|
int nextTokenPrecedence = GetTokenPrecedence(nextOp.type);
|
||||||
if (tokenPrecedence < nextTokenPrecedence)
|
if (tokenPrecedence < nextTokenPrecedence)
|
||||||
|
|
@ -266,46 +268,62 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::ParseIdentifier()
|
ShaderAst::ExpressionPtr Parser::ParseIdentifier()
|
||||||
{
|
{
|
||||||
const Token& identifier = ExpectNext(TokenType::Identifier);
|
const Token& identifierToken = Expect(Advance(), TokenType::Identifier);
|
||||||
|
const std::string& identifier = std::get<std::string>(identifierToken.data);
|
||||||
|
|
||||||
return ShaderBuilder::Identifier(std::get<std::string>(identifier.data));
|
return ShaderBuilder::Identifier(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::ParseIntegerExpression()
|
ShaderAst::ExpressionPtr Parser::ParseIntegerExpression()
|
||||||
{
|
{
|
||||||
const Token& integer = ExpectNext(TokenType::IntegerValue);
|
const Token& integerToken = Expect(Advance(), TokenType::Identifier);
|
||||||
return ShaderBuilder::Constant(static_cast<Nz::Int32>(std::get<long long>(integer.data)));
|
return ShaderBuilder::Constant(static_cast<Nz::Int32>(std::get<long long>(integerToken.data)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::ParseParenthesisExpression()
|
ShaderAst::ExpressionPtr Parser::ParseParenthesisExpression()
|
||||||
{
|
{
|
||||||
ExpectNext(TokenType::OpenParenthesis);
|
Expect(Advance(), TokenType::OpenParenthesis);
|
||||||
ShaderAst::ExpressionPtr expression = ParseExpression();
|
ShaderAst::ExpressionPtr expression = ParseExpression();
|
||||||
ExpectNext(TokenType::ClosingParenthesis);
|
Expect(Advance(), TokenType::ClosingParenthesis);
|
||||||
|
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::ExpressionPtr Parser::ParsePrimaryExpression()
|
ShaderAst::ExpressionPtr Parser::ParsePrimaryExpression()
|
||||||
{
|
{
|
||||||
const Token& token = PeekNext();
|
const Token& token = Peek();
|
||||||
switch (token.type)
|
switch (token.type)
|
||||||
{
|
{
|
||||||
case TokenType::BoolFalse: return ShaderBuilder::Constant(false);
|
case TokenType::BoolFalse:
|
||||||
case TokenType::BoolTrue: return ShaderBuilder::Constant(true);
|
Advance();
|
||||||
case TokenType::FloatingPointValue: return ShaderBuilder::Constant(float(std::get<double>(Advance().data))); //< FIXME
|
return ShaderBuilder::Constant(false);
|
||||||
case TokenType::Identifier: return ParseIdentifier();
|
|
||||||
case TokenType::IntegerValue: return ParseIntegerExpression();
|
case TokenType::BoolTrue:
|
||||||
case TokenType::OpenParenthesis: return ParseParenthesisExpression();
|
Advance();
|
||||||
default: throw UnexpectedToken{};
|
return ShaderBuilder::Constant(true);
|
||||||
|
|
||||||
|
case TokenType::FloatingPointValue:
|
||||||
|
Advance();
|
||||||
|
return ShaderBuilder::Constant(float(std::get<double>(token.data))); //< FIXME
|
||||||
|
|
||||||
|
case TokenType::Identifier:
|
||||||
|
return ParseIdentifier();
|
||||||
|
|
||||||
|
case TokenType::IntegerValue:
|
||||||
|
return ParseIntegerExpression();
|
||||||
|
|
||||||
|
case TokenType::OpenParenthesis:
|
||||||
|
return ParseParenthesisExpression();
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw UnexpectedToken{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Parser::ParseIdentifierAsName()
|
const std::string& Parser::ParseIdentifierAsName()
|
||||||
{
|
{
|
||||||
const Token& identifierToken = ExpectNext(TokenType::Identifier);
|
const Token& identifierToken = Expect(Advance(), TokenType::Identifier);
|
||||||
|
const std::string& identifier = std::get<std::string>(identifierToken.data);
|
||||||
std::string identifier = std::get<std::string>(identifierToken.data);
|
|
||||||
|
|
||||||
auto it = identifierToBasicType.find(identifier);
|
auto it = identifierToBasicType.find(identifier);
|
||||||
if (it != identifierToBasicType.end())
|
if (it != identifierToBasicType.end())
|
||||||
|
|
@ -316,9 +334,10 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
ShaderAst::ShaderExpressionType Parser::ParseIdentifierAsType()
|
ShaderAst::ShaderExpressionType Parser::ParseIdentifierAsType()
|
||||||
{
|
{
|
||||||
const Token& identifier = ExpectNext(TokenType::Identifier);
|
const Token& identifierToken = Expect(Advance(), TokenType::Identifier);
|
||||||
|
const std::string& identifier = std::get<std::string>(identifierToken.data);
|
||||||
|
|
||||||
auto it = identifierToBasicType.find(std::get<std::string>(identifier.data));
|
auto it = identifierToBasicType.find(identifier);
|
||||||
if (it == identifierToBasicType.end())
|
if (it == identifierToBasicType.end())
|
||||||
throw UnknownType{};
|
throw UnknownType{};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue