PlaceholderParser: Simplified the parser after introducing
the writable variables.
This commit is contained in:
parent
b9d8fe7118
commit
d152b67ce5
@ -173,7 +173,11 @@ namespace client
|
|||||||
OptWithPos(ConfigOptionConstPtr opt, boost::iterator_range<Iterator> it_range) : opt(opt), it_range(it_range) {}
|
OptWithPos(ConfigOptionConstPtr opt, boost::iterator_range<Iterator> it_range) : opt(opt), it_range(it_range) {}
|
||||||
ConfigOptionConstPtr opt { nullptr };
|
ConfigOptionConstPtr opt { nullptr };
|
||||||
bool writable { false };
|
bool writable { false };
|
||||||
|
// -1 means it is a scalar variable, or it is a vector variable and index was not assigned yet or the whole vector is considered.
|
||||||
|
int index { -1 };
|
||||||
boost::iterator_range<Iterator> it_range;
|
boost::iterator_range<Iterator> it_range;
|
||||||
|
|
||||||
|
bool has_index() const { return index != -1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ITERATOR>
|
template<typename ITERATOR>
|
||||||
@ -802,128 +806,127 @@ namespace client
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Iterator>
|
template <typename Iterator>
|
||||||
static void scalar_variable_reference(
|
static void store_variable_index(
|
||||||
const MyContext *ctx,
|
const MyContext *ctx,
|
||||||
OptWithPos<Iterator> &opt,
|
OptWithPos<Iterator> &opt,
|
||||||
expr<Iterator> &output)
|
int index,
|
||||||
|
Iterator it_end,
|
||||||
|
OptWithPos<Iterator> &output)
|
||||||
{
|
{
|
||||||
if (opt.opt->is_vector())
|
if (! opt.opt->is_vector())
|
||||||
ctx->throw_exception("Referencing a vector variable when scalar is expected", opt.it_range);
|
ctx->throw_exception("Cannot index a scalar variable", opt.it_range);
|
||||||
switch (opt.opt->type()) {
|
if (index < 0)
|
||||||
case coFloat: output.set_d(opt.opt->getFloat()); break;
|
ctx->throw_exception("Referencing a vector variable with a negative index", opt.it_range);
|
||||||
case coInt: output.set_i(opt.opt->getInt()); break;
|
output = opt;
|
||||||
case coString: output.set_s(static_cast<const ConfigOptionString*>(opt.opt)->value); break;
|
output.index = index;
|
||||||
case coPercent: output.set_d(opt.opt->getFloat()); break;
|
output.it_range.end() = it_end;
|
||||||
case coEnum:
|
|
||||||
case coPoint: output.set_s(opt.opt->serialize()); break;
|
|
||||||
case coBool: output.set_b(opt.opt->getBool()); break;
|
|
||||||
case coFloatOrPercent:
|
|
||||||
{
|
|
||||||
std::string opt_key(opt.it_range.begin(), opt.it_range.end());
|
|
||||||
if (boost::ends_with(opt_key, "extrusion_width")) {
|
|
||||||
// Extrusion width supports defaults and a complex graph of dependencies.
|
|
||||||
output.set_d(Flow::extrusion_width(opt_key, *ctx, static_cast<unsigned int>(ctx->current_extruder_id)));
|
|
||||||
} else if (! static_cast<const ConfigOptionFloatOrPercent*>(opt.opt)->percent) {
|
|
||||||
// Not a percent, just return the value.
|
|
||||||
output.set_d(opt.opt->getFloat());
|
|
||||||
} else {
|
|
||||||
// Resolve dependencies using the "ratio_over" link to a parent value.
|
|
||||||
const ConfigOptionDef *opt_def = print_config_def.get(opt_key);
|
|
||||||
assert(opt_def != nullptr);
|
|
||||||
double v = opt.opt->getFloat() * 0.01; // percent to ratio
|
|
||||||
for (;;) {
|
|
||||||
const ConfigOption *opt_parent = opt_def->ratio_over.empty() ? nullptr : ctx->resolve_symbol(opt_def->ratio_over);
|
|
||||||
if (opt_parent == nullptr)
|
|
||||||
ctx->throw_exception("FloatOrPercent variable failed to resolve the \"ratio_over\" dependencies", opt.it_range);
|
|
||||||
if (boost::ends_with(opt_def->ratio_over, "extrusion_width")) {
|
|
||||||
// Extrusion width supports defaults and a complex graph of dependencies.
|
|
||||||
assert(opt_parent->type() == coFloatOrPercent);
|
|
||||||
v *= Flow::extrusion_width(opt_def->ratio_over, static_cast<const ConfigOptionFloatOrPercent*>(opt_parent), *ctx, static_cast<unsigned int>(ctx->current_extruder_id));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (opt_parent->type() == coFloat || opt_parent->type() == coFloatOrPercent) {
|
|
||||||
v *= opt_parent->getFloat();
|
|
||||||
if (opt_parent->type() == coFloat || ! static_cast<const ConfigOptionFloatOrPercent*>(opt_parent)->percent)
|
|
||||||
break;
|
|
||||||
v *= 0.01; // percent to ratio
|
|
||||||
}
|
|
||||||
// Continue one level up in the "ratio_over" hierarchy.
|
|
||||||
opt_def = print_config_def.get(opt_def->ratio_over);
|
|
||||||
assert(opt_def != nullptr);
|
|
||||||
}
|
|
||||||
output.set_d(v);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
ctx->throw_exception("Unknown scalar variable type", opt.it_range);
|
|
||||||
}
|
|
||||||
output.it_range = opt.it_range;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Iterator>
|
template <typename Iterator>
|
||||||
static void vector_variable_reference(
|
static void variable_value(
|
||||||
const MyContext *ctx,
|
const MyContext *ctx,
|
||||||
OptWithPos<Iterator> &opt,
|
OptWithPos<Iterator> &opt,
|
||||||
int &index,
|
|
||||||
Iterator it_end,
|
|
||||||
expr<Iterator> &output)
|
expr<Iterator> &output)
|
||||||
{
|
{
|
||||||
if (opt.opt->is_scalar())
|
if (opt.opt->is_vector()) {
|
||||||
ctx->throw_exception("Referencing a scalar variable when vector is expected", opt.it_range);
|
if (! opt.has_index())
|
||||||
const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
|
ctx->throw_exception("Referencing a vector variable when scalar is expected", opt.it_range);
|
||||||
if (vec->empty())
|
const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
|
||||||
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
if (vec->empty())
|
||||||
size_t idx = (index < 0) ? 0 : (index >= int(vec->size())) ? 0 : size_t(index);
|
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
||||||
switch (opt.opt->type()) {
|
size_t idx = (opt.index < 0) ? 0 : (opt.index >= int(vec->size())) ? 0 : size_t(opt.index);
|
||||||
case coFloats: output.set_d(static_cast<const ConfigOptionFloats *>(opt.opt)->values[idx]); break;
|
switch (opt.opt->type()) {
|
||||||
case coInts: output.set_i(static_cast<const ConfigOptionInts *>(opt.opt)->values[idx]); break;
|
case coFloats: output.set_d(static_cast<const ConfigOptionFloats *>(opt.opt)->values[idx]); break;
|
||||||
case coStrings: output.set_s(static_cast<const ConfigOptionStrings *>(opt.opt)->values[idx]); break;
|
case coInts: output.set_i(static_cast<const ConfigOptionInts *>(opt.opt)->values[idx]); break;
|
||||||
case coPercents: output.set_d(static_cast<const ConfigOptionPercents*>(opt.opt)->values[idx]); break;
|
case coStrings: output.set_s(static_cast<const ConfigOptionStrings *>(opt.opt)->values[idx]); break;
|
||||||
case coPoints: output.set_s(to_string(static_cast<const ConfigOptionPoints *>(opt.opt)->values[idx])); break;
|
case coPercents: output.set_d(static_cast<const ConfigOptionPercents*>(opt.opt)->values[idx]); break;
|
||||||
case coBools: output.set_b(static_cast<const ConfigOptionBools *>(opt.opt)->values[idx] != 0); break;
|
case coPoints: output.set_s(to_string(static_cast<const ConfigOptionPoints *>(opt.opt)->values[idx])); break;
|
||||||
//case coEnums: output.set_s(opt.opt->vserialize()[idx]); break;
|
case coBools: output.set_b(static_cast<const ConfigOptionBools *>(opt.opt)->values[idx] != 0); break;
|
||||||
default:
|
//case coEnums: output.set_s(opt.opt->vserialize()[idx]); break;
|
||||||
ctx->throw_exception("Unknown vector variable type", opt.it_range);
|
default:
|
||||||
|
ctx->throw_exception("Unknown vector variable type", opt.it_range);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(opt.opt->is_scalar());
|
||||||
|
switch (opt.opt->type()) {
|
||||||
|
case coFloat: output.set_d(opt.opt->getFloat()); break;
|
||||||
|
case coInt: output.set_i(opt.opt->getInt()); break;
|
||||||
|
case coString: output.set_s(static_cast<const ConfigOptionString*>(opt.opt)->value); break;
|
||||||
|
case coPercent: output.set_d(opt.opt->getFloat()); break;
|
||||||
|
case coEnum:
|
||||||
|
case coPoint: output.set_s(opt.opt->serialize()); break;
|
||||||
|
case coBool: output.set_b(opt.opt->getBool()); break;
|
||||||
|
case coFloatOrPercent:
|
||||||
|
{
|
||||||
|
std::string opt_key(opt.it_range.begin(), opt.it_range.end());
|
||||||
|
if (boost::ends_with(opt_key, "extrusion_width")) {
|
||||||
|
// Extrusion width supports defaults and a complex graph of dependencies.
|
||||||
|
output.set_d(Flow::extrusion_width(opt_key, *ctx, static_cast<unsigned int>(ctx->current_extruder_id)));
|
||||||
|
} else if (! static_cast<const ConfigOptionFloatOrPercent*>(opt.opt)->percent) {
|
||||||
|
// Not a percent, just return the value.
|
||||||
|
output.set_d(opt.opt->getFloat());
|
||||||
|
} else {
|
||||||
|
// Resolve dependencies using the "ratio_over" link to a parent value.
|
||||||
|
const ConfigOptionDef *opt_def = print_config_def.get(opt_key);
|
||||||
|
assert(opt_def != nullptr);
|
||||||
|
double v = opt.opt->getFloat() * 0.01; // percent to ratio
|
||||||
|
for (;;) {
|
||||||
|
const ConfigOption *opt_parent = opt_def->ratio_over.empty() ? nullptr : ctx->resolve_symbol(opt_def->ratio_over);
|
||||||
|
if (opt_parent == nullptr)
|
||||||
|
ctx->throw_exception("FloatOrPercent variable failed to resolve the \"ratio_over\" dependencies", opt.it_range);
|
||||||
|
if (boost::ends_with(opt_def->ratio_over, "extrusion_width")) {
|
||||||
|
// Extrusion width supports defaults and a complex graph of dependencies.
|
||||||
|
assert(opt_parent->type() == coFloatOrPercent);
|
||||||
|
v *= Flow::extrusion_width(opt_def->ratio_over, static_cast<const ConfigOptionFloatOrPercent*>(opt_parent), *ctx, static_cast<unsigned int>(ctx->current_extruder_id));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (opt_parent->type() == coFloat || opt_parent->type() == coFloatOrPercent) {
|
||||||
|
v *= opt_parent->getFloat();
|
||||||
|
if (opt_parent->type() == coFloat || ! static_cast<const ConfigOptionFloatOrPercent*>(opt_parent)->percent)
|
||||||
|
break;
|
||||||
|
v *= 0.01; // percent to ratio
|
||||||
|
}
|
||||||
|
// Continue one level up in the "ratio_over" hierarchy.
|
||||||
|
opt_def = print_config_def.get(opt_def->ratio_over);
|
||||||
|
assert(opt_def != nullptr);
|
||||||
|
}
|
||||||
|
output.set_d(v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
ctx->throw_exception("Unknown scalar variable type", opt.it_range);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
output.it_range = boost::iterator_range<Iterator>(opt.it_range.begin(), it_end);
|
|
||||||
|
output.it_range = opt.it_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a boolean value, true if the scalar variable referenced by "opt" is nullable and it has a nil value.
|
// Return a boolean value, true if the scalar variable referenced by "opt" is nullable and it has a nil value.
|
||||||
template <typename Iterator>
|
|
||||||
static void is_nil_test_scalar(
|
|
||||||
const MyContext *ctx,
|
|
||||||
OptWithPos<Iterator> &opt,
|
|
||||||
expr<Iterator> &output)
|
|
||||||
{
|
|
||||||
if (opt.opt->is_vector())
|
|
||||||
ctx->throw_exception("Referencing a vector variable when scalar is expected", opt.it_range);
|
|
||||||
output.set_b(opt.opt->is_nil());
|
|
||||||
output.it_range = opt.it_range;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a boolean value, true if an element of a vector variable referenced by "opt[index]" is nullable and it has a nil value.
|
// Return a boolean value, true if an element of a vector variable referenced by "opt[index]" is nullable and it has a nil value.
|
||||||
template <typename Iterator>
|
template <typename Iterator>
|
||||||
static void is_nil_test_vector(
|
static void is_nil_test(
|
||||||
const MyContext *ctx,
|
const MyContext *ctx,
|
||||||
OptWithPos<Iterator> &opt,
|
OptWithPos<Iterator> &opt,
|
||||||
int &index,
|
|
||||||
Iterator it_end,
|
|
||||||
expr<Iterator> &output)
|
expr<Iterator> &output)
|
||||||
{
|
{
|
||||||
if (opt.opt->is_scalar())
|
if (opt.opt->is_vector()) {
|
||||||
ctx->throw_exception("Referencing a scalar variable when vector is expected", opt.it_range);
|
if (! opt.has_index())
|
||||||
const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
|
ctx->throw_exception("Referencing a vector variable when scalar is expected", opt.it_range);
|
||||||
if (vec->empty())
|
const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
|
||||||
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
if (vec->empty())
|
||||||
size_t idx = (index < 0) ? 0 : (index >= int(vec->size())) ? 0 : size_t(index);
|
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
||||||
output.set_b(static_cast<const ConfigOptionVectorBase*>(opt.opt)->is_nil(idx));
|
output.set_b(static_cast<const ConfigOptionVectorBase*>(opt.opt)->is_nil(opt.index >= int(vec->size()) ? 0 : size_t(opt.index)));
|
||||||
output.it_range = boost::iterator_range<Iterator>(opt.it_range.begin(), it_end);
|
} else {
|
||||||
|
assert(opt.opt->is_scalar());
|
||||||
|
output.set_b(opt.opt->is_nil());
|
||||||
|
}
|
||||||
|
output.it_range = opt.it_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decoding a scalar variable symbol "opt", assigning it a value of "param".
|
// Decoding a scalar variable symbol "opt", assigning it a value of "param".
|
||||||
template <typename Iterator>
|
template <typename Iterator>
|
||||||
static void scalar_variable_assign(
|
static void variable_assign(
|
||||||
const MyContext *ctx,
|
const MyContext *ctx,
|
||||||
OptWithPos<Iterator> &opt,
|
OptWithPos<Iterator> &opt,
|
||||||
expr<Iterator> ¶m,
|
expr<Iterator> ¶m,
|
||||||
@ -932,83 +935,71 @@ namespace client
|
|||||||
{
|
{
|
||||||
if (! opt.writable)
|
if (! opt.writable)
|
||||||
ctx->throw_exception("Cannot modify a read-only variable", opt.it_range);
|
ctx->throw_exception("Cannot modify a read-only variable", opt.it_range);
|
||||||
if (opt.opt->is_vector())
|
if (opt.opt->is_vector()) {
|
||||||
ctx->throw_exception("Referencing an output vector variable when scalar is expected", opt.it_range);
|
if (! opt.has_index())
|
||||||
ConfigOption *wropt = const_cast<ConfigOption*>(opt.opt);
|
ctx->throw_exception("Referencing an output vector variable when scalar is expected", opt.it_range);
|
||||||
switch (wropt->type()) {
|
ConfigOptionVectorBase *vec = const_cast<ConfigOptionVectorBase*>(static_cast<const ConfigOptionVectorBase*>(opt.opt));
|
||||||
case coFloat:
|
if (vec->empty())
|
||||||
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
||||||
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
if (opt.index >= int(vec->size()))
|
||||||
static_cast<ConfigOptionFloat*>(wropt)->value = param.as_d();
|
ctx->throw_exception("Index out of range", opt.it_range);
|
||||||
break;
|
switch (opt.opt->type()) {
|
||||||
case coInt:
|
case coFloats:
|
||||||
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
||||||
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
||||||
static_cast<ConfigOptionInt*>(wropt)->value = param.as_i();
|
static_cast<ConfigOptionFloats*>(vec)->values[opt.index] = param.as_d();
|
||||||
break;
|
break;
|
||||||
case coString:
|
case coInts:
|
||||||
static_cast<ConfigOptionString*>(wropt)->value = param.to_string();
|
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
||||||
break;
|
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
||||||
case coPercent:
|
static_cast<ConfigOptionInts*>(vec)->values[opt.index] = param.as_i();
|
||||||
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
break;
|
||||||
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
case coStrings:
|
||||||
static_cast<ConfigOptionPercent*>(wropt)->value = param.as_d();
|
static_cast<ConfigOptionStrings*>(vec)->values[opt.index] = param.to_string();
|
||||||
break;
|
break;
|
||||||
case coBool:
|
case coPercents:
|
||||||
if (param.type() != expr<Iterator>::TYPE_BOOL)
|
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
||||||
ctx->throw_exception("Right side is not a boolean expression", param.it_range);
|
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
||||||
static_cast<ConfigOptionBool*>(wropt)->value = param.b();
|
static_cast<ConfigOptionPercents*>(vec)->values[opt.index] = param.as_d();
|
||||||
break;
|
break;
|
||||||
default:
|
case coBools:
|
||||||
ctx->throw_exception("Unsupported output scalar variable type", opt.it_range);
|
if (param.type() != expr<Iterator>::TYPE_BOOL)
|
||||||
}
|
ctx->throw_exception("Right side is not a boolean expression", param.it_range);
|
||||||
out.clear();
|
static_cast<ConfigOptionBools*>(vec)->values[opt.index] = param.b();
|
||||||
}
|
break;
|
||||||
|
default:
|
||||||
template <typename Iterator>
|
ctx->throw_exception("Unsupported output vector variable type", opt.it_range);
|
||||||
static void vector_variable_assign(
|
}
|
||||||
const MyContext *ctx,
|
} else {
|
||||||
OptWithPos<Iterator> &opt,
|
assert(opt.opt->is_scalar());
|
||||||
int &index,
|
ConfigOption *wropt = const_cast<ConfigOption*>(opt.opt);
|
||||||
expr<Iterator> ¶m,
|
switch (wropt->type()) {
|
||||||
// Not used, just clear it.
|
case coFloat:
|
||||||
std::string &out)
|
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
||||||
{
|
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
||||||
if (! opt.writable)
|
static_cast<ConfigOptionFloat*>(wropt)->value = param.as_d();
|
||||||
ctx->throw_exception("Cannot modify a read-only variable", opt.it_range);
|
break;
|
||||||
if (opt.opt->is_scalar())
|
case coInt:
|
||||||
ctx->throw_exception("Referencing an output scalar variable when vector is expected", opt.it_range);
|
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
||||||
ConfigOptionVectorBase *vec = const_cast<ConfigOptionVectorBase*>(static_cast<const ConfigOptionVectorBase*>(opt.opt));
|
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
||||||
if (vec->empty())
|
static_cast<ConfigOptionInt*>(wropt)->value = param.as_i();
|
||||||
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
break;
|
||||||
if (index < 0 || index >= int(vec->size()))
|
case coString:
|
||||||
ctx->throw_exception("Index out of range", opt.it_range);
|
static_cast<ConfigOptionString*>(wropt)->value = param.to_string();
|
||||||
switch (opt.opt->type()) {
|
break;
|
||||||
case coFloats:
|
case coPercent:
|
||||||
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
||||||
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
||||||
static_cast<ConfigOptionFloats*>(vec)->values[index] = param.as_d();
|
static_cast<ConfigOptionPercent*>(wropt)->value = param.as_d();
|
||||||
break;
|
break;
|
||||||
case coInts:
|
case coBool:
|
||||||
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
if (param.type() != expr<Iterator>::TYPE_BOOL)
|
||||||
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
ctx->throw_exception("Right side is not a boolean expression", param.it_range);
|
||||||
static_cast<ConfigOptionInts*>(vec)->values[index] = param.as_i();
|
static_cast<ConfigOptionBool*>(wropt)->value = param.b();
|
||||||
break;
|
break;
|
||||||
case coStrings:
|
default:
|
||||||
static_cast<ConfigOptionStrings*>(vec)->values[index] = param.to_string();
|
ctx->throw_exception("Unsupported output scalar variable type", opt.it_range);
|
||||||
break;
|
}
|
||||||
case coPercents:
|
|
||||||
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
|
||||||
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
|
||||||
static_cast<ConfigOptionPercents*>(vec)->values[index] = param.as_d();
|
|
||||||
break;
|
|
||||||
case coBools:
|
|
||||||
if (param.type() != expr<Iterator>::TYPE_BOOL)
|
|
||||||
ctx->throw_exception("Right side is not a boolean expression", param.it_range);
|
|
||||||
static_cast<ConfigOptionBools*>(vec)->values[index] = param.b();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ctx->throw_exception("Unsupported output vector variable type", opt.it_range);
|
|
||||||
}
|
}
|
||||||
out.clear();
|
out.clear();
|
||||||
}
|
}
|
||||||
@ -1110,9 +1101,9 @@ namespace client
|
|||||||
{ "multiplicative_expression", "Expecting an expression." },
|
{ "multiplicative_expression", "Expecting an expression." },
|
||||||
{ "unary_expression", "Expecting an expression." },
|
{ "unary_expression", "Expecting an expression." },
|
||||||
{ "optional_parameter", "Expecting a closing brace or an optional parameter." },
|
{ "optional_parameter", "Expecting a closing brace or an optional parameter." },
|
||||||
{ "scalar_variable_reference", "Expecting a scalar variable reference."},
|
|
||||||
{ "is_nil_test", "Expecting a scalar variable reference."},
|
|
||||||
{ "variable_reference", "Expecting a variable reference."},
|
{ "variable_reference", "Expecting a variable reference."},
|
||||||
|
{ "is_nil_test", "Expecting a scalar variable reference."},
|
||||||
|
{ "variable", "Expecting a variable name."},
|
||||||
{ "regular_expression", "Expecting a regular expression."}
|
{ "regular_expression", "Expecting a regular expression."}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1359,13 +1350,8 @@ namespace client
|
|||||||
multiplicative_expression.name("multiplicative_expression");
|
multiplicative_expression.name("multiplicative_expression");
|
||||||
|
|
||||||
assignment_statement =
|
assignment_statement =
|
||||||
variable_reference(_r1)[_a = _1] >>
|
(variable_reference(_r1) >> '=' > additive_expression(_r1))
|
||||||
(
|
[px::bind(&MyContext::variable_assign<Iterator>, _r1, _1, _2, _val)];
|
||||||
('[' >> additive_expression(_r1)[px::bind(&MyContext::evaluate_index<Iterator>, _1, _b)] >> ']' >> '=' >> additive_expression(_r1))
|
|
||||||
[px::bind(&MyContext::vector_variable_assign<Iterator>, _r1, _a, _b, _2, _val)]
|
|
||||||
| ('=' >> additive_expression(_r1))
|
|
||||||
[px::bind(&MyContext::scalar_variable_assign<Iterator>, _r1, _a, _1, _val)]
|
|
||||||
);
|
|
||||||
|
|
||||||
struct FactorActions {
|
struct FactorActions {
|
||||||
static void set_start_pos(Iterator &start_pos, expr<Iterator> &out)
|
static void set_start_pos(Iterator &start_pos, expr<Iterator> &out)
|
||||||
@ -1392,7 +1378,7 @@ namespace client
|
|||||||
static void noexpr(expr<Iterator> &out) { out.reset(); }
|
static void noexpr(expr<Iterator> &out) { out.reset(); }
|
||||||
};
|
};
|
||||||
unary_expression = iter_pos[px::bind(&FactorActions::set_start_pos, _1, _val)] >> (
|
unary_expression = iter_pos[px::bind(&FactorActions::set_start_pos, _1, _val)] >> (
|
||||||
scalar_variable_reference(_r1) [ _val = _1 ]
|
variable_reference(_r1) [px::bind(&MyContext::variable_value<Iterator>, _r1, _1, _val)]
|
||||||
| (lit('(') > conditional_expression(_r1) > ')' > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ]
|
| (lit('(') > conditional_expression(_r1) > ')' > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ]
|
||||||
| (lit('-') > unary_expression(_r1) ) [ px::bind(&FactorActions::minus_, _1, _val) ]
|
| (lit('-') > unary_expression(_r1) ) [ px::bind(&FactorActions::minus_, _1, _val) ]
|
||||||
| (lit('+') > unary_expression(_r1) > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ]
|
| (lit('+') > unary_expression(_r1) > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ]
|
||||||
@ -1424,27 +1410,20 @@ namespace client
|
|||||||
);
|
);
|
||||||
optional_parameter.name("optional_parameter");
|
optional_parameter.name("optional_parameter");
|
||||||
|
|
||||||
scalar_variable_reference =
|
is_nil_test = variable_reference(_r1)[px::bind(&MyContext::is_nil_test<Iterator>, _r1, _1, _val)];
|
||||||
variable_reference(_r1)[_a=_1] >>
|
is_nil_test.name("is_nil test");
|
||||||
(
|
|
||||||
('[' > additive_expression(_r1)[px::bind(&MyContext::evaluate_index<Iterator>, _1, _b)] > ']' >
|
|
||||||
iter_pos[px::bind(&MyContext::vector_variable_reference<Iterator>, _r1, _a, _b, _1, _val)])
|
|
||||||
| eps[px::bind(&MyContext::scalar_variable_reference<Iterator>, _r1, _a, _val)]
|
|
||||||
);
|
|
||||||
scalar_variable_reference.name("scalar variable reference");
|
|
||||||
|
|
||||||
variable_reference = identifier
|
variable_reference =
|
||||||
[ px::bind(&MyContext::resolve_variable<Iterator>, _r1, _1, _val) ];
|
variable(_r1)[_a=_1] >>
|
||||||
|
(
|
||||||
|
('[' > additive_expression(_r1)[px::bind(&MyContext::evaluate_index<Iterator>, _1, _b)] > ']' > iter_pos)
|
||||||
|
[px::bind(&MyContext::store_variable_index<Iterator>, _r1, _a, _b, _2, _val)]
|
||||||
|
| eps[_val=_a]
|
||||||
|
);
|
||||||
variable_reference.name("variable reference");
|
variable_reference.name("variable reference");
|
||||||
|
|
||||||
is_nil_test =
|
variable = identifier[ px::bind(&MyContext::resolve_variable<Iterator>, _r1, _1, _val) ];
|
||||||
variable_reference(_r1)[_a=_1] >>
|
variable.name("variable reference");
|
||||||
(
|
|
||||||
('[' > additive_expression(_r1)[px::bind(&MyContext::evaluate_index<Iterator>, _1, _b)] > ']' >
|
|
||||||
iter_pos[px::bind(&MyContext::is_nil_test_vector<Iterator>, _r1, _a, _b, _1, _val)])
|
|
||||||
| eps[px::bind(&MyContext::is_nil_test_scalar<Iterator>, _r1, _a, _val)]
|
|
||||||
);
|
|
||||||
is_nil_test.name("is_nil test");
|
|
||||||
|
|
||||||
regular_expression = raw[lexeme['/' > *((utf8char - char_('\\') - char_('/')) | ('\\' > char_)) > '/']];
|
regular_expression = raw[lexeme['/' > *((utf8char - char_('\\') - char_('/')) | ('\\' > char_)) > '/']];
|
||||||
regular_expression.name("regular_expression");
|
regular_expression.name("regular_expression");
|
||||||
@ -1488,8 +1467,8 @@ namespace client
|
|||||||
debug(multiplicative_expression);
|
debug(multiplicative_expression);
|
||||||
debug(unary_expression);
|
debug(unary_expression);
|
||||||
debug(optional_parameter);
|
debug(optional_parameter);
|
||||||
debug(scalar_variable_reference);
|
|
||||||
debug(variable_reference);
|
debug(variable_reference);
|
||||||
|
debug(variable);
|
||||||
debug(is_nil_test);
|
debug(is_nil_test);
|
||||||
debug(regular_expression);
|
debug(regular_expression);
|
||||||
}
|
}
|
||||||
@ -1533,11 +1512,11 @@ namespace client
|
|||||||
// Evaluate boolean expression into bool.
|
// Evaluate boolean expression into bool.
|
||||||
qi::rule<Iterator, bool(const MyContext*), spirit_encoding::space_type> bool_expr_eval;
|
qi::rule<Iterator, bool(const MyContext*), spirit_encoding::space_type> bool_expr_eval;
|
||||||
// Reference of a scalar variable, or reference to a field of a vector variable.
|
// Reference of a scalar variable, or reference to a field of a vector variable.
|
||||||
qi::rule<Iterator, expr<Iterator>(const MyContext*), qi::locals<OptWithPos<Iterator>, int>, spirit_encoding::space_type> scalar_variable_reference;
|
qi::rule<Iterator, OptWithPos<Iterator>(const MyContext*), qi::locals<OptWithPos<Iterator>, int>, spirit_encoding::space_type> variable_reference;
|
||||||
// Rule to translate an identifier to a ConfigOption, or to fail.
|
// Rule to translate an identifier to a ConfigOption, or to fail.
|
||||||
qi::rule<Iterator, OptWithPos<Iterator>(const MyContext*), spirit_encoding::space_type> variable_reference;
|
qi::rule<Iterator, OptWithPos<Iterator>(const MyContext*), spirit_encoding::space_type> variable;
|
||||||
// Evaluating whether a nullable variable is nil.
|
// Evaluating whether a nullable variable is nil.
|
||||||
qi::rule<Iterator, expr<Iterator>(const MyContext*), qi::locals<OptWithPos<Iterator>, int>, spirit_encoding::space_type> is_nil_test;
|
qi::rule<Iterator, expr<Iterator>(const MyContext*), spirit_encoding::space_type> is_nil_test;
|
||||||
|
|
||||||
qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool, bool>, spirit_encoding::space_type> if_else_output;
|
qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool, bool>, spirit_encoding::space_type> if_else_output;
|
||||||
qi::rule<Iterator, std::string(const MyContext*), qi::locals<OptWithPos<Iterator>, int>, spirit_encoding::space_type> assignment_statement;
|
qi::rule<Iterator, std::string(const MyContext*), qi::locals<OptWithPos<Iterator>, int>, spirit_encoding::space_type> assignment_statement;
|
||||||
|
Loading…
Reference in New Issue
Block a user