Im vonfused

This commit is contained in:
Pasha Bibko
2025-04-22 22:32:07 +01:00
parent 8e1fa45a44
commit 099e543e95
8 changed files with 100 additions and 15 deletions

View File

@@ -75,6 +75,12 @@ namespace LX
IDENTIFIER, IDENTIFIER,
RETURN, RETURN,
// Symbols //
OPEN_BRACKET, CLOSE_BRACKET,
OPEN_BRACE, CLOSE_BRACE,
OPEN_PAREN, CLOSE_PAREN,
// Operators // // Operators //
ADD, SUB, MUL, DIV, ADD, SUB, MUL, DIV,

View File

@@ -34,6 +34,12 @@ namespace LX
TOKEN_CASE(Token::DIV); TOKEN_CASE(Token::DIV);
TOKEN_CASE(Token::NUMBER_LITERAL); TOKEN_CASE(Token::NUMBER_LITERAL);
TOKEN_CASE(Token::RETURN); TOKEN_CASE(Token::RETURN);
TOKEN_CASE(Token::OPEN_BRACE);
TOKEN_CASE(Token::CLOSE_BRACE);
TOKEN_CASE(Token::OPEN_BRACKET);
TOKEN_CASE(Token::CLOSE_BRACKET);
TOKEN_CASE(Token::OPEN_PAREN);
TOKEN_CASE(Token::CLOSE_PAREN);
default: default:
return "Unknown: " + std::to_string(type); return "Unknown: " + std::to_string(type);
@@ -99,6 +105,17 @@ namespace LX
{ "return" , Token::RETURN } { "return" , Token::RETURN }
}; };
// All the symbols supported by the lexer //
static const std::unordered_map<char, Token::TokenType> symbols =
{
{ '{', Token::OPEN_BRACKET },
{ '}', Token::CLOSE_BRACKET },
{ '[', Token::OPEN_BRACE },
{ ']', Token::CLOSE_BRACE },
{ '(', Token::OPEN_PAREN },
{ ')', Token::CLOSE_PAREN }
};
// All the single-char operators currently supported by the lexer with their token-enum equivalents // // All the single-char operators currently supported by the lexer with their token-enum equivalents //
// TODO: Support multi-char operators such as: ==, -> +=, && // TODO: Support multi-char operators such as: ==, -> +=, &&
static const std::unordered_map<char, Token::TokenType> operators = static const std::unordered_map<char, Token::TokenType> operators =
@@ -257,6 +274,12 @@ namespace LX
// During a word // // During a word //
else if (info.isAlpha == true); else if (info.isAlpha == true);
// Symbols //
else if (auto sym = symbols.find(current); sym != symbols.end())
{
tokens.push_back({ sym->second, info, 1 });
}
// Operators (+, -, /, *) // // Operators (+, -, /, *) //
else if (auto op = operators.find(current); op != operators.end()) else if (auto op = operators.find(current); op != operators.end())
{ {

View File

@@ -141,6 +141,7 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="src\AST-Constructors.cpp" /> <ClCompile Include="src\AST-Constructors.cpp" />
<ClCompile Include="src\AST-LLVM.cpp" /> <ClCompile Include="src\AST-LLVM.cpp" />
<ClCompile Include="src\AST-Loggers.cpp" />
<ClCompile Include="src\GenIR.cpp" /> <ClCompile Include="src\GenIR.cpp" />
<ClCompile Include="src\Parser.cpp" /> <ClCompile Include="src\Parser.cpp" />
</ItemGroup> </ItemGroup>

View File

@@ -23,6 +23,9 @@
<ClCompile Include="src\GenIR.cpp"> <ClCompile Include="src\GenIR.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\AST-Loggers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="inc\AST.h"> <ClInclude Include="inc\AST.h">

View File

@@ -2,6 +2,8 @@
#include <LLVM.h> #include <LLVM.h>
#include <memory>
namespace LX namespace LX
{ {
// Wrapper over the LLVM variables for easier passing around // // Wrapper over the LLVM variables for easier passing around //
@@ -14,6 +16,9 @@ namespace LX
llvm::Module module; llvm::Module module;
llvm::IRBuilder<> builder; llvm::IRBuilder<> builder;
}; };
// Function to turn a AST node into string //
std::string ToString(std::unique_ptr<AST::Node>& node);
} }
namespace LX::AST namespace LX::AST

View File

@@ -0,0 +1,17 @@
#include <AST.h>
namespace LX
{
std::string ToString(std::unique_ptr<AST::Node>& node)
{
if (node == nullptr) { return "NULL Node"; }
switch (node->m_Type)
{
case AST::Node::IDENTIFIER: return "IDENTIFIER";
case AST::Node::OPERATION: return "OPERATION";
case AST::Node::RETURN_STATEMENT: return "return";
case AST::Node::NUMBER_LITERAL: return "number";
}
}
}

View File

