Finished parser functions
Time for fixing bugs YAYYYYYYYYYYY
This commit is contained in:
@@ -9,7 +9,7 @@ int main(int argc, char** argv)
|
|||||||
using namespace PashaBibko::LXC;
|
using namespace PashaBibko::LXC;
|
||||||
using namespace PashaBibko;
|
using namespace PashaBibko;
|
||||||
|
|
||||||
std::filesystem::path src = "examples/Fib.lx";
|
std::filesystem::path src = "examples/Basic.lx";
|
||||||
|
|
||||||
// Reads the given file to a string //
|
// Reads the given file to a string //
|
||||||
Util::ReturnVal fileContents = Util::ReadFile(src);
|
Util::ReturnVal fileContents = Util::ReadFile(src);
|
||||||
|
|||||||
6
examples/Basic.lx
Normal file
6
examples/Basic.lx
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
func<int> main()
|
||||||
|
{
|
||||||
|
int: res = 5 + 34
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
@@ -109,7 +109,7 @@ namespace PashaBibko::LXC::Parser
|
|||||||
static Util::ReturnVal<AST::NodeValuePtr, ParserError> ParseFunctionCall(ParserContext& ctx)
|
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)] //
|
// 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 //
|
// Captures the function name and advances over it and the start paren //
|
||||||
const Lexer::Token* functionNameToken = ctx.At();
|
const Lexer::Token* functionNameToken = ctx.At();
|
||||||
@@ -130,7 +130,10 @@ namespace PashaBibko::LXC::Parser
|
|||||||
ctx.Advance();
|
ctx.Advance();
|
||||||
|
|
||||||
// Adds the current argument to the ValueList //
|
// 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);
|
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)
|
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> 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)
|
static Util::ReturnVal<FunctionAST, ParserError> ParseFunction(ParserContext& ctx)
|
||||||
|
|||||||
Reference in New Issue
Block a user