#include #include #include #include #include #include "../include/teakra/disassembler.h" #include "common_types.h" #include "crash.h" #include "parser.h" using NodeAsConst = std::string; struct NodeAsExpansion {}; bool operator==(NodeAsExpansion, NodeAsExpansion) { return true; } namespace std { template <> struct hash { typedef NodeAsExpansion argument_type; typedef std::size_t result_type; result_type operator()(argument_type const& s) const { return 0x12345678; } }; } // namespace std namespace Teakra { class ParserImpl : public Parser { public: using NodeKey = std::variant; struct Node { bool end = false; u16 opcode = 0; bool expansion = false; std::unordered_map> children; }; Node root; Opcode Parse(const std::vector& tokens) override { Node* current = &root; for (auto& token : tokens) { auto const_find = current->children.find(token); if (const_find != current->children.end()) { current = const_find->second.get(); } else { return Opcode{Opcode::Invalid}; } } if (!current->end) { return Opcode{Opcode::Invalid}; } return Opcode{current->expansion ? Opcode::ValidWithExpansion : Opcode::Valid, current->opcode}; } }; std::unique_ptr GenerateParser() { std::unique_ptr parser = std::make_unique(); for (u32 opcode = 0; opcode < 0x10000; ++opcode) { u16 o = (u16)opcode; bool expansion = Disassembler::NeedExpansion(o); auto tokens = Disassembler::GetTokenList(o); if (std::any_of(tokens.begin(), tokens.end(), [](const auto& token) { return token.find("[ERROR]") != std::string::npos; })) continue; ParserImpl::Node* current = &parser->root; for (const auto& token : tokens) { auto& next = current->children[token]; if (!next) next = std::make_unique(); current = next.get(); } if (current->end) { ASSERT((current->opcode & (u16)(~o)) == 0); continue; } current->end = true; current->opcode = o; current->expansion = expansion; } return parser; } } // namespace Teakra