| 997 | } |
| 998 | |
| 999 | std::string common_peg_arena::dump_impl(common_peg_parser_id id, |
| 1000 | std::unordered_set<common_peg_parser_id> & visited) const { |
| 1001 | // Check for cycles |
| 1002 | if (visited.count(id)) { |
| 1003 | return "[cycle]"; |
| 1004 | } |
| 1005 | visited.insert(id); |
| 1006 | |
| 1007 | const auto & parser = parsers_.at(id); |
| 1008 | |
| 1009 | return std::visit([this, &visited](const auto & p) -> std::string { |
| 1010 | using T = std::decay_t<decltype(p)>; |
| 1011 | |
| 1012 | if constexpr (std::is_same_v<T, common_peg_epsilon_parser>) { |
| 1013 | return "Epsilon"; |
| 1014 | } else if constexpr (std::is_same_v<T, common_peg_start_parser>) { |
| 1015 | return "Start"; |
| 1016 | } else if constexpr (std::is_same_v<T, common_peg_end_parser>) { |
| 1017 | return "End"; |
| 1018 | } else if constexpr (std::is_same_v<T, common_peg_literal_parser>) { |
| 1019 | return "Literal(" + p.literal + ")"; |
| 1020 | } else if constexpr (std::is_same_v<T, common_peg_sequence_parser>) { |
| 1021 | std::vector<std::string> parts; |
| 1022 | for (const auto & child : p.children) { |
| 1023 | parts.push_back(dump_impl(child, visited)); |
| 1024 | } |
| 1025 | return "Sequence(" + string_join(parts, ", ") + ")"; |
| 1026 | } else if constexpr (std::is_same_v<T, common_peg_choice_parser>) { |
| 1027 | std::vector<std::string> parts; |
| 1028 | for (const auto & child : p.children) { |
| 1029 | parts.push_back(dump_impl(child, visited)); |
| 1030 | } |
| 1031 | return "Choice(" + string_join(parts, ", ") + ")"; |
| 1032 | } else if constexpr (std::is_same_v<T, common_peg_repetition_parser>) { |
| 1033 | if (p.max_count == -1) { |
| 1034 | return "Repetition(" + dump_impl(p.child, visited) + ", " + std::to_string(p.min_count) + |
| 1035 | ", unbounded)"; |
| 1036 | } |
| 1037 | return "Repetition(" + dump_impl(p.child, visited) + ", " + std::to_string(p.min_count) + ", " + std::to_string(p.max_count) + ")"; |
| 1038 | } else if constexpr (std::is_same_v<T, common_peg_and_parser>) { |
| 1039 | return "And(" + dump_impl(p.child, visited) + ")"; |
| 1040 | } else if constexpr (std::is_same_v<T, common_peg_not_parser>) { |
| 1041 | return "Not(" + dump_impl(p.child, visited) + ")"; |
| 1042 | } else if constexpr (std::is_same_v<T, common_peg_atomic_parser>) { |
| 1043 | return "Atomic(" + dump_impl(p.child, visited) + ")"; |
| 1044 | } else if constexpr (std::is_same_v<T, common_peg_gbnf_parser>) { |
| 1045 | return "Gbnf(" + p.grammar + ", " + dump_impl(p.child, visited) + ")"; |
| 1046 | } else if constexpr (std::is_same_v<T, common_peg_any_parser>) { |
| 1047 | return "Any"; |
| 1048 | } else if constexpr (std::is_same_v<T, common_peg_space_parser>) { |
| 1049 | return "Space"; |
| 1050 | } else if constexpr (std::is_same_v<T, common_peg_chars_parser>) { |
| 1051 | if (p.max_count == -1) { |
| 1052 | return "CharRepeat(" + p.pattern + ", " + std::to_string(p.min_count) + ", unbounded)"; |
| 1053 | } |
| 1054 | return "CharRepeat(" + p.pattern + ", " + std::to_string(p.min_count) + ", " + std::to_string(p.max_count) + ")"; |
| 1055 | } else if constexpr (std::is_same_v<T, common_peg_string_parser>) { |
| 1056 | return "String(" + std::string(1, p.delimiter) + ")"; |