Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::client::MyContext Struct Reference
+ Inheritance diagram for Slic3r::client::MyContext:
+ Collaboration diagram for Slic3r::client::MyContext:

Classes

struct  NewOldVariable
 

Public Member Functions

bool skipping () const
 
const ConfigOptionoptptr (const t_config_option_key &opt_key) const override
 
const ConfigOptionresolve_symbol (const std::string &opt_key) const
 
ConfigOptionresolve_output_symbol (const std::string &opt_key) const
 
void store_new_variable (const std::string &opt_key, std::unique_ptr< ConfigOption > &&opt, bool global_variable)
 
bool has (const t_config_option_key &opt_key) const
 
const ConfigOptionoption (const t_config_option_key &opt_key) const
 
template<typename TYPE >
const TYPE * option (const t_config_option_key &opt_key) const
 
const ConfigOptionoption_throw (const t_config_option_key &opt_key) const
 
template<typename TYPE >
const TYPE * option_throw (const t_config_option_key &opt_key) const
 

Static Public Member Functions

static bool evaluate_full_macro (const MyContext *ctx)
 
static void block_enter (const MyContext *ctx, const bool condition)
 
static void block_exit (const MyContext *ctx, const bool condition, bool &not_yet_consumed, std::string &data_in, std::string &data_out)
 
static void block_exit_ternary (const MyContext *ctx, const bool condition, expr &data_in, expr &data_out)
 
static void legacy_variable_expansion (const MyContext *ctx, IteratorRange &opt_key, std::string &output)
 
static void legacy_variable_expansion2 (const MyContext *ctx, IteratorRange &opt_key, IteratorRange &opt_vector_index, std::string &output)
 
static void resolve_variable (const MyContext *ctx, IteratorRange &opt_key, OptWithPos &output)
 
static void store_variable_index (const MyContext *ctx, OptWithPos &opt, int index, Iterator it_end, OptWithPos &output)
 
static void scalar_variable_to_expr (const MyContext *ctx, OptWithPos &opt, expr &output)
 
static void vector_element_to_expr (const MyContext *ctx, OptWithPos &opt, expr &output)
 
static void check_writable (const MyContext *ctx, OptWithPos &opt)
 
static void check_numeric (const expr &param)
 
static size_t evaluate_count (const expr &expr_count)
 
static void scalar_variable_assign_scalar (const MyContext *ctx, OptWithPos &lhs, const expr &rhs)
 
static void vector_variable_element_assign_scalar (const MyContext *ctx, OptWithPos &lhs, const expr &rhs)
 
static void vector_variable_assign_expr_with_count (const MyContext *ctx, OptWithPos &lhs, const expr &rhs_count, const expr &rhs_value)
 
static void variable_value (const MyContext *ctx, OptWithPos &opt, expr &output)
 
static void is_nil_test (const MyContext *ctx, OptWithPos &opt, expr &output)
 
static void new_old_variable (const MyContext *ctx, bool global_variable, const IteratorRange &it_range, NewOldVariable &out)
 
static void scalar_variable_assign_scalar_expression (const MyContext *ctx, OptWithPos &opt, const expr &param)
 
static void scalar_variable_new_from_scalar_expression (const MyContext *ctx, bool global_variable, NewOldVariable &lhs, const expr &rhs)
 
static void vector_variable_new_from_array (const MyContext *ctx, bool global_variable, NewOldVariable &lhs, const expr &rhs_count, const expr &rhs_value)
 
static void vector_variable_assign_array (const MyContext *ctx, OptWithPos &lhs, const expr &rhs_count, const expr &rhs_value)
 
template<typename ConfigOptionType , typename RightValueEvaluate >
static void fill_vector_from_initializer_list (ConfigOption *opt, const std::vector< expr > &il, RightValueEvaluate rv_eval)
 
static void vector_variable_assign_initializer_list (const MyContext *ctx, OptWithPos &lhs, const std::vector< expr > &il)
 
static void vector_variable_new_from_initializer_list (const MyContext *ctx, bool global_variable, NewOldVariable &lhs, const std::vector< expr > &il)
 
static bool is_vector_variable_reference (const OptWithPos &var)
 
static bool could_be_vector_variable_reference (const NewOldVariable &var)
 
static void copy_vector_variable_to_vector_variable (const MyContext *ctx, OptWithPos &lhs, const OptWithPos &rhs)
 
static bool vector_variable_new_from_copy (const MyContext *ctx, bool global_variable, NewOldVariable &lhs, const OptWithPos &rhs)
 
static void initializer_list_append (std::vector< expr > &list, expr &param)
 
static void is_vector_empty (const MyContext *ctx, OptWithPos &opt, expr &out)
 
static void vector_size (const MyContext *ctx, OptWithPos &opt, expr &out)
 
static void evaluate_index (expr &expr_index, int &output)
 
static void random (const MyContext *ctx, expr &param1, expr &param2)
 
static void throw_exception (const std::string &msg, const IteratorRange &it_range)
 
static void process_error_message (const MyContext *context, const boost::spirit::info &info, const Iterator &it_begin, const Iterator &it_end, const Iterator &it_error)
 

Public Attributes

const DynamicConfigexternal_config = nullptr
 
const DynamicConfigconfig = nullptr
 
const DynamicConfigconfig_override = nullptr
 
DynamicConfigconfig_outputs = nullptr
 
DynamicConfig config_local
 
size_t current_extruder_id = 0
 
PlaceholderParser::ContextDatacontext_data = nullptr
 
bool just_boolean_expression = false
 
std::string error_message
 

Static Public Attributes

static std::map< std::string, std::string > tag_to_error_message
 

Private Attributes

int m_depth_suppressed { 0 }
 

Detailed Description


Class Documentation

◆ Slic3r::client::MyContext::NewOldVariable

struct Slic3r::client::MyContext::NewOldVariable
+ Collaboration diagram for Slic3r::client::MyContext::NewOldVariable:
Class Members
IteratorRange it_range
string name
ConfigOption * opt { nullptr }

Member Function Documentation

◆ block_enter()

static void Slic3r::client::MyContext::block_enter ( const MyContext ctx,
const bool  condition 
)
inlinestatic
805 {
806 if (ctx->skipping() || ! condition)
807 ++ ctx->m_depth_suppressed;
808 }

References m_depth_suppressed, and skipping().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ block_exit()

static void Slic3r::client::MyContext::block_exit ( const MyContext ctx,
const bool  condition,
bool &  not_yet_consumed,
std::string &  data_in,
std::string &  data_out 
)
inlinestatic
811 {
812 if (ctx->skipping())
813 -- ctx->m_depth_suppressed;
814 else if (condition && not_yet_consumed) {
815 data_out = std::move(data_in);
816 not_yet_consumed = false;
817 }
818 }

References m_depth_suppressed, and skipping().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ block_exit_ternary()

static void Slic3r::client::MyContext::block_exit_ternary ( const MyContext ctx,
const bool  condition,
expr data_in,
expr data_out 
)
inlinestatic
820 {
821 if (ctx->skipping())
822 -- ctx->m_depth_suppressed;
823 else if (condition)
824 data_out = std::move(data_in);
825 }

References m_depth_suppressed, and skipping().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ check_numeric()

static void Slic3r::client::MyContext::check_numeric ( const expr param)
inlinestatic
1077 {
1078 if (! param.numeric_type())
1079 param.throw_exception("Right side is not a numeric expression");
1080 };

References Slic3r::client::expr::numeric_type(), and Slic3r::client::expr::throw_exception().

Referenced by scalar_variable_assign_scalar(), vector_variable_assign_expr_with_count(), and vector_variable_element_assign_scalar().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ check_writable()

static void Slic3r::client::MyContext::check_writable ( const MyContext ctx,
OptWithPos opt 
)
inlinestatic
1072 {
1073 if (! opt.writable)
1074 ctx->throw_exception("Cannot modify a read-only variable", opt.it_range);
1075 }

References Slic3r::client::OptWithPos::it_range, throw_exception(), and Slic3r::client::OptWithPos::writable.

Referenced by copy_vector_variable_to_vector_variable(), scalar_variable_assign_scalar(), scalar_variable_assign_scalar_expression(), vector_variable_assign_array(), vector_variable_assign_initializer_list(), and vector_variable_element_assign_scalar().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ copy_vector_variable_to_vector_variable()

