#include #include #include #include #include "katom.h" #include "ktype.h" #include "katomize.h" #include "error.h" #include "log.h" #include "show.h" #include "util.h" #include "file.h" bool dbg = false; // KATOMIZATION IS NOT HERE. Turning text into katoms moved to // katomize.{h,cpp} (2026-09-02), leaving this file the KATOM: what it is, // what its type means, and the operations on a list of them. The test that // decided the split is in katomize.h -- does a character stream enter? // Everything below answers no. size_t Katom::index = 0; // A katom holds its source text and its text, and decides nothing about // either. It used to strip the "^" from a quoted special here -- knowledge // of what a construct looks like IN SOURCE, inside the datum, which is the // one thing the katom/katomization split says does not belong here. That // moved to source_katom() in katomize.{h,cpp} on 2026-09-02, the one place // a katom is made from matched source text. Katom::Katom(const std::string& src, katom_t type, Locator loc) : m_index(Katom::index++) , m_text(src) , m_src(src) , m_loc(loc) , m_type(type) , m_initial_type(type) { } int active_count(const katom_list& katoms) { return std::ranges::count_if( katoms, [] (const Katom& k) { return k.m_type != katom_t::replaced && k.m_type != katom_t::ignored && k.m_type != katom_t::space && k.m_type != katom_t::newline; }); } bool active(const katom_list& katoms) { return active_count(katoms) > 0; } void restore_initial_type(katom_iter begin, katom_iter end) { std::for_each( begin, end, [](Katom& k) { k.m_type = k.m_initial_type; }); } void modify_type(katom_t new_type, katom_iter begin, katom_iter end) { std::for_each( begin, end, [&new_type](Katom& k) { k.m_type = new_type; }); } void modify_type(katom_t old_type, katom_t new_type, katom_iter begin, katom_iter end) { std::for_each( begin, end, [&](Katom& k) { if (k.m_type == old_type) k.m_type = new_type; }); } void ignore_whitespace(katom_iter& begin, katom_list& katoms) { constexpr bool _dbg = false; if (begin < katoms.end()) { katom_iter ki = begin; if (_dbg) std::cout << "IGNORE_WHITESPACE: "; auto end = katoms.end(); while (ki < end && ki->is_whitespace()) { if (_dbg) std::cout << kall << ktype << *ki << sp_arrow; ki->m_type = katom_t::ignored; if (_dbg) std::cout << kignored << kall << ktype << *ki << " " << "\n"; ++ki; } if (_dbg) std::cout << black << kreset; } } katom_iter after_whitespace(katom_iter begin) { katom_iter result = begin; while (result->is_whitespace()) { result++; } return result; } std::vector text_katoms(katom_iter& begin, katom_iter& end) { katom_list result {}; for (auto ki = begin; ki < end; ki++) { if (!ki->is_whitespace()) { auto k = *ki; //msg() << " push: " << kindex << ktype << kall << kws << k << "\n"; result.push_back(k); } } return result; } std::string as_string(std::vector::const_iterator begin, std::vector::const_iterator end, bool strip_whitespace) { auto include = [&](katom_t t) { return t != katom_t::replaced and t != katom_t::ignored; }; std::string result {}; for (auto ki = begin; ki < end; ki++) { katom_t t = ki->m_type; if (include(t)) { std::string text = !ki->m_display.empty() ? ki->m_display : ki->m_text; result += text; } } if (strip_whitespace) result = trim(result); return result; } std::string as_string(const katom_list& ks, bool strip_whitespace) { return as_string(ks.begin(), ks.end(), strip_whitespace); } std::string as_source(std::vector::const_iterator begin, std::vector::const_iterator end, bool strip_whitespace) { std::string result {}; for (auto ki = begin; ki < end; ki++) { if (ki->m_type != katom_t::replaced && ki->m_type != katom_t::ignored) result += ki->m_src; } if (strip_whitespace) result = trim(result); return result; } katom_list trim(katom_list& katoms, std::set trim_types) { katom_iter begin = std::find_if(katoms.begin(), katoms.end(), [&trim_types](const Katom& k) { return !trim_types.contains(k.m_type); }); if (begin == katoms.end()) { return katom_list{}; } katom_iter end = katoms.end() - 1; while (trim_types.contains(end->m_type)) { --end; } return katom_list(begin, end+1); } katom_list trim(const katom_list& katoms, bool trim_inactive) { katom_list result = katoms; std::set trim_types {katom_t::space, katom_t::newline}; if (trim_inactive) { trim_types.insert(katom_t::replaced); trim_types.insert(katom_t::ignored); } return trim(result, trim_types); } // I'm, like, this is // some weird shit; // what the fuck? // Whitespace std::pair whitespace_span(const katom_list& katoms, const katom_iter& start, katom_t start_type) { katom_iter ki = start; if (ki != katoms.begin()) { --ki; while (ki != katoms.begin() && ki->is_whitespace()) { --ki; } if (!ki->is_whitespace()) { ++ki; } } katom_iter begin = ki; while (ki != katoms.end() && (ki->is_whitespace() || ki->m_type == start_type || ki->m_type == katom_t::ignored || ki->m_type == katom_t::replaced)) { ++ki; } //katom_iter end = ki; return {begin, ki}; //end}; } std::vector find_katoms_of_type(const katom_list& katoms, katom_t type) { auto result = katoms | std::views::filter([type](const Katom& k) { return k.m_type == type; }); return std::vector(result.begin(), result.end()); } katom_iter find_katom_of_type(katom_iter begin, katom_iter end, katom_t type) { return std::find_if(begin, end, [&](const Katom& k) { return k.m_type == type; }); } // #- void remove_whitespace(katom_list& katoms) // Lint error { (void)K::log(3); auto begin = katoms.begin(); while (begin < katoms.end()) { auto ki = find_katom_of_type(begin, katoms.end(), katom_t::ws_remove); if (ki == katoms.end()) break; auto [b, e] = whitespace_span(katoms, ki, katom_t::ws_remove); std::for_each(b, e, [](Katom& k) { k.m_type = katom_t::ignored; }); begin = e; } } // #+n and #/n int whitespace_arg(Katom& k) { int result = 1; std::smatch match{}; if (std::regex_match(k.m_text, match, std::regex(R"(#[+/](\d*))"))) { if (!match[1].str().empty()) { result = stoi(match[1]); } } return result; } void insert_whitespace(katom_list& katoms, katom_t type, const std::string& c) { (void)K::log(3); for (Katom k : find_katoms_of_type(katoms, type)) { katom_iter ki = find_katom(katoms.begin(), katoms.end(), k.m_index); auto count = whitespace_arg(k); auto [b, e] = whitespace_span(katoms, ki, type); std::for_each(b, e, [](Katom& ka) { ka.m_type = katom_t::ignored; }); katom_list inserted = std::vector{}; for (int i = 0; i < count; ++i) { inserted.push_back(Katom(c, katom_t::ws_added, k.m_loc)); } katoms.insert(e, inserted.begin(), inserted.end()); } } void process_whitespace_modifiers(katom_list& katoms) { (void)K::log(4); remove_whitespace(katoms); insert_whitespace(katoms, katom_t::ws_space, " "); insert_whitespace(katoms, katom_t::ws_newline, "\n"); } katom_list trim_whitespace(katom_list katoms) { return trim(katoms, {katom_t::space, katom_t::newline}); }