diff --git a/sol/macrosol.cpp b/sol/macrosol.cpp index 15feb8bc311b2c6c46439bd9e6d13a09a1385e51..39724f201ce6d83f9ad058c82eab3b539f27d2c9 100644 --- a/sol/macrosol.cpp +++ b/sol/macrosol.cpp @@ -3,14 +3,98 @@ #include "macrosol.hpp" +#include +#include + namespace macrosol { - template< typename policy> - bool macroprocessor::process(const std::string& s, std::string& output) - { - output = s; +void macroprocessor_impl::apply_defines(std::string_view token, std::string& out) { + if (pf.is_present(token)) { + auto it = defines.find(token); + if (it != defines.end()) { + for (auto&& t : it->second) { + apply_defines(t, out); + } + return; + } + } + out.append(token.begin(), token.end()); + out.push_back(' '); +} + +bool macroprocessor_impl::process(const std::string& s, std::string& output) { + token_iterator tit(s.begin(), s.end()), tend(s.end(), s.end()); + if (tit == tend) { + output = ""; return true; } + auto first = *tit; + ++tit; + if (tit != tend && *tit == "=") { + auto it = defines.find(first); + if (it != defines.end()) it->second.update(tit, tend); + else { + macro m(first, tit, tend); + auto view = m.get_left_view(); + pf.insert(view); + defines.emplace(std::move(view), std::move(m)); + } + return false; + } + + assert(output.size() == 0); + apply_defines(first, output); + for (; tit != tend; ++tit) apply_defines(*tit, output); + if (output.size()) output.pop_back(); + return true; +} + +macroprocessor_impl::macro::macro(std::string_view define, macroprocessor_impl::macro::stoken_iterator_t tit, macroprocessor_impl::macro::stoken_iterator_t tend) { + left_len = define.size(); + this->left = new char[left_len + 1]; + define.copy(left, left_len); + left[left_len] = 0; + assert(define == left); + update(tit, tend); +} - template class macroprocessor< policy_scalar>; +void macroprocessor_impl::macro::update(macroprocessor_impl::macro::stoken_iterator_t tit, macroprocessor_impl::macro::stoken_iterator_t tend) { + assert(*tit == "="); + right.clear(); + for (++tit; tit != tend; ++tit) right.push_back(std::string(*tit)); } + +macroprocessor_impl::macro::macro(macro&& m) { + left = m.left; + m.left = 0; + left_len = m.left_len; + m.left_len = 0; + right = std::move(m.right); +} + +macroprocessor_impl::macro::~macro() { + delete[] left; +} + +void macroprocessor_impl::prefix_filter::insert(const std::string_view& val) { + filter[hash(val)] = 1; +} + +bool macroprocessor_impl::prefix_filter::is_present(const std::string_view& val) { + return filter[hash(val)]; +} + +size_t macroprocessor_impl::prefix_filter::chtoi(char c) { + return (c <= 'Z') ? (c - 'A') : (c - 'a'); +} + +size_t macroprocessor_impl::prefix_filter::hash(const std::string_view& val) { + size_t ret = chtoi(val[0]); + for (size_t i = 1; i < cnt; ++i) { + ret *= 26; + if (i < val.size()) ret += chtoi(val[i]); + } + return ret; +} + +} // namespace macrosol diff --git a/sol/macrosol.hpp b/sol/macrosol.hpp index 767c1ebec1d583cf71fae5a0aab2ed913aee8e7e..d7fa941cf03fc3ea771e97c4f995f28265c0cbec 100644 --- a/sol/macrosol.hpp +++ b/sol/macrosol.hpp @@ -4,32 +4,117 @@ #ifndef macrosol_hpp_ #define macrosol_hpp_ +#include +#include +#include +#include #include +#include +#include +#include +#include namespace macrosol { - struct policy_scalar { - }; +struct policy_scalar { +}; - struct policy_sse { - }; +struct policy_sse { +}; #ifdef USE_AVX - struct policy_avx { - }; +struct policy_avx { +}; #endif #ifdef USE_AVX512 - struct policy_avx512 { - }; +struct policy_avx512 { +}; #endif - template< typename policy> - class macroprocessor { +class macroprocessor_impl { +public: + macroprocessor_impl() : + defines(100) {} + bool process(const std::string& s, std::string& output); + +private: + template + class token_iterator { public: - bool process(const std::string& s, std::string& output); - + token_iterator(T begin, T end) : + ibegin(begin), iend(begin), end(end) { this->operator++(); } + token_iterator& operator++() { + ibegin = iend; + while (ibegin != end && *ibegin == ' ') ++ibegin; + iend = ibegin; + if (ibegin == end) return *this; + ++iend; + if (*ibegin == '=') return *this; + while (iend != end && *iend != ' ' && *iend != '=') ++iend; + return *this; + } + std::string_view operator*() { + return std::string_view(&*ibegin, iend - ibegin); + } + + template + bool operator==(const token_iterator& other) { + return ibegin == other.ibegin; + } + template + bool operator!=(const token_iterator& other) { + return !(*this == other); + } + private: + T ibegin; + T iend; + const T end; }; -} + + class macro { + typedef token_iterator stoken_iterator_t; + + public: + macro(std::string_view define, stoken_iterator_t tit, stoken_iterator_t tend); + macro(macro&& m); + macro& operator=(macro&& m) = delete; + macro(macro& m) = delete; + macro& operator=(macro& m) = delete; + ~macro(); + void update(stoken_iterator_t tit, stoken_iterator_t tend); + inline std::string_view get_left_view() const { return std::string_view(left, left_len); } + inline auto begin() const { return right.cbegin(); } + inline auto end() const { return right.cend(); } + + private: + char* left = 0; + size_t left_len = 0; + std::vector right; + }; + + class prefix_filter { + public: + void insert(const std::string_view& val); + bool is_present(const std::string_view& val); + + private: + const static size_t cnt = 3; // number of chars compares by hash() + bool filter[26 * 26 * 26]; + + inline size_t chtoi(char c); + size_t hash(const std::string_view& val); + }; + + std::unordered_map defines; + prefix_filter pf; + + void apply_defines(std::string_view token, std::string& out); +}; + +template +class macroprocessor : public macroprocessor_impl {}; + +} // namespace macrosol #endif diff --git a/upload_to_parlab.sh b/upload_to_parlab.sh new file mode 100755 index 0000000000000000000000000000000000000000..6aeb951bc71ea33d6f25acf35883342482f29780 --- /dev/null +++ b/upload_to_parlab.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +cd "$(dirname -- "$0")" || exit 1 + +rsync -rP --inplace * mff-parlab:asgn/ --exclude build --exclude "gold-*" --exclude "*.vscode*"