static void Slic3r::client::MyContext::copy_vector_variable_to_vector_variable ( const MyContext ctx,
OptWithPos lhs,
const OptWithPos rhs 
)
inlinestatic
1447 {
1448 if (ctx->skipping())
1449 return;
1450
1451 check_writable(ctx, lhs);
1452 assert(lhs.opt->is_vector());
1453 if (rhs.has_index() || ! rhs.opt->is_vector())
1454 ctx->throw_exception("Cannot assign scalar to a vector", lhs.it_range);
1455 if (rhs.opt->is_nil())
1456 ctx->throw_exception("Some elements of the right hand side vector variable of optional values are undefined (nil)", rhs.it_range);
1457 if (lhs.opt->type() != rhs.opt->type()) {
1458 // Vector types are not compatible.
1459 switch (lhs.opt->type()) {
1460 case coFloats:
1461 ctx->throw_exception("Left hand side is a float vector, while the right hand side is not.", lhs.it_range);
1462 case coInts:
1463 ctx->throw_exception("Left hand side is an int vector, while the right hand side is not.", lhs.it_range);
1464 case coStrings:
1465 ctx->throw_exception("Left hand side is a string vector, while the right hand side is not.", lhs.it_range);
1466 case coBools:
1467 ctx->throw_exception("Left hand side is a bool vector, while the right hand side is not.", lhs.it_range);
1468 default:
1469 ctx->throw_exception("Left hand side / right hand side vectors are not compatible.", lhs.it_range);
1470 }
1471 }
1472 const_cast<ConfigOption*>(lhs.opt)->set(rhs.opt);
1473 }
@ coBools
Definition Config.hpp:192
@ coInts
Definition Config.hpp:170
@ coStrings
Definition Config.hpp:174
@ coFloats
Definition Config.hpp:166
static void check_writable(const MyContext *ctx, OptWithPos &opt)
Definition PlaceholderParser.cpp:1072

References check_writable(), Slic3r::coBools, Slic3r::coFloats, Slic3r::coInts, Slic3r::coStrings, Slic3r::client::OptWithPos::has_index(), Slic3r::ConfigOption::is_nil(), Slic3r::ConfigOption::is_vector(), Slic3r::client::OptWithPos::it_range, Slic3r::client::OptWithPos::opt, skipping(), throw_exception(), and Slic3r::ConfigOption::type().

Referenced by Slic3r::client::macro_processor::macro_processor(), and vector_variable_new_from_copy().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ could_be_vector_variable_reference()

static bool Slic3r::client::MyContext::could_be_vector_variable_reference ( const NewOldVariable var)
inlinestatic
1442 {
1443 return var.opt == nullptr || var.opt->is_vector();
1444 }
std::string var(const std::string &file_name)
Definition utils.cpp:154

References Slic3r::var().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ evaluate_count()

static size_t Slic3r::client::MyContext::evaluate_count ( const expr expr_count)
inlinestatic
1082 {
1083 if (expr_count.type() != expr::TYPE_INT)
1084 expr_count.throw_exception("Expected number of elements to fill a vector with.");
1085 int count = expr_count.i();
1086 if (count < 0)
1087 expr_count.throw_exception("Negative number of elements specified.");
1088 return size_t(count);
1089 };
IGL_INLINE void count(const Eigen::SparseMatrix< XType > &X, const int dim, Eigen::SparseVector< SType > &S)
Definition count.cpp:12
@ TYPE_INT
Definition PlaceholderParser.cpp:251

References Slic3r::client::expr::i(), Slic3r::client::expr::throw_exception(), Slic3r::client::expr::type(), and Slic3r::client::expr::TYPE_INT.

Referenced by vector_variable_assign_expr_with_count(), and vector_variable_new_from_array().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ evaluate_full_macro()

static bool Slic3r::client::MyContext::evaluate_full_macro ( const MyContext ctx)
inlinestatic
801{ return ! ctx->just_boolean_expression; }

References just_boolean_expression.

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the caller graph for this function:

◆ evaluate_index()

static void Slic3r::client::MyContext::evaluate_index ( expr expr_index,
int &  output 
)
inlinestatic
1539 {
1540 if (expr_index.type() != expr::TYPE_EMPTY) {
1541 if (expr_index.type() != expr::TYPE_INT)
1542 expr_index.throw_exception("Non-integer index is not allowed to address a vector variable.");
1543 output = expr_index.i();
1544 }
1545 }
@ TYPE_EMPTY
Definition PlaceholderParser.cpp:249

References Slic3r::client::expr::i(), Slic3r::client::expr::throw_exception(), Slic3r::client::expr::type(), Slic3r::client::expr::TYPE_EMPTY, and Slic3r::client::expr::TYPE_INT.

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fill_vector_from_initializer_list()

template<typename ConfigOptionType , typename RightValueEvaluate >
static void Slic3r::client::MyContext::fill_vector_from_initializer_list ( ConfigOption opt,
const std::vector< expr > &  il,
RightValueEvaluate  rv_eval 
)
inlinestatic
1331 {
1332 auto& out = static_cast<ConfigOptionType*>(opt)->values;
1333 out.clear();
1334 out.reserve(il.size());
1335 for (const expr& i : il)
1336 out.emplace_back(rv_eval(i));
1337 }
ConfigOptionType
Definition Config.hpp:160

◆ has()

◆ initializer_list_append()

static void Slic3r::client::MyContext::initializer_list_append ( std::vector< expr > &  list,
expr param 
)
inlinestatic
1510 {
1511 if (param.type() != expr::TYPE_EMPTY)
1512 // not skipping
1513 list.emplace_back(std::move(param));
1514 }

References Slic3r::client::expr::type(), and Slic3r::client::expr::TYPE_EMPTY.

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_nil_test()

static void Slic3r::client::MyContext::is_nil_test ( const MyContext ctx,
OptWithPos opt,
expr output 
)
inlinestatic
1201 {
1202 if (ctx->skipping()) {
1203 } else if (opt.opt->is_vector()) {
1204 if (! opt.has_index())
1205 ctx->throw_exception("Referencing a vector variable when scalar is expected", opt.it_range);
1206 const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
1207 if (vec->empty())
1208 ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
1209 output.set_b(static_cast<const ConfigOptionVectorBase*>(opt.opt)->is_nil(opt.index >= int(vec->size()) ? 0 : size_t(opt.index)));
1210 } else {
1211 assert(opt.opt->is_scalar());
1212 output.set_b(opt.opt->is_nil());
1213 }
1214 output.it_range = opt.it_range;
1215 }

References Slic3r::ConfigOptionVectorBase::empty(), Slic3r::client::OptWithPos::has_index(), Slic3r::client::OptWithPos::index, Slic3r::ConfigOption::is_nil(), Slic3r::ConfigOptionVectorBase::is_nil(), Slic3r::ConfigOption::is_scalar(), Slic3r::ConfigOption::is_vector(), Slic3r::client::OptWithPos::it_range, Slic3r::client::expr::it_range, Slic3r::client::OptWithPos::opt, Slic3r::client::expr::set_b(), Slic3r::ConfigOptionVectorBase::size(), skipping(), and throw_exception().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_vector_empty()

static void Slic3r::client::MyContext::is_vector_empty ( const MyContext ctx,
OptWithPos opt,
expr out 
)
inlinestatic
1517 {
1518 if (! ctx->skipping()) {
1519 if (opt.has_index() || ! opt.opt->is_vector())
1520 ctx->throw_exception("parameter of empty() is not a vector variable", opt.it_range);
1521 out.set_b(static_cast<const ConfigOptionVectorBase*>(opt.opt)->size() == 0);
1522 }
1523 out.it_range = opt.it_range;
1524 }

References Slic3r::client::OptWithPos::has_index(), Slic3r::ConfigOption::is_vector(), Slic3r::client::OptWithPos::it_range, Slic3r::client::expr::it_range, Slic3r::client::OptWithPos::opt, Slic3r::client::expr::set_b(), Slic3r::ConfigOptionVectorBase::size(), skipping(), and throw_exception().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_vector_variable_reference()

static bool Slic3r::client::MyContext::is_vector_variable_reference ( const OptWithPos var)
inlinestatic
1437 {
1438 return ! var.empty() && ! var.has_index() && var.opt->is_vector();
1439 }

References Slic3r::var().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ legacy_variable_expansion()

static void Slic3r::client::MyContext::legacy_variable_expansion ( const MyContext ctx,
IteratorRange opt_key,
std::string &  output 
)
inlinestatic
862 {
863 if (ctx->skipping())
864 return;
865
866 std::string opt_key_str(opt_key.begin(), opt_key.end());
867 const ConfigOption *opt = ctx->resolve_symbol(opt_key_str);
868 size_t idx = ctx->current_extruder_id;
869 if (opt == nullptr) {
870 // Check whether this is a legacy vector indexing.
871 idx = opt_key_str.rfind('_');
872 if (idx != std::string::npos) {
873 opt = ctx->resolve_symbol(opt_key_str.substr(0, idx));
874 if (opt != nullptr) {
875 if (! opt->is_vector())
876 ctx->throw_exception("Trying to index a scalar variable", opt_key);
877 char *endptr = nullptr;
878 idx = strtol(opt_key_str.c_str() + idx + 1, &endptr, 10);
879 if (endptr == nullptr || *endptr != 0)
880 ctx->throw_exception("Invalid vector index", IteratorRange(opt_key.begin() + idx + 1, opt_key.end()));
881 }
882 }
883 }
884 if (opt == nullptr)
885 ctx->throw_exception("Variable does not exist", opt_key);
886 if (opt->is_scalar()) {
887 if (opt->is_nil())
888 ctx->throw_exception("Trying to reference an undefined (nil) optional variable", opt_key);
889 output = opt->serialize();
890 } else {
891 const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt);
892 if (vec->empty())
893 ctx->throw_exception("Indexing an empty vector variable", opt_key);
894 if (idx >= vec->size())
895 idx = 0;
896 if (vec->is_nil(idx))
897 ctx->throw_exception("Trying to reference an undefined (nil) element of vector of optional values", opt_key);
898 output = vec->vserialize()[idx];
899 }
900 }
boost::iterator_range< Iterator > IteratorRange
Definition PlaceholderParser.cpp:172

