9#ifndef __EXTENDED_NEWICK_FORMATTER_H_INCLUDED__
10#define __EXTENDED_NEWICK_FORMATTER_H_INCLUDED__
41bool check_if_balanced(
const std::string &input,
const char &open =
'(',
const char &close =
')')
44 for (
const auto &ch : input)
62 static std::string edit(
const std::string &s)
78 static bool check(
const std::string &s)
88 static bool check(
const std::string &s)
96using namespace std::string_literals;
100static inline std::vector<std::string> forbidden_labels = {
" "s,
","s,
";"s,
"("s,
")"s,
"["s,
"]"s};
108static inline constexpr char blank =
'_';
128 static std::string edit(
const std::string &s)
130 return std::regex_replace(s, std::regex(R
"(\[[^()]*\])"), "");
140 static std::string edit(
const std::string &s)
144 for (
const auto &ch : s)
150 if (ch ==
'[' && counter == 2)
152 if (ch ==
']' && counter == 1)
154 if (!(counter >= 2 || (counter == 1 && ch ==
']')))
155 buffer.append(std::string(1, ch));
166 static inline std::string root_branch_length()
171 static inline std::string treat_comments(std::string &s)
182 static inline std::string root_branch_length()
187 static inline std::string treat_comments(
const std::string &s)
198 static inline std::string root_branch_length()
203 static inline std::string treat_comments(std::string &s)
212template <
class F,
class... Args>
213concept Formattable = std::invocable<F, Args...> && std::convertible_to<std::invoke_result_t<F, Args...>, std::string>;
218template <
class T, std::predicate<T> P1, std::predicate<T> P2, Formattable<T> F1, Formattable<T> F2,
240 static inline constexpr char _end =
';';
281 bool has_forbidden_characters(
const std::string &s)
const
284 for (
const std::string &piece : forbidden_labels)
286 bool is_forbidden = std::regex_search(s, std::regex(
"^[^"s + joined +
"]"s));
295 void _pre_order(
const node_type &node)
const
297 if (std::invoke(_has_children, node))
316 void _post_order(
const node_type &node)
const
319 if (std::invoke(_has_children, node))
325 if (std::invoke(_has_parent, node))
327 auto label = std::invoke(_label, node);
329 if (has_forbidden_characters(remove_comments_of_depth<1>::edit(label)))
331 throw std::invalid_argument(std::string(
"Label with forbidden characters:") + std::string(label));
336 auto branch = std::invoke(_branch_length, node);
345 _formula += std::invoke(_label, node);
346 _formula += policy_type::root_branch_length();
354 Formatter(P1 &&has_parent, P2 &&has_children, F1 &&label, F2 &&branch_length)
355 : _has_parent(std::forward<P1>(has_parent)), _has_children(std::forward<P2>(has_children)),
356 _label(std::forward<F1>(label)), _branch_length(std::forward<F2>(branch_length))
367 return [
this](
const node_type &node) { this->_pre_order(node); };
374 return [
this](
const node_type &node) { this->_in_order(node); };
384 return [
this](
const node_type &node) { this->_post_order(node); };
401 _formula.push_back(this->_end);
403 _formula = policy_type::treat_comments(_formula);
407 throw std::runtime_error(std::string(
"Failed: formula parenthesis are not balanced:") + _formula);
412 throw std::runtime_error(std::string(
"Failed: formula square brackets are not balanced:") + _formula);
431template <
typename P1>
using single_function_argument_t =
typename single_function_argument_impl<P1>::type;
434template <
class P1,
class P2,
class F1,
class F2,
class Policy = PAUP>
440template <
class P1,
class P2,
class F1,
class F2,
class Policy = PAUP>
441auto make_formatter(P1 &&has_parent, P2 &&has_children, F1 &&label, F2 &&branch_length, Policy policy = Policy())
445 std::forward<P1>(has_parent), std::forward<P2>(has_children), std::forward<F1>(label),
446 std::forward<F2>(branch_length));
453template <
class T, std::predicate<T> P1, std::predicate<T> P2, Formattable<T> F1, Formattable<T> F2,
class Policy>
454auto make_formatter(P1 &&has_parent, P2 &&has_children, F1 &&label, F2 &&branch_length, Policy policy = Policy())
458 std::forward<F1>(label), std::forward<F2>(branch_length));
Simulation of coalescence-based models of molecular evolution.
Definition coalescence.hpp:21