Files
klammertext/mac/katom.cpp
T

277 lines
7.8 KiB
C++
Raw Normal View History

#include <iostream>
#include <fstream>
#include <ranges>
#include <algorithm>
#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<Katom> 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<Katom>::const_iterator begin, std::vector<Katom>::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<Katom>::const_iterator begin, std::vector<Katom>::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<katom_t> 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<katom_t> 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<katom_iter,katom_iter> 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<Katom> 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<Katom>{};
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});
}