Moved Common to external git repo

Also changed namespace from LXC to PashaBibko::LXC
This commit is contained in:
Pasha Bibko
2025-08-09 21:31:36 +01:00
parent 3c638fa92b
commit a54c0ccbab
26 changed files with 135 additions and 632 deletions

9
.gitattributes vendored
View File

@@ -1,2 +1,9 @@
# Auto detect text files and perform LF normalization # Normalizes line ending characters across all files #
* text=auto * text=auto
# Makes sure git propely recognises all languages used #
*.cpp linguist-language=C++
*.h linguist-language=C++
*.lx linguist-language=Text

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "external/googletest"] [submodule "external/googletest"]
path = external/googletest path = external/googletest
url = https://github.com/google/googletest.git url = https://github.com/google/googletest.git
[submodule "external/util"]
path = external/util
url = https://github.com/PashaBibko/PashaBibko-Util.git

View File

@@ -14,6 +14,9 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})
enable_testing() enable_testing()
add_subdirectory(external/googletest) add_subdirectory(external/googletest)
# Adds external projects #
add_subdirectory(external/util)
# Adds the sub-directories of all of the binaries # # Adds the sub-directories of all of the binaries #
# The order is equivalent to which order they are compiled # # The order is equivalent to which order they are compiled #
add_subdirectory(lexer) add_subdirectory(lexer)

View File

@@ -1,30 +0,0 @@
#pragma once
// MSVC Built in macros for non-MSVC enviroments //
#ifndef _UNLIKELY
#define _UNLIKELY [[unlikely]]
#endif // _UNLIKELY
#ifndef _LIKELY
#define _LIKELY [[likely]]
#endif // _LIKELY
// Standard libraries //
#include <unordered_map>
#include <type_traits>
#include <functional>
#include <cstdint>
#include <cstring>
#include <memory>
#include <vector>
#include <ranges>
#include <array>
#include <span>
// LXC util files //
#include <modules/Result.h>
#include <modules/File.h>
#include <modules/IO.h>

View File

@@ -1,102 +0,0 @@
#pragma once
#include <filesystem>
#include <fstream>
namespace LXC::Util
{
// Error returned when Util::ReadFile runs into errors //
struct FileReadError final
{
// Different reasons why the error can occur //
enum Reason
{
FileNotFound,
PermissionDenied,
NotAFile
};
// Constructor to pass arguments to the struct //
FileReadError(const std::filesystem::path& _path, Reason _reason)
: path(_path), reason(_reason)
{}
// Error information //
const std::filesystem::path path;
const Reason reason;
// Turns the error into a c-string //
inline static const char* const ReasonStr(Reason reason)
{
static const char* reasons[] =
{
"File cannot be found",
"File reading permissions are denied",
"Not a file"
};
return reasons[reason];
}
};
// Util function to read a file as quick as possible with error handling //
inline ReturnVal<std::string, FileReadError> ReadFile(const std::filesystem::path& filepath)
{
// Checks the file exists //
if (!std::filesystem::exists(filepath))
return FunctionFail<FileReadError>(std::filesystem::absolute(filepath), FileReadError::FileNotFound);
// Checks it is a regular file //
if (!std::filesystem::is_regular_file(filepath))
return FunctionFail<FileReadError>(std::filesystem::absolute(filepath), FileReadError::NotAFile);
// Checks it can open the file //
std::ifstream file(filepath, std::ios::binary | std::ios::ate);
if (!file)
return FunctionFail<FileReadError>(std::filesystem::absolute(filepath), FileReadError::PermissionDenied);
// Copies the file to the output string //
const std::streamsize len = file.tellg();
file.seekg(0, std::ios::beg);
std::string contents(len, '\0');
file.read(&contents[0], len);
return contents;
}
// Struct to hold a position within a file //
struct FileLocation
{
unsigned short col;
unsigned short line;
};
// Finds the location of a given index within a file //
inline bool GetFileLocationAtIndex(FileLocation& location, const std::string& file, uint32_t index)
{
// Resets location //
location.line = 1;
location.col = 1;
// Returns false if outside the bounds //
if (index < 0 || index > file.length())
return false;
// Finds the location //
uint32_t localIndex = 0;
while (localIndex != index)
{
if (file[localIndex] == '\n')
{
location.line += 1;
location.col = 0;
}
location.col++;
localIndex++;
}
return true;
}
}

View File

