From a0f19047af6749a3a7f963b89b00a61bf4d7e839 Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Sat, 8 Jun 2024 21:46:18 +0100 Subject: [PATCH] nit: move + rename _build_min_max_int --- common/json-schema-to-grammar.cpp | 366 +++++++++++++++--------------- 1 file changed, 183 insertions(+), 183 deletions(-) diff --git a/common/json-schema-to-grammar.cpp b/common/json-schema-to-grammar.cpp index 4c25829bd..b60966a2c 100644 --- a/common/json-schema-to-grammar.cpp +++ b/common/json-schema-to-grammar.cpp @@ -40,6 +40,188 @@ static std::string build_repetition(const std::string & item_rule, const int min return result; } +static void _build_min_max_int(int min_value, int max_value, std::stringstream & out, int decimals_left = 16, bool top_level = true) { + auto has_min = min_value != std::numeric_limits::min(); + auto has_max = max_value != std::numeric_limits::max(); + + auto digit_range = [&](char from, char to) { + out << "["; + if (from == to) { + out << from; + } else { + out << from << "-" << to; + } + out << "]"; + }; + auto more_digits = [&](int min_digits, int max_digits) { + out << "[0-9]"; + if (min_digits == max_digits && min_digits == 1) { + return; + } + out << "{"; + out << min_digits; + if (max_digits != min_digits) { + out << ","; + if (max_digits != std::numeric_limits::max()) { + out << max_digits; + } + } + out << "}"; + }; + std::function uniform_range = [&](const std::string_view & from, const std::string_view & to) { + size_t i = 0; + while (from[i] == to[i]) { + i++; + } + if (i > 0) { + out << "\"" << from.substr(0, i) << "\""; + } + if (i < from.length()) { + if (i > 0) { + out << " "; + } + auto sub_len = from.length() - i - 1; + if (sub_len > 0) { + auto from_sub = from.substr(i + 1); + auto to_sub = to.substr(i + 1); + auto sub_zeros = repeat("0", sub_len); + auto sub_nines = repeat("9", sub_len); + + auto to_reached = false; + out << "("; + if (from_sub == sub_zeros) { + digit_range(from[i], to[i] - 1); + out << " "; + more_digits(sub_len, sub_len); + } else { + out << "[" << from[i] << "] "; + out << "("; + uniform_range(from_sub, sub_nines); + out << ")"; + if (from[i] < to[i] - 1) { + out << " | "; + if (to_sub == sub_nines) { + digit_range(from[i] + 1, to[i]); + to_reached = true; + } else { + digit_range(from[i] + 1, to[i] - 1); + } + out << " "; + more_digits(sub_len, sub_len); + } + } + if (!to_reached) { + out << " | "; + digit_range(to[i], to[i]); + out << " "; + uniform_range(sub_zeros, to_sub); + } + out << ")"; + } else { + out << "[" << from[i] << "-" << to[i] << "]"; + } + } + }; + + if (has_min && has_max) { + if (min_value < 0 && max_value < 0) { + out << "\"-\" ("; + _build_min_max_int(-max_value, -min_value, out, decimals_left, /* top_level= */ true); + out << ")"; + return; + } + + if (min_value < 0) { + out << "\"-\" ("; + _build_min_max_int(0, -min_value, out, decimals_left, /* top_level= */ true); + out << ") | "; + min_value = 0; + } + + auto min_s = std::to_string(min_value); + auto max_s = std::to_string(max_value); + auto min_digits = min_s.length(); + auto max_digits = max_s.length(); + + for (auto digits = min_digits; digits < max_digits; digits++) { + uniform_range(min_s, repeat("9", digits)); + min_s = "1" + repeat("0", digits); + out << " | "; + } + uniform_range(min_s, max_s); + return; + } + + auto less_decimals = std::max(decimals_left - 1, 1); + + if (has_min) { + if (min_value < 0) { + out << "\"-\" ("; + _build_min_max_int(std::numeric_limits::min(), -min_value, out, decimals_left, /* top_level= */ false); + out << ") | [0] | [1-9] "; + more_digits(0, decimals_left - 1); + } else if (min_value == 0) { + if (top_level) { + out << "[0] | [1-9] "; + more_digits(0, less_decimals); + } else { + more_digits(1, decimals_left); + } + } else if (min_value <= 9) { + char c = '0' + min_value; + if (min_value > (top_level ? 1 : 0)) { + digit_range('0', c - 1); + out << " "; + more_digits(1, less_decimals); + out << " | "; + } + digit_range(c, '9'); + out << " "; + more_digits(0, less_decimals); + } else { + auto min_s = std::to_string(min_value); + auto len = min_s.length(); + auto c = min_s[0]; + + if (c > '1') { + digit_range(top_level ? '1' : '0', c - 1); + out << " "; + more_digits(len, less_decimals); + out << " | "; + } + digit_range(c, c); + out << " ("; + _build_min_max_int(std::stoi(min_s.substr(1)), std::numeric_limits::max(), out, less_decimals, /* top_level= */ false); + out << ")"; + if (c < '9') { + out << " | "; + digit_range(c + 1, '9'); + out << " "; + more_digits(len - 1, less_decimals); + } + } + return; + } + + if (has_max) { + if (max_value >= 0) { + if (top_level) { + out << "\"-\" [1-9] "; + more_digits(0, less_decimals); + out << " | "; + } + _build_min_max_int(0, max_value, out, decimals_left, /* top_level= */ true); + } else { + out << "\"-\" ("; + _build_min_max_int(-max_value, std::numeric_limits::max(), out, decimals_left, /* top_level= */ false); + out << ")"; + } + return; + } + + throw std::runtime_error("At least one of min_value or max_value must be set"); +} + const std::string SPACE_RULE = "\" \"?"; struct BuiltinRule { @@ -160,188 +342,6 @@ static std::string format_literal(const std::string & literal) { return "\"" + escaped + "\""; } -static void _generate_min_max_int(int min_value, int max_value, std::stringstream & out, int decimals_left = 16, bool top_level = true) { - auto has_min = min_value != std::numeric_limits::min(); - auto has_max = max_value != std::numeric_limits::max(); - - auto digit_range = [&](char from, char to) { - out << "["; - if (from == to) { - out << from; - } else { - out << from << "-" << to; - } - out << "]"; - }; - auto more_digits = [&](int min_digits, int max_digits) { - out << "[0-9]"; - if (min_digits == max_digits && min_digits == 1) { - return; - } - out << "{"; - out << min_digits; - if (max_digits != min_digits) { - out << ","; - if (max_digits != std::numeric_limits::max()) { - out << max_digits; - } - } - out << "}"; - }; - std::function uniform_range = [&](const std::string_view & from, const std::string_view & to) { - size_t i = 0; - while (from[i] == to[i]) { - i++; - } - if (i > 0) { - out << "\"" << from.substr(0, i) << "\""; - } - if (i < from.length()) { - if (i > 0) { - out << " "; - } - auto sub_len = from.length() - i - 1; - if (sub_len > 0) { - auto from_sub = from.substr(i + 1); - auto to_sub = to.substr(i + 1); - auto sub_zeros = repeat("0", sub_len); - auto sub_nines = repeat("9", sub_len); - - auto to_reached = false; - out << "("; - if (from_sub == sub_zeros) { - digit_range(from[i], to[i] - 1); - out << " "; - more_digits(sub_len, sub_len); - } else { - out << "[" << from[i] << "] "; - out << "("; - uniform_range(from_sub, sub_nines); - out << ")"; - if (from[i] < to[i] - 1) { - out << " | "; - if (to_sub == sub_nines) { - digit_range(from[i] + 1, to[i]); - to_reached = true; - } else { - digit_range(from[i] + 1, to[i] - 1); - } - out << " "; - more_digits(sub_len, sub_len); - } - } - if (!to_reached) { - out << " | "; - digit_range(to[i], to[i]); - out << " "; - uniform_range(sub_zeros, to_sub); - } - out << ")"; - } else { - out << "[" << from[i] << "-" << to[i] << "]"; - } - } - }; - - if (has_min && has_max) { - if (min_value < 0 && max_value < 0) { - out << "\"-\" ("; - _generate_min_max_int(-max_value, -min_value, out, decimals_left, /* top_level= */ true); - out << ")"; - return; - } - - if (min_value < 0) { - out << "\"-\" ("; - _generate_min_max_int(0, -min_value, out, decimals_left, /* top_level= */ true); - out << ") | "; - min_value = 0; - } - - auto min_s = std::to_string(min_value); - auto max_s = std::to_string(max_value); - auto min_digits = min_s.length(); - auto max_digits = max_s.length(); - - for (auto digits = min_digits; digits < max_digits; digits++) { - uniform_range(min_s, repeat("9", digits)); - min_s = "1" + repeat("0", digits); - out << " | "; - } - uniform_range(min_s, max_s); - return; - } - - auto less_decimals = std::max(decimals_left - 1, 1); - - if (has_min) { - if (min_value < 0) { - out << "\"-\" ("; - _generate_min_max_int(std::numeric_limits::min(), -min_value, out, decimals_left, /* top_level= */ false); - out << ") | [0] | [1-9] "; - more_digits(0, decimals_left - 1); - } else if (min_value == 0) { - if (top_level) { - out << "[0] | [1-9] "; - more_digits(0, less_decimals); - } else { - more_digits(1, decimals_left); - } - } else if (min_value <= 9) { - char c = '0' + min_value; - if (min_value > (top_level ? 1 : 0)) { - digit_range('0', c - 1); - out << " "; - more_digits(1, less_decimals); - out << " | "; - } - digit_range(c, '9'); - out << " "; - more_digits(0, less_decimals); - } else { - auto min_s = std::to_string(min_value); - auto len = min_s.length(); - auto c = min_s[0]; - - if (c > '1') { - digit_range(top_level ? '1' : '0', c - 1); - out << " "; - more_digits(len, less_decimals); - out << " | "; - } - digit_range(c, c); - out << " ("; - _generate_min_max_int(std::stoi(min_s.substr(1)), std::numeric_limits::max(), out, less_decimals, /* top_level= */ false); - out << ")"; - if (c < '9') { - out << " | "; - digit_range(c + 1, '9'); - out << " "; - more_digits(len - 1, less_decimals); - } - } - return; - } - - if (has_max) { - if (max_value >= 0) { - if (top_level) { - out << "\"-\" [1-9] "; - more_digits(0, less_decimals); - out << " | "; - } - _generate_min_max_int(0, max_value, out, decimals_left, /* top_level= */ true); - } else { - out << "\"-\" ("; - _generate_min_max_int(-max_value, std::numeric_limits::max(), out, decimals_left, /* top_level= */ false); - out << ")"; - } - return; - } - - throw std::runtime_error("At least one of min_value or max_value must be set"); -} - class SchemaConverter { private: std::function _fetch_json; @@ -882,7 +882,7 @@ public: } std::stringstream out; out << "("; - _generate_min_max_int(min_value, max_value, out); + _build_min_max_int(min_value, max_value, out); out << ") space"; return _add_rule(rule_name, out.str()); } else if (schema.empty() || schema_type == "object") {