@@ -7,18 +7,12 @@
namespace LX namespace LX
{ {
template<Token::TokenType type>
static inline void ExpectToken(const Token& t)
{
ThrowIf<int>(type != t.type);
}
// Local struct so everything can be public // // Local struct so everything can be public //
struct Parser struct Parser
{ {
// Passes constructor args to members // // Passes constructor args to members //
Parser(std::vector<Token>& _tokens, std::ofstream* _log) Parser(std::vector<Token>& _tokens, std::ofstream* _log)
: tokens(_tokens), log(_log), index(0), len(_tokens.size()) : tokens(_tokens), log(_log), index(0), len(_tokens.size()), scopeDepth(0)
{} {}
// Tokens created by the lexer // // Tokens created by the lexer //
@@ -32,6 +26,9 @@ namespace LX
// Current index within the token vector // // Current index within the token vector //
size_t index; size_t index;
// Current scope depth //
size_t scopeDepth;
}; };
// Base of the call stack to handle the simplest of tokens // // Base of the call stack to handle the simplest of tokens //
@@ -45,6 +42,18 @@ namespace LX
case Token::NUMBER_LITERAL: case Token::NUMBER_LITERAL:
return std::make_unique<AST::NumberLiteral>(p.tokens[p.index++].GetContents()); return std::make_unique<AST::NumberLiteral>(p.tokens[p.index++].GetContents());
//
case Token::OPEN_BRACKET:
p.scopeDepth++;
p.index++;
return nullptr;
case Token::CLOSE_BRACE:
ThrowIf<UnexpectedToken>(p.scopeDepth == 0, Token::UNDEFINED, "need a different error", p.tokens[p.index]);
p.scopeDepth--;
p.index++;
return nullptr;
// Returns nullptr, the parsing function that recives that value will decide if that is valid // // Returns nullptr, the parsing function that recives that value will decide if that is valid //
default: default:
p.index++; p.index++;
@@ -90,7 +99,7 @@ namespace LX
if (p.tokens[p.index].type == Token::RETURN) if (p.tokens[p.index].type == Token::RETURN)
{ {
// If so it adds an AST node with the value being returned // // If so it adds an AST node with the value being returned //
// TODO: Allow this to return nullptr // // Does not mind if this returns nullptr as that just means nothing was returned //
p.index++; p.index++;
return std::make_unique<AST::ReturnStatement>(ParseOperation(p)); return std::make_unique<AST::ReturnStatement>(ParseOperation(p));
} }
@@ -99,11 +108,15 @@ namespace LX
return ParseOperation(p); return ParseOperation(p);
} }
// Helper function to call the top of the Parse-Call-Stack // Helper function to call the top of the Parse-Call-Stack //
static inline std::unique_ptr<AST::Node> Parse(Parser& p) static inline std::unique_ptr<AST::Node> Parse(Parser& p)
{ {
// ParseReturn is currently the topmost function in the call stack // // Parses the current token //
return ParseReturn(p); std::unique_ptr<AST::Node> out = ParseReturn(p);
// Checks it is valid before returning //
ThrowIf<UnexpectedToken>(out == nullptr, Token::UNDEFINED, "top level statement", p.tokens[p.index - 1]);
return out;
} }
// Turns the tokens of a file into it's abstract syntax tree equivalent // // Turns the tokens of a file into it's abstract syntax tree equivalent //
@@ -124,7 +137,7 @@ namespace LX
{ {
case Token::FUNCTION: case Token::FUNCTION:
{ {
// Skips over function token + name token // // Skips over function token //
p.index++; p.index++;
// Pushes a new function to the vector and gets a reference to it for adding the body // // Pushes a new function to the vector and gets a reference to it for adding the body //
@@ -132,20 +145,30 @@ namespace LX
FunctionDefinition& func = output.functions.back(); FunctionDefinition& func = output.functions.back();
// Assigns the function name // // Assigns the function name //
ExpectToken<Token::IDENTIFIER>(p.tokens[p.index]); ThrowIf<UnexpectedToken>(p.tokens[p.index].type != Token::IDENTIFIER, Token::IDENTIFIER, "", p.tokens[p.index]);
func.name = p.tokens[p.index++].GetContents(); func.name = p.tokens[p.index++].GetContents();
// Checks for opening bracket '{' //
ThrowIf<UnexpectedToken>(p.tokens[p.index].type != Token::OPEN_BRACKET, Token::OPEN_BRACKET, "", p.tokens[p.index]);
p.index++;
// Loops over the body until it reaches the end // // Loops over the body until it reaches the end //
// TODO: Detect the end instead of looping over the entire token vector // TODO: Detect the end instead of looping over the entire token vector
while (p.index < p.len) while (p.index < p.len && (p.tokens[p.index].type == Token::CLOSE_BRACKET && p.scopeDepth == 0) == false)
{ {
// Actually parses the function // Actually parses the function
std::unique_ptr<AST::Node> node = Parse(p); std::unique_ptr<AST::Node> node = Parse(p);
// Logs the node to the log //
SafeLog(log, ToString(node));
// Adds it to the vector // Adds it to the vector
func.body.push_back(std::move(node)); func.body.push_back(std::move(node));
} }
// Skips over closing bracket //
p.index++;
// Goes to the next iteration of the loop // // Goes to the next iteration of the loop //
continue; continue;
} }
@@ -153,7 +176,7 @@ namespace LX
// Lets the user know there is an error // // Lets the user know there is an error //
// TODO: Makes this error actually output useful information // // TODO: Makes this error actually output useful information //
default: default:
std::cout << "UNKNOWN TOKEN FOUND: " << p.tokens[p.index].type << std::endl; std::cout << "UNKNOWN TOKEN FOUND: " << ToString(p.tokens[p.index].type) << std::endl;
return output; return output;
} }
} }

View File

@@ -1,2 +1,9 @@
func add
{
return 1 + 2
}
func main func main
{
return 375 + 32 return 375 + 32
}