@@ -1,292 +0,0 @@
#pragma once
#include <modules/OS.h>
#include <iostream>
#include <utility>
#include <cstdlib>
#include <ostream>
#include <ranges>
namespace LXC::Util
{
// Enum to translate to the Win32 code for the colors //
enum Color
{
DEFAULT = 0x07,
BLACK = 0x00,
BLUE = 0x01,
GREEN = 0x02,
AQUA = 0x03,
RED = 0x04,
PURPLE = 0x05,
YELLOW = 0x06,
LIGHT_GRAY = 0x07,
LIGHT_BLUE = 0x09,
LIGHT_GREEN = 0x0a,
LIGHT_AQUA = 0x0b,
LIGHT_RED = 0x0c,
LIGHT_PURPLE = 0x0d,
LIGHT_YELLOW = 0x0e,
WHITE = 0x0f
};
}
namespace LXC::Internal
{
// Checks if a type can be outputted to std::ostream //
template<typename T> concept Logable = requires(std::ostream & os, T t)
{
// I have no idea what this part does at all //
{ os << t } -> std::same_as<std::ostream&>;
};
// Checks if a list of types can be outputted to std::ostream //
template<typename... Args> concept AllLogable = (Logable<Args> && ...);
// Checks if the type has a custom log method //
template<typename T> concept HasLogStrFunc = requires(T obj)
{
// Checks the type has a function LogStr that returns a string //
{ obj.LogStr() } -> std::same_as<std::string>;
};
// Returns a reference to the log file //
inline std::ofstream& Log()
{
static std::ofstream sLog;
return sLog;
}
#if defined(_WIN32)
// Base function for all derived Print() functions //
template<Util::Color col, bool newLine, typename... Args>
inline void WriteImpl(std::ostream& os, Args&&... args)
{
static HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if constexpr (col != Util::Color::DEFAULT)
SetConsoleTextAttribute(hConsole, static_cast<WORD>(col));
(os << ... << std::forward<Args>(args));
if constexpr (newLine)
os << std::endl;
if constexpr (col != Util::Color::DEFAULT)
SetConsoleTextAttribute(hConsole, static_cast<WORD>(Util::Color::DEFAULT));
}
#elif defined(__unix__)
static const char* GetAnsiCode(Util::Color color)
{
switch (color)
{
case Util::Color::BLACK: return "\x1b[30m";
case Util::Color::BLUE: return "\x1b[34m";
case Util::Color::GREEN: return "\x1b[32m";
case Util::Color::AQUA: return "\x1b[36m";
case Util::Color::RED: return "\x1b[31m";
case Util::Color::PURPLE: return "\x1b[35m";
case Util::Color::YELLOW: return "\x1b[33m";
case Util::Color::LIGHT_GRAY: return "\x1b[0m";
case Util::Color::LIGHT_BLUE: return "\x1b[94m";
case Util::Color::LIGHT_GREEN: return "\x1b[92m";
case Util::Color::LIGHT_AQUA: return "\x1b[96m";
case Util::Color::LIGHT_RED: return "\x1b[91m";
case Util::Color::LIGHT_PURPLE: return "\x1b[95m";
case Util::Color::LIGHT_YELLOW: return "\x1b[93m";
case Util::Color::WHITE: return "\x1b[97m";
default: return "\x1b[0m";
}
}
template<Util::Color col, bool newLine, typename... Args>
inline void WriteImpl(std::ostream& os, Args&&... args)
{
if constexpr (col != Util::Color::DEFAULT)
os << GetAnsiCode(col);
(os << ... << std::forward<Args>(args));
if constexpr (newLine)
os << std::endl;
if constexpr (col != Util::Color::DEFAULT)
os << GetAnsiCode(Util::Color::DEFAULT);
}
#endif
}
namespace LXC::Util
{
// Prints arguments to the console with the given color //
template<Color col, typename... Args>
requires Internal::AllLogable<Args...>
inline void PrintAs(Args&&... args)
{
Internal::WriteImpl<col, false>(std::cout, std::forward<Args>(args)...);
}
// Prints arguments to the console //
template<typename... Args>
requires Internal::AllLogable<Args...>
inline void Print(Args&&... args)
{
Internal::WriteImpl<Util::Color::DEFAULT, false>(std::cout, std::forward<Args>(args)...);
}
// Prints arguments to the console with a new-line character at the end //
template<typename... Args>
requires Internal::AllLogable<Args...> && (sizeof...(Args) > 1)
inline void PrintLn(Args&&... args)
{
Internal::WriteImpl<Util::Color::DEFAULT, true>(std::cout, std::forward<Args>(args)...);
}
// Prints a new line within the console //
inline void PrintLn()
{
Internal::WriteImpl<Util::Color::DEFAULT, true>(std::cout);
}
// Prints argument to the console with a new line character at the end //
template<typename T>
requires (Internal::HasLogStrFunc<T> || Internal::Logable<T>) && (!std::is_pointer_v<T>)
inline void PrintLn(T&& arg)
{
if constexpr (Internal::HasLogStrFunc<T>)
Internal::WriteImpl<Util::Color::DEFAULT, true>(std::cout, arg.LogStr());
else
Internal::WriteImpl<Util::Color::DEFAULT, true>(std::cout, arg);
}
// Prints the value of a pointer to the console, prints an error if null //
template<typename T, typename Raw = std::remove_pointer_t<T>>
requires (Internal::HasLogStrFunc<Raw> || Internal::Logable<Raw>) && std::is_pointer_v<T>
inline void PrintLn(T&& arg)
{
if (arg != nullptr) _LIKELY
PrintLn(*arg);
else
Internal::WriteImpl<Util::Color::DEFAULT, true>(std::cout, "Nullptr to: [", typeid(Raw).name(), "]");
}
// Prints a container to the console //
template<typename T, std::ranges::range Container, typename CargoType = std::ranges::range_value_t<Container>>
requires (Internal::HasLogStrFunc<T> || Internal::Logable<T>) && (!std::is_pointer_v<T>) &&
(Internal::HasLogStrFunc<CargoType> || Internal::Logable<CargoType>) && (!std::is_pointer_v<CargoType>)
inline void PrintContainer(T&& containerName, const Container& container)
{
// Prints a starting section for the container //
Internal::WriteImpl<Util::Color::DEFAULT, true>(std::cout, "[LXC] \"", containerName, "\":\n{");
// Iterates over each of the items in the container and prints them //
unsigned counter = 0;
for (const auto& item : container)
{
if constexpr (Internal::HasLogStrFunc<CargoType>)
Internal::WriteImpl<Util::Color::DEFAULT, true>(std::cout, '\t', std::setw(3), std::left, counter, "| ", item.LogStr());
else
Internal::WriteImpl<Util::Color::DEFAULT, true>(std::cout, '\t', std::setw(3), std::left, counter, "| ", item);
counter++;
}
// Prints the ending bracket //
Internal::WriteImpl<Util::Color::DEFAULT, true>(std::cout, '}');
}
// Logs all the arguments to the file (automatically flushes) //
template<typename... Args>
requires Internal::AllLogable<Args...> && (sizeof...(Args) > 1)
inline void Log(Args&&... args)
{
std::ofstream& log = Internal::Log();
if (log.is_open()) _UNLIKELY
Internal::WriteImpl<Util::Color::DEFAULT, true>(log, R"([LXC] ")", std::forward<Args>(args)..., '"');
}
// Logs a singular argument to the log, calls Log() if it can on the object //
template<typename T>
requires (Internal::HasLogStrFunc<T> || Internal::Logable<T>) && (!std::is_pointer_v<T>)
inline void Log(T&& arg)
{
std::ofstream& log = Internal::Log();
if (log.is_open()) _UNLIKELY
{
if constexpr (Internal::HasLogStrFunc<T>)
Internal::WriteImpl<Util::Color::DEFAULT, true>(log, "[LXC] ", '{', arg.LogStr(), '}');
else
Internal::WriteImpl<Util::Color::DEFAULT, true>(log, "[LXC] ", '"', arg, '"');
}
}
// Prints the value of a pointer to the log, prints an error to the log if null //
template<typename T, typename Raw = std::remove_pointer_t<T>>
requires (Internal::HasLogStrFunc<Raw> || Internal::Logable<Raw>) && std::is_pointer_v<T>
inline void Log(T&& arg)
{
std::ofstream& log = Internal::Log();
if (log.is_open()) _UNLIKELY
{
if (arg != nullptr) _LIKELY
Log(*arg);
else
Internal::WriteImpl<Util::Color::DEFAULT, true>(log, "[LXC] Nullptr to: [", typeid(Raw).name(), ']');
}
}
// Prints the contents of a container to the log //
template<typename T, std::ranges::range Container, typename CargoType = std::ranges::range_value_t<Container>>
requires (Internal::HasLogStrFunc<T> || Internal::Logable<T>) && (!std::is_pointer_v<T>) &&
(Internal::HasLogStrFunc<CargoType> || Internal::Logable<CargoType>) && (!std::is_pointer_v<CargoType>)
inline void LogContainer(T&& containerName, const Container& container)
{
// Gets the log if it is open //
std::ofstream& log = Internal::Log();
if (!log.is_open()) _LIKELY { return; }
// Prints a starting section for the container //
Internal::WriteImpl<Util::Color::DEFAULT, true>(log, "[LXC] \"", containerName, "\":\n{");
// Iterates over each of the items in the container and prints them //
unsigned counter = 0;
for (const auto& item : container)
{
if constexpr (Internal::HasLogStrFunc<CargoType>)
Internal::WriteImpl<Util::Color::DEFAULT, true>(log, '\t', std::setw(3), std::left, counter, "| ", item.LogStr());
else
Internal::WriteImpl<Util::Color::DEFAULT, true>(log, '\t', std::setw(3), std::left, counter, "| ", item);
counter++;
}
// Prints the ending bracket //
Internal::WriteImpl<Util::Color::DEFAULT, true>(log, '}');
}
// Intitalises the log with the given file name //
inline void CreateLog(const std::filesystem::path& path)
{
// Opens the log file with the given path //
std::ofstream& log = Internal::Log();
log.open(path);
// Assigns a function to close the log file on program exit //
std::atexit([]()
{
std::ofstream& log = Internal::Log();
log.close();
});
}
}

