Added regex matching operators to the conditional G-code processor
in a form similar to Perl: Following expression returns true, if the variable matches the regex: variable =~ /regex/ Following expression returns true, if the variable does not match the regex: variable !~ /regex/
This commit is contained in:
parent
88e9ba510b
commit
bbfb9a4190
1 changed files with 39 additions and 2 deletions
|
@ -22,6 +22,7 @@
|
|||
#endif
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
// Unicode iterator to iterate over utf8.
|
||||
#include <boost/regex/pending/unicode_iterator.hpp>
|
||||
|
||||
|
@ -382,9 +383,37 @@ namespace client
|
|||
lhs.type = TYPE_BOOL;
|
||||
lhs.data.b = (op == '=') ? value : !value;
|
||||
}
|
||||
static void equal(expr &lhs, expr &rhs) { compare_op(lhs, rhs, '='); }
|
||||
static void equal (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '='); }
|
||||
static void not_equal(expr &lhs, expr &rhs) { compare_op(lhs, rhs, '!'); }
|
||||
|
||||
static void regex_op(expr &lhs, boost::iterator_range<Iterator> &rhs, char op)
|
||||
{
|
||||
const std::string *subject = nullptr;
|
||||
const std::string *mask = nullptr;
|
||||
if (lhs.type == TYPE_STRING) {
|
||||
// One type is string, the other could be converted to string.
|
||||
subject = &lhs.s();
|
||||
} else {
|
||||
lhs.throw_exception("Left hand side of a regex match must be a string.");
|
||||
}
|
||||
try {
|
||||
std::string pattern(++ rhs.begin(), -- rhs.end());
|
||||
bool result = boost::regex_match(*subject, boost::regex(pattern));
|
||||
if (op == '!')
|
||||
result = ! result;
|
||||
lhs.reset();
|
||||
lhs.type = TYPE_BOOL;
|
||||
lhs.data.b = result;
|
||||
} catch (boost::regex_error &ex) {
|
||||
// Syntax error in the regular expression
|
||||
boost::throw_exception(qi::expectation_failure<Iterator>(
|
||||
rhs.begin(), rhs.end(), spirit::info(std::string("*Regular expression compilation failed: ") + ex.what())));
|
||||
}
|
||||
}
|
||||
|
||||
static void regex_matches (expr &lhs, boost::iterator_range<Iterator> &rhs) { return regex_op(lhs, rhs, '='); }
|
||||
static void regex_doesnt_match(expr &lhs, boost::iterator_range<Iterator> &rhs) { return regex_op(lhs, rhs, '!'); }
|
||||
|
||||
static void set_if(bool &cond, bool ¬_yet_consumed, std::string &str_in, std::string &str_out)
|
||||
{
|
||||
if (cond && not_yet_consumed) {
|
||||
|
@ -810,6 +839,8 @@ namespace client
|
|||
>> *( ("==" > additive_expression(_r1) ) [px::bind(&expr<Iterator>::equal, _val, _1)]
|
||||
| ("!=" > additive_expression(_r1) ) [px::bind(&expr<Iterator>::not_equal, _val, _1)]
|
||||
| ("<>" > additive_expression(_r1) ) [px::bind(&expr<Iterator>::not_equal, _val, _1)]
|
||||
| ("=~" > regular_expression ) [px::bind(&expr<Iterator>::regex_matches, _val, _1)]
|
||||
| ("!~" > regular_expression ) [px::bind(&expr<Iterator>::regex_doesnt_match, _val, _1)]
|
||||
);
|
||||
bool_expr.name("bool expression");
|
||||
|
||||
|
@ -877,6 +908,9 @@ namespace client
|
|||
[ px::bind(&MyContext::resolve_variable<Iterator>, _r1, _1, _val) ];
|
||||
variable_reference.name("variable reference");
|
||||
|
||||
regular_expression = raw[lexeme['/' > *((utf8char - char_('\\') - char_('/')) | ('\\' > char_)) > '/']];
|
||||
regular_expression.name("regular_expression");
|
||||
|
||||
keywords.add
|
||||
("and")
|
||||
("if")
|
||||
|
@ -905,6 +939,7 @@ namespace client
|
|||
debug(factor);
|
||||
debug(scalar_variable_reference);
|
||||
debug(variable_reference);
|
||||
debug(regular_expression);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -919,9 +954,11 @@ namespace client
|
|||
// Legacy variable expansion of the original Slic3r, in the form of [scalar_variable] or [vector_variable_index].
|
||||
qi::rule<Iterator, std::string(const MyContext*), spirit::ascii::space_type> legacy_variable_expansion;
|
||||
// Parsed identifier name.
|
||||
qi::rule<Iterator, boost::iterator_range<Iterator>(), spirit::ascii::space_type> identifier;
|
||||
qi::rule<Iterator, boost::iterator_range<Iterator>(), spirit::ascii::space_type> identifier;
|
||||
// Math expression consisting of +- operators over terms.
|
||||
qi::rule<Iterator, expr<Iterator>(const MyContext*), spirit::ascii::space_type> additive_expression;
|
||||
// Rule to capture a regular expression enclosed in //.
|
||||
qi::rule<Iterator, boost::iterator_range<Iterator>(), spirit::ascii::space_type> regular_expression;
|
||||
// Boolean expressions over expressions.
|
||||
qi::rule<Iterator, expr<Iterator>(const MyContext*), spirit::ascii::space_type> bool_expr;
|
||||
// Evaluate boolean expression into bool.
|
||||
|
|
Loading…
Reference in a new issue