Finished parser functions

Time for fixing bugs YAYYYYYYYYYYY
This commit is contained in:
Pasha Bibko
2025-08-11 17:46:58 +01:00
parent c59d8cfb5c
commit 3d1865de59
3 changed files with 100 additions and 10 deletions

View File

@@ -9,7 +9,7 @@ int main(int argc, char** argv)
using namespace PashaBibko::LXC;
using namespace PashaBibko;
std::filesystem::path src = "examples/Fib.lx";
std::filesystem::path src = "examples/Basic.lx";
// Reads the given file to a string //
Util::ReturnVal fileContents = Util::ReadFile(src);

6
examples/Basic.lx Normal file
View File

@@ -0,0 +1,6 @@
func<int> main()
{
int: res = 5 + 34
return res
}

View File

@@ -109,7 +109,7 @@ namespace PashaBibko::LXC::Parser
static Util::ReturnVal<AST::NodeValuePtr, ParserError> ParseFunctionCall(ParserContext& ctx)
{
// Checks if the upcoming pattern matches a function signature: [Identifier(function name), OpenBracket(Start of params)] //
if (!ctx.Expect(std::array{ Lexer::Token::Identifier, Lexer::Token::OpenParen }))
if (ctx.Expect(std::array{ Lexer::Token::Identifier, Lexer::Token::OpenParen }))
{
// Captures the function name and advances over it and the start paren //
const Lexer::Token* functionNameToken = ctx.At();
@@ -130,7 +130,10 @@ namespace PashaBibko::LXC::Parser
ctx.Advance();
// Adds the current argument to the ValueList //
arguments.push_back(std::move(ParsePrimary(ctx).Result()));
Util::ReturnVal arg = ParsePrimary(ctx);
if (arg.Failed())
return Util::FunctionFail<ParserError>(arg.Error<Util::Result::Force>());
arguments.push_back(std::move(arg.Result<Util::Result::Force>()));
}
}
@@ -138,18 +141,99 @@ namespace PashaBibko::LXC::Parser
return ParsePrimary(ctx);
}
static Util::ReturnVal<AST::NodePtr, ParserError> ParseOperation(ParserContext& ctx)
{}
static Util::ReturnVal<AST::NodeValuePtr, ParserError> ParseOperation(ParserContext& ctx)
{
// Parses the left hand side of the operation //
Util::ReturnVal lhs = ParseFunctionCall(ctx);
if (lhs.Failed())
return Util::FunctionFail<ParserError>(lhs.Error<Util::Result::Force>());
// Checks if the left hand side was part of an operation //
const Lexer::Token* operand = ctx.At();
if (operand != nullptr && Lexer::Token::IsTypeClass<Lexer::TokenClass::Operator>(operand->type))
{
// Iterates over the operand and parses the right hand side of the operation //
ctx.Advance();
Util::ReturnVal rhs = ParseOperation(ctx);
if (rhs.Failed())
return Util::FunctionFail<ParserError>(rhs.Error<Util::Result::Force>());
// Else the sides can be returned as an operation //
return Internal::CreateNodeV<AST::Operation>(lhs.Result<Util::Result::Force>(), operand->type, rhs.Result<Util::Result::Force>());
}
// If not returns the left node on its own //
return std::move(lhs.Result<Util::Result::Force>());
}
static Util::ReturnVal<AST::NodePtr, ParserError> ParseReturn(ParserContext& ctx)
{}
{
// Checks if it is at a return statement //
const Lexer::Token* at = ctx.At();
if (at == nullptr)
return Util::FunctionFail<ParserError>(); // <- TODO: Make an actual error
if (at->type == Lexer::Token::Return)
{
// Iterates over the return token and parses the value to be returned //
ctx.Advance();
Util::ReturnVal returnVal = ParseOperation(ctx);
if (returnVal.Failed())
return Util::FunctionFail<ParserError>(returnVal.Error<Util::Result::Force>());
return Internal::CreateNode<AST::ReturnStatement>(returnVal.Result<Util::Result::Force>());
}
// Else traverses down the call stack (has to be upcasted) //
Util::ReturnVal value = ParseOperation(ctx);
if (value.Failed())
return Util::FunctionFail<ParserError>(value.Error());
AST::NodePtr upcast = std::move(value.Result<Util::Result::Force>());
return upcast;
}
static Util::ReturnVal<AST::NodePtr, ParserError> ParseVarDeclaration(ParserContext& ctx)
{}
static Util::ReturnVal<AST::NodePtr, ParserError> Parse(ParserContext& ctx)
{
return (AST::NodePtr)nullptr;
// Checks for the pattern of a variable declaration //
if (ctx.Expect(std::array{ Lexer::Token::Identifier, Lexer::Token::Colon }))
{
// Can safely advance over the pattern (types are not checked/stored yet) //
ctx.Advance(2);
const Lexer::Token* varName = ctx.At();
std::string varNameStr = varName->Str();
if (varName == nullptr)
return Util::FunctionFail<ParserError>(); // <- TODO: Make an actual error
if (varName->type != Lexer::Token::Identifier)
return Util::FunctionFail<ParserError>(); // <- TODO: Make an actual error
// Checks for a default value for the variable //
const Lexer::Token* varAssign = ctx.Peek();
if (varAssign == nullptr)
return Internal::CreateNode<AST::VarDeclaration>(varNameStr);
if (varAssign->type != Lexer::Token::Assign)
return Internal::CreateNode<AST::VarDeclaration>(varNameStr);
// Creates a node with the default value of the variable //
ctx.Advance();
Util::ReturnVal defaultVal = ParseOperation(ctx);
if (defaultVal.Failed())
return Util::FunctionFail<ParserError>(defaultVal.Error<Util::Result::Force>());
return Internal::CreateNode<AST::VarDeclaration>(varNameStr, defaultVal.Result<Util::Result::Force>());
}
// Else traverses up the call stack //
return ParseReturn(ctx);
}
static inline Util::ReturnVal<AST::NodePtr, ParserError> Parse(ParserContext& ctx)
{
// Alias for the top of the call stack //
return ParseVarDeclaration(ctx);
}
static Util::ReturnVal<FunctionAST, ParserError> ParseFunction(ParserContext& ctx)