View File

@@ -1,12 +0,0 @@
#pragma once
// Platform specific includes //
#if defined(_WIN32)
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#elif defined(__unix__)
// No platform specific includes are needed for UNIX based systems //
#else
#error "OS is not supported"
#endif

View File

@@ -1,135 +0,0 @@
#pragma once
#include <modules/OS.h>
#include <type_traits>
#include <cstdlib>
namespace LXC::Util
{
// Util function to stop the program //
inline void Stop()
{
// Only checks for a debugger when compiled in Debug mode //
#ifdef _DEBUG
// Triggers a breakpoint so the debugger can work out where the program exits //
if (IsDebuggerPresent())
DebugBreak();
#endif // _DEBUG
// Force exits the program //
std::exit(EXIT_FAILURE);
}
// Custom version of std::unexpected //
template<typename ErrorType> struct FunctionFail final
{
// Basic constructor to copy the error across //
explicit FunctionFail(ErrorType _err) : error(_err)
{
// Only checks for a debugger when compiled in Debug mode //
#ifdef _DEBUG
// Triggers a breakpoint when a debugger is attached as a function has failed //
if (IsDebuggerPresent())
DebugBreak();
#endif // _DEBUG
}
// Constructs the FunctionFail with the error itself //
template<typename... Args> requires std::constructible_from<ErrorType, Args...>
explicit FunctionFail(Args&&... args)
: error(std::forward<Args>(args)...)
{
// Only checks for a debugger when compiled in Debug mode //
#ifdef _DEBUG
// Triggers a breakpoint when a debugger is attached as a function has failed //
if (IsDebuggerPresent())
DebugBreak();
#endif // _DEBUG
}
const ErrorType error;
};
// Custom version of std::expected //
template<typename ResultType, typename ErrorType>
requires (!std::same_as<ResultType, bool>) // ResultType being bool causes issues with operator overloads
class ReturnVal final
{
public:
// Constructor for function sucess //
ReturnVal(const ResultType& result)
: m_Result(result), m_FunctionFailed(false)
{}
// Move constructor (for large objects) //
ReturnVal(ResultType&& result)
: m_Result(std::move(result)), m_FunctionFailed(false)
{}
// Constructor for function fail //
ReturnVal(FunctionFail<ErrorType> error)
: m_Error(error.error), m_FunctionFailed(true)
{}
// Constructor to support upcasting //
template<typename Other>
requires std::is_convertible_v<Other, ResultType>
ReturnVal(ReturnVal<Other, ErrorType>&& other)
: m_FunctionFailed(other.m_FunctionFailed)
{
// Transfers the correct member of the union //
if (m_FunctionFailed)
m_Error = std::move(other.m_Error);
else
m_Result = std::move(other.m_Result);
}
// Destructor //
~ReturnVal() {};
// Different getters of the class //
inline bool Failed() const { return m_FunctionFailed; }
inline bool Suceeded() const { return !m_FunctionFailed; }
inline ResultType& Result()
{
if (Suceeded()) _LIKELY
return m_Result;
std::exit(EXIT_FAILURE);
}
inline ErrorType& Error()
{
if (Failed()) _LIKELY
return m_Error;
std::exit(EXIT_FAILURE);
}
// Operator overloads //
explicit operator bool() const { return !m_FunctionFailed; }
operator ResultType&() { return Result(); }
private:
// Union to hold either the result or the error //
union
{
ResultType m_Result;
ErrorType m_Error;
};
// Tracks what item is currently in the union //
bool m_FunctionFailed;
};
}