References current_extruder_id, Slic3r::ConfigOptionVectorBase::empty(), Slic3r::ConfigOption::is_nil(), Slic3r::ConfigOptionVectorBase::is_nil(), Slic3r::ConfigOption::is_scalar(), Slic3r::ConfigOption::is_vector(), resolve_symbol(), Slic3r::ConfigOption::serialize(), Slic3r::ConfigOptionVectorBase::size(), skipping(), throw_exception(), and Slic3r::ConfigOptionVectorBase::vserialize().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ legacy_variable_expansion2()

static void Slic3r::client::MyContext::legacy_variable_expansion2 ( const MyContext ctx,
IteratorRange opt_key,
IteratorRange opt_vector_index,
std::string &  output 
)
inlinestatic
907 {
908 if (ctx->skipping())
909 return;
910
911 std::string opt_key_str(opt_key.begin(), opt_key.end());
912 const ConfigOption *opt = ctx->resolve_symbol(opt_key_str);
913 if (opt == nullptr) {
914 // Check whether the opt_key ends with '_'.
915 if (opt_key_str.back() == '_') {
916 opt_key_str.resize(opt_key_str.size() - 1);
917 opt = ctx->resolve_symbol(opt_key_str);
918 }
919 if (opt == nullptr)
920 ctx->throw_exception("Variable does not exist", opt_key);
921 }
922 if (! opt->is_vector())
923 ctx->throw_exception("Trying to index a scalar variable", opt_key);
924 const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt);
925 if (vec->empty())
926 ctx->throw_exception("Indexing an empty vector variable", opt_key);
927 const ConfigOption *opt_index = ctx->resolve_symbol(std::string(opt_vector_index.begin(), opt_vector_index.end()));
928 if (opt_index == nullptr)
929 ctx->throw_exception("Variable does not exist", opt_key);
930 if (opt_index->type() != coInt)
931 ctx->throw_exception("Indexing variable has to be integer", opt_key);
932 int idx = opt_index->getInt();
933 if (idx < 0)
934 ctx->throw_exception("Negative vector index", opt_key);
935 if (idx >= (int)vec->size())
936 idx = 0;
937 if (vec->is_nil(idx))
938 ctx->throw_exception("Trying to reference an undefined (nil) element of vector of optional values", opt_key);
939 output = vec->vserialize()[idx];
940 }
@ coInt
Definition Config.hpp:168

References Slic3r::coInt, Slic3r::ConfigOptionVectorBase::empty(), Slic3r::ConfigOption::getInt(), Slic3r::ConfigOptionVectorBase::is_nil(), Slic3r::ConfigOption::is_vector(), resolve_symbol(), Slic3r::ConfigOptionVectorBase::size(), skipping(), throw_exception(), Slic3r::ConfigOption::type(), and Slic3r::ConfigOptionVectorBase::vserialize().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ new_old_variable()

static void Slic3r::client::MyContext::new_old_variable ( const MyContext ctx,
bool  global_variable,
const IteratorRange it_range,
NewOldVariable out 
)
inlinestatic
1228 {
1229 if (! ctx->skipping()) {
1230 t_config_option_key key(std::string(it_range.begin(), it_range.end()));
1231 if (const ConfigOption* opt = ctx->resolve_symbol(key); opt)
1232 ctx->throw_exception("Symbol is already defined in read-only system dictionary", it_range);
1233 if (ctx->config_outputs && ctx->config_outputs->optptr(key))
1234 ctx->throw_exception("Symbol is already defined as system output variable", it_range);
1235 bool has_global_dictionary = ctx->context_data != nullptr && ctx->context_data->global_config;
1236 if (global_variable) {
1237 if (! has_global_dictionary)
1238 ctx->throw_exception("Global variables are not available in this context", it_range);
1239 if (ctx->config_local.optptr(key))
1240 ctx->throw_exception("Variable name already defined in local scope", it_range);
1241 out.opt = ctx->context_data->global_config->optptr(key);
1242 } else {
1243 if (has_global_dictionary && ctx->context_data->global_config->optptr(key))
1244 ctx->throw_exception("Variable name already defined in global scope", it_range);
1245 out.opt = ctx->config_local.optptr(key);
1246 }
1247 out.name = std::move(key);
1248 }
1249 out.it_range = it_range;
1250 }
std::string t_config_option_key
Definition Config.hpp:76

References config_local, config_outputs, context_data, Slic3r::PlaceholderParser::ContextData::global_config, Slic3r::client::MyContext::NewOldVariable::it_range, Slic3r::client::MyContext::NewOldVariable::name, Slic3r::client::MyContext::NewOldVariable::opt, Slic3r::DynamicConfig::optptr(), resolve_symbol(), skipping(), and throw_exception().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ option() [1/2]

const ConfigOption * Slic3r::ConfigOptionResolver::option ( const t_config_option_key opt_key) const
inlineinherited
2107{ return this->optptr(opt_key); }

References Slic3r::ConfigOptionResolver::optptr().

Referenced by Slic3r::Flow::extrusion_width(), Slic3r::Flow::extrusion_width(), and Slic3r::PrintObject::invalidate_state_by_config_options().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ option() [2/2]

template<typename TYPE >
const TYPE * Slic3r::ConfigOptionResolver::option ( const t_config_option_key opt_key) const
inlineinherited
2111 {
2112 const ConfigOption* opt = this->optptr(opt_key);
2113 return (opt == nullptr || opt->type() != TYPE::static_type()) ? nullptr : static_cast<const TYPE*>(opt);
2114 }

References Slic3r::ConfigOptionResolver::optptr(), and Slic3r::ConfigOption::type().

+ Here is the call graph for this function:

◆ option_throw() [1/2]

const ConfigOption * Slic3r::ConfigOptionResolver::option_throw ( const t_config_option_key opt_key) const
inlineinherited
2117 {
2118 const ConfigOption* opt = this->optptr(opt_key);
2119 if (opt == nullptr)
2120 throw UnknownOptionException(opt_key);
2121 return opt;
2122 }

References Slic3r::ConfigOptionResolver::optptr().

Referenced by Slic3r::ConfigOptionResolver::option_throw().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ option_throw() [2/2]

template<typename TYPE >
const TYPE * Slic3r::ConfigOptionResolver::option_throw ( const t_config_option_key opt_key) const
inlineinherited
2126 {
2127 const ConfigOption* opt = this->option_throw(opt_key);
2128 if (opt->type() != TYPE::static_type())
2129 throw BadOptionTypeException("Conversion to a wrong type");
2130 return static_cast<TYPE*>(opt);
2131 }
const ConfigOption * option_throw(const t_config_option_key &opt_key) const
Definition Config.hpp:2116

References Slic3r::ConfigOptionResolver::option_throw(), and Slic3r::ConfigOption::type().

+ Here is the call graph for this function:

◆ optptr()

const ConfigOption * Slic3r::client::MyContext::optptr ( const t_config_option_key opt_key) const
inlineoverridevirtual

Implements Slic3r::ConfigOptionResolver.

830 {
831 const ConfigOption *opt = nullptr;
832 if (config_override != nullptr)
833 opt = config_override->option(opt_key);
834 if (opt == nullptr)
835 opt = config->option(opt_key);
836 if (opt == nullptr && external_config != nullptr)
837 opt = external_config->option(opt_key);
838 return opt;
839 }
ConfigOption * option(const t_config_option_key &opt_key, bool create=false)
Definition Config.hpp:2169
const DynamicConfig * config
Definition PlaceholderParser.cpp:781
const DynamicConfig * external_config
Definition PlaceholderParser.cpp:779
const DynamicConfig * config_override
Definition PlaceholderParser.cpp:783

References config, config_override, external_config, and Slic3r::ConfigBase::option().

Referenced by resolve_symbol().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_error_message()

