Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2017-12-18 14:14:09 +0300
committerbubnikv <bubnikv@gmail.com>2017-12-18 14:14:09 +0300
commitbb61de83795b10f77107e81384b62405ba2bbc89 (patch)
tree6a03fede6e62dcdb112f37eeac092d789e9ade67 /xs/src/libslic3r
parentbbfb9a4190adea0a2864ecf3a98cb0ab9942035e (diff)
Fixed a regression error: The "current_extruder" identifier was not set
at the placeholder parser. Implemented a new PlaceholderParser::evaluate_boolean_expression() functionality to evaluate just a boolean expression using the full expressive power of the macro processing syntax. This function will now be used for deciding, which print or filament preset is compatible with which printer preset.
Diffstat (limited to 'xs/src/libslic3r')
-rw-r--r--xs/src/libslic3r/PlaceholderParser.cpp71
-rw-r--r--xs/src/libslic3r/PlaceholderParser.hpp10
2 files changed, 62 insertions, 19 deletions
diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp
index b9f6b803e..0b33304a8 100644
--- a/xs/src/libslic3r/PlaceholderParser.cpp
+++ b/xs/src/libslic3r/PlaceholderParser.cpp
@@ -361,6 +361,13 @@ namespace client
out = self.b();
}
+ static void evaluate_boolean_to_string(expr &self, std::string &out)
+ {
+ if (self.type != TYPE_BOOL)
+ self.throw_exception("Not a boolean expression");
+ out = self.b() ? "true" : "false";
+ }
+
// Is lhs==rhs? Store the result into lhs.
static void compare_op(expr &lhs, expr &rhs, char op)
{
@@ -452,18 +459,23 @@ namespace client
}
struct MyContext {
- const PlaceholderParser *pp = nullptr;
- const DynamicConfig *config_override = nullptr;
- const size_t current_extruder_id = 0;
+ const DynamicConfig *config = nullptr;
+ const DynamicConfig *config_override = nullptr;
+ size_t current_extruder_id = 0;
+ // If false, the macro_processor will evaluate a full macro.
+ // If true, the macro processor will evaluate just a boolean condition using the full expressive power of the macro processor.
+ bool just_boolean_expression = false;
std::string error_message;
+ static void evaluate_full_macro(const MyContext *ctx, bool &result) { result = ! ctx->just_boolean_expression; }
+
const ConfigOption* resolve_symbol(const std::string &opt_key) const
{
const ConfigOption *opt = nullptr;
if (config_override != nullptr)
opt = config_override->option(opt_key);
if (opt == nullptr)
- opt = pp->option(opt_key);
+ opt = config->option(opt_key);
return opt;
}
@@ -734,13 +746,13 @@ namespace client
};
///////////////////////////////////////////////////////////////////////////
- // Our calculator grammar
+ // Our macro_processor grammar
///////////////////////////////////////////////////////////////////////////
// Inspired by the C grammar rules https://www.lysator.liu.se/c/ANSI-C-grammar-y.html
template <typename Iterator>
- struct calculator : qi::grammar<Iterator, std::string(const MyContext*), spirit::ascii::space_type>
+ struct macro_processor : qi::grammar<Iterator, std::string(const MyContext*), qi::locals<bool>, spirit::ascii::space_type>
{
- calculator() : calculator::base_type(start)
+ macro_processor() : macro_processor::base_type(start)
{
using namespace qi::labels;
qi::alpha_type alpha;
@@ -772,7 +784,13 @@ namespace client
// Starting symbol of the grammer.
// The leading eps is required by the "expectation point" operator ">".
// Without it, some of the errors would not trigger the error handler.
- start = eps > text_block(_r1);
+ // Also the start symbol switches between the "full macro syntax" and a "boolean expression only",
+ // depending on the context->just_boolean_expression flag. This way a single static expression parser
+ // could serve both purposes.
+ start = eps[px::bind(&MyContext::evaluate_full_macro, _r1, _a)] >
+ ( eps(_a==true) > text_block(_r1) [_val=_1]
+ | bool_expr(_r1) [ px::bind(&expr<Iterator>::evaluate_boolean_to_string, _1, _val) ]
+ );
start.name("start");
qi::on_error<qi::fail>(start, px::bind(&MyContext::process_error_message<Iterator>, _r1, _4, _1, _2, _3));
@@ -944,7 +962,7 @@ namespace client
}
// The start of the grammar.
- qi::rule<Iterator, std::string(const MyContext*), spirit::ascii::space_type> start;
+ qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool>, spirit::ascii::space_type> start;
// A free-form text.
qi::rule<Iterator, std::string(), spirit::ascii::space_type> text;
// A free-form text, possibly empty, possibly containing macro expansions.
@@ -979,24 +997,23 @@ namespace client
};
}
-std::string PlaceholderParser::process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override) const
+static std::string process_macro(const std::string &templ, client::MyContext &context)
{
typedef std::string::const_iterator iterator_type;
- typedef client::calculator<iterator_type> calculator;
+ typedef client::macro_processor<iterator_type> macro_processor;
// Our whitespace skipper.
spirit::ascii::space_type space;
- // Our grammar.
- calculator calc;
+ // Our grammar, statically allocated inside the method, meaning it will be allocated the first time
+ // PlaceholderParser::process() runs.
+ //FIXME this kind of initialization is not thread safe!
+ static macro_processor macro_processor_instance;
// Iterators over the source template.
std::string::const_iterator iter = templ.begin();
std::string::const_iterator end = templ.end();
// Accumulator for the processed template.
std::string output;
- client::MyContext context;
- context.pp = this;
- context.config_override = config_override;
- bool res = phrase_parse(iter, end, calc(&context), space, output);
+ bool res = phrase_parse(iter, end, macro_processor_instance(&context), space, output);
if (! context.error_message.empty()) {
if (context.error_message.back() != '\n' && context.error_message.back() != '\r')
context.error_message += '\n';
@@ -1005,4 +1022,24 @@ std::string PlaceholderParser::process(const std::string &templ, unsigned int cu
return output;
}
+std::string PlaceholderParser::process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override) const
+{
+ client::MyContext context;
+ context.config = &this->config();
+ context.config_override = config_override;
+ context.current_extruder_id = current_extruder_id;
+ return process_macro(templ, context);
+}
+
+// Evaluate a boolean expression using the full expressive power of the PlaceholderParser boolean expression syntax.
+// Throws std::runtime_error on syntax or runtime error.
+bool PlaceholderParser::evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config)
+{
+ client::MyContext context;
+ context.config = &config;
+ // Let the macro processor parse just a boolean expression, not the full macro language.
+ context.just_boolean_expression = true;
+ return process_macro(templ, context) == "true";
+}
+
}
diff --git a/xs/src/libslic3r/PlaceholderParser.hpp b/xs/src/libslic3r/PlaceholderParser.hpp
index 25264d461..ec2b837ad 100644
--- a/xs/src/libslic3r/PlaceholderParser.hpp
+++ b/xs/src/libslic3r/PlaceholderParser.hpp
@@ -26,11 +26,17 @@ public:
void set(const std::string &key, double value) { this->set(key, new ConfigOptionFloat(value)); }
void set(const std::string &key, const std::vector<std::string> &values) { this->set(key, new ConfigOptionStrings(values)); }
void set(const std::string &key, ConfigOption *opt) { m_config.set_key_value(key, opt); }
- const ConfigOption* option(const std::string &key) const { return m_config.option(key); }
+ const DynamicConfig& config() const { return m_config; }
+ const ConfigOption* option(const std::string &key) const { return m_config.option(key); }
- // Fill in the template.
+ // Fill in the template using a macro processing language.
+ // Throws std::runtime_error on syntax or runtime error.
std::string process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override = nullptr) const;
+ // Evaluate a boolean expression using the full expressive power of the PlaceholderParser boolean expression syntax.
+ // Throws std::runtime_error on syntax or runtime error.
+ static bool evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config);
+
private:
DynamicConfig m_config;
};