throw exception(err.str()); \
} while (0)
+#define Parse_error_(message) \
+do { \
+ std::ostringstream err; \
+ err << "GiNaC: parse error at line " << scanner->line_num << \
+ ", column " << scanner->column << ": "; \
+ err << message << std::endl; \
+ err << '[' << __PRETTY_FUNCTION__ << "(" << __FILE__ << ':' << __LINE__ << ")]" << std::endl; \
+ throw parse_error(err.str(), scanner->line_num, scanner->column); \
+} while (0)
+
+#define Parse_error(message) \
+ Parse_error_(message << ", got: " << scanner->tok2str(token))
+
#define bug(message) bail_out(std::logic_error, message)
#define dout(condition, message) \
c = ' ';
}
+/// Symbolic name of current token (for error reporting)
+std::string lexer::tok2str(const int tok) const
+{
+ switch (tok) {
+ case lexer::token_type::identifier:
+ case lexer::token_type::number:
+ return std::string("\"") + str + "\"";
+ case lexer::token_type::eof:
+ return std::string("EOF");
+ default:
+ return std::string("\"") + char(tok) + "\"";
+ }
+}
+
} // namespace GiNaC
};
};
+
+ /// Symbolic name of the token (for error reporting)
+ std::string tok2str(const int tok) const;
};
} // namespace GiNaC
break;
if (token != ',')
- throw std::invalid_argument("Expected ')' or ',' in argument list");
+ Parse_error("expected ')' or ',' in argument list");
get_next_tok();
}
prototype the_prototype = make_pair(name, args.size());
prototype_table::const_iterator reader = funcs.find(the_prototype);
if (reader == funcs.end()) {
- bail_out(std::invalid_argument,
- "no function \"" << name << "\" with " << args.size()
- << " arguments");
+ Parse_error_("no function \"" << name << "\" with " <<
+ args.size() << " arguments");
}
ex ret = reader->second(args);
return ret;
ex e = parse_expression();
if (token != ')')
- throw std::invalid_argument("parser::parse_paren_expr: expected ')'");
+ Parse_error("expected ')'");
get_next_tok(); // eat ).
return e;
}
case '+':
return v;
default:
- throw std::invalid_argument(
- std::string(__func__)
- + ": invalid unary operator \""
- + char(s) + "\"");
+ Parse_error_("invalid unary operator \"" << char(s) << "\"");
}
}
case lexer::token_type::literal:
return parse_literal_expr();
case lexer::token_type::eof:
- bail_out(std::invalid_argument, "got EOF while parsing the expression");
default:
- bail_out(std::invalid_argument, "unknown token " <<
- token << " (\"" <<
- (token ? std::string("") + char(token) : "NULL")
- << "\")");
+ Parse_error("unexpected token");
}
}
class lexer;
+class parse_error : public std::invalid_argument
+{
+public:
+ const std::size_t line;
+ const std::size_t column;
+ parse_error(const std::string& what_,
+ const std::size_t line_ = 0,
+ const std::size_t column_ = 0) throw () :
+ std::invalid_argument(what_), line(line_), column(column_)
+ { }
+};
+
/**
* Recursive descent parser for GiNaC expressions.
*/