static void Slic3r::client::MyContext::process_error_message ( const MyContext context,
const boost::spirit::info &  info,
const Iterator it_begin,
const Iterator it_end,
const Iterator it_error 
)
inlinestatic
1566 {
1567 std::string &msg = const_cast<MyContext*>(context)->error_message;
1568 std::string first(it_begin, it_error);
1569 std::string last(it_error, it_end);
1570 auto first_pos = first.rfind('\n');
1571 auto last_pos = last.find('\n');
1572 int line_nr = 1;
1573 if (first_pos == std::string::npos)
1574 first_pos = 0;
1575 else {
1576 // Calculate the current line number.
1577 for (size_t i = 0; i <= first_pos; ++ i)
1578 if (first[i] == '\n')
1579 ++ line_nr;
1580 ++ first_pos;
1581 }
1582 auto error_line = std::string(first, first_pos) + std::string(last, 0, last_pos);
1583 // Position of the it_error from the start of its line.
1584 auto error_pos = (it_error - it_begin) - first_pos;
1585 msg += "Parsing error at line " + std::to_string(line_nr);
1586 if (! info.tag.empty() && info.tag.front() == '*') {
1587 // The gat contains an explanatory string.
1588 msg += ": ";
1589 msg += info.tag.substr(1);
1590 } else {
1591 auto it = tag_to_error_message.find(info.tag);
1592 if (it == tag_to_error_message.end()) {
1593 // A generic error report based on the nonterminal or terminal symbol name.
1594 msg += ". Expecting tag ";
1595 msg += info.tag;
1596 } else {
1597 // Use the human readable error message.
1598 msg += ". ";
1599 msg += it->second;
1600 }
1601 }
1602 msg += '\n';
1603 // This hack removes all non-UTF8 characters from the source line, so that the upstream wxWidgets conversions
1604 // from UTF8 to UTF16 don't bail out.
1605 msg += boost::nowide::narrow(boost::nowide::widen(error_line));
1606 msg += '\n';
1607 for (size_t i = 0; i < error_pos; ++ i)
1608 msg += ' ';
1609 msg += "^\n";
1610 }
char * narrow(char *output, size_t output_size, wchar_t const *source)
Convert NULL terminated UTF source string to NULL terminated output string of size at most output_siz...
Definition convert.hpp:73
wchar_t * widen(wchar_t *output, size_t output_size, char const *source)
Convert NULL terminated UTF source string to NULL terminated output string of size at most output_siz...
Definition convert.hpp:95
static std::map< std::string, std::string > tag_to_error_message
Definition PlaceholderParser.cpp:798
std::string error_message
Definition PlaceholderParser.cpp:795

References error_message, boost::nowide::narrow(), tag_to_error_message, and boost::nowide::widen().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ random()

static void Slic3r::client::MyContext::random ( const MyContext ctx,
expr param1,
expr param2 
)
inlinestatic
1548 {
1549 if (ctx->skipping())
1550 return;
1551
1552 if (ctx->context_data == nullptr)
1553 ctx->throw_exception("Random number generator not available in this context.",
1554 IteratorRange(param1.it_range.begin(), param2.it_range.end()));
1555 expr::random(param1, param2, ctx->context_data->rng);
1556 }
static void random(expr &param1, expr &param2, std::mt19937 &rng)
Definition PlaceholderParser.cpp:609

References context_data, Slic3r::client::expr::it_range, Slic3r::client::expr::random(), Slic3r::PlaceholderParser::ContextData::rng, skipping(), and throw_exception().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ resolve_output_symbol()

ConfigOption * Slic3r::client::MyContext::resolve_output_symbol ( const std::string &  opt_key) const
inline
842 {
843 ConfigOption *out = nullptr;
844 if (this->config_outputs)
845 out = this->config_outputs->optptr(opt_key, false);
846 if (out == nullptr && this->context_data != nullptr && this->context_data->global_config)
847 out = this->context_data->global_config->optptr(opt_key);
848 if (out == nullptr)
849 out = this->config_local.optptr(opt_key);
850 return out;
851 }
const ConfigOption * optptr(const t_config_option_key &opt_key) const override
Definition Config.cpp:1106
std::unique_ptr< DynamicConfig > global_config
Definition PlaceholderParser.hpp:26
DynamicConfig config_local
Definition PlaceholderParser.cpp:788
DynamicConfig * config_outputs
Definition PlaceholderParser.cpp:786
PlaceholderParser::ContextData * context_data
Definition PlaceholderParser.cpp:791

References Slic3r::PlaceholderParser::ContextData::global_config, and Slic3r::DynamicConfig::optptr().

Referenced by resolve_variable().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ resolve_symbol()

const ConfigOption * Slic3r::client::MyContext::resolve_symbol ( const std::string &  opt_key) const
inline
841{ return this->optptr(opt_key); }
const ConfigOption * optptr(const t_config_option_key &opt_key) const override
Definition PlaceholderParser.cpp:829

References optptr().

Referenced by legacy_variable_expansion(), legacy_variable_expansion2(), new_old_variable(), resolve_variable(), and scalar_variable_to_expr().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ resolve_variable()

static void Slic3r::client::MyContext::resolve_variable ( const MyContext ctx,
IteratorRange opt_key,
OptWithPos output 
)
inlinestatic
946 {
947 if (! ctx->skipping()) {
948 const std::string key{ opt_key.begin(), opt_key.end() };
949 const ConfigOption *opt = ctx->resolve_symbol(key);
950 if (opt == nullptr) {
951 opt = ctx->resolve_output_symbol(key);
952 if (opt == nullptr)
953 ctx->throw_exception("Not a variable name", opt_key);
954 output.writable = true;
955 }
956 output.opt = opt;
957 }
958 output.it_range = opt_key;
959 }

References Slic3r::client::OptWithPos::it_range, Slic3r::client::OptWithPos::opt, resolve_output_symbol(), resolve_symbol(), skipping(), throw_exception(), and Slic3r::client::OptWithPos::writable.

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ scalar_variable_assign_scalar()

static void Slic3r::client::MyContext::scalar_variable_assign_scalar ( const MyContext ctx,
OptWithPos lhs,
const expr rhs 
)
inlinestatic
1092 {
1093 assert(! ctx->skipping());
1094 assert(lhs.opt->is_scalar());
1095 check_writable(ctx, lhs);
1096 ConfigOption *wropt = const_cast<ConfigOption*>(lhs.opt);
1097 switch (wropt->type()) {
1098 case coFloat:
1099 check_numeric(rhs);
1100 static_cast<ConfigOptionFloat*>(wropt)->value = rhs.as_d();
1101 break;
1102 case coInt:
1103 check_numeric(rhs);
1104 static_cast<ConfigOptionInt*>(wropt)->value = rhs.as_i();
1105 break;
1106 case coString:
1107 static_cast<ConfigOptionString*>(wropt)->value = rhs.to_string();
1108 break;
1109 case coPercent:
1110 check_numeric(rhs);
1111 static_cast<ConfigOptionPercent*>(wropt)->value = rhs.as_d();
1112 break;
1113 case coBool:
1114 if (rhs.type() != expr::TYPE_BOOL)
1115 ctx->throw_exception("Right side is not a boolean expression", rhs.it_range);
1116 static_cast<ConfigOptionBool*>(wropt)->value = rhs.b();
1117 break;
1118 default:
1119 ctx->throw_exception("Unsupported output scalar variable type", lhs.it_range);
1120 }
1121 }
ConfigOptionFloat
Definition PrintConfig.hpp:570
ConfigOptionBool
Definition PrintConfig.hpp:665
@ coString
Definition Config.hpp:172
@ coBool
Definition Config.hpp:190
@ coFloat
Definition Config.hpp:164
@ coPercent
Definition Config.hpp:176
static void check_numeric(const expr &param)
Definition PlaceholderParser.cpp:1077
@ TYPE_BOOL
Definition PlaceholderParser.cpp:250

References Slic3r::client::expr::as_d(), Slic3r::client::expr::as_i(), Slic3r::client::expr::b(), check_numeric(), check_writable(), Slic3r::coBool, Slic3r::coFloat, Slic3r::coInt, Slic3r::coPercent, Slic3r::coString, Slic3r::ConfigOption::is_scalar(), Slic3r::client::OptWithPos::it_range, Slic3r::client::expr::it_range, Slic3r::client::OptWithPos::opt, skipping(), throw_exception(), Slic3r::client::expr::to_string(), Slic3r::client::expr::type(), Slic3r::ConfigOption::type(), and Slic3r::client::expr::TYPE_BOOL.

Referenced by scalar_variable_assign_scalar_expression(), and scalar_variable_new_from_scalar_expression().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ scalar_variable_assign_scalar_expression()

static void Slic3r::client::MyContext::scalar_variable_assign_scalar_expression ( const MyContext ctx,
OptWithPos opt,
const expr param 
)
inlinestatic
1254 {
1255 if (! ctx->skipping()) {
1256 check_writable(ctx, opt);
1257 if (opt.opt->is_vector())
1259 else
1260 scalar_variable_assign_scalar(ctx, opt, param);
1261 }
1262 }
static void scalar_variable_assign_scalar(const MyContext *ctx, OptWithPos &lhs, const expr &rhs)
Definition PlaceholderParser.cpp:1091
static void vector_variable_element_assign_scalar(const MyContext *ctx, OptWithPos &lhs, const expr &rhs)
Definition PlaceholderParser.cpp:1123