55
LXC.exe.log Normal file
View File

@@ -0,0 +1,55 @@
[PB_Util::Log]: "Lexer output"
{
0 | Token::FunctionDef | EMPTY
1 | Token::OpenCrocodile | EMPTY
2 | Token::Identifier | "int"
3 | Token::CloseCrocodile | EMPTY
4 | Token::Identifier | "fib"
5 | Token::OpenParen | EMPTY
6 | Token::Identifier | "int"
7 | Token::Colon | EMPTY
8 | Token::Identifier | "num"
9 | Token::CloseParen | EMPTY
10 | Token::OpenBrace | EMPTY
11 | Token::Return | EMPTY
12 | Token::Identifier | "fib"
13 | Token::OpenParen | EMPTY
14 | Token::Identifier | "n"
15 | Token::Sub | EMPTY
16 | Token::NumLiteral | "1"
17 | Token::CloseParen | EMPTY
18 | Token::Add | EMPTY
19 | Token::Identifier | "fib"
20 | Token::OpenParen | EMPTY
21 | Token::Identifier | "n"
22 | Token::Sub | EMPTY
23 | Token::NumLiteral | "2"
24 | Token::CloseParen | EMPTY
25 | Token::CloseBrace | EMPTY
26 | Token::FunctionDef | EMPTY
27 | Token::OpenCrocodile | EMPTY
28 | Token::Identifier | "int"
29 | Token::CloseCrocodile | EMPTY
30 | Token::Identifier | "main"
31 | Token::OpenParen | EMPTY
32 | Token::CloseParen | EMPTY
33 | Token::OpenBrace | EMPTY
34 | Token::Identifier | "int"
35 | Token::Colon | EMPTY
36 | Token::Identifier | "res"
37 | Token::Assign | EMPTY
38 | Token::Identifier | "fib"
39 | Token::OpenParen | EMPTY
40 | Token::NumLiteral | "8"
41 | Token::CloseParen | EMPTY
42 | Token::Return | EMPTY
43 | Token::Identifier | "res"
44 | Token::Eql | EMPTY
45 | Token::NumLiteral | "21"
46 | Token::CloseBrace | EMPTY
}
[PB_Util::Log]: "Function AST"
{
0 | fib (int num)
1 | main ()
}

