Started implementing parser
This commit is contained in:
@@ -15,7 +15,7 @@ namespace LXC::Parser
|
||||
name{}, contents{}
|
||||
{}
|
||||
|
||||
FunctionAST(FunctionAST&& other) :
|
||||
FunctionAST(FunctionAST&& other) noexcept :
|
||||
name{}, contents{}
|
||||
{}
|
||||
|
||||
|
||||
@@ -23,8 +23,11 @@ namespace LXC::Parser
|
||||
return &input[peekIndex];
|
||||
}
|
||||
|
||||
// Returns a pointer to the current token //
|
||||
inline const Lexer::Token* At() const { return Peek(0); }
|
||||
|
||||
// Advances x-distance in the tokens (default 1) //
|
||||
inline const Lexer::Token* Next(size_t distance = 1)
|
||||
inline const Lexer::Token* Advance(size_t distance = 1)
|
||||
{
|
||||
// Adds the distance and checks if in bounds to stop read errors //
|
||||
index += distance;
|
||||
@@ -34,6 +37,19 @@ namespace LXC::Parser
|
||||
return &input[index];
|
||||
}
|
||||
|
||||
// Checks if the tokens are the correct types //
|
||||
inline bool Expect(const std::span<const Lexer::Token::TokenType>& tokens) const
|
||||
{
|
||||
for (int i = 0; i < tokens.size(); i++)
|
||||
{
|
||||
const Lexer::Token* current = Peek(i);
|
||||
if (!current || current->type != tokens[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Is the current index in bounds //
|
||||
inline bool InBounds() const { return index < length; }
|
||||
|
||||
@@ -47,9 +63,90 @@ namespace LXC::Parser
|
||||
const size_t length;
|
||||
};
|
||||
|
||||
static Util::ReturnVal<void*, ParserError> ParseFunction(const ParserContext& ctx)
|
||||
static void ParseBlock(ParserContext& ctx)
|
||||
{
|
||||
return Util::FunctionFail<ParserError>();
|
||||
// Local lamdba for working out if at the end (static to avoid double initalisation) //
|
||||
static const std::function<bool(const ParserContext&)> AtEnd = [](const ParserContext& context)
|
||||
{
|
||||
// Peeks the current tokens type //
|
||||
const Lexer::Token* current = context.Peek();
|
||||
if (current != nullptr)
|
||||
{
|
||||
return current->type == Lexer::Token::CloseBrace;
|
||||
}
|
||||
|
||||
// If nullptr means it has overflowed so it is at the end //
|
||||
return true;
|
||||
};
|
||||
|
||||
// Loops over the body until it reaches the end //
|
||||
while (!AtEnd(ctx))
|
||||
{
|
||||
// Force ends if it has gone over the end of the tokens //
|
||||
const Lexer::Token* current = ctx.Advance();
|
||||
if (current != nullptr)
|
||||
{
|
||||
// Recurses if at the start of another block //
|
||||
if (current->type == Lexer::Token::OpenBrace)
|
||||
ParseBlock(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// Advances over the ending close brace //
|
||||
ctx.Advance();
|
||||
}
|
||||
|
||||
static Util::ReturnVal<FunctionAST, ParserError> ParseFunction(ParserContext& ctx)
|
||||
{
|
||||
// Checks for the sequence of: func<T> funcName( //
|
||||
if (!ctx.Expect(std::array{ Lexer::Token::FunctionDef, Lexer::Token::OpenCrocodile, Lexer::Token::Identifier, Lexer::Token::CloseCrocodile, Lexer::Token::Identifier, Lexer::Token::OpenParen }))
|
||||
return Util::FunctionFail<ParserError>(); // <- TODO: Make an actual error
|
||||
|
||||
// Assumes int for now so skips over func<T> //
|
||||
const Lexer::Token* funcName = ctx.Advance(4);
|
||||
|
||||
// Assigns the name of the function //
|
||||
FunctionAST currentFunction;
|
||||
currentFunction.name = funcName->Str();
|
||||
|
||||
// Looks for the parameters of the function //
|
||||
const Lexer::Token* paramsStart = ctx.Advance(2);
|
||||
if (paramsStart == nullptr )
|
||||
return Util::FunctionFail<ParserError>(); // <- TODO: Make an actual error
|
||||
|
||||
// Parses the parameters of the function //
|
||||
if (paramsStart->type == Lexer::Token::Identifier && paramsStart->Str() == "void")
|
||||
{ /* No parameters/arguments for the function */}
|
||||
|
||||
// Loops over the parameters/arguments of the function declaration //
|
||||
else
|
||||
{
|
||||
while (ctx.At()->type != Lexer::Token::CloseParen)
|
||||
{
|
||||
// Checks for parameter pattern: identifier, identifier //
|
||||
if (!ctx.Expect(std::array{ Lexer::Token::Identifier, Lexer::Token::Identifier }))
|
||||
return Util::FunctionFail<ParserError>(); // <- TODO: Make an actual error
|
||||
|
||||
const Lexer::Token* paramType = ctx.At();
|
||||
const Lexer::Token* paramName = ctx.Advance();
|
||||
|
||||
// Expects a comma or close bracket for the next token //
|
||||
const Lexer::Token* end = ctx.Advance();
|
||||
if (end == nullptr)
|
||||
return Util::FunctionFail<ParserError>(); // <- TODO: Make an actual error
|
||||
|
||||
if (end->type == Lexer::Token::Comma || end->type == Lexer::Token::CloseParen)
|
||||
continue;
|
||||
|
||||
return Util::FunctionFail<ParserError>(); // <- TODO: Make an actual error
|
||||
}
|
||||
}
|
||||
|
||||
// Parses the function body //
|
||||
ParseBlock(ctx);
|
||||
ctx.Advance(); // <- Goes over the closing brace
|
||||
|
||||
return currentFunction;
|
||||
}
|
||||
|
||||
Util::ReturnVal<std::vector<FunctionAST>, ParserError> TurnTokensIntoAST(const Lexer::LexerOutput& input)
|
||||
@@ -58,10 +155,10 @@ namespace LXC::Parser
|
||||
ParserContext ctx(input);
|
||||
|
||||
// Continues whilst in the bounds of the tokens //
|
||||
while (ctx.InBounds())
|
||||
while (ctx.InBounds())
|
||||
{
|
||||
// Peeks the next token (guaranteed to not be at the end) //
|
||||
const Lexer::Token* current = ctx.Peek();
|
||||
const Lexer::Token* current = ctx.At();
|
||||
|
||||
// Switches over the type of the current token to run the correct logic //
|
||||
switch (current->type)
|
||||
@@ -84,6 +181,6 @@ namespace LXC::Parser
|
||||
}
|
||||
|
||||
// Returns the output as it has gone through all the tokens //
|
||||
return std::move(ctx.output); // Moves instead of copying, (required due to std::unique_ptr<>)
|
||||
return std::move(ctx.output); // Moves instead of copying, (required due to std::unique_ptr<> within the class)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user