References check_writable(), Slic3r::ConfigOption::is_vector(), Slic3r::client::OptWithPos::opt, scalar_variable_assign_scalar(), skipping(), and vector_variable_element_assign_scalar().

Referenced by Slic3r::client::macro_processor::macro_processor(), and vector_variable_assign_initializer_list().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ scalar_variable_new_from_scalar_expression()

static void Slic3r::client::MyContext::scalar_variable_new_from_scalar_expression ( const MyContext ctx,
bool  global_variable,
NewOldVariable lhs,
const expr rhs 
)
inlinestatic
1269 {
1270 if (ctx->skipping()) {
1271 } else if (lhs.opt) {
1272 if (lhs.opt->is_vector())
1273 rhs.throw_exception("Cannot assign a scalar value to a vector variable.");
1274 OptWithPos lhs_opt{ lhs.opt, lhs.it_range, true };
1275 scalar_variable_assign_scalar(ctx, lhs_opt, rhs);
1276 } else {
1277 std::unique_ptr<ConfigOption> opt_new;
1278 switch (rhs.type()) {
1279 case expr::TYPE_BOOL: opt_new = std::make_unique<ConfigOptionBool>(rhs.b()); break;
1280 case expr::TYPE_INT: opt_new = std::make_unique<ConfigOptionInt>(rhs.i()); break;
1281 case expr::TYPE_DOUBLE: opt_new = std::make_unique<ConfigOptionFloat>(rhs.d()); break;
1282 case expr::TYPE_STRING: opt_new = std::make_unique<ConfigOptionString>(rhs.s()); break;
1283 default: assert(false);
1284 }
1285 const_cast<MyContext*>(ctx)->store_new_variable(lhs.name, std::move(opt_new), global_variable);
1286 }
1287 }
void store_new_variable(const std::string &opt_key, std::unique_ptr< ConfigOption > &&opt, bool global_variable)
Definition PlaceholderParser.cpp:852
@ TYPE_STRING
Definition PlaceholderParser.cpp:253
@ TYPE_DOUBLE
Definition PlaceholderParser.cpp:252

References Slic3r::client::expr::b(), Slic3r::client::expr::d(), Slic3r::client::expr::i(), Slic3r::ConfigOption::is_vector(), Slic3r::client::MyContext::NewOldVariable::it_range, Slic3r::client::MyContext::NewOldVariable::name, Slic3r::client::MyContext::NewOldVariable::opt, Slic3r::client::expr::s(), scalar_variable_assign_scalar(), skipping(), store_new_variable(), Slic3r::client::expr::throw_exception(), Slic3r::client::expr::type(), Slic3r::client::expr::TYPE_BOOL, Slic3r::client::expr::TYPE_DOUBLE, Slic3r::client::expr::TYPE_INT, and Slic3r::client::expr::TYPE_STRING.

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ scalar_variable_to_expr()

static void Slic3r::client::MyContext::scalar_variable_to_expr ( const MyContext ctx,
OptWithPos opt,
expr output 
)
inlinestatic
983 {
984 if (ctx->skipping())
985 return;
986
987 assert(opt.opt->is_scalar());
988
989 if (opt.opt->is_nil())
990 ctx->throw_exception("Trying to reference an undefined (nil) optional variable", opt.it_range);
991
992 switch (opt.opt->type()) {
993 case coFloat: output.set_d(opt.opt->getFloat()); break;
994 case coInt: output.set_i(opt.opt->getInt()); break;
995 case coString: output.set_s(static_cast<const ConfigOptionString*>(opt.opt)->value); break;
996 case coPercent: output.set_d(opt.opt->getFloat()); break;
997 case coEnum:
998 case coPoint: output.set_s(opt.opt->serialize()); break;
999 case coBool: output.set_b(opt.opt->getBool()); break;
1000 case coFloatOrPercent:
1001 {
1002 std::string opt_key(opt.it_range.begin(), opt.it_range.end());
1003 if (boost::ends_with(opt_key, "extrusion_width")) {
1004 // Extrusion width supports defaults and a complex graph of dependencies.
1005 output.set_d(Flow::extrusion_width(opt_key, *ctx, static_cast<unsigned int>(ctx->current_extruder_id)));
1006 } else if (! static_cast<const ConfigOptionFloatOrPercent*>(opt.opt)->percent) {
1007 // Not a percent, just return the value.
1008 output.set_d(opt.opt->getFloat());
1009 } else {
1010 // Resolve dependencies using the "ratio_over" link to a parent value.
1011 const ConfigOptionDef *opt_def = print_config_def.get(opt_key);
1012 assert(opt_def != nullptr);
1013 double v = opt.opt->getFloat() * 0.01; // percent to ratio
1014 for (;;) {
1015 const ConfigOption *opt_parent = opt_def->ratio_over.empty() ? nullptr : ctx->resolve_symbol(opt_def->ratio_over);
1016 if (opt_parent == nullptr)
1017 ctx->throw_exception("FloatOrPercent variable failed to resolve the \"ratio_over\" dependencies", opt.it_range);
1018 if (boost::ends_with(opt_def->ratio_over, "extrusion_width")) {
1019 // Extrusion width supports defaults and a complex graph of dependencies.
1020 assert(opt_parent->type() == coFloatOrPercent);
1021 v *= Flow::extrusion_width(opt_def->ratio_over, static_cast<const ConfigOptionFloatOrPercent*>(opt_parent), *ctx, static_cast<unsigned int>(ctx->current_extruder_id));
1022 break;
1023 }
1024 if (opt_parent->type() == coFloat || opt_parent->type() == coFloatOrPercent) {
1025 v *= opt_parent->getFloat();
1026 if (opt_parent->type() == coFloat || ! static_cast<const ConfigOptionFloatOrPercent*>(opt_parent)->percent)
1027 break;
1028 v *= 0.01; // percent to ratio
1029 }
1030 // Continue one level up in the "ratio_over" hierarchy.
1031 opt_def = print_config_def.get(opt_def->ratio_over);
1032 assert(opt_def != nullptr);
1033 }
1034 output.set_d(v);
1035 }
1036 break;
1037 }
1038 default:
1039 ctx->throw_exception("Unsupported scalar variable type", opt.it_range);
1040 }
1041 }
const ConfigOptionDef * get(const t_config_option_key &opt_key) const
Definition Config.hpp:2069
static double extrusion_width(const std::string &opt_key, const ConfigOptionFloatOrPercent *opt, const ConfigOptionResolver &config, const unsigned int first_printing_extruder=0)
Definition Flow.cpp:62
const PrintConfigDef print_config_def
Definition PrintConfig.cpp:4288
@ coPoint
Definition Config.hpp:184
@ coEnum
Definition Config.hpp:194
@ coFloatOrPercent
Definition Config.hpp:180

References Slic3r::coBool, Slic3r::coEnum, Slic3r::coFloat, Slic3r::coFloatOrPercent, Slic3r::coInt, Slic3r::coPercent, Slic3r::coPoint, Slic3r::coString, current_extruder_id, Slic3r::Flow::extrusion_width(), Slic3r::ConfigDef::get(), Slic3r::ConfigOption::getBool(), Slic3r::ConfigOption::getFloat(), Slic3r::ConfigOption::getInt(), Slic3r::ConfigOption::is_nil(), Slic3r::ConfigOption::is_scalar(), Slic3r::client::OptWithPos::it_range, Slic3r::client::OptWithPos::opt, Slic3r::ConfigOptionFloatOrPercent::percent, Slic3r::print_config_def, Slic3r::ConfigOptionDef::ratio_over, resolve_symbol(), Slic3r::ConfigOption::serialize(), Slic3r::client::expr::set_b(), Slic3r::client::expr::set_d(), Slic3r::client::expr::set_i(), Slic3r::client::expr::set_s(), skipping(), throw_exception(), Slic3r::ConfigOption::type(), and Slic3r::ConfigOptionSingle< T >::value.

Referenced by variable_value().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ skipping()

◆ store_new_variable()

void Slic3r::client::MyContext::store_new_variable ( const std::string &  opt_key,
std::unique_ptr< ConfigOption > &&  opt,
bool  global_variable 
)
inline
852 {
853 assert(opt);
854 if (global_variable) {
855 assert(this->context_data != nullptr && this->context_data->global_config);
856 this->context_data->global_config->set_key_value(opt_key, opt.release());
857 } else
858 this->config_local.set_key_value(opt_key, opt.release());
859 }
bool set_key_value(const std::string &opt_key, ConfigOption *opt)
Definition Config.hpp:2431

References Slic3r::PlaceholderParser::ContextData::global_config, and Slic3r::DynamicConfig::set_key_value().

