mirror of
https://github.com/PashaBibko/LX.git
synced 2026-04-03 17:39:02 +00:00
Im vonfused
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
17
Parser/src/AST-Loggers.cpp
Normal file
17
Parser/src/AST-Loggers.cpp
Normal 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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,9 @@
|
|||||||
|
func add
|
||||||
|
{
|
||||||
|
return 1 + 2
|
||||||
|
}
|
||||||
|
|
||||||
func main
|
func main
|
||||||
|
{
|
||||||
return 375 + 32
|
return 375 + 32
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user