PlaceholderParser: Improved error reporting https://github.com/prusa3d/Slic3r/issues/600

Fixed '+' operator for strings.
This commit is contained in:
bubnikv 2017-12-05 17:38:29 +01:00
parent 8746f84fa2
commit c34ec9b7d3
2 changed files with 57 additions and 45 deletions

View file

@ -815,9 +815,9 @@ std::string GCode::placeholder_parser_process(const std::string &name, const std
this->m_placeholder_parser_failed_templates.insert(name); this->m_placeholder_parser_failed_templates.insert(name);
// Insert the macro error message into the G-code. // Insert the macro error message into the G-code.
return return
std::string("!!!!! Failed to process the custom G-code template ") + name + "\n" + std::string("\n!!!!! Failed to process the custom G-code template ") + name + "\n" +
err.what() + err.what() +
"!!!!! End of an error report for the custom G-code template " + name + "\n"; "!!!!! End of an error report for the custom G-code template " + name + "\n\n";
} }
} }

View file

@ -280,22 +280,31 @@ namespace client
expr &operator+=(const expr &rhs) expr &operator+=(const expr &rhs)
{ {
const char *err_msg = "Cannot multiply with non-numeric type."; if (this->type == TYPE_STRING) {
this->throw_if_not_numeric(err_msg); // Convert the right hand side to string and append.
rhs.throw_if_not_numeric(err_msg); *this->data.s += rhs.to_string();
if (this->type == TYPE_DOUBLE || rhs.type == TYPE_DOUBLE) { } else if (rhs.type == TYPE_STRING) {
double d = this->as_d() + rhs.as_d(); // Conver the left hand side to string, append rhs.
this->data.d = d; this->data.s = new std::string(this->to_string() + rhs.s());
this->type = TYPE_DOUBLE; this->type = TYPE_STRING;
} else } else {
this->data.i += rhs.i(); const char *err_msg = "Cannot add non-numeric types.";
this->throw_if_not_numeric(err_msg);
rhs.throw_if_not_numeric(err_msg);
if (this->type == TYPE_DOUBLE || rhs.type == TYPE_DOUBLE) {
double d = this->as_d() + rhs.as_d();
this->data.d = d;
this->type = TYPE_DOUBLE;
} else
this->data.i += rhs.i();
}
this->it_range = boost::iterator_range<Iterator>(this->it_range.begin(), rhs.it_range.end()); this->it_range = boost::iterator_range<Iterator>(this->it_range.begin(), rhs.it_range.end());
return *this; return *this;
} }
expr &operator-=(const expr &rhs) expr &operator-=(const expr &rhs)
{ {
const char *err_msg = "Cannot multiply with non-numeric type."; const char *err_msg = "Cannot subtract non-numeric types.";
this->throw_if_not_numeric(err_msg); this->throw_if_not_numeric(err_msg);
rhs.throw_if_not_numeric(err_msg); rhs.throw_if_not_numeric(err_msg);
if (this->type == TYPE_DOUBLE || rhs.type == TYPE_DOUBLE) { if (this->type == TYPE_DOUBLE || rhs.type == TYPE_DOUBLE) {
@ -578,39 +587,42 @@ namespace client
} }
template <typename Iterator> template <typename Iterator>
static void process_error_message(const MyContext *context, const boost::spirit::info &info, const Iterator &it_begin, const Iterator &it_end) 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)
{ {
struct expectation_printer
{
expectation_printer(std::string &msg) : result(msg) {}
std::string &result;
void element(std::string const& tag, std::string const& value, int depth)
{
// Indent to depth.
for (int i = 0; i < depth * 4; ++ i)
result += ' ';
if (tag.empty() || tag.front() != '*') {
if (depth == 0)
this->result += "Expecting ";
this->result += "tag: ";
this->result += tag;
} else
this->result += tag.substr(1);
if (! value.empty()) {
this->result += ", value: ";
this->result += value;
}
this->result += '\n';
}
};
std::string &msg = const_cast<MyContext*>(context)->error_message; std::string &msg = const_cast<MyContext*>(context)->error_message;
msg += "Error! "; std::string first(it_begin, it_error);
expectation_printer ep(msg); std::string last(it_error, it_end);
spirit::basic_info_walker<expectation_printer> walker(ep, info.tag, 0); auto first_pos = first.rfind('\n');
boost::apply_visitor(walker, info.value); auto last_pos = last.find('\n');
msg += " got: \""; int line_nr = 1;
msg += std::string(it_begin, it_end) + "\"\n"; if (first_pos == std::string::npos)
first_pos = 0;
else {
// Calculate the current line number.
for (size_t i = 0; i <= first_pos; ++ i)
if (first[i] == '\n')
++ line_nr;
++ first_pos;
}
auto error_line = std::string(first, first_pos) + std::string(last, 0, last_pos);
// Position of the it_error from the start of its line.
auto error_pos = (it_error - it_begin) - first_pos;
msg += "Parsing error at line " + std::to_string(line_nr);
if (! info.tag.empty() && info.tag.front() == '*') {
// The gat contains an explanatory string.
msg += ": ";
msg += info.tag.substr(1);
} else {
// A generic error report based on the nonterminal or terminal symbol name.
msg += ". Expecting tag ";
msg += info.tag;
}
msg += '\n';
msg += error_line;
msg += '\n';
for (size_t i = 0; i < error_pos; ++ i)
msg += ' ';
msg += "^\n";
} }
}; };
@ -733,7 +745,7 @@ namespace client
// Without it, some of the errors would not trigger the error handler. // Without it, some of the errors would not trigger the error handler.
start = eps > text_block(_r1); start = eps > text_block(_r1);
start.name("start"); start.name("start");
qi::on_error<qi::fail>(start, px::bind(&MyContext::process_error_message<Iterator>, _r1, _4, _3, _2)); qi::on_error<qi::fail>(start, px::bind(&MyContext::process_error_message<Iterator>, _r1, _4, _1, _2, _3));
text_block = *( text_block = *(
text [_val+=_1] text [_val+=_1]