Referenced by scalar_variable_new_from_scalar_expression(), vector_variable_new_from_array(), vector_variable_new_from_copy(), and vector_variable_new_from_initializer_list().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ store_variable_index()

static void Slic3r::client::MyContext::store_variable_index ( const MyContext ctx,
OptWithPos opt,
int  index,
Iterator  it_end,
OptWithPos output 
)
inlinestatic
967 {
968 if (! ctx->skipping()) {
969 if (! opt.opt->is_vector())
970 ctx->throw_exception("Cannot index a scalar variable", opt.it_range);
971 if (index < 0)
972 ctx->throw_exception("Referencing a vector variable with a negative index", opt.it_range);
973 output = opt;
974 output.index = index;
975 } else
976 output = opt;
977 output.it_range.end() = it_end;
978 }

References Slic3r::client::OptWithPos::index, Slic3r::ConfigOption::is_vector(), Slic3r::client::OptWithPos::it_range, Slic3r::client::OptWithPos::opt, skipping(), and throw_exception().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ throw_exception()

static void Slic3r::client::MyContext::throw_exception ( const std::string &  msg,
const IteratorRange it_range 
)
inlinestatic
1559 {
1560 // An asterix is added to the start of the string to differentiate the boost::spirit::info::tag content
1561 // between the grammer terminal / non-terminal symbol name and a free-form error message.
1562 boost::throw_exception(qi::expectation_failure(it_range.begin(), it_range.end(), spirit::info(std::string("*") + msg)));
1563 }

Referenced by check_writable(), copy_vector_variable_to_vector_variable(), is_nil_test(), is_vector_empty(), legacy_variable_expansion(), legacy_variable_expansion2(), new_old_variable(), Slic3r::client::utf8_char_parser::parse(), Slic3r::client::ascii_char_skipper_parser::parse(), random(), resolve_variable(), scalar_variable_assign_scalar(), scalar_variable_to_expr(), store_variable_index(), Slic3r::client::FactorActions::string_(), vector_element_to_expr(), vector_size(), vector_variable_assign_initializer_list(), vector_variable_element_assign_scalar(), vector_variable_new_from_copy(), and vector_variable_new_from_initializer_list().

+ Here is the caller graph for this function:

◆ variable_value()

static void Slic3r::client::MyContext::variable_value ( const MyContext ctx,
OptWithPos opt,
expr output 
)
inlinestatic
1188 {
1189 if (! ctx->skipping()) {
1190 if (opt.opt->is_vector())
1191 vector_element_to_expr(ctx, opt, output);
1192 else
1193 scalar_variable_to_expr(ctx, opt, output);
1194 }
1195 output.it_range = opt.it_range;
1196 }
static void scalar_variable_to_expr(const MyContext *ctx, OptWithPos &opt, expr &output)
Definition PlaceholderParser.cpp:982
static void vector_element_to_expr(const MyContext *ctx, OptWithPos &opt, expr &output)
Definition PlaceholderParser.cpp:1045

References Slic3r::ConfigOption::is_vector(), Slic3r::client::OptWithPos::it_range, Slic3r::client::expr::it_range, Slic3r::client::OptWithPos::opt, scalar_variable_to_expr(), skipping(), and vector_element_to_expr().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ vector_element_to_expr()

static void Slic3r::client::MyContext::vector_element_to_expr ( const MyContext ctx,
OptWithPos opt,
expr output 
)
inlinestatic
1046 {
1047 if (ctx->skipping())
1048 return;
1049
1050 assert(opt.opt->is_vector());
1051 if (! opt.has_index())
1052 ctx->throw_exception("Referencing a vector variable when scalar is expected", opt.it_range);
1053 const ConfigOptionVectorBase* vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
1054 if (vec->empty())
1055 ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
1056 size_t idx = (opt.index < 0) ? 0 : (opt.index >= int(vec->size())) ? 0 : size_t(opt.index);
1057 if (vec->is_nil(idx))
1058 ctx->throw_exception("Trying to reference an undefined (nil) element of vector of optional values", opt.it_range);
1059 switch (opt.opt->type()) {
1060 case coFloats: output.set_d(static_cast<const ConfigOptionFloats*>(opt.opt)->values[idx]); break;
1061 case coInts: output.set_i(static_cast<const ConfigOptionInts*>(opt.opt)->values[idx]); break;
1062 case coStrings: output.set_s(static_cast<const ConfigOptionStrings*>(opt.opt)->values[idx]); break;
1063 case coPercents: output.set_d(static_cast<const ConfigOptionPercents*>(opt.opt)->values[idx]); break;
1064 case coPoints: output.set_s(to_string(static_cast<const ConfigOptionPoints*>(opt.opt)->values[idx])); break;
1065 case coBools: output.set_b(static_cast<const ConfigOptionBools*>(opt.opt)->values[idx] != 0); break;
1066 //case coEnums: output.set_s(opt.opt->vserialize()[idx]); break;
1067 default:
1068 ctx->throw_exception("Unsupported vector variable type", opt.it_range);
1069 }
1070 }
ConfigOptionPercentsTempl< false > ConfigOptionPercents
Definition Config.hpp:1008
ConfigOptionBoolsTempl< false > ConfigOptionBools
Definition Config.hpp:1491
ConfigOptionFloatsTempl< false > ConfigOptionFloats
Definition Config.hpp:716
ConfigOptionIntsTempl< false > ConfigOptionInts
Definition Config.hpp:844
@ coPercents
Definition Config.hpp:178
@ coPoints
Definition Config.hpp:186
std::string to_string(const Vec2crd &pt)
Definition Point.hpp:139
constexpr auto size(const C &c) -> decltype(c.size())
Definition span.hpp:183

References Slic3r::coBools, Slic3r::coFloats, Slic3r::coInts, Slic3r::coPercents, Slic3r::coPoints, Slic3r::coStrings, Slic3r::ConfigOptionVectorBase::empty(), Slic3r::client::OptWithPos::has_index(), Slic3r::client::OptWithPos::index, Slic3r::ConfigOptionVectorBase::is_nil(), Slic3r::ConfigOption::is_vector(), Slic3r::client::OptWithPos::it_range, Slic3r::client::OptWithPos::opt, Slic3r::client::expr::set_b(), Slic3r::client::expr::set_d(), Slic3r::client::expr::set_i(), Slic3r::client::expr::set_s(), Slic3r::ConfigOptionVectorBase::size(), skipping(), throw_exception(), Slic3r::to_string(), Slic3r::ConfigOption::type(), and Slic3r::ConfigOptionVector< T >::values.

Referenced by variable_value().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ vector_size()

static void Slic3r::client::MyContext::vector_size ( const MyContext ctx,
OptWithPos opt,
expr out 
)
inlinestatic
1527 {
1528 if (! ctx->skipping()) {
1529 if (opt.has_index() || ! opt.opt->is_vector())
1530 ctx->throw_exception("parameter of size() is not a vector variable", opt.it_range);
1531 out.set_i(int(static_cast<const ConfigOptionVectorBase*>(opt.opt)->size()));
1532 }
1533 out.it_range = opt.it_range;
1534 }

References Slic3r::client::OptWithPos::has_index(), Slic3r::ConfigOption::is_vector(), Slic3r::client::OptWithPos::it_range, Slic3r::client::expr::it_range, Slic3r::client::OptWithPos::opt, Slic3r::client::expr::set_i(), Slic3r::ConfigOptionVectorBase::size(), skipping(), and throw_exception().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ vector_variable_assign_array()

static void Slic3r::client::MyContext::vector_variable_assign_array ( const MyContext ctx,
OptWithPos lhs,
const expr rhs_count,
const expr rhs_value 
)
inlinestatic
1321 {
1322 if (! ctx->skipping()) {
1323 check_writable(ctx, lhs);
1324 if (lhs.opt->is_scalar())
1325 rhs_value.throw_exception("Cannot assign a vector value to a scalar variable.");
1326 vector_variable_assign_expr_with_count(ctx, lhs, rhs_count, rhs_value);
1327 }
1328 }
static void vector_variable_assign_expr_with_count(const MyContext *ctx, OptWithPos &lhs, const expr &rhs_count, const expr &rhs_value)
Definition PlaceholderParser.cpp:1161

References check_writable(), Slic3r::ConfigOption::is_scalar(), Slic3r::client::OptWithPos::opt, skipping(), Slic3r::client::expr::throw_exception(), and vector_variable_assign_expr_with_count().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ vector_variable_assign_expr_with_count()

