Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#include <SSVUtils/SSVUtils.hpp>
namespace Eng
{
template<typename TTokenType, typename TTokenDataType, typename TASTType> struct LangSpec
{
using TokenType = TTokenType;
using TokenDataType = TTokenDataType;
using ASTType = TASTType;
};
template<typename TL> using TokenType = typename TL::TokenType;
template<typename TL> using TokenDataType = typename TL::TokenDataType;
template<typename TL> using ASTType = typename TL::ASTType;
template<typename TL> class Token
{
private:
TokenType<TL> type;
TokenDataType<TL> data;
public:
inline Token(const TokenType<TL>& mType) noexcept : type{mType} { }
inline Token(const TokenType<TL>& mType, const TokenDataType<TL>& mData) : Token{mType}, data{mData} { }
inline const TokenType<TL>& getType() const noexcept { return type; }
inline const TokenDataType<TL>& getData() const noexcept { return data; }
};
template<typename TL> class ASTImpl
{};
template<typename TL> class ASTNode
{
private:
ASTType<TL> type;
ssvu::Uptr<ASTImpl<TL>> impl;
ASTNode<TL>* parent{nullptr};
std::vector<ssvu::Uptr<ASTNode<TL>>> children;
public:
template<typename T, typename... TArgs> T& emplaceChild(TArgs&&... mArgs)
{
auto& result(ssvu::getEmplaceUptr<T>(children, std::forward<TArgs>(mArgs)...));
result.parent = this;
return result;
}
inline ASTImpl<TL>* getImpl() noexcept { return impl.get(); }
inline ASTNode<TL>* getParent() noexcept { return parent; }
inline decltype(children)& getChildren() noexcept { return children; }
template<typename T> T& getImplAs() noexcept
{
SSVU_ASSERT(impl != nullptr);
return *reinterpret_cast<T*>(impl.get());
}
};
enum class ParseletType{Token, Node};
template<typename TL> class Parselet
{
private:
ParseletType type;
union
{
Token<TL> token;
ASTNode<TL> node;
};
public:
inline ParseletType getType() const noexcept { return type; }
inline decltype(token)& getToken() noexcept { SSVU_ASSERT(type == ParseletType::Token); return token; }
inline decltype(node)& getNode() noexcept { SSVU_ASSERT(type == ParseletType::Node); return node; }
};
template<typename TL> class RulePart
{
private:
ParseletType type;
union
{
TokenType<TL> tokenType;
ASTType<TL> astType;
};
public:
inline RulePart(TokenType<TL> mTokenType) noexcept : type{ParseletType::Token}, tokenType{mTokenType} { }
inline RulePart(ASTType<TL> mASTType) noexcept : type{ParseletType::Node}, astType{mASTType} { }
inline ParseletType getType() const noexcept { return type; }
inline const decltype(tokenType)& getTokenType() const noexcept { SSVU_ASSERT(type == ParseletType::Token); return tokenType; }
inline const decltype(astType)& getASTType() const noexcept { SSVU_ASSERT(type == ParseletType::Token); return astType; }
inline bool operator==(const RulePart<TL>& mRhs) const noexcept
{
if(type != mRhs.type) return false;
if(type == ParseletType::Token && tokenType == mRhs.tokenType) return true;
if(type == ParseletType::Node && astType == mRhs.astType) return true;
return false;
}
inline bool operator!=(const RulePart<TL>& mRhs) const noexcept { return !this->operator==(mRhs); }
};
template<typename TL> class RuleKey
{
private:
std::vector<RulePart<TL>> ruleParts;
template<typename T> inline void ctorImpl(T mP) { ruleParts.emplace_back(mP); }
template<typename T1, typename T2, typename... TArgs> inline void ctorImpl(T1 mP1, T2 mP2, TArgs... mArgs)
{
ctorImpl(mP1); ctorImpl(mP2, mArgs...);
}
template<std::size_t TIdx> inline bool matchesImpl(const RulePart<TL>& mPart) const { return mPart == ruleParts.at(TIdx); }
template<std::size_t TIdx, typename T1, typename T2, typename... TArgs> inline bool matchesImpl(T1 mP1, T2 mP2, TArgs... mArgs) const
{
return !matchesImpl<TIdx>(mP1) ? false : matchesImpl<TIdx + 1>(mP2, mArgs...);
}
public:
template<typename... TArgs> inline RuleKey(TArgs... mArgs)
{
ctorImpl(mArgs...);
}
template<typename... TArgs> inline bool matches(TArgs... mArgs)
{
return sizeof...(TArgs) != ruleParts.size() ? false : matchesImpl<0>(mArgs...);
}
};
template<typename TL> class Rule
{
private:
RuleKey<TL> ruleKey;
ASTType<TL> result;
ssvu::Func<ssvu::Uptr<ASTImpl<TL>>(const std::vector<Parselet<TL>>&)> func;
public:
inline Rule(RuleKey<TL> mKey, ASTType<TL> mResult, const decltype(func)& mFunc) :
ruleKey{std::move(mKey)}, result{mResult}, func{mFunc} { }
};
template<typename TL> class RuleSet
{
private:
public:
template<typename... TArgs> inline void createRule(TArgs&&... mArgs)
{
Rule<TL> result(std::forward<TArgs>(mArgs)...);
}
};
template<typename TL> class Parser
{
private:
std::vector<Token<TL>> sourceStack;
std::vector<Parselet<TL>> parseStack, nodeStack;
public:
inline void pushOnSource(Token<TL> mToken) { sourceStack.emplace_back(std::move(mToken)); }
inline void pushOnParse(Parselet<TL> mParselet) { parseStack.emplace_back(std::move(mParselet)); }
inline void pushOnNode(Parselet<TL> mParselet) { nodeStack.emplace_back(std::move(mParselet)); }
inline void shift()
{
SSVU_ASSERT(!sourceStack.empty());
// Take top of source stack
const auto& tkn(sourceStack.back());
// Push it both on parse and node stacks
pushOnParse(tkn);
pushOnNode(tkn);
// Pop from source stack
sourceStack.pop_back();
}
inline void reduceRecursively()
{
}
};
}
namespace Lang
{
enum class Tkn
{
Number,
POpen,
PClose
};
struct TknData { };
enum class ASTT
{
Expr,
Number
};
using Spec = Eng::LangSpec<Tkn, TknData, ASTT>;
struct ASTExpr : public Eng::ASTImpl<Spec>
{
inline virtual void eval() { }
};
struct ASTNumber : public ASTExpr
{
int value;
inline ASTNumber(int mValue) : value{mValue} { }
inline void eval() override { }
};
}
int main()
{
using namespace Eng;
using namespace Lang;
RuleSet<Spec> ruleSet;
ruleSet.createRule(RuleKey<Spec>{Tkn::Number}, ASTT::Number, [](const std::vector<Parselet<Spec>>& mParselets)
{
//return std::make_unique<ASTNumber>(mParselets[0].getToken())
return std::make_unique<ASTNumber>(1);
});
//ruleSet.createRule(RuleKey<Spec>{ASTT::Expr, Tkn::Plus, ASTT::Expr}, ASTT::AddOp);
RuleKey<Spec> testKey{Tkn::Number, ASTT::Number};
ssvu::lo() << testKey.matches(Tkn::Number, ASTT::Number) << std::endl;
//ssvu::lo() << testKey.matches(ASTT::Number, Tkn::Number) << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.