#include #include #include #include "argtype.h" #include "error.h" #include "util.h" Argtype::Argtype(std::string name, std::string desc, std::string symbolic_pattern, std::string pattern, std::string default_value, std::string alone_value, std::string python_cast, modify_string_f python_format, const Locator& loc) : m_name(name) , m_desc(desc) , m_symbolic_pattern(symbolic_pattern) , m_pattern(pattern) , m_default(default_value) , m_alone(alone_value) , m_python_cast(python_cast) , m_python_format(python_format) , m_regex(std::regex(pattern)) , m_loc(loc) { } static bool empty_value(const strings_t& v) { return v.empty() || (v.size() == 1 && v[0].empty()); } std::string pyformat_string(const strings_t& v) { std::string p = v.empty() ? "" : v[0]; p = string_replace(p, "\\", "\\\\"); p = string_replace(p, "\"", "\\\""); p = string_replace(p, "\n", "\\n"); return "\"" + p + "\""; } std::string pyformat_bool(const strings_t& v) { if (empty_value(v)) { return "None"; } std::string value = v[0]; std::set true_values { "1", "true", "True", "yes" }; std::set false_values { "0", "false", "False", "no" }; if (true_values.contains(value)) { return "True"; } else if (false_values.contains(value)) { return "False"; } else { throw Argument_error("The argument\"" + value + "\" is not a Boolean value"); } } std::string pyformat_number(const strings_t& value) { if (empty_value(value)) { return "None"; } return value[0]; } std::string pylist(strings_t words) { std::transform(words.begin(), words.end(), words.begin(), [](const std::string& s) { return pyformat_string({s}); }); return "[" + join(words, ", ") + "]"; } std::string pyformat_list(const strings_t& value) { strings_t words {}; for (const std::string& v : value) { for (const std::string& word : word_split(v)) { if (!word.empty()) { words.push_back(word); } } } return pylist(words); } std::string pyformat_dlist(const strings_t& value) { strings_t items {}; for (const std::string& v : value) { if (v.empty()) { continue; } for (const std::string& item : dlist_split(v)) { items.push_back(item); } } return pylist(items); } std::string Argtype::python_value(const std::string& var_name, std::vector value, size_t name_size) { std::stringstream ss {}; ss << " " << std::left << std::setw(name_size) << var_name << " = "; if (m_python_format) { ss << m_python_format(value); } else if (m_python_cast.empty() || m_python_cast == "str") { // String-family types (and untyped variables): plain quoted string. ss << pyformat_string(value); } else if (!m_parameter.empty()) { // Parameterized type: bind the type parameter as N around the // cast, e.g. (lambda N: )(2)("A | B || C | D"). ss << "(lambda N: " << m_python_cast << ")(" << m_parameter << ")(" << pyformat_string(value) << ")"; } else { // User-defined :python_cast expression, applied to the raw value. // The cast is applied to an empty value too, so e.g. a split lambda // yields [] for an unsupplied argument. ss << m_python_cast << "(" << pyformat_string(value) << ")"; } return ss.str(); }