static void Slic3r::client::MyContext::vector_variable_assign_expr_with_count ( const MyContext ctx,
OptWithPos lhs,
const expr rhs_count,
const expr rhs_value 
)
inlinestatic
1162 {
1163 assert(! ctx->skipping());
1164 size_t count = evaluate_count(rhs_count);
1165 auto *opt = const_cast<ConfigOption*>(lhs.opt);
1166 switch (lhs.opt->type()) {
1167 case coFloats:
1168 check_numeric(rhs_value);
1169 static_cast<ConfigOptionFloats*>(opt)->values.assign(count, rhs_value.as_d());
1170 break;
1171 case coInts:
1172 check_numeric(rhs_value);
1173 static_cast<ConfigOptionInts*>(opt)->values.assign(count, rhs_value.as_i());
1174 break;
1175 case coStrings:
1176 static_cast<ConfigOptionStrings*>(opt)->values.assign(count, rhs_value.to_string());
1177 break;
1178 case coBools:
1179 if (rhs_value.type() != expr::TYPE_BOOL)
1180 rhs_value.throw_exception("Right side is not a boolean expression");
1181 static_cast<ConfigOptionBools*>(opt)->values.assign(count, rhs_value.b());
1182 break;
1183 default: assert(false);
1184 }
1185 }
static size_t evaluate_count(const expr &expr_count)
Definition PlaceholderParser.cpp:1082

References Slic3r::client::expr::as_d(), Slic3r::client::expr::as_i(), Slic3r::client::expr::b(), check_numeric(), Slic3r::coBools, Slic3r::coFloats, Slic3r::coInts, Slic3r::coStrings, evaluate_count(), Slic3r::client::OptWithPos::opt, skipping(), Slic3r::client::expr::throw_exception(), Slic3r::client::expr::to_string(), Slic3r::client::expr::type(), Slic3r::ConfigOption::type(), and Slic3r::client::expr::TYPE_BOOL.

Referenced by vector_variable_assign_array(), and vector_variable_new_from_array().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ vector_variable_assign_initializer_list()

static void Slic3r::client::MyContext::vector_variable_assign_initializer_list ( const MyContext ctx,
OptWithPos lhs,
const std::vector< expr > &  il 
)
inlinestatic
1340 {
1341 if (ctx->skipping())
1342 return;
1343
1344 check_writable(ctx, lhs);
1345
1346 if (lhs.opt->is_scalar()) {
1347 if (il.size() == 1)
1348 // scalar_var = ( scalar )
1349 scalar_variable_assign_scalar_expression(ctx, lhs, il.front());
1350 else
1351 // scalar_var = ()
1352 // or
1353 // scalar_var = ( scalar, scalar, ... )
1354 ctx->throw_exception("Cannot assign a vector value to a scalar variable.", lhs.it_range);
1355 }
1356
1357 auto check_numeric_vector = [](const std::vector<expr> &il) {
1358 for (auto &i : il)
1359 if (! i.numeric_type())
1360 i.throw_exception("Right side is not a numeric expression");
1361 };
1362
1363 ConfigOption *opt = const_cast<ConfigOption*>(lhs.opt);
1364 switch (lhs.opt->type()) {
1365 case coFloats:
1366 check_numeric_vector(il);
1367 fill_vector_from_initializer_list<ConfigOptionFloats>(opt, il, [](auto &v){ return v.as_d(); });
1368 break;
1369 case coInts:
1370 check_numeric_vector(il);
1371 fill_vector_from_initializer_list<ConfigOptionInts>(opt, il, [](auto &v){ return v.as_i(); });
1372 break;
1373 case coStrings:
1374 fill_vector_from_initializer_list<ConfigOptionStrings>(opt, il, [](auto &v){ return v.to_string(); });
1375 break;
1376 case coBools:
1377 for (auto &i : il)
1378 if (i.type() != expr::TYPE_BOOL)
1379 i.throw_exception("Right side is not a boolean expression");
1380 fill_vector_from_initializer_list<ConfigOptionBools>(opt, il, [](auto &v){ return v.b(); });
1381 break;
1382 default: assert(false);
1383 }
1384 }
if(!(yy_init))
Definition lexer.c:1190
static void throw_exception(const std::string &msg, const IteratorRange &it_range)
Definition PlaceholderParser.cpp:1558
static void scalar_variable_assign_scalar_expression(const MyContext *ctx, OptWithPos &opt, const expr &param)
Definition PlaceholderParser.cpp:1253

References check_writable(), Slic3r::coBools, Slic3r::coFloats, Slic3r::coInts, Slic3r::coStrings, Slic3r::ConfigOption::is_scalar(), Slic3r::client::OptWithPos::it_range, Slic3r::client::OptWithPos::opt, scalar_variable_assign_scalar_expression(), skipping(), throw_exception(), Slic3r::ConfigOption::type(), and Slic3r::client::expr::TYPE_BOOL.

Referenced by Slic3r::client::macro_processor::macro_processor(), and vector_variable_new_from_initializer_list().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ vector_variable_element_assign_scalar()

static void Slic3r::client::MyContext::vector_variable_element_assign_scalar ( const MyContext ctx,
OptWithPos lhs,
const expr rhs 
)
inlinestatic
1124 {
1125 assert(! ctx->skipping());
1126 assert(lhs.opt->is_vector());
1127 check_writable(ctx, lhs);
1128 if (! lhs.has_index())
1129 ctx->throw_exception("Referencing an output vector variable when scalar is expected", lhs.it_range);
1130 ConfigOptionVectorBase *vec = const_cast<ConfigOptionVectorBase*>(static_cast<const ConfigOptionVectorBase*>(lhs.opt));
1131 if (vec->empty())
1132 ctx->throw_exception("Indexing an empty vector variable", lhs.it_range);
1133 if (lhs.index >= int(vec->size()))
1134 ctx->throw_exception("Index out of range", lhs.it_range);
1135 switch (lhs.opt->type()) {
1136 case coFloats:
1137 check_numeric(rhs);
1138 static_cast<ConfigOptionFloats*>(vec)->values[lhs.index] = rhs.as_d();
1139 break;
1140 case coInts:
1141 check_numeric(rhs);
1142 static_cast<ConfigOptionInts*>(vec)->values[lhs.index] = rhs.as_i();
1143 break;
1144 case coStrings:
1145 static_cast<ConfigOptionStrings*>(vec)->values[lhs.index] = rhs.to_string();
1146 break;
1147 case coPercents:
1148 check_numeric(rhs);
1149 static_cast<ConfigOptionPercents*>(vec)->values[lhs.index] = rhs.as_d();
1150 break;
1151 case coBools:
1152 if (rhs.type() != expr::TYPE_BOOL)
1153 ctx->throw_exception("Right side is not a boolean expression", rhs.it_range);
1154 static_cast<ConfigOptionBools*>(vec)->values[lhs.index] = rhs.b();
1155 break;
1156 default:
1157 ctx->throw_exception("Unsupported output vector variable type", lhs.it_range);
1158 }
1159 }

References Slic3r::client::expr::as_d(), Slic3r::client::expr::as_i(), Slic3r::client::expr::b(), check_numeric(), check_writable(), Slic3r::coBools, Slic3r::coFloats, Slic3r::coInts, Slic3r::coPercents, Slic3r::coStrings, Slic3r::ConfigOptionVectorBase::empty(), Slic3r::client::OptWithPos::has_index(), Slic3r::client::OptWithPos::index, Slic3r::ConfigOption::is_vector(), Slic3r::client::OptWithPos::it_range, Slic3r::client::expr::it_range, Slic3r::client::OptWithPos::opt, Slic3r::ConfigOptionVectorBase::size(), skipping(), throw_exception(), Slic3r::client::expr::to_string(), Slic3r::client::expr::type(), Slic3r::ConfigOption::type(), and Slic3r::client::expr::TYPE_BOOL.

Referenced by scalar_variable_assign_scalar_expression().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ vector_variable_new_from_array()

static void Slic3r::client::MyContext::vector_variable_new_from_array ( const MyContext ctx,
bool  global_variable,
NewOldVariable lhs,
const expr rhs_count,
const expr rhs_value 
)
inlinestatic
1295 {
1296 if (ctx->skipping()) {
1297 } else if (lhs.opt) {
1298 if (lhs.opt->is_scalar())
1299 rhs_value.throw_exception("Cannot assign a vector value to a scalar variable.");
1300 OptWithPos lhs_opt{ lhs.opt, lhs.it_range, true };
1301 vector_variable_assign_expr_with_count(ctx, lhs_opt, rhs_count, rhs_value);
1302 } else {
1303 size_t count = evaluate_count(rhs_count);
1304 std::unique_ptr<ConfigOption> opt_new;
1305 switch (rhs_value.type()) {
1306 case expr::TYPE_BOOL: opt_new = std::make_unique<ConfigOptionBools>(count, rhs_value.b()); break;
1307 case expr::TYPE_INT: opt_new = std::make_unique<ConfigOptionInts>(count, rhs_value.i()); break;
1308 case expr::TYPE_DOUBLE: opt_new = std::make_unique<ConfigOptionFloats>(count, rhs_value.d()); break;
1309 case expr::TYPE_STRING: opt_new = std::make_unique<ConfigOptionStrings>(count, rhs_value.s()); break;
1310 default: assert(false);
1311 }
1312 const_cast<MyContext*>(ctx)->store_new_variable(lhs.name, std::move(opt_new), global_variable);
1313 }
1314 }

