mirror of
https://github.com/PashaBibko/LX.git
synced 2026-04-04 01:49:05 +00:00
Parser is held together by duck-tape and a wish
This commit is contained in:
@@ -45,6 +45,7 @@ namespace LX
|
|||||||
{ "else" , Token::ELSE },
|
{ "else" , Token::ELSE },
|
||||||
{ "elif" , Token::ELIF },
|
{ "elif" , Token::ELIF },
|
||||||
{ "func" , Token::FUNCTION },
|
{ "func" , Token::FUNCTION },
|
||||||
|
{ "return" , Token::RETURN }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::unordered_map<char, Token::TokenType> operators =
|
static const std::unordered_map<char, Token::TokenType> operators =
|
||||||
|
|||||||
3
Main.cpp
3
Main.cpp
@@ -52,6 +52,9 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
// Create tokens out of the input file
|
// Create tokens out of the input file
|
||||||
std::vector<LX::Token>tokens = LX::LexicalAnalyze(inpFile, log.get());
|
std::vector<LX::Token>tokens = LX::LexicalAnalyze(inpFile, log.get());
|
||||||
|
|
||||||
|
// Turns the tokens into an AST
|
||||||
|
LX::FileAST AST = LX::TurnTokensIntoAbstractSyntaxTree(tokens, log.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (LX::IncorrectCommandLineArgs)
|
catch (LX::IncorrectCommandLineArgs)
|
||||||
|
|||||||
@@ -1,9 +1,113 @@
|
|||||||
#include <Parser.h>
|
#include <Parser.h>
|
||||||
|
#include <Util.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace LX
|
namespace LX
|
||||||
{
|
{
|
||||||
|
// Local struct so everything can be public //
|
||||||
|
struct Parser
|
||||||
|
{
|
||||||
|
Parser(std::vector<Token>& _tokens, std::ofstream* _log)
|
||||||
|
: tokens(_tokens), log(_log), index(0), len(_tokens.size())
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::vector<Token>& tokens;
|
||||||
|
std::ofstream* log;
|
||||||
|
|
||||||
|
const size_t len;
|
||||||
|
size_t index;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::unique_ptr<AST::Node> ParsePrimary(Parser& p)
|
||||||
|
{
|
||||||
|
switch (p.tokens[p.index].type)
|
||||||
|
{
|
||||||
|
case Token::NUMBER_LITERAL:
|
||||||
|
return std::make_unique<AST::NumberLiteral>(p.tokens[p.index].contents);
|
||||||
|
|
||||||
|
default:
|
||||||
|
std::cout << "UNKNOWN TOKEN: " << p.tokens[p.index].type << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<AST::Node> ParseOperation(Parser& p)
|
||||||
|
{
|
||||||
|
if (p.tokens[p.index + 1].type == Token::ADD)
|
||||||
|
{
|
||||||
|
std::unique_ptr<AST::Node> lhs = ParsePrimary(p);
|
||||||
|
p.index++;
|
||||||
|
|
||||||
|
// Skips over operator (again i'm lazy)
|
||||||
|
p.index++;
|
||||||
|
|
||||||
|
std::unique_ptr<AST::Node> rhs = ParsePrimary(p);
|
||||||
|
|
||||||
|
return std::make_unique<AST::Operation>(std::move(lhs), Token::ADD, std::move(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParsePrimary(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<AST::Node> ParseReturn(Parser& p)
|
||||||
|
{
|
||||||
|
if (p.tokens[p.index].type == Token::RETURN)
|
||||||
|
{
|
||||||
|
p.index++;
|
||||||
|
return std::make_unique<AST::ReturnStatement>(ParseOperation(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParseOperation(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<AST::Node> Parse(Parser& p)
|
||||||
|
{
|
||||||
|
return ParseReturn(p);
|
||||||
|
}
|
||||||
|
|
||||||
FileAST TurnTokensIntoAbstractSyntaxTree(std::vector<Token>& tokens, std::ofstream* log)
|
FileAST TurnTokensIntoAbstractSyntaxTree(std::vector<Token>& tokens, std::ofstream* log)
|
||||||
{
|
{
|
||||||
return FileAST();
|
// Logs the start of the parsing
|
||||||
|
SafeLog(log, LOG_BREAK, "Started parsing tokens", LOG_BREAK);
|
||||||
|
|
||||||
|
FileAST output;
|
||||||
|
Parser p(tokens, log);
|
||||||
|
|
||||||
|
while (p.index < p.len)
|
||||||
|
{
|
||||||
|
switch (p.tokens[p.index].type)
|
||||||
|
{
|
||||||
|
case Token::FUNCTION:
|
||||||
|
{
|
||||||
|
// Skips over function token + name token
|
||||||
|
// TEMPORARY
|
||||||
|
p.index++; p.index++;
|
||||||
|
|
||||||
|
output.functions.emplace_back();
|
||||||
|
FunctionDefinition& func = output.functions.back();
|
||||||
|
|
||||||
|
// TEMPORARY casue im lazy
|
||||||
|
while (p.index < p.len)
|
||||||
|
{
|
||||||
|
// Actually parses the function
|
||||||
|
std::unique_ptr<AST::Node> node = Parse(p);
|
||||||
|
|
||||||
|
// Adds it to the vector and iterates to the next token
|
||||||
|
func.body.push_back(std::move(node));
|
||||||
|
p.index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
std::cout << "UNKNOWN TOKEN FOUND" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SafeLog(log, "AST length: ", output.functions[0].body.size());
|
||||||
|
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,13 @@ Started lexing file
|
|||||||
|
|
||||||
Token::FUNCTION
|
Token::FUNCTION
|
||||||
Token::IDENTIFIER: main
|
Token::IDENTIFIER: main
|
||||||
Token::IDENTIFIER: return
|
Unknown: 3
|
||||||
Token::NUMBER_LITERAL: 34
|
Token::NUMBER_LITERAL: 34
|
||||||
Token::ADD
|
Token::ADD
|
||||||
Token::NUMBER_LITERAL: 4
|
Token::NUMBER_LITERAL: 4324
|
||||||
|
|
||||||
|
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
Started parsing tokens
|
||||||
|
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
|
||||||
|
AST length: 1
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
func main
|
func main
|
||||||
return 34 + 4
|
return 34 + 4324
|
||||||
|
|
||||||
|
|||||||
@@ -24,9 +24,8 @@ namespace llvm
|
|||||||
namespace LX::AST
|
namespace LX::AST
|
||||||
{
|
{
|
||||||
// Base node that everything else inherits from
|
// Base node that everything else inherits from
|
||||||
class Node
|
struct Node
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
// Enum for storing the type of node //
|
// Enum for storing the type of node //
|
||||||
// Used so a pointer to Node can be used and then turned into it's true type //
|
// Used so a pointer to Node can be used and then turned into it's true type //
|
||||||
enum NodeType
|
enum NodeType
|
||||||
@@ -34,9 +33,13 @@ namespace LX::AST
|
|||||||
// General Nodes //
|
// General Nodes //
|
||||||
|
|
||||||
IDENTIFIER,
|
IDENTIFIER,
|
||||||
|
NUMBER_LITERAL,
|
||||||
|
OPERATION,
|
||||||
|
|
||||||
// Control flow Nodes //
|
// Control flow Nodes //
|
||||||
|
|
||||||
|
RETURN_STATEMENT,
|
||||||
|
|
||||||
// If an error happened somewhere //
|
// If an error happened somewhere //
|
||||||
UNDEFINED = -1
|
UNDEFINED = -1
|
||||||
};
|
};
|
||||||
@@ -53,23 +56,90 @@ namespace LX::AST
|
|||||||
virtual llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder) = 0;
|
virtual llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder) = 0;
|
||||||
|
|
||||||
// Function for generating C/C++ code (Currently not implemented) //
|
// Function for generating C/C++ code (Currently not implemented) //
|
||||||
virtual void GenC() = 0;
|
//virtual void GenC() = 0;
|
||||||
|
|
||||||
// The type of the node //
|
// The type of the node //
|
||||||
const NodeType m_Type;
|
const NodeType m_Type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NumberLiteral : public Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NumberLiteral(std::string num)
|
||||||
|
: Node(Node::NUMBER_LITERAL), m_Number(num)
|
||||||
|
{}
|
||||||
|
|
||||||
|
llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The number it stores
|
||||||
|
// Yes the number is stored as a string
|
||||||
|
// It's horrible I know
|
||||||
|
std::string m_Number;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
class Operation : public Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Operation(std::unique_ptr<Node> lhs, Token::TokenType op, std::unique_ptr<Node> rhs)
|
||||||
|
: Node(Node::OPERATION), m_Lhs(std::move(lhs)), m_Operand(op), m_Rhs(std::move(rhs))
|
||||||
|
{}
|
||||||
|
|
||||||
|
llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The sides of the operation
|
||||||
|
// Unary operations are handled by a different class
|
||||||
|
std::unique_ptr<Node> m_Lhs, m_Rhs;
|
||||||
|
|
||||||
|
// The operation to be applied to the two sides
|
||||||
|
Token::TokenType m_Operand;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
class ReturnStatement : public Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReturnStatement(std::unique_ptr<Node> val)
|
||||||
|
: Node(Node::RETURN_STATEMENT), m_Val(std::move(val))
|
||||||
|
{}
|
||||||
|
|
||||||
|
llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// What it is returning (can be null)
|
||||||
|
std::unique_ptr<Node> m_Val;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace LX
|
namespace LX
|
||||||
{
|
{
|
||||||
struct FunctionDeclaration
|
struct FunctionDefinition
|
||||||
{
|
{
|
||||||
|
FunctionDefinition()
|
||||||
|
: body{}
|
||||||
|
{}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<AST::Node>> body;
|
std::vector<std::unique_ptr<AST::Node>> body;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FileAST
|
struct FileAST
|
||||||
{
|
{
|
||||||
std::vector<FunctionDeclaration> functions;
|
FileAST()
|
||||||
|
: functions{}
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::vector<FunctionDefinition> functions;
|
||||||
};
|
};
|
||||||
|
|
||||||
FileAST TurnTokensIntoAbstractSyntaxTree(std::vector<Token>& tokens, std::ofstream* log);
|
FileAST TurnTokensIntoAbstractSyntaxTree(std::vector<Token>& tokens, std::ofstream* log);
|
||||||
|
|||||||
Reference in New Issue
Block a user