Moved Common to external git repo
Also changed namespace from LXC to PashaBibko::LXC
This commit is contained in:
9
.gitattributes
vendored
9
.gitattributes
vendored
@@ -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
3
.gitmodules
vendored
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
30
Common/LXC.h
30
Common/LXC.h
@@ -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>
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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
55
LXC.exe.log
Normal 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 ()
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
35
LXC/LXC.cpp
35
LXC/LXC.cpp
@@ -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;
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <Token.h>
|
#include <Token.h>
|
||||||
|
|
||||||
namespace LXC::Lexer
|
namespace PashaBibko::LXC::Lexer
|
||||||
{
|
{
|
||||||
struct LexerContext final
|
struct LexerContext final
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) :
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
2
external/googletest
vendored
2
external/googletest
vendored
Submodule external/googletest updated: 7e17b15f15...373af2e3df
1
external/util
vendored
Submodule
1
external/util
vendored
Submodule
Submodule external/util added at a5b7282bfa
@@ -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)
|
||||||
|
|||||||
@@ -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))
|
||||||
{}
|
{}
|
||||||
|
|||||||
@@ -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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user