82 lines
3.1 KiB
C++
82 lines
3.1 KiB
C++
//============================================================================//
|
|
// //
|
|
// artichoke programming language //
|
|
// //
|
|
// Copyright (C) 2025 Erick Saul Guzman Ramos, whoami.artichoke.dev //
|
|
// //
|
|
// //
|
|
// This program is free software: you can redistribute it and/or modify //
|
|
// it under the terms of the GNU Affero General Public License as published //
|
|
// by the Free Software Foundation, either version 3 of the License, or //
|
|
// (at your option) any later version. //
|
|
// //
|
|
// This program is distributed in the hope that it will be useful, //
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
|
// GNU Affero General Public License for more details. //
|
|
// //
|
|
// You should have received a copy of the GNU Affero General Public License //
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>. //
|
|
// //
|
|
//============================================================================//
|
|
|
|
#pragma once
|
|
|
|
#include <random>
|
|
#include <ranges>
|
|
|
|
#include <artichoke/Coroutine/Generator.hpp>
|
|
|
|
template <std::ranges::range R1, std::ranges::range R2>
|
|
requires(
|
|
std::is_convertible_v<std::ranges::range_value_t<R1>, std::string_view> and
|
|
std::is_same_v<std::ranges::range_value_t<R1>, std::ranges::range_value_t<R2>>
|
|
)
|
|
arti::lang::Generator<std::ranges::range_value_t<R1>>
|
|
InterleaveRanges(R1 &&r1, R2 &&r2) {
|
|
auto it1 = std::ranges::begin(r1);
|
|
auto end1 = std::ranges::end(r1);
|
|
|
|
auto it2 = std::ranges::begin(r2);
|
|
auto end2 = std::ranges::end(r2);
|
|
|
|
while (it1 != end1 && it2 != end2) {
|
|
yield *it1;
|
|
++it1;
|
|
yield *it2;
|
|
++it2;
|
|
}
|
|
}
|
|
|
|
static arti::lang::Generator<std::string_view>
|
|
WhitespaceGenerator(uint32_t maxLen = 5) {
|
|
constexpr std::array<char, 3> spaceChars{ ' ', '\t', '\n' };
|
|
|
|
std::string str;
|
|
std::random_device device;
|
|
std::mt19937 engine(device());
|
|
std::uniform_int_distribution<uint32_t> dist(1, maxLen);
|
|
std::uniform_int_distribution<uint32_t> distChars(0, 2);
|
|
|
|
str.reserve(maxLen);
|
|
|
|
while (true) {
|
|
str.resize(0);
|
|
|
|
auto sz = dist(engine);
|
|
|
|
for (uint32_t i = 0; i < sz; ++i) {
|
|
str += spaceChars[distChars(engine)];
|
|
}
|
|
|
|
yield str;
|
|
}
|
|
}
|
|
|
|
template <std::ranges::range R>
|
|
requires(std::is_same_v<std::ranges::range_value_t<R>, std::string_view>)
|
|
static std::string SourceFromTokens(R &&tokens) {
|
|
return InterleaveRanges(tokens, WhitespaceGenerator(10)) | std::views::join |
|
|
std::ranges::to<std::string>();
|
|
}
|