References Slic3r::client::expr::b(), Slic3r::client::expr::d(), evaluate_count(), Slic3r::client::expr::i(), Slic3r::ConfigOption::is_scalar(), Slic3r::client::MyContext::NewOldVariable::it_range, Slic3r::client::MyContext::NewOldVariable::name, Slic3r::client::MyContext::NewOldVariable::opt, Slic3r::client::expr::s(), skipping(), store_new_variable(), Slic3r::client::expr::throw_exception(), Slic3r::client::expr::type(), Slic3r::client::expr::TYPE_BOOL, Slic3r::client::expr::TYPE_DOUBLE, Slic3r::client::expr::TYPE_INT, Slic3r::client::expr::TYPE_STRING, and vector_variable_assign_expr_with_count().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ vector_variable_new_from_copy()

static bool Slic3r::client::MyContext::vector_variable_new_from_copy ( const MyContext ctx,
bool  global_variable,
NewOldVariable lhs,
const OptWithPos rhs 
)
inlinestatic
1480 {
1481 if (ctx->skipping())
1482 // Skipping, continue parsing.
1483 return true;
1484
1485 if (lhs.opt) {
1486 assert(lhs.opt->is_vector());
1487 OptWithPos lhs_opt{ lhs.opt, lhs.it_range, true };
1488 copy_vector_variable_to_vector_variable(ctx, lhs_opt, rhs);
1489 } else {
1490 if (rhs.has_index() || ! rhs.opt->is_vector())
1491 // Stop parsing, let the other rules resolve this case.
1492 return false;
1493 if (rhs.opt->is_nil())
1494 ctx->throw_exception("Some elements of the right hand side vector variable of optional values are undefined (nil)", rhs.it_range);
1495 // Clone the vector variable.
1496 std::unique_ptr<ConfigOption> opt_new;
1497 if (one_of(rhs.opt->type(), { coFloats, coInts, coStrings, coBools }))
1498 opt_new = std::unique_ptr<ConfigOption>(rhs.opt->clone());
1499 else if (rhs.opt->type() == coPercents)
1500 opt_new = std::make_unique<ConfigOptionFloats>(static_cast<const ConfigOptionPercents*>(rhs.opt)->values);
1501 else
1502 ctx->throw_exception("Duplicating this type of vector variable is not supported", rhs.it_range);
1503 const_cast<MyContext*>(ctx)->store_new_variable(lhs.name, std::move(opt_new), global_variable);
1504 }
1505 // Continue parsing.
1506 return true;
1507 }
bool one_of(const ValueType &v, const ContainerType &c)
Definition libslic3r.h:252
static void copy_vector_variable_to_vector_variable(const MyContext *ctx, OptWithPos &lhs, const OptWithPos &rhs)
Definition PlaceholderParser.cpp:1446

References Slic3r::ConfigOption::clone(), Slic3r::coPercents, copy_vector_variable_to_vector_variable(), Slic3r::client::OptWithPos::has_index(), Slic3r::ConfigOption::is_nil(), Slic3r::ConfigOption::is_vector(), Slic3r::client::OptWithPos::it_range, Slic3r::client::MyContext::NewOldVariable::it_range, Slic3r::client::MyContext::NewOldVariable::name, Slic3r::one_of(), Slic3r::client::OptWithPos::opt, Slic3r::client::MyContext::NewOldVariable::opt, skipping(), store_new_variable(), throw_exception(), Slic3r::ConfigOption::type(), and Slic3r::ConfigOptionVector< T >::values.

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ vector_variable_new_from_initializer_list()

static void Slic3r::client::MyContext::vector_variable_new_from_initializer_list ( const MyContext ctx,
bool  global_variable,
NewOldVariable lhs,
const std::vector< expr > &  il 
)
inlinestatic
1391 {
1392 if (ctx->skipping())
1393 return;
1394
1395 if (lhs.opt) {
1396 // Assign to an existing vector variable.
1397 OptWithPos lhs_opt{ lhs.opt, lhs.it_range, true };
1399 } else {
1400 if (il.empty())
1401 ctx->throw_exception("Cannot create vector variable from an empty initializer list, because its type cannot be deduced.", lhs.it_range);
1402 // Allocate a new vector variable.
1403 // First guesstimate type of the output vector.
1404 size_t num_bool = 0;
1405 size_t num_int = 0;
1406 size_t num_double = 0;
1407 size_t num_string = 0;
1408 for (auto &i : il)
1409 switch (i.type()) {
1410 case expr::TYPE_BOOL: ++ num_bool; break;
1411 case expr::TYPE_INT: ++ num_int; break;
1412 case expr::TYPE_DOUBLE: ++ num_double; break;
1413 case expr::TYPE_STRING: ++ num_string; break;
1414 default: assert(false);
1415 }
1416 std::unique_ptr<ConfigOption> opt_new;
1417 if (num_string > 0)
1418 // Convert everything to strings.
1419 opt_new = std::make_unique<ConfigOptionStrings>();
1420 else if (num_bool > 0) {
1421 if (num_double + num_int > 0)
1422 ctx->throw_exception("Right side is not valid: Mixing numeric and boolean types.", IteratorRange{ il.front().it_range.begin(), il.back().it_range.end() });
1423 opt_new = std::make_unique<ConfigOptionBools>();
1424 } else {
1425 // Output is numeric.
1426 if (num_double == 0)
1427 opt_new = std::make_unique<ConfigOptionInts>();
1428 else
1429 opt_new = std::make_unique<ConfigOptionFloats>();
1430 }
1431 OptWithPos lhs_opt{ opt_new.get(), lhs.it_range, true };
1433 const_cast<MyContext*>(ctx)->store_new_variable(lhs.name, std::move(opt_new), global_variable);
1434 }
1435 }
static void vector_variable_assign_initializer_list(const MyContext *ctx, OptWithPos &lhs, const std::vector< expr > &il)
Definition PlaceholderParser.cpp:1339

References Slic3r::client::MyContext::NewOldVariable::it_range, Slic3r::client::MyContext::NewOldVariable::name, Slic3r::client::MyContext::NewOldVariable::opt, skipping(), store_new_variable(), throw_exception(), Slic3r::client::expr::TYPE_BOOL, Slic3r::client::expr::TYPE_DOUBLE, Slic3r::client::expr::TYPE_INT, Slic3r::client::expr::TYPE_STRING, and vector_variable_assign_initializer_list().

Referenced by Slic3r::client::macro_processor::macro_processor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ config

◆ config_local

DynamicConfig Slic3r::client::MyContext::config_local
mutable

Referenced by new_old_variable().

◆ config_outputs

DynamicConfig* Slic3r::client::MyContext::config_outputs = nullptr
mutable

◆ config_override

const DynamicConfig* Slic3r::client::MyContext::config_override = nullptr

◆ context_data

PlaceholderParser::ContextData* Slic3r::client::MyContext::context_data = nullptr

◆ current_extruder_id

size_t Slic3r::client::MyContext::current_extruder_id = 0

◆ error_message

std::string Slic3r::client::MyContext::error_message

◆ external_config

const DynamicConfig* Slic3r::client::MyContext::external_config = nullptr

◆ just_boolean_expression

bool Slic3r::client::MyContext::just_boolean_expression = false

◆ m_depth_suppressed

int Slic3r::client::MyContext::m_depth_suppressed { 0 }
mutableprivate

◆ tag_to_error_message

std::map< std::string, std::string > Slic3r::client::MyContext::tag_to_error_message
static
Initial value:
= {
{ "eoi", "Unknown syntax error" },
{ "start", "Unknown syntax error" },
{ "text", "Invalid text." },
{ "text_block", "Invalid text block." },
{ "macro", "Invalid macro." },
{ "repeat", "Unknown syntax error" },
{ "if_else_output", "Not an {if}{else}{endif} macro." },
{ "switch_output", "Not a {switch} macro." },
{ "legacy_variable_expansion", "Expecting a legacy variable expansion format" },
{ "identifier", "Expecting an identifier." },
{ "conditional_expression", "Expecting a conditional expression." },
{ "logical_or_expression", "Expecting a boolean expression." },
{ "logical_and_expression", "Expecting a boolean expression." },
{ "equality_expression", "Expecting an expression." },
{ "bool_expr_eval", "Expecting a boolean expression."},
{ "relational_expression", "Expecting an expression." },
{ "additive_expression", "Expecting an expression." },
{ "multiplicative_expression", "Expecting an expression." },
{ "unary_expression", "Expecting an expression." },
{ "optional_parameter", "Expecting a closing brace or an optional parameter." },
{ "one_of_list", "Expecting a list of string patterns (simple text or rexep)" },
{ "variable_reference", "Expecting a variable reference."},
{ "variable", "Expecting a variable name."},
{ "regular_expression", "Expecting a regular expression."}
}

Referenced by process_error_message().


The documentation for this struct was generated from the following file: