mirror of
https://github.com/PashaBibko/LX.git
synced 2026-04-03 17:39:02 +00:00
Improved syntax for functions
Added logging system for AST nodes as well.
This commit is contained in:
@@ -81,6 +81,8 @@ namespace LX
|
|||||||
OPEN_BRACE, CLOSE_BRACE,
|
OPEN_BRACE, CLOSE_BRACE,
|
||||||
OPEN_PAREN, CLOSE_PAREN,
|
OPEN_PAREN, CLOSE_PAREN,
|
||||||
|
|
||||||
|
COMMA,
|
||||||
|
|
||||||
// Operators //
|
// Operators //
|
||||||
|
|
||||||
ADD, SUB, MUL, DIV,
|
ADD, SUB, MUL, DIV,
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ namespace LX::AST
|
|||||||
{
|
{
|
||||||
// General Nodes //
|
// General Nodes //
|
||||||
|
|
||||||
IDENTIFIER,
|
|
||||||
NUMBER_LITERAL,
|
NUMBER_LITERAL,
|
||||||
OPERATION,
|
OPERATION,
|
||||||
|
|
||||||
@@ -48,6 +47,9 @@ namespace LX::AST
|
|||||||
// Function for generating LLVN IR (Intermediate representation) //
|
// Function for generating LLVN IR (Intermediate representation) //
|
||||||
virtual llvm::Value* GenIR(InfoLLVM& LLVM) = 0;
|
virtual llvm::Value* GenIR(InfoLLVM& LLVM) = 0;
|
||||||
|
|
||||||
|
// Function to log the node to a file //
|
||||||
|
virtual void Log(std::ofstream* log, unsigned depth) = 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;
|
||||||
|
|
||||||
|
|||||||
@@ -178,9 +178,11 @@ int main(int argc, char** argv)
|
|||||||
LX::PrintStringAsColor("Error: ", LX::Color::LIGHT_RED);
|
LX::PrintStringAsColor("Error: ", LX::Color::LIGHT_RED);
|
||||||
std::cout << "Invalid character found in ";
|
std::cout << "Invalid character found in ";
|
||||||
LX::PrintStringAsColor(inpPath.filename().string(), LX::Color::WHITE);
|
LX::PrintStringAsColor(inpPath.filename().string(), LX::Color::WHITE);
|
||||||
std::cout << ":\n";
|
std::cout << " {";
|
||||||
|
LX::PrintStringAsColor(std::string(1, e.invalid), LX::Color::LIGHT_RED);
|
||||||
|
std::cout << "}:\n";
|
||||||
std::cout << "Line: " << std::setw(lineNumberWidthInConsole) << e.line << " | " << line << "\n";
|
std::cout << "Line: " << std::setw(lineNumberWidthInConsole) << e.line << " | " << line << "\n";
|
||||||
std::cout << " " << std::setw(lineNumberWidthInConsole) << "" << " | " << std::setw(e.col);
|
std::cout << " " << std::setw(lineNumberWidthInConsole) << "" << " | " << std::setw(e.col + 1);
|
||||||
LX::PrintStringAsColor("^", LX::Color::LIGHT_RED);
|
LX::PrintStringAsColor("^", LX::Color::LIGHT_RED);
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
|
|
||||||
@@ -215,7 +217,7 @@ int main(int argc, char** argv)
|
|||||||
// Prints the code with the error to the console //
|
// Prints the code with the error to the console //
|
||||||
std::string errorSquiggle(e.got.length, '~');
|
std::string errorSquiggle(e.got.length, '~');
|
||||||
std::cout << "Line: " << std::setw(lineNumberWidthInConsole) << e.got.line << " | " << line << "\n";
|
std::cout << "Line: " << std::setw(lineNumberWidthInConsole) << e.got.line << " | " << line << "\n";
|
||||||
std::cout << " " << std::setw(lineNumberWidthInConsole) << "" << " | " << std::setw(e.got.column) << "";
|
std::cout << " " << std::setw(lineNumberWidthInConsole) << "" << " | " << std::setw(e.got.column + 1) << "";
|
||||||
LX::PrintStringAsColor(errorSquiggle, LX::Color::LIGHT_RED);
|
LX::PrintStringAsColor(errorSquiggle, LX::Color::LIGHT_RED);
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,8 @@ namespace LX
|
|||||||
{ '[', Token::OPEN_BRACE },
|
{ '[', Token::OPEN_BRACE },
|
||||||
{ ']', Token::CLOSE_BRACE },
|
{ ']', Token::CLOSE_BRACE },
|
||||||
{ '(', Token::OPEN_PAREN },
|
{ '(', Token::OPEN_PAREN },
|
||||||
{ ')', Token::CLOSE_PAREN }
|
{ ')', Token::CLOSE_PAREN },
|
||||||
|
{ ',', Token::COMMA }
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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 //
|
||||||
|
|||||||
@@ -16,9 +16,6 @@ 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
|
||||||
@@ -33,6 +30,9 @@ namespace LX::AST
|
|||||||
// Function for generating LLVN IR (Intermediate representation) //
|
// Function for generating LLVN IR (Intermediate representation) //
|
||||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
||||||
|
|
||||||
|
// Function to log the node to a file //
|
||||||
|
void Log(std::ofstream* log, unsigned depth) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The number it stores //
|
// The number it stores //
|
||||||
// Yes the number is stored as a string, It's horrible I know //
|
// Yes the number is stored as a string, It's horrible I know //
|
||||||
@@ -49,6 +49,9 @@ namespace LX::AST
|
|||||||
// Function for generating LLVN IR (Intermediate representation) //
|
// Function for generating LLVN IR (Intermediate representation) //
|
||||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
||||||
|
|
||||||
|
// Function to log the node to a file //
|
||||||
|
void Log(std::ofstream* log, unsigned depth) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The sides of the operation //
|
// The sides of the operation //
|
||||||
// Unary operations are handled by a different class //
|
// Unary operations are handled by a different class //
|
||||||
@@ -68,6 +71,9 @@ namespace LX::AST
|
|||||||
// Function for generating LLVN IR (Intermediate representation) //
|
// Function for generating LLVN IR (Intermediate representation) //
|
||||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
||||||
|
|
||||||
|
// Function to log the node to a file //
|
||||||
|
void Log(std::ofstream* log, unsigned depth) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// What it is returning (can be null) //
|
// What it is returning (can be null) //
|
||||||
std::unique_ptr<Node> m_Val;
|
std::unique_ptr<Node> m_Val;
|
||||||
|
|||||||
@@ -1,17 +1,43 @@
|
|||||||
#include <AST.h>
|
#include <AST.h>
|
||||||
|
|
||||||
namespace LX
|
#include <fstream>
|
||||||
{
|
|
||||||
std::string ToString(std::unique_ptr<AST::Node>& node)
|
|
||||||
{
|
|
||||||
if (node == nullptr) { return "NULL Node"; }
|
|
||||||
|
|
||||||
switch (node->m_Type)
|
namespace LX::AST
|
||||||
|
{
|
||||||
|
void Node::Log(std::ofstream* log, unsigned depth)
|
||||||
|
{
|
||||||
|
(*log) << std::string(depth, '\t') << "NULL node";
|
||||||
|
}
|
||||||
|
|
||||||
|
void NumberLiteral::Log(std::ofstream* log, unsigned depth)
|
||||||
|
{
|
||||||
|
(*log) << std::string(depth, '\t');
|
||||||
|
(*log) << "Number: " << m_Number << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Operation::Log(std::ofstream* log, unsigned depth)
|
||||||
|
{
|
||||||
|
(*log) << std::string(depth, '\t');
|
||||||
|
(*log) << "Operation {" << ToString(m_Operand) << "}:\n";
|
||||||
|
(*log) << std::string(depth + 1, '\t') << "LHS:\n";
|
||||||
|
m_Lhs.get()->Log(log, depth + 2);
|
||||||
|
(*log) << std::string(depth + 1, '\t') << "RHS:\n";
|
||||||
|
m_Rhs.get()->Log(log, depth + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReturnStatement::Log(std::ofstream* log, unsigned depth)
|
||||||
|
{
|
||||||
|
(*log) << std::string(depth, '\t');
|
||||||
|
|
||||||
|
if (m_Val == nullptr)
|
||||||
{
|
{
|
||||||
case AST::Node::IDENTIFIER: return "IDENTIFIER";
|
(*log) << "Return\n";
|
||||||
case AST::Node::OPERATION: return "OPERATION";
|
}
|
||||||
case AST::Node::RETURN_STATEMENT: return "return";
|
|
||||||
case AST::Node::NUMBER_LITERAL: return "number";
|
else
|
||||||
|
{
|
||||||
|
(*log) << "Return:\n";
|
||||||
|
m_Val->Log(log, depth + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,12 +42,13 @@ 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());
|
||||||
|
|
||||||
//
|
// TODO: Fix this //
|
||||||
case Token::OPEN_BRACKET:
|
case Token::OPEN_BRACKET:
|
||||||
p.scopeDepth++;
|
p.scopeDepth++;
|
||||||
p.index++;
|
p.index++;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
// TODO: Fix this //
|
||||||
case Token::CLOSE_BRACE:
|
case Token::CLOSE_BRACE:
|
||||||
ThrowIf<UnexpectedToken>(p.scopeDepth == 0, Token::UNDEFINED, "need a different error", p.tokens[p.index]);
|
ThrowIf<UnexpectedToken>(p.scopeDepth == 0, Token::UNDEFINED, "need a different error", p.tokens[p.index]);
|
||||||
p.scopeDepth--;
|
p.scopeDepth--;
|
||||||
@@ -148,19 +149,31 @@ namespace LX
|
|||||||
ThrowIf<UnexpectedToken>(p.tokens[p.index].type != Token::IDENTIFIER, 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 paren '(' //
|
||||||
|
ThrowIf<UnexpectedToken>(p.tokens[p.index].type != Token::OPEN_PAREN, Token::OPEN_PAREN, "", p.tokens[p.index]);
|
||||||
|
p.index++;
|
||||||
|
|
||||||
|
// Loops over all the arguments of the function //
|
||||||
|
while (p.index < p.len && (p.tokens[p.index].type == Token::CLOSE_PAREN) == false)
|
||||||
|
{
|
||||||
|
p.index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skips over close bracket //
|
||||||
|
p.index++;
|
||||||
|
|
||||||
// Checks for opening bracket '{' //
|
// Checks for opening bracket '{' //
|
||||||
ThrowIf<UnexpectedToken>(p.tokens[p.index].type != Token::OPEN_BRACKET, Token::OPEN_BRACKET, "", p.tokens[p.index]);
|
ThrowIf<UnexpectedToken>(p.tokens[p.index].type != Token::OPEN_BRACKET, Token::OPEN_BRACKET, "", p.tokens[p.index]);
|
||||||
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
|
|
||||||
while (p.index < p.len && (p.tokens[p.index].type == Token::CLOSE_BRACKET && p.scopeDepth == 0) == false)
|
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 //
|
// Logs the node to the log //
|
||||||
SafeLog(log, ToString(node));
|
if (log != nullptr) { node->Log(log, 0); }
|
||||||
|
|
||||||
// Adds it to the vector
|
// Adds it to the vector
|
||||||
func.body.push_back(std::move(node));
|
func.body.push_back(std::move(node));
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
func add
|
func main()
|
||||||
{
|
{
|
||||||
return 1 + 2
|
return 1 + 2
|
||||||
}
|
}
|
||||||
|
|
||||||
func main
|
|
||||||
{
|
|
||||||
return 375 + 32
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user