View File

@@ -1,11 +1,12 @@
# Creates the .exe from the single source file of the app # # Creates the .exe from the single source file of the app #
add_executable(LXC LXC.cpp) add_executable(LXC LXC.cpp)
# Links the other binaries # # Links to the all needed internal libraries #
target_link_libraries(LXC PRIVATE PashaBibko-UTIL)
target_link_libraries(LXC PRIVATE Lexer) target_link_libraries(LXC PRIVATE Lexer)
target_link_libraries(LXC PRIVATE AST) target_link_libraries(LXC PRIVATE AST)
target_link_libraries(LXC PRIVATE Parser) target_link_libraries(LXC PRIVATE Parser)
# Creates the precompiled header for the binary # # Creates the precompiled header for the binary #
target_include_directories(LXC PRIVATE ${CMAKE_SOURCE_DIR}/common) target_include_directories(LXC PRIVATE ${CMAKE_SOURCE_DIR}/external/util)
target_precompile_headers(LXC PRIVATE ${CMAKE_SOURCE_DIR}/common/LXC.h) target_precompile_headers(LXC PRIVATE ${CMAKE_SOURCE_DIR}/external/util/Util.h)

View File

@@ -1,4 +1,4 @@
#include <LXC.h> #include <Util.h>
#include <NodeTypes.h> #include <NodeTypes.h>
#include <Parser.h> #include <Parser.h>
@@ -6,10 +6,8 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
using namespace LXC; using namespace PashaBibko::LXC;
using namespace PashaBibko;
// Creates the debug log //
Util::CreateLog("LXC.log");
std::filesystem::path src = "examples/Fib.lx"; std::filesystem::path src = "examples/Fib.lx";
@@ -21,29 +19,28 @@ int main(int argc, char** argv)
Util::FileReadError& err = fileContents.Error(); Util::FileReadError& err = fileContents.Error();
// Prints the error to the console // // Prints the error to the console //
Util::PrintAs<Util::WHITE>("[LXC]"); Util::Print<Util::Colour::White>("[LXC]");
Util::PrintAs<Util::LIGHT_RED>(" Error: "); Util::Print<Util::Colour::LightRed>(" Error: ");
Util::PrintLn(Util::FileReadError::ReasonStr(err.reason), " [", std::filesystem::absolute(err.path), ']'); Util::PrintLn(Util::FileReadError::ReasonStr(err.reason), " [", std::filesystem::absolute(err.path), ']');
Util::Log("Opening source file failed. Stopping program."); Util::Log("Opening source file failed. Stopping program.");
Util::Stop(); Util::EndProcess();
} }
// Turns the file contents into a vector of tokens // // Turns the file contents into a vector of tokens //
Util::ReturnVal tokens = Lexer::TokenizeFile(fileContents); Util::ReturnVal tokens = Lexer::TokenizeFile(fileContents.Result());
if (tokens.Failed()) _UNLIKELY if (tokens.Failed()) _UNLIKELY
{ {
// Stores the error for easier access // // Stores the error for easier access //
Lexer::LexerError& err = tokens.Error(); Lexer::LexerError& err = tokens.Error();
// Finds the file location of the error // // Finds the file location of the error //
Util::FileLocation location; Util::StringLocation location = Util::GetLocationAtStringIndex(fileContents.Result(), err.index);
Util::GetFileLocationAtIndex(location, fileContents, err.index);
// Prints the error to the console // // Prints the error to the console //
Util::PrintAs<Util::WHITE>("[LXC] "); Util::Print<Util::Colour::White>("[LXC] ");
Util::Print(src.filename().string(), '(', location.line, ',', location.col, ')'); Util::Print(src.filename().string(), '(', location.line, ',', location.colummn, ')');
Util::PrintAs<Util::LIGHT_RED>(" Error: "); Util::Print<Util::Colour::LightRed>(" Error: ");
Util::Print(Lexer::LexerError::ReasonStr(err.reason)); Util::Print(Lexer::LexerError::ReasonStr(err.reason));
if (err.reason == Lexer::LexerError::InvalidCharacter) if (err.reason == Lexer::LexerError::InvalidCharacter)
@@ -56,24 +53,24 @@ int main(int argc, char** argv)
Util::PrintLn(); Util::PrintLn();
Util::Log("Error occured in Lexer: ", Lexer::LexerError::ReasonStr(err.reason)); Util::Log("Error occured in Lexer: ", Lexer::LexerError::ReasonStr(err.reason));
Util::Stop(); Util::EndProcess();
} }
else else
{ {
// Prints all of the tokens to the log // // Prints all of the tokens to the log //
Lexer::LexerOutput lexerOutput = tokens.Result(); Lexer::LexerOutput lexerOutput = tokens.Result();
Util::LogContainer("Lexer output", lexerOutput); Util::Log("Lexer output", lexerOutput);
} }
// Turns the tokens into into an abstract syntax tree // // Turns the tokens into into an abstract syntax tree //
Util::ReturnVal functionsAST = Parser::TurnTokensIntoAST(tokens); Util::ReturnVal functionsAST = Parser::TurnTokensIntoAST(tokens.Result());
if (functionsAST.Failed()) _UNLIKELY if (functionsAST.Failed()) _UNLIKELY
{ {
Util::Stop(); Util::EndProcess();
} }
else else
{ {
Util::PrintContainer("Function AST", functionsAST.Result()); Util::Log("Function AST", functionsAST.Result());
} }
return 0; return 0;

View File

@@ -10,6 +10,9 @@ target_include_directories (
${CMAKE_CURRENT_SOURCE_DIR}/inc ${CMAKE_CURRENT_SOURCE_DIR}/inc
) )
# Links to the all needed internal libraries #
target_link_libraries(Lexer PRIVATE PashaBibko-UTIL)
# Creates the precompiled header for the binary # # Creates the precompiled header for the binary #
target_include_directories(Lexer PRIVATE ${CMAKE_SOURCE_DIR}/common) target_include_directories(Lexer PRIVATE ${CMAKE_SOURCE_DIR}/external/util)
target_precompile_headers(Lexer PRIVATE ${CMAKE_SOURCE_DIR}/common/LXC.h) target_precompile_headers(Lexer PRIVATE ${CMAKE_SOURCE_DIR}/external/util/Util.h)

View File

@@ -2,7 +2,7 @@
#include <Token.h> #include <Token.h>
namespace LXC::Lexer namespace PashaBibko::LXC::Lexer
{ {
struct LexerContext final struct LexerContext final
{ {

View File

@@ -1,8 +1,8 @@
#pragma once #pragma once
#include <LXC.h> #include <Util.h>
namespace LXC::Lexer namespace PashaBibko::LXC::Lexer
{ {
namespace TokenClass namespace TokenClass
{ {

View File

@@ -1,9 +1,9 @@
#include <LXC.h> #include <Util.h>
#include <Lexer.h> #include <Lexer.h>
#include <Token.h> #include <Token.h>
namespace LXC::Internal namespace PashaBibko::LXC::Internal
{ {
static constexpr bool IsNumeric(const char c) static constexpr bool IsNumeric(const char c)
{ {
@@ -81,7 +81,7 @@ namespace LXC::Internal
}; };
} }
namespace LXC::Lexer namespace PashaBibko::LXC::Lexer
{ {
LexerContext::LexerContext(const std::string& _source) : LexerContext::LexerContext(const std::string& _source) :
source(_source), index(0), out{}, len((uint32_t)_source.length()), column(0), line(0) source(_source), index(0), out{}, len((uint32_t)_source.length()), column(0), line(0)
@@ -210,6 +210,6 @@ namespace LXC::Lexer
if (trackers.inStrLiteral) if (trackers.inStrLiteral)
return Util::FunctionFail<LexerError>(LexerError::UnterminatedStringLiteral, trackers.sectionStart); return Util::FunctionFail<LexerError>(LexerError::UnterminatedStringLiteral, trackers.sectionStart);
return ctx.out; return std::move(ctx.out);
} }
} }

View File

@@ -1,11 +1,11 @@
#include <LXC.h> #include <Util.h>
#include <Lexer.h> #include <Lexer.h>
#include <Token.h> #include <Token.h>
#include <iomanip> #include <iomanip>
namespace LXC::Lexer namespace PashaBibko::LXC::Lexer
{ {
// Constructor to assign the members of the token class // // Constructor to assign the members of the token class //
Token::Token(const LexerContext& ctx, const uint32_t start, unsigned short len, TokenType _type) : Token::Token(const LexerContext& ctx, const uint32_t start, unsigned short len, TokenType _type) :

View File

@@ -10,9 +10,10 @@ target_include_directories (
${CMAKE_CURRENT_SOURCE_DIR}/inc ${CMAKE_CURRENT_SOURCE_DIR}/inc
) )
# Links to the Lexer so it can use tokens as data types # # Links to the all needed internal libraries #
target_link_libraries(AST PUBLIC Lexer) target_link_libraries(AST PRIVATE PashaBibko-UTIL)
target_link_libraries(AST PRIVATE Lexer)
# Creates the precompiled header of the binary # # Creates the precompiled header of the binary #
target_include_directories(AST PRIVATE ${CMAKE_SOURCE_DIR}/common) target_include_directories(AST PRIVATE ${CMAKE_SOURCE_DIR}/external/util)
target_precompile_headers(AST PRIVATE ${CMAKE_SOURCE_DIR}/common/LXC.h) target_precompile_headers(AST PRIVATE ${CMAKE_SOURCE_DIR}/external/util/Util.h)

View File

@@ -1,8 +1,8 @@
#pragma once #pragma once
#include <LXC.h> #include <Util.h>
namespace LXC::AST namespace PashaBibko::LXC::AST
{ {
// Enum to track which node it was created as // // Enum to track which node it was created as //
enum class NodeType enum class NodeType

View File

@@ -1,11 +1,11 @@
#pragma once #pragma once
#include <LXC.h> #include <Util.h>
#include <NodeBase.h> #include <NodeBase.h>
#include <Token.h> #include <Token.h>
namespace LXC::AST namespace PashaBibko::LXC::AST
{ {
class FunctionCall final : public NodeValue class FunctionCall final : public NodeValue
{ {

View File

@@ -1,8 +1,8 @@
#include <LXC.h> #include <Util.h>
#include <NodeTypes.h> #include <NodeTypes.h>
namespace LXC::AST namespace PashaBibko::LXC::AST
{ {
FunctionCall::FunctionCall (const Identifier& functionName, ValueList& arguments) FunctionCall::FunctionCall (const Identifier& functionName, ValueList& arguments)
: NodeValue(NodeType::FunctionCall), m_FuncName(functionName), m_Arguments(std::move(arguments)) : NodeValue(NodeType::FunctionCall), m_FuncName(functionName), m_Arguments(std::move(arguments))

1
external/util vendored Submodule

Submodule external/util added at a5b7282bfa

View File

@@ -1,7 +1,7 @@
# Fetches all .cpp files for the binary # # Fetches all .cpp files for the binary #
add_library(Parser STATIC add_library(Parser STATIC
src/Parser.cpp src/Parser.cpp
"inc/Parser.h") )
# Adds the headers in the current directory # # Adds the headers in the current directory #
target_include_directories ( target_include_directories (
@@ -9,10 +9,11 @@ target_include_directories (
${CMAKE_CURRENT_SOURCE_DIR}/inc ${CMAKE_CURRENT_SOURCE_DIR}/inc
) )
# Links to the Lexer and AST so it can use their data types # # Links to the all needed internal libraries #
target_link_libraries(Parser PUBLIC Lexer) target_link_libraries(Parser PRIVATE PashaBibko-UTIL)
target_link_libraries(Parser PUBLIC AST) target_link_libraries(Parser PRIVATE Lexer)
target_link_libraries(Parser PRIVATE AST)
# Creates the precompiled header of the binary # # Creates the precompiled header of the binary #
target_include_directories(Parser PRIVATE ${CMAKE_SOURCE_DIR}/common) target_include_directories(Parser PRIVATE ${CMAKE_SOURCE_DIR}/external/util)
target_precompile_headers(Parser PRIVATE ${CMAKE_SOURCE_DIR}/common/LXC.h) target_precompile_headers(Parser PRIVATE ${CMAKE_SOURCE_DIR}/external/util/Util.h)

View File

@@ -1,11 +1,11 @@
#pragma once #pragma once
#include <LXC.h> #include <Util.h>
#include <NodeTypes.h> #include <NodeTypes.h>
#include <Lexer.h> #include <Lexer.h>
namespace LXC::Parser namespace PashaBibko::LXC::Parser
{ {
struct ParserError {}; struct ParserError {};
@@ -15,6 +15,8 @@ namespace LXC::Parser
name{}, contents{}, funcParams{} name{}, contents{}, funcParams{}
{} {}
FunctionAST(const FunctionAST& other) = delete;
FunctionAST(FunctionAST&& other) noexcept : FunctionAST(FunctionAST&& other) noexcept :
name(std::move(other.name)), contents(std::move(other.contents)), funcParams(std::move(other.funcParams)) name(std::move(other.name)), contents(std::move(other.contents)), funcParams(std::move(other.funcParams))
{} {}

View File

@@ -1,25 +1,25 @@
#include <LXC.h> #include <Util.h>
#include <Parser.h> #include <Parser.h>
namespace LXC::Internal namespace PashaBibko::LXC::Internal
{ {
template<typename NodeType, typename... Args> template<typename NodeType, typename... Args>
requires std::is_base_of_v<AST::Node, NodeType> && std::is_constructible_v<NodeType, Args...> requires std::is_base_of_v<AST::Node, NodeType> && std::is_constructible_v<NodeType, Args...>
static const inline Util::ReturnVal<AST::NodePtr, Parser::ParserError> CreateNode(Args&&... args) static const inline Util::ReturnVal<AST::NodePtr, Parser::ParserError> CreateNode(Args&&... args)
{ {
return Util::ReturnVal<AST::NodePtr, Parser::ParserError>(std::make_unique<NodeType>(std::forward<Args>(args)...)); return AST::NodePtr(std::make_unique<NodeType>(std::forward<Args>(args)...));
} }
template<typename NodeType, typename... Args> template<typename NodeType, typename... Args>
requires std::is_base_of_v<AST::NodeValue, NodeType> && std::is_constructible_v<NodeType, Args...> requires std::is_base_of_v<AST::NodeValue, NodeType> && std::is_constructible_v<NodeType, Args...>
static const inline Util::ReturnVal<AST::NodeValuePtr, Parser::ParserError> CreateNodeV(Args&&... args) static const inline Util::ReturnVal<AST::NodeValuePtr, Parser::ParserError> CreateNodeV(Args&&... args)
{ {
return Util::ReturnVal<AST::NodeValuePtr, Parser::ParserError>(std::make_unique<NodeType>(std::forward<Args>(args)...)); return AST::NodeValuePtr(std::make_unique<NodeType>(std::forward<Args>(args)...));
} }
} }
namespace LXC::Parser namespace PashaBibko::LXC::Parser
{ {
class ParserContext final class ParserContext final
{ {
@@ -130,7 +130,7 @@ namespace LXC::Parser
ctx.Advance(); ctx.Advance();
// Adds the current argument to the ValueList // // Adds the current argument to the ValueList //
arguments.push_back(ParsePrimary(ctx)); arguments.push_back(std::move(ParsePrimary(ctx).Result()));
} }
} }

View File

@@ -4,7 +4,7 @@
#include <Token.h> #include <Token.h>
// Local util functions // // Local util functions //
namespace LXC::Internal namespace PashaBibko::LXC::Internal
{ {
static void ExpectTokens(const Lexer::LexerOutput& tokens, const std::vector<Lexer::Token::TokenType>& expected) static void ExpectTokens(const Lexer::LexerOutput& tokens, const std::vector<Lexer::Token::TokenType>& expected)
{ {
@@ -15,7 +15,7 @@ namespace LXC::Internal
} }
// The tests for the lexer // // The tests for the lexer //
namespace LXC::Lexer namespace PashaBibko::LXC::Lexer
{ {
TEST(LexerTests, ReturnsTrueForMatching) TEST(LexerTests, ReturnsTrueForMatching)
{ {