Fixed a 32bit build bug in the new PlaceholderParser macro processor.

This commit is contained in:
bubnikv 2017-11-29 19:27:26 +01:00
parent da8ffd477d
commit ae118519ab
2 changed files with 43 additions and 28 deletions

View file

@ -1,4 +1,4 @@
use Test::More tests => 48; use Test::More tests => 49;
use strict; use strict;
use warnings; use warnings;
@ -66,6 +66,7 @@ use Slic3r::Test;
is $parser->process('{2*(3-12)}'), '-18', 'math: 2*(3-12)'; is $parser->process('{2*(3-12)}'), '-18', 'math: 2*(3-12)';
is $parser->process('{2*foo*(3-12)}'), '0', 'math: 2*foo*(3-12)'; is $parser->process('{2*foo*(3-12)}'), '0', 'math: 2*foo*(3-12)';
is $parser->process('{2*bar*(3-12)}'), '-36', 'math: 2*bar*(3-12)'; is $parser->process('{2*bar*(3-12)}'), '-36', 'math: 2*bar*(3-12)';
ok abs($parser->process('{2.5*bar*(3-12)}') - -45) < 1e-7, 'math: 2.5*bar*(3-12)';
} }
{ {

View file

@ -145,7 +145,7 @@ namespace client
template<typename Iterator> template<typename Iterator>
struct expr struct expr
{ {
expr() : type(TYPE_EMPTY) { data.s = nullptr; } expr() { this->reset(); }
explicit expr(bool b) : type(TYPE_BOOL) { data.b = b; } explicit expr(bool b) : type(TYPE_BOOL) { data.b = b; }
explicit expr(bool b, const Iterator &it_begin, const Iterator &it_end) : type(TYPE_BOOL), it_range(it_begin, it_end) { data.b = b; } explicit expr(bool b, const Iterator &it_begin, const Iterator &it_end) : type(TYPE_BOOL), it_range(it_begin, it_end) { data.b = b; }
explicit expr(int i) : type(TYPE_INT) { data.i = i; } explicit expr(int i) : type(TYPE_INT) { data.i = i; }
@ -156,33 +156,39 @@ namespace client
explicit expr(const std::string &s) : type(TYPE_STRING) { data.s = new std::string(s); } explicit expr(const std::string &s) : type(TYPE_STRING) { data.s = new std::string(s); }
explicit expr(const std::string &s, const Iterator &it_begin, const Iterator &it_end) : explicit expr(const std::string &s, const Iterator &it_begin, const Iterator &it_end) :
type(TYPE_STRING), it_range(it_begin, it_end) { data.s = new std::string(s); } type(TYPE_STRING), it_range(it_begin, it_end) { data.s = new std::string(s); }
expr(const expr &rhs) : type(rhs.type) { data.s = (rhs.type == TYPE_STRING) ? new std::string(*rhs.data.s) : rhs.data.s; } expr(const expr &rhs) : type(rhs.type), it_range(rhs.it_range)
explicit expr(expr &&rhs) : type(rhs.type) { data.s = rhs.data.s; rhs.data.s = nullptr; rhs.type = TYPE_EMPTY; } { if (rhs.type == TYPE_STRING) data.s = new std::string(*rhs.data.s); else data.set(rhs.data); }
explicit expr(expr &&rhs) : type(rhs.type), it_range(rhs.it_range)
{ data.set(rhs.data); rhs.type = TYPE_EMPTY; }
explicit expr(expr &&rhs, const Iterator &it_begin, const Iterator &it_end) : type(rhs.type), it_range(it_begin, it_end) explicit expr(expr &&rhs, const Iterator &it_begin, const Iterator &it_end) : type(rhs.type), it_range(it_begin, it_end)
{ data.s = rhs.data.s; rhs.data.s = nullptr; rhs.type = TYPE_EMPTY; } { data.set(rhs.data); rhs.type = TYPE_EMPTY; }
~expr() { this->reset(); } ~expr() { this->reset(); }
expr &operator=(const expr &rhs) expr &operator=(const expr &rhs)
{ {
type = rhs.type; this->type = rhs.type;
data.s = (type == TYPE_STRING) ? new std::string(*rhs.data.s) : rhs.data.s; this->it_range = rhs.it_range;
if (rhs.type == TYPE_STRING)
this->data.s = new std::string(*rhs.data.s);
else
this->data.set(rhs.data);
return *this; return *this;
} }
expr &operator=(expr &&rhs) expr &operator=(expr &&rhs)
{ {
type = rhs.type; type = rhs.type;
data.s = rhs.data.s; this->it_range = rhs.it_range;
rhs.data.s = nullptr; data.set(rhs.data);
rhs.type = TYPE_EMPTY; rhs.type = TYPE_EMPTY;
return *this; return *this;
} }
void reset() void reset()
{ {
if (this->type == TYPE_STRING) if (this->type == TYPE_STRING)
delete data.s; delete data.s;
data.s = nullptr; memset(data.raw, 0, sizeof(data.raw));
this->type = TYPE_EMPTY; this->type = TYPE_EMPTY;
} }
@ -210,15 +216,23 @@ namespace client
case TYPE_INT: out = boost::to_string(data.i); break; case TYPE_INT: out = boost::to_string(data.i); break;
case TYPE_DOUBLE: out = boost::to_string(data.d); break; case TYPE_DOUBLE: out = boost::to_string(data.d); break;
case TYPE_STRING: out = *data.s; break; case TYPE_STRING: out = *data.s; break;
default: break;
} }
return out; return out;
} }
union { union Data {
// Raw image of the other data members.
// The C++ compiler will consider a possible aliasing of char* with any other union member,
// therefore copying the raw data is safe.
char raw[8];
bool b; bool b;
int i; int i;
double d; double d;
std::string *s; std::string *s;
// Copy the largest member variable through char*, which will alias with all other union members by default.
void set(const Data &rhs) { memcpy(this->raw, rhs.raw, sizeof(rhs.raw)); }
} data; } data;
enum Type { enum Type {
@ -386,7 +400,7 @@ namespace client
std::ostream& operator<<(std::ostream &os, const expr<ITERATOR> &expression) std::ostream& operator<<(std::ostream &os, const expr<ITERATOR> &expression)
{ {
typedef expr<ITERATOR> Expr; typedef expr<ITERATOR> Expr;
os << std::string(expression.it_range.begin(), expression.it_range.end()) << ' - '; os << std::string(expression.it_range.begin(), expression.it_range.end()) << " - ";
switch (expression.type) { switch (expression.type) {
case Expr::TYPE_EMPTY: os << "empty"; break; case Expr::TYPE_EMPTY: os << "empty"; break;
case Expr::TYPE_BOOL: os << "bool (" << expression.b() << ")"; break; case Expr::TYPE_BOOL: os << "bool (" << expression.b() << ")"; break;
@ -588,7 +602,7 @@ namespace client
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Our calculator grammar // Our calculator grammar
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Inspired by the C grammar https://www.lysator.liu.se/c/ANSI-C-grammar-y.html // Inspired by the C grammar rules https://www.lysator.liu.se/c/ANSI-C-grammar-y.html
template <typename Iterator> template <typename Iterator>
struct calculator : qi::grammar<Iterator, std::string(const MyContext*), spirit::ascii::space_type> struct calculator : qi::grammar<Iterator, std::string(const MyContext*), spirit::ascii::space_type>
{ {
@ -644,7 +658,7 @@ namespace client
macro = macro =
(kw["if"] > if_else_output(_r1) [_val = _1]) (kw["if"] > if_else_output(_r1) [_val = _1])
| (kw["switch"] > switch_output(_r1) [_val = _1]) | (kw["switch"] > switch_output(_r1) [_val = _1])
| expression(_r1) [ px::bind(&expr<Iterator>::to_string2, _1, _val) ]; | additive_expression(_r1) [ px::bind(&expr<Iterator>::to_string2, _1, _val) ];
macro.name("macro"); macro.name("macro");
// An if expression enclosed in {} (the outmost {} are already parsed by the caller). // An if expression enclosed in {} (the outmost {} are already parsed by the caller).
@ -683,10 +697,10 @@ namespace client
identifier.name("identifier"); identifier.name("identifier");
bool_expr = bool_expr =
expression(_r1) [_val = _1] additive_expression(_r1) [_val = _1]
>> *( ("==" > expression(_r1) ) [px::bind(&expr<Iterator>::equal, _val, _1)] >> *( ("==" > additive_expression(_r1) ) [px::bind(&expr<Iterator>::equal, _val, _1)]
| ("!=" > expression(_r1) ) [px::bind(&expr<Iterator>::not_equal, _val, _1)] | ("!=" > additive_expression(_r1) ) [px::bind(&expr<Iterator>::not_equal, _val, _1)]
| ("<>" > expression(_r1) ) [px::bind(&expr<Iterator>::not_equal, _val, _1)] | ("<>" > additive_expression(_r1) ) [px::bind(&expr<Iterator>::not_equal, _val, _1)]
); );
bool_expr.name("bool expression"); bool_expr.name("bool expression");
@ -695,12 +709,12 @@ namespace client
bool_expr_eval = bool_expr(_r1) [ px::bind(&expr<Iterator>::evaluate_boolean, _1, _val) ]; bool_expr_eval = bool_expr(_r1) [ px::bind(&expr<Iterator>::evaluate_boolean, _1, _val) ];
bool_expr_eval.name("bool_expr_eval"); bool_expr_eval.name("bool_expr_eval");
expression = additive_expression =
term(_r1) [_val = _1] term(_r1) [_val = _1]
>> *( (lit('+') > term(_r1) ) [_val += _1] >> *( (lit('+') > term(_r1) ) [_val += _1]
| (lit('-') > term(_r1) ) [_val -= _1] | (lit('-') > term(_r1) ) [_val -= _1]
); );
expression.name("expression"); additive_expression.name("additive_expression");
term = term =
factor(_r1) [_val = _1] factor(_r1) [_val = _1]
@ -729,14 +743,14 @@ namespace client
}; };
factor = iter_pos[px::bind(&FactorActions::set_start_pos, _1, _val)] >> ( factor = iter_pos[px::bind(&FactorActions::set_start_pos, _1, _val)] >> (
scalar_variable_reference(_r1) [ _val = _1 ] scalar_variable_reference(_r1) [ _val = _1 ]
| (lit('(') > expression(_r1) > ')' > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ] | (lit('(') > additive_expression(_r1) > ')' > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ]
| (lit('-') > factor(_r1) ) [ px::bind(&FactorActions::minus_, _1, _val) ] | (lit('-') > factor(_r1) ) [ px::bind(&FactorActions::minus_, _1, _val) ]
| (lit('+') > factor(_r1) > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ] | (lit('+') > factor(_r1) > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ]
| ((kw["not"] | '!') > factor(_r1) > iter_pos) [ px::bind(&FactorActions::not_, _1, _val) ] | ((kw["not"] | '!') > factor(_r1) > iter_pos) [ px::bind(&FactorActions::not_, _1, _val) ]
| (strict_double > iter_pos) [ px::bind(&FactorActions::double_, _1, _2, _val) ] | (strict_double > iter_pos) [ px::bind(&FactorActions::double_, _1, _2, _val) ]
| (int_ > iter_pos) [ px::bind(&FactorActions::int_, _1, _2, _val) ] | (int_ > iter_pos) [ px::bind(&FactorActions::int_, _1, _2, _val) ]
| (kw[bool_] > iter_pos) [ px::bind(&FactorActions::bool_, _1, _2, _val) ] | (kw[bool_] > iter_pos) [ px::bind(&FactorActions::bool_, _1, _2, _val) ]
| raw[lexeme['"' > *(char_ - char_('\\') - char_('"') | ('\\' > char_)) > '"']] | raw[lexeme['"' > *((char_ - char_('\\') - char_('"')) | ('\\' > char_)) > '"']]
[ px::bind(&FactorActions::string_, _1, _val) ] [ px::bind(&FactorActions::string_, _1, _val) ]
); );
factor.name("factor"); factor.name("factor");
@ -744,7 +758,7 @@ namespace client
scalar_variable_reference = scalar_variable_reference =
variable_reference(_r1)[_a=_1] >> variable_reference(_r1)[_a=_1] >>
( (
('[' > expression(_r1)[px::bind(&MyContext::evaluate_index<Iterator>, _1, _b)] > ']' > ('[' > 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)]) 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)] | eps[px::bind(&MyContext::scalar_variable_reference<Iterator>, _r1, _a, _val)]
); );
@ -787,7 +801,7 @@ namespace client
debug(identifier); debug(identifier);
debug(bool_expr); debug(bool_expr);
debug(bool_expr_eval); debug(bool_expr_eval);
debug(expression); debug(additive_expression);
debug(term); debug(term);
debug(factor); debug(factor);
debug(scalar_variable_reference); debug(scalar_variable_reference);
@ -808,7 +822,7 @@ namespace client
// Parsed identifier name. // 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. // Math expression consisting of +- operators over terms.
qi::rule<Iterator, expr<Iterator>(const MyContext*), spirit::ascii::space_type> expression; qi::rule<Iterator, expr<Iterator>(const MyContext*), spirit::ascii::space_type> additive_expression;
// Boolean expressions over expressions. // Boolean expressions over expressions.
qi::rule<Iterator, expr<Iterator>(const MyContext*), spirit::ascii::space_type> bool_expr; qi::rule<Iterator, expr<Iterator>(const MyContext*), spirit::ascii::space_type> bool_expr;
// Evaluate boolean expression into bool. // Evaluate boolean expression into bool.