Skip to content

Commit

Permalink
Refactor Parser
Browse files Browse the repository at this point in the history
  • Loading branch information
fintarin committed Feb 1, 2024
1 parent 7604308 commit 84afe8a
Show file tree
Hide file tree
Showing 19 changed files with 265 additions and 342 deletions.
16 changes: 9 additions & 7 deletions include/fintamath/core/IArithmetic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
namespace fintamath {

class IArithmetic : public IMathObject {
using ArithmeticParser = Parser<std::unique_ptr<IArithmetic>>;

public:
friend inline std::unique_ptr<IArithmetic> operator+(const IArithmetic &lhs, const IArithmetic &rhs) {
return lhs.addAbstract(rhs);
Expand All @@ -32,17 +34,16 @@ class IArithmetic : public IMathObject {
}

template <std::derived_from<IArithmetic> T>
static void registerType() {
Parser::registerType<T>(getParser());
static void registerConstructor() {
getParser().registerConstructor<T>();
}

template <std::derived_from<IArithmetic> T>
static void registerType(Parser::Function<std::unique_ptr<IArithmetic>, const std::string &> &&parserFunc) {
Parser::registerType<T>(getParser(), std::move(parserFunc));
static void registerConstructor(ArithmeticParser::Constructor constructor) {
getParser().registerConstructor(std::move(constructor));
}

static std::unique_ptr<IArithmetic> parse(const std::string &str) {
return Parser::parse(getParser(), str);
return getParser().parse(str);
}

static MathObjectType getTypeStatic() {
Expand All @@ -61,13 +62,14 @@ class IArithmetic : public IMathObject {
virtual std::unique_ptr<IArithmetic> negateAbstract() const = 0;

private:
static Parser::Vector<std::unique_ptr<IArithmetic>, const std::string &> &getParser();
static ArithmeticParser &getParser();
};

template <typename Derived>
class IArithmeticCRTP : public IArithmetic {
#define I_ARITHMETIC_CRTP IArithmeticCRTP<Derived>
#include "fintamath/core/IArithmeticCRTP.hpp"

#undef I_ARITHMETIC_CRTP
};

Expand Down
11 changes: 6 additions & 5 deletions include/fintamath/core/IComparable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@
namespace fintamath {

class IComparable : public IArithmetic {
using ComparableParser = Parser<std::unique_ptr<IComparable>>;

public:
friend inline std::strong_ordering operator<=>(const IComparable &lhs, const IComparable &rhs) {
return lhs.compareAbstract(rhs);
}

template <std::derived_from<IComparable> T>
static void registerType(Parser::Function<std::unique_ptr<IComparable>, const std::string &> &&parserFunc) {
Parser::registerType<T>(getParser(), std::move(parserFunc));
static void registerConstructor(ComparableParser::Constructor constructor) {
getParser().registerConstructor(std::move(constructor));
}

static std::unique_ptr<IComparable> parse(const std::string &str) {
return Parser::parse(getParser(), str);
return getParser().parse(str);
}

static MathObjectType getTypeStatic() {
Expand All @@ -28,7 +29,7 @@ class IComparable : public IArithmetic {
virtual std::strong_ordering compareAbstract(const IComparable &rhs) const = 0;

private:
static Parser::Vector<std::unique_ptr<IComparable>, const std::string &> &getParser();
static ComparableParser &getParser();
};

template <typename Derived>
Expand Down
11 changes: 6 additions & 5 deletions include/fintamath/core/IMathObject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
namespace fintamath {

class IMathObject {
using MathObjectParser = Parser<std::unique_ptr<IMathObject>>;

public:
virtual ~IMathObject() = default;

Expand All @@ -32,13 +34,12 @@ class IMathObject {
return lhs.equalsAbstract(rhs);
}

template <std::derived_from<IMathObject> T>
static void registerType(Parser::Function<std::unique_ptr<IMathObject>, const std::string &> &&parserFunc) {
Parser::registerType<T>(getParser(), std::move(parserFunc));
static void registerConstructor(MathObjectParser::Constructor constructor) {
getParser().registerConstructor(std::move(constructor));
}

static std::unique_ptr<IMathObject> parse(const std::string &str) {
return Parser::parse(getParser(), str);
return getParser().parse(str);
}

static MathObjectType getTypeStatic() {
Expand All @@ -49,7 +50,7 @@ class IMathObject {
virtual bool equalsAbstract(const IMathObject &rhs) const = 0;

private:
static Parser::Vector<std::unique_ptr<IMathObject>, const std::string &> &getParser();
static MathObjectParser &getParser();
};

template <typename Derived>
Expand Down
173 changes: 44 additions & 129 deletions include/fintamath/core/Parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,171 +10,86 @@
#include "fintamath/core/Tokenizer.hpp"
#include "fintamath/exceptions/InvalidInputException.hpp"

#include <algorithm>

namespace fintamath {

template <typename Return, typename... Args>
class Parser final {
public:
template <typename Return, typename... Args>
using Function = std::function<Return(Args...)>;

template <typename... Args>
using Comparator = std::function<bool(Args...)>;
using Validator = std::function<bool(const Return &)>;

template <typename Return, typename... Args>
using Map = std::unordered_multimap<std::string, Function<Return, Args...>>;
using Constructor = std::function<Return(const std::string &, Args &&...)>;

template <typename Return, typename... Args>
using Vector = std::vector<Function<Return, Args...>>;

template <typename Type, typename BasePtr, typename... Args>
static void add(Map<BasePtr, Args...> &parserMap) {
Function<BasePtr, Args...> constructor = [](const Args &...args) {
return std::make_unique<Type>(args...);
};
using TypeConstructor = std::function<Return(Args &&...)>;

static const std::string name = Type().toString();
parserMap.emplace(name, constructor);

Tokenizer::registerToken(name);
}
using ConstructorVector = std::vector<Constructor>;

template <typename Type, typename BasePtr, typename... Args>
static void add(Map<BasePtr, Args...> &parserMap, Function<BasePtr, Args...> &&parserFunc) {
static const std::string name = Type().toString();
parserMap.emplace(name, std::move(parserFunc));
using ConstructorMap = std::unordered_multimap<std::string, TypeConstructor>;

Tokenizer::registerToken(name);
}

template <typename Type, typename BasePtr, typename... Args>
static void add(Vector<BasePtr, Args...> &parserVect) {
Function<BasePtr, Args...> constructor = [](const Args &...args) {
try {
return std::make_unique<Type>(args...);
}
catch (const InvalidInputException &) {
return std::unique_ptr<Type>();
}
};

parserVect.emplace_back(constructor);
}

template <typename Type, typename BasePtr, typename... Args>
static void add(Vector<BasePtr, Args...> &parserVect, Function<BasePtr, Args...> &&parserFunc) {
parserVect.emplace_back(std::move(parserFunc));
public:
Return parse(const std::string &str, Args &&...args) const {
constexpr auto trueValidator = [](const Return &) { return true; };
return parse(trueValidator, str, std::move(args)...);
}

template <typename Return, typename... Args>
static Return parse(const Map<Return, const Args &...> &parserMap,
const std::string &parsedStr,
const Args &...args) {
Return parse(const Validator &validator, const std::string &str, Args &&...args) const {
for (const auto &valuePairs = constructorMap.equal_range(str);
const auto &pair : stdv::iota(valuePairs.first, valuePairs.second)) {

const auto &valuePairs = parserMap.equal_range(parsedStr);

for (const auto &pair : stdv::iota(valuePairs.first, valuePairs.second)) {
if (Return value = pair->second(args...)) {
if (Return value = pair->second(std::move(args)...); value && validator(value)) {
return value;
}
}

return nullptr;
}

template <typename Return, typename... Args>
requires(sizeof...(Args) > 0)
static Return parse(const Map<Return, Args &&...> &parserMap,
const std::string &parsedStr,
Args &&...args) {

const auto &valuePairs = parserMap.equal_range(parsedStr);

for (const auto &pair : stdv::iota(valuePairs.first, valuePairs.second)) {
if (Return value = pair->second(std::forward<Args>(args)...)) {
for (const auto &constructor : extraConstructors) {
if (Return value = constructor(str, std::move(args)...); value && validator(value)) {
return value;
}
}

return nullptr;
return Return{};
}

template <typename Return, typename... Args>
static Return parse(const Map<Return, const Args &...> &parserMap,
const Comparator<const Return &> &comp,
const std::string &parsedStr,
const Args &...args) {

const auto &valuePairs = parserMap.equal_range(parsedStr);

for (const auto &pair : stdv::iota(valuePairs.first, valuePairs.second)) {
if (Return value = pair->second(args...); value && comp(value)) {
return value;
}
}
template <typename Type>
void registerType() {
TypeConstructor constructor = [](Args &&...args) -> Return {
return std::make_unique<Type>(std::move(args)...);
};

return nullptr;
registerType<Type>(std::move(constructor));
}

template <typename Return, typename... Args>
requires(sizeof...(Args) > 0)
static Return parse(const Map<Return, Args &&...> &parserMap,
const Comparator<const Return &> &comp,
const std::string &parsedStr,
Args &&...args) {

const auto &valuePairs = parserMap.equal_range(parsedStr);
template <typename Type>
void registerType(TypeConstructor constructor) {
static const std::string name = Type{}.toString();
constructorMap.emplace(name, std::move(constructor));

for (const auto &pair : stdv::iota(valuePairs.first, valuePairs.second)) {
if (Return value = pair->second(std::forward<Args>(args)...); value && comp(value)) {
return value;
}
}

return nullptr;
Tokenizer::registerToken(name);
}

template <typename Return, typename... Args>
static Return parse(const Vector<Return, const Args &...> &parserVect, const Args &...args) {
for (const auto &constructor : parserVect) {
if (Return value = constructor(args...)) {
return value;
template <typename Type>
void registerConstructor() {
Constructor constructor = [](const std::string &str, Args &&...args) -> Return {
try {
return std::make_unique<Type>(str, std::move(args)...);
}
}

return nullptr;
}

template <typename Return, typename... Args>
requires(sizeof...(Args) > 0)
static Return parse(const Vector<Return, Args &&...> &parserVect, Args &&...args) {
for (const auto &constructor : parserVect) {
if (Return value = constructor(std::forward<Args>(args)...)) {
return value;
catch (const InvalidInputException &) {
return std::unique_ptr<Type>{};
}
}

return nullptr;
}
};

template <typename Type, typename BasePtr, typename... Args>
static void registerType(Map<BasePtr, Args...> &parserMap) {
add<Type>(parserMap);
registerConstructor(std::move(constructor));
}

template <typename Type, typename BasePtr, typename... Args>
static void registerType(Map<BasePtr, Args...> &parserMap, const Function<BasePtr, Args...> &parserFunc) {
add<Type>(parserMap, parserFunc);
void registerConstructor(Constructor constructor) {
extraConstructors.emplace_back(std::move(constructor));
}

template <typename Type, typename BasePtr, typename... Args>
static void registerType(Vector<BasePtr, Args...> &parserVect) {
add<Type>(parserVect);
}
private:
ConstructorMap constructorMap;

template <typename Type, typename BasePtr, typename... Args>
static void registerType(Vector<BasePtr, Args...> &parserVect, Function<BasePtr, Args...> &&parserFunc) {
add<Type>(parserVect, std::move(parserFunc));
}
ConstructorVector extraConstructors;
};

}
Loading

0 comments on commit 84afe8a

Please sign in to comment.