diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc index 855da295f7928eb9085c453e0aa55fcf0e1ad289..37924dc92a061ac6083acdad3970bac689572707 100644 --- a/src/ComputingTasks.cc +++ b/src/ComputingTasks.cc @@ -3465,69 +3465,57 @@ SvarIdentificationStatement::writeJsonOutput(ostream &output) const MarkovSwitchingStatement::MarkovSwitchingStatement(OptionsList options_list_arg) : options_list{move(options_list_arg)} { - if (auto it_num = options_list.num_options.find("ms.restrictions"); - it_num != options_list.num_options.end()) + if (auto it_num = options_list.vector_of_vector_value_options.find("ms.restrictions"); + it_num != options_list.vector_of_vector_value_options.end()) { - using namespace boost; auto it_num_regimes = options_list.num_options.find("ms.number_of_regimes"); assert(it_num_regimes != options_list.num_options.end()); auto num_regimes = stoi(it_num_regimes->second); - vector<string> tokenizedRestrictions; - split(tokenizedRestrictions, it_num->second, is_any_of("["), token_compress_on); - for (auto &tokenizedRestriction : tokenizedRestrictions) - if (tokenizedRestriction.size() > 0) - { - vector<string> restriction; - split(restriction, tokenizedRestriction, is_any_of("], ")); - for (auto it1 = restriction.begin(); it1 != restriction.end();) - if (it1->empty()) - restriction.erase(it1); - else - ++it1; - - if (restriction.size() != 3) - { - cerr << "ERROR: restrictions in the subsample statement must be specified in the form " - << "[current_period_regime, next_period_regime, transition_probability]" << endl; - exit(EXIT_FAILURE); - } + for (const vector<string> &restriction : it_num->second) + { + if (restriction.size() != 3) + { + cerr << "ERROR: restrictions in the subsample statement must be specified in the form " + << "[current_period_regime, next_period_regime, transition_probability]" << endl; + exit(EXIT_FAILURE); + } - try - { - auto from_regime = stoi(restriction[0]); - auto to_regime = stoi(restriction[1]); - if (from_regime > num_regimes || to_regime > num_regimes) - { - cerr << "ERROR: the regimes specified in the restrictions option must be " - << "<= the number of regimes specified in the number_of_regimes option" << endl; - exit(EXIT_FAILURE); - } - - if (restriction_map.contains({ from_regime, to_regime })) - { - cerr << "ERROR: two restrictions were given for: " << from_regime << ", " - << to_regime << endl; - exit(EXIT_FAILURE); - } - - auto transition_probability = stod(restriction[2]); - if (transition_probability > 1.0) - { - cerr << "ERROR: the transition probability, " << transition_probability - << " must be less than 1" << endl; - exit(EXIT_FAILURE); - } - restriction_map[{ from_regime, to_regime }] = transition_probability; - } - catch (const invalid_argument &) - { - cerr << "ERROR: The first two arguments for a restriction must be integers " - << "specifying the regime and the last must be a double specifying the " - << "transition probability. You wrote [" << tokenizedRestriction << endl; - exit(EXIT_FAILURE); - } - } + try + { + auto from_regime = stoi(restriction[0]); + auto to_regime = stoi(restriction[1]); + if (from_regime > num_regimes || to_regime > num_regimes) + { + cerr << "ERROR: the regimes specified in the restrictions option must be " + << "<= the number of regimes specified in the number_of_regimes option" << endl; + exit(EXIT_FAILURE); + } + + if (restriction_map.contains({ from_regime, to_regime })) + { + cerr << "ERROR: two restrictions were given for: " << from_regime << ", " + << to_regime << endl; + exit(EXIT_FAILURE); + } + + auto transition_probability = stod(restriction[2]); + if (transition_probability > 1.0) + { + cerr << "ERROR: the transition probability, " << transition_probability + << " must be less than 1" << endl; + exit(EXIT_FAILURE); + } + restriction_map[{ from_regime, to_regime }] = transition_probability; + } + catch (const invalid_argument &) + { + cerr << "ERROR: The first two arguments for a restriction must be integers " + << "specifying the regime and the last must be a floating point specifying the " + << "transition probability."; + exit(EXIT_FAILURE); + } + } } } @@ -3544,10 +3532,8 @@ MarkovSwitchingStatement::checkPass(ModFileStructure &mod_file_struct, WarningCo exit(EXIT_FAILURE); } - if (auto it_num = options_list.num_options.find("ms.restrictions"); - it_num != options_list.num_options.end()) + if (options_list.vector_of_vector_value_options.contains("ms.restrictions")) { - using namespace boost; auto it_num_regimes = options_list.num_options.find("ms.number_of_regimes"); assert(it_num_regimes != options_list.num_options.end()); auto num_regimes = stoi(it_num_regimes->second); @@ -3613,21 +3599,32 @@ MarkovSwitchingStatement::checkPass(ModFileStructure &mod_file_struct, WarningCo void MarkovSwitchingStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const { - bool isDurationAVec = true; - string infStr("Inf"); - OptionsList::num_options_t::const_iterator itChain, itNOR, itDuration; - map<pair<int, int>, double >::const_iterator itR; - - itChain = options_list.num_options.find("ms.chain"); + auto itChain = options_list.num_options.find("ms.chain"); assert(itChain != options_list.num_options.end()); - itDuration = options_list.num_options.find("ms.duration"); - assert(itDuration != options_list.num_options.end()); - if (stod(itDuration->second) || infStr.compare(itDuration->second) == 0) - isDurationAVec = false; - output << "options_.ms.duration = " << itDuration->second << ";" << endl; + assert(options_list.num_options.contains("ms.duration") + || options_list.vector_value_options.contains("ms.duration")); - itNOR = options_list.num_options.find("ms.number_of_regimes"); + bool isDurationAVec = options_list.vector_value_options.contains("ms.duration"); + + output << "options_.ms.duration = "; + if (isDurationAVec) + { + output << "["; + auto &v = options_list.vector_value_options.at("ms.duration"); + for (auto it = v.begin(); it != v.end(); ++it) + { + if (it != v.begin()) + output << ", "; + output << *it; + } + output << "]"; + } + else + output << options_list.num_options.at("ms.duration"); + output << ";" << endl; + + auto itNOR = options_list.num_options.find("ms.number_of_regimes"); assert(itNOR != options_list.num_options.end()); for (int i = 0; i < stoi(itNOR->second); i++) { @@ -3639,7 +3636,7 @@ MarkovSwitchingStatement::writeOutput(ostream &output, const string &basename, b } int restrictions_index = 0; - for (itR = restriction_map.begin(); itR != restriction_map.end(); itR++) + for (auto itR = restriction_map.begin(); itR != restriction_map.end(); itR++) output << "options_.ms.ms_chain(" << itChain->second << ").restrictions(" << ++restrictions_index << ") = {[" << itR->first.first << ", " << itR->first.second << ", " << itR->second << "]};" << endl; @@ -4034,21 +4031,19 @@ JointPriorStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli } if (!options_list.num_options.contains("mean") + && !options_list.vector_value_options.contains("mean") && !options_list.num_options.contains("mode")) { cerr << "ERROR: You must pass at least one of mean and mode to the prior statement." << endl; exit(EXIT_FAILURE); } - if (auto it_num = options_list.num_options.find("domain"); - it_num != options_list.num_options.end()) + if (auto it = options_list.vector_value_options.find("domain"); + it != options_list.vector_value_options.end()) { - using namespace boost; - vector<string> tokenizedDomain; - split(tokenizedDomain, it_num->second, is_any_of("[ ]"), token_compress_on); - if (tokenizedDomain.size() != 4) + if (it->second.size() != 4) { - cerr << "ERROR: You must pass exactly two values to the domain option." << endl; + cerr << "ERROR: You must pass exactly four values to the domain option." << endl; exit(EXIT_FAILURE); } } @@ -4103,15 +4098,38 @@ void JointPriorStatement::writeOutputHelper(ostream &output, const string &field, const string &lhs_field) const { output << lhs_field << "." << field << " = {"; - if (field == "variance") - output << "{"; - if (auto itn = options_list.num_options.find(field); - itn != options_list.num_options.end()) - output << itn->second; - else - output << "{}"; - if (field == "variance") - output << "}"; + if (auto it = options_list.num_options.find(field); + it != options_list.num_options.end()) + output << it->second; + else if (auto it = options_list.vector_value_options.find(field); + it != options_list.vector_value_options.end()) + { + output << "["; + for (auto it2 = it->second.begin(); it2 != it->second.end(); ++it2) + { + if (it2 != it->second.begin()) + output << ", "; + output << *it2; + } + output << "]"; + } + else if (auto it = options_list.vector_of_vector_value_options.find(field); + it != options_list.vector_of_vector_value_options.end()) + { + for (auto it2 = it->second.begin(); it2 != it->second.end(); ++it2) + { + if (it2 != it->second.begin()) + output << ", "; + output << "["; + for (auto it3 = it2->begin(); it3 != it2->end(); ++it3) + { + if (it3 != it2->begin()) + output << ", "; + output << *it3; + } + output << "]"; + } + } output << "};" << endl; } @@ -4191,6 +4209,7 @@ BasicPriorStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsoli } if (!options_list.num_options.contains("mean") + && !options_list.vector_value_options.contains("mean") && !options_list.num_options.contains("mode")) { cerr << "ERROR: You must pass at least one of mean and mode to the prior statement." << endl; diff --git a/src/DynareBison.yy b/src/DynareBison.yy index 3ebfb6879624f67f011333a83e5ac9c251a1367a..69761e37cd68180317ac8d2c7953f25da04876ee 100644 --- a/src/DynareBison.yy +++ b/src/DynareBison.yy @@ -194,15 +194,15 @@ class ParsingDriver; %type <expr_t> equation hand_side %type <string> non_negative_number signed_number signed_integer date_str %type <string> filename symbol namespace_qualified_filename namespace_qualified_symbol -%type <string> vec_of_vec_value vec_value_list date_expr -%type <string> vec_value_1 vec_value signed_inf signed_number_w_inf -%type <string> range vec_value_w_inf vec_value_1_w_inf +%type <string> date_expr signed_inf signed_number_w_inf range %type <string> integer_range signed_integer_range boolean %type <string> name_value_pair name_value_pair_list %type <string> name_value_pair_with_boolean name_value_pair_with_boolean_list %type <string> name_value_pair_with_suboptions name_value_pair_with_suboptions_list %type <SymbolType> change_type_arg %type <vector<string>> vec_str vec_str_1 +%type <vector<string>> vec_value vec_value_1 vec_value_w_inf vec_value_w_inf_1 +%type <vector<vector<string>>> vec_of_vec_value vec_of_vec_value_1 %type <vector<string>> symbol_list symbol_list_or_wildcard %type <vector<int>> vec_int_elem vec_int_1 vec_int vec_int_number %type <PriorDistributions> prior_pdf prior_distribution @@ -3535,16 +3535,16 @@ o_shift : SHIFT EQUAL signed_number { driver.option_num("shift", $3); }; o_shape : SHAPE EQUAL prior_distribution { driver.prior_shape = $3; }; o_mode : MODE EQUAL signed_number { driver.option_num("mode", $3); }; o_mean : MEAN EQUAL signed_number { driver.option_num("mean", $3); }; -o_mean_vec : MEAN EQUAL vec_value { driver.option_num("mean", $3); }; -o_truncate : TRUNCATE EQUAL vec_value { driver.option_num("truncate", $3); }; +o_mean_vec : MEAN EQUAL vec_value { driver.option_vec_value("mean", $3); }; +o_truncate : TRUNCATE EQUAL vec_value { driver.option_vec_value("truncate", $3); }; o_stdev : STDEV EQUAL non_negative_number { driver.option_num("stdev", $3); }; o_jscale : JSCALE EQUAL non_negative_number { driver.option_num("jscale", $3); }; o_init : INIT EQUAL signed_number { driver.option_num("init", $3); }; -o_bounds : BOUNDS EQUAL vec_value_w_inf { driver.option_num("bounds", $3); }; -o_domain : DOMAINN EQUAL vec_value { driver.option_num("domain", $3); }; -o_interval : INTERVAL EQUAL vec_value { driver.option_num("interval", $3); }; +o_bounds : BOUNDS EQUAL vec_value_w_inf { driver.option_vec_value("bounds", $3); }; +o_domain : DOMAINN EQUAL vec_value { driver.option_vec_value("domain", $3); }; +o_interval : INTERVAL EQUAL vec_value { driver.option_vec_value("interval", $3); }; o_variance : VARIANCE EQUAL expression { driver.set_prior_variance($3); } -o_variance_mat : VARIANCE EQUAL vec_of_vec_value { driver.option_num("variance",$3); } +o_variance_mat : VARIANCE EQUAL vec_of_vec_value { driver.option_vec_of_vec_value("variance",$3); } o_prefilter : PREFILTER EQUAL INT_NUMBER { driver.option_num("prefilter", $3); }; o_presample : PRESAMPLE EQUAL INT_NUMBER { driver.option_num("presample", $3); }; o_lik_algo : LIK_ALGO EQUAL INT_NUMBER { driver.option_num("lik_algo", $3); }; @@ -3684,9 +3684,9 @@ o_xls_sheet : XLS_SHEET EQUAL symbol { driver.option_str("xls_sheet", $3); } // o_xls_range : XLS_RANGE EQUAL range { driver.option_str("xls_range", $3); }; o_filter_step_ahead : FILTER_STEP_AHEAD EQUAL vec_int { driver.option_vec_int("filter_step_ahead", $3); }; o_taper_steps : TAPER_STEPS EQUAL vec_int { driver.option_vec_int("convergence.geweke.taper_steps", $3); }; -o_geweke_interval : GEWEKE_INTERVAL EQUAL vec_value { driver.option_num("convergence.geweke.geweke_interval",$3); }; +o_geweke_interval : GEWEKE_INTERVAL EQUAL vec_value { driver.option_vec_value("convergence.geweke.geweke_interval",$3); }; o_raftery_lewis_diagnostics : RAFTERY_LEWIS_DIAGNOSTICS { driver.option_num("convergence.rafterylewis.indicator", "true"); }; -o_raftery_lewis_qrs : RAFTERY_LEWIS_QRS EQUAL vec_value { driver.option_num("convergence.rafterylewis.qrs",$3); }; +o_raftery_lewis_qrs : RAFTERY_LEWIS_QRS EQUAL vec_value { driver.option_vec_value("convergence.rafterylewis.qrs",$3); }; o_constant : CONSTANT { driver.option_num("noconstant", "false"); }; o_noconstant : NOCONSTANT { driver.option_num("noconstant", "true"); }; o_mh_recover : MH_RECOVER { driver.option_num("mh_recover", "true"); }; @@ -3796,7 +3796,7 @@ o_gsa_load_rmse : LOAD_RMSE EQUAL INT_NUMBER { driver.option_num("load_rmse", $3 o_gsa_load_stab : LOAD_STAB EQUAL INT_NUMBER { driver.option_num("load_stab", $3); }; o_gsa_alpha2_stab : ALPHA2_STAB EQUAL non_negative_number { driver.option_num("alpha2_stab", $3); }; o_gsa_logtrans_redform : LOGTRANS_REDFORM EQUAL INT_NUMBER { driver.option_num("logtrans_redform", $3); }; -o_gsa_threshold_redform : THRESHOLD_REDFORM EQUAL vec_value_w_inf { driver.option_num("threshold_redform",$3); }; +o_gsa_threshold_redform : THRESHOLD_REDFORM EQUAL vec_value_w_inf { driver.option_vec_value("threshold_redform",$3); }; o_gsa_ksstat_redform : KSSTAT_REDFORM EQUAL non_negative_number { driver.option_num("ksstat_redform", $3); }; o_gsa_alpha2_redform : ALPHA2_REDFORM EQUAL non_negative_number { driver.option_num("alpha2_redform", $3); }; o_gsa_namendo : NAMENDO EQUAL '(' symbol_list_or_wildcard ')' { driver.option_symbol_list("namendo", $4); }; @@ -3923,12 +3923,12 @@ o_k_order_solver : K_ORDER_SOLVER {driver.option_num("k_order_solver","true"); } o_pruning : PRUNING { driver.option_num("pruning", "true"); }; o_chain : CHAIN EQUAL INT_NUMBER { driver.option_num("ms.chain",$3); }; o_restrictions : RESTRICTIONS EQUAL vec_of_vec_value - { driver.option_num("ms.restrictions",$3); } + { driver.option_vec_of_vec_value("ms.restrictions",$3); } ; o_duration : DURATION EQUAL non_negative_number { driver.option_num("ms.duration",$3); } | DURATION EQUAL vec_value_w_inf - { driver.option_num("ms.duration",$3); } + { driver.option_vec_value("ms.duration",$3); } ; o_number_of_regimes : NUMBER_OF_REGIMES EQUAL INT_NUMBER { driver.option_num("ms.number_of_regimes",$3); }; o_number_of_lags : NUMBER_OF_LAGS EQUAL INT_NUMBER { driver.option_num("ms.number_of_lags",$3); }; @@ -3981,7 +3981,7 @@ o_file_tag : FILE_TAG EQUAL filename { driver.option_str("ms.file_tag", $3); }; o_no_create_init : NO_CREATE_INIT { driver.option_num("ms.create_init", "false"); }; o_simulation_file_tag : SIMULATION_FILE_TAG EQUAL filename { driver.option_str("ms.simulation_file_tag", $3); }; o_coefficients_prior_hyperparameters : COEFFICIENTS_PRIOR_HYPERPARAMETERS EQUAL vec_value - { driver.option_num("ms.coefficients_prior_hyperparameters",$3); }; + { driver.option_vec_value("ms.coefficients_prior_hyperparameters",$3); }; o_convergence_starting_value : CONVERGENCE_STARTING_VALUE EQUAL non_negative_number { driver.option_num("ms.convergence_starting_value",$3); }; o_convergence_ending_value : CONVERGENCE_ENDING_VALUE EQUAL non_negative_number @@ -4025,10 +4025,10 @@ o_horizon : HORIZON EQUAL INT_NUMBER { driver.option_num("ms.horizon",$3); }; o_filtered_probabilities : FILTERED_PROBABILITIES { driver.option_num("ms.filtered_probabilities","true"); }; o_real_time_smoothed : REAL_TIME_SMOOTHED { driver.option_num("ms.real_time_smoothed_probabilities","true"); }; o_no_error_bands : NO_ERROR_BANDS { driver.option_num("ms.error_bands","false"); }; -o_error_band_percentiles : ERROR_BAND_PERCENTILES EQUAL vec_value { driver.option_num("ms.percentiles",$3); }; +o_error_band_percentiles : ERROR_BAND_PERCENTILES EQUAL vec_value { driver.option_vec_value("ms.percentiles",$3); }; o_shock_draws : SHOCK_DRAWS EQUAL INT_NUMBER { driver.option_num("ms.shock_draws",$3); }; o_shocks_per_parameter : SHOCKS_PER_PARAMETER EQUAL INT_NUMBER { driver.option_num("ms.shocks_per_parameter",$3); }; -o_free_parameters : FREE_PARAMETERS EQUAL vec_value { driver.option_num("ms.free_parameters",$3); }; +o_free_parameters : FREE_PARAMETERS EQUAL vec_value { driver.option_vec_value("ms.free_parameters",$3); }; o_median : MEDIAN { driver.option_num("ms.median","1"); } | MEDIAN EQUAL signed_number { driver.option_num("median", $3); }; o_regimes : REGIMES { driver.option_num("ms.regimes","true"); }; @@ -4240,39 +4240,55 @@ vec_str : vec_str_1 ']' ; vec_value_1 : '[' signed_number - { $$ = '[' + $2; } + { $$ = { $2 }; } | '[' COMMA signed_number - { $$ = '[' + $3; } + { $$ = { $3 }; } | vec_value_1 signed_number - { $$ = $1 + ' ' + $2; } + { + $$ = $1; + $$.push_back($2); + } | vec_value_1 COMMA signed_number - { $$ = $1 + ' ' + $3; } + { + $$ = $1; + $$.push_back($3); + } ; vec_value : vec_value_1 ']' - { $$ = $1 + ']'; } | vec_value_1 COMMA ']' - { $$ = $1 + ']'; } ; -vec_value_list : vec_value_list COMMA vec_value - { $$ = $1 + ',' + $3; } - | vec_value - ; +vec_value_w_inf_1 : signed_number_w_inf + { $$ = { $1 }; } + | vec_value_w_inf_1 signed_number_w_inf + { + $$ = $1; + $$.push_back($2); + } + | vec_value_w_inf_1 COMMA signed_number_w_inf + { + $$ = $1; + $$.push_back($3); + } + ; -vec_of_vec_value : '[' vec_value_list ']' - { $$ = $2; } - | vec_value - ; +vec_value_w_inf : '[' vec_value_w_inf_1 ']' + { $$ = $2; } + ; -vec_value_1_w_inf : '[' signed_number_w_inf - { $$ = '[' + $2; } - | vec_value_1_w_inf signed_number_w_inf - { $$ = $1 + ' ' + $2; } - ; +vec_of_vec_value_1 : vec_of_vec_value_1 COMMA vec_value + { + $$ = $1; + $$.push_back($3); + } + | vec_value + { $$ = { $1 }; } + ; -vec_value_w_inf : vec_value_1_w_inf ']' - { $$ = $1 + ']'; }; +vec_of_vec_value : '[' vec_of_vec_value_1 ']' + { $$ = $2; } + ; symbol : NAME | ALPHA diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc index 4a10761423d2d109287c022d6b54e57637501acb..c576e9ab05e98278ef77e1729a07fb33d064192e 100644 --- a/src/ParsingDriver.cc +++ b/src/ParsingDriver.cc @@ -1471,6 +1471,30 @@ ParsingDriver::option_vec_cellstr(string name_option, vector<string> opt) options_list.vector_cellstr_options[move(name_option)] = move(opt); } +void +ParsingDriver::option_vec_value(string name_option, vector<string> opt) +{ + if (options_list.vector_value_options.contains(name_option)) + error("option " + name_option + " declared twice"); + + if (opt.empty()) + error("option " + name_option + " was passed an empty vector."); + + options_list.vector_value_options[move(name_option)] = move(opt); +} + +void +ParsingDriver::option_vec_of_vec_value(string name_option, vector<vector<string>> opt) +{ + if (options_list.vector_of_vector_value_options.contains(name_option)) + error("option " + name_option + " declared twice"); + + if (opt.empty()) + error("option " + name_option + " was passed an empty vector."); + + options_list.vector_of_vector_value_options[move(name_option)] = move(opt); +} + void ParsingDriver::linear() { diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh index 2284720d5354334eb43a9f750256e7c1d6ec9cc9..c17d7eed892cc27d94f077435a04414a36cc324d 100644 --- a/src/ParsingDriver.hh +++ b/src/ParsingDriver.hh @@ -512,6 +512,10 @@ public: void option_vec_str(string name_option, vector<string> opt); //! Sets an option to a celll array of strings void option_vec_cellstr(string name_option, vector<string> opt); + //! Sets an option to a vector of (numerical) values + void option_vec_value(string name_option, vector<string> opt); + //! Sets an option to a vector of vectors of (numerical) values + void option_vec_of_vec_value(string name_option, vector<vector<string>> opt); //! Indicates that the model is linear void linear(); //! Writes a rplot() command diff --git a/src/Statement.cc b/src/Statement.cc index 1631283629ec45a17201520af42905873710f3a9..ba574eb8213de816c955712b96503b775f6cc7fa 100644 --- a/src/Statement.cc +++ b/src/Statement.cc @@ -238,6 +238,30 @@ OptionsList::writeOutputCommon(ostream &output, const string &option_group) cons output << "'" << viit << "';"; output << "};" << endl; } + + /* For historical reason, those vectors are output as row vectors (contrary + to vectors of integers which are output as column vectors) */ + for (const auto &[name, vals] : vector_value_options) + { + output << option_group << "." << name << " = ["; + for (const auto &viit : vals) + output << viit << ","; + output << "];" << endl; + } + + // Same remark as for vectors of (floating point) values + for (const auto &[name, vec_vals] : vector_of_vector_value_options) + { + output << option_group << "." << name << " = {"; + for (const auto &vals : vec_vals) + { + output << "["; + for (const auto &viit : vals) + output << viit << ","; + output << "], "; + } + output << "};" << endl; + } } void @@ -336,6 +360,43 @@ OptionsList::writeJsonOutput(ostream &output) const opt_written = true; } + for (const auto &[name, vals] : vector_value_options) + { + if (opt_written) + output << ", "; + output << R"(")" << name << R"(": [)"; + for (auto it = vals.begin(); it != vals.end(); ++it) + { + if (it != vals.begin()) + output << ", "; + output << *it; + } + output << "]"; + opt_written = true; + } + + for (const auto &[name, vec_vals] : vector_of_vector_value_options) + { + if (opt_written) + output << ", "; + output << R"(")" << name << R"(": [)"; + for (auto it = vec_vals.begin(); it != vec_vals.end(); ++it) + { + if (it != vec_vals.begin()) + output << ", "; + output << "["; + for (auto it2 = it->begin(); it2 != it->end(); ++it2) + { + if (it2 != it->begin()) + output << ", "; + output << *it2; + } + output << "]"; + } + output << "]"; + opt_written = true; + } + output << "}"; } @@ -350,6 +411,8 @@ OptionsList::clear() vector_int_options.clear(); vector_str_options.clear(); vector_cellstr_options.clear(); + vector_value_options.clear(); + vector_of_vector_value_options.clear(); } int @@ -362,5 +425,7 @@ OptionsList::getNumberOfOptions() const + symbol_list_options.size() + vector_int_options.size() + vector_str_options.size() - + vector_cellstr_options.size(); + + vector_cellstr_options.size() + + vector_value_options.size() + + vector_of_vector_value_options.size(); } diff --git a/src/Statement.hh b/src/Statement.hh index 16f04fcce8ece6440abc948cd66a47ac75cde662..4b800123e29f54a158b7dc51224bff9e1637ebe8 100644 --- a/src/Statement.hh +++ b/src/Statement.hh @@ -215,6 +215,8 @@ public: using vec_int_options_t = map<string, vector<int>>; using vec_str_options_t = map<string, vector<string >>; using vec_cellstr_options_t = map<string, vector<string >>; + using vec_value_options_t = map<string, vector<string>>; + using vec_of_vec_value_options_t = map<string, vector<vector<string>>>; num_options_t num_options; paired_num_options_t paired_num_options; string_options_t string_options; @@ -223,6 +225,8 @@ public: vec_int_options_t vector_int_options; vec_str_options_t vector_str_options; vec_cellstr_options_t vector_cellstr_options; + vec_value_options_t vector_value_options; + vec_of_vec_value_options_t vector_of_vector_value_options; int getNumberOfOptions() const; void writeOutput(ostream &output) const; void writeOutput(ostream &output, const string &option_group) const;