Skip to content

Commit

Permalink
+ use dedicated exception classes for expression and parsing errors
Browse files Browse the repository at this point in the history
  • Loading branch information
wwmayer committed Sep 27, 2015
1 parent ee28daa commit e959450
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 35 deletions.
5 changes: 3 additions & 2 deletions src/App/DocumentPyImp.cpp
Expand Up @@ -611,8 +611,9 @@ int DocumentPy::setCustomAttributes(const char* attr, PyObject *)
std::stringstream str;
str << "'Document' object attribute '" << attr
<< "' must not be set this way" << std::ends;
throw Py::AttributeError(str.str());
PyErr_SetString(PyExc_RuntimeError, str.str().c_str());
return -1;
}

return 0;
}
66 changes: 33 additions & 33 deletions src/App/Expression.cpp
Expand Up @@ -312,17 +312,17 @@ Expression * OperatorExpression::eval() const
v2 = freecad_dynamic_cast<NumberExpression>(e2.get());

if (v1 == 0 || v2 == 0)
throw Exception("Invalid expression");
throw ExpressionError("Invalid expression");

switch (op) {
case ADD:
if (v1->getUnit() != v2->getUnit())
throw Exception("Incompatible units for + operator");
throw ExpressionError("Incompatible units for + operator");
output = new NumberExpression(owner, v1->getQuantity() + v2->getQuantity());
break;
case SUB:
if (v1->getUnit() != v2->getUnit())
throw Exception("Incompatible units for - operator");
throw ExpressionError("Incompatible units for - operator");
output = new NumberExpression(owner, v1->getQuantity()- v2->getQuantity());
break;
case MUL:
Expand All @@ -337,32 +337,32 @@ Expression * OperatorExpression::eval() const
break;
case EQ:
if (v1->getUnit() != v2->getUnit())
throw Exception("Incompatible units for + operator");
throw ExpressionError("Incompatible units for + operator");
output = new NumberExpression(owner, Quantity(fabs(v1->getValue() - v2->getValue()) < 1e-7));
break;
case NEQ:
if (v1->getUnit() != v2->getUnit())
throw Exception("Incompatible units for + operator");
throw ExpressionError("Incompatible units for + operator");
output = new NumberExpression(owner, Quantity(fabs(v1->getValue() - v2->getValue()) > 1e-7));
break;
case LT:
if (v1->getUnit() != v2->getUnit())
throw Exception("Incompatible units for + operator");
throw ExpressionError("Incompatible units for + operator");
output = new NumberExpression(owner, Quantity(v1->getValue() < v2->getValue()));
break;
case GT:
if (v1->getUnit() != v2->getUnit())
throw Exception("Incompatible units for + operator");
throw ExpressionError("Incompatible units for + operator");
output = new NumberExpression(owner, Quantity(v1->getValue() > v2->getValue()));
break;
case LTE:
if (v1->getUnit() != v2->getUnit())
throw Exception("Incompatible units for + operator");
throw ExpressionError("Incompatible units for + operator");
output = new NumberExpression(owner, Quantity(v1->getValue() - v2->getValue() < 1e-7));
break;
case GTE:
if (v1->getUnit() != v2->getUnit())
throw Exception("Incompatible units for + operator");
throw ExpressionError("Incompatible units for + operator");
output = new NumberExpression(owner, Quantity(v2->getValue() - v1->getValue()) < 1e-7);
break;
case NEG:
Expand Down Expand Up @@ -551,16 +551,16 @@ FunctionExpression::FunctionExpression(const DocumentObject *_owner, Function _f
{
switch (f) {
case NONE:
throw Exception("Unknown function");
throw ExpressionError("Unknown function");
case MOD:
case ATAN2:
case POW:
if (args.size() != 2)
throw Exception("Invalid number of arguments.");
throw ExpressionError("Invalid number of arguments.");
break;
default:
if (args.size() != 1)
throw Exception("Invalid number of arguments.");
throw ExpressionError("Invalid number of arguments.");
break;
}
}
Expand Down Expand Up @@ -596,7 +596,7 @@ bool FunctionExpression::isTouched() const

/**
* Evaluate function. Returns a NumberExpression if evaluation is successfuly.
* Throws an exception if something fails.
* Throws an ExpressionError exception if something fails.
*
* @returns A NumberExpression with the result.
*/
Expand All @@ -612,7 +612,7 @@ Expression * FunctionExpression::eval() const
double scaler = 1;

if (v1 == 0)
throw Exception("Invalid argument.");
throw ExpressionError("Invalid argument.");

double value = v1->getValue();

Expand All @@ -622,7 +622,7 @@ Expression * FunctionExpression::eval() const
case SIN:
case TAN:
if (!(v1->getUnit() == Unit::Angle || v1->getUnit().isEmpty()))
throw Exception("Unit must be either empty or an angle.");
throw ExpressionError("Unit must be either empty or an angle.");

// Convert value to radians
value *= M_PI / 180.0;
Expand All @@ -632,7 +632,7 @@ Expression * FunctionExpression::eval() const
case ASIN:
case ATAN:
if (!v1->getUnit().isEmpty())
throw Exception("Unit must be empty.");
throw ExpressionError("Unit must be empty.");
unit = Unit::Angle;
scaler = 180.0 / M_PI;
break;
Expand All @@ -643,7 +643,7 @@ Expression * FunctionExpression::eval() const
case TANH:
case COSH:
if (!v1->getUnit().isEmpty())
throw Exception("Unit must be empty.");
throw ExpressionError("Unit must be empty.");
unit = Unit();
break;
case ROUND:
Expand All @@ -666,7 +666,7 @@ Expression * FunctionExpression::eval() const
((s.AmountOfSubstance % 2) == 0) &&
((s.LuminoseIntensity % 2) == 0) &&
((s.Angle % 2) == 0))
throw Exception("All dimensions must be even to compute the square root.");
throw ExpressionError("All dimensions must be even to compute the square root.");

unit = Unit(s.Length /2,
s.Mass / 2,
Expand All @@ -680,34 +680,34 @@ Expression * FunctionExpression::eval() const
}
case ATAN2:
if (v2 == 0)
throw Exception("Invalid second argument.");
throw ExpressionError("Invalid second argument.");

if (v1->getUnit() != v2->getUnit())
throw Exception("Units must be equal");
throw ExpressionError("Units must be equal");
unit = Unit::Angle;
scaler = 180.0 / M_PI;
break;
case MOD:
if (v2 == 0)
throw Exception("Invalid second argument.");
throw ExpressionError("Invalid second argument.");
if (!v2->getUnit().isEmpty())
throw Exception("Second argument must have empty unit.");
throw ExpressionError("Second argument must have empty unit.");
unit = v1->getUnit();
break;
case POW: {
if (v2 == 0)
throw Exception("Invalid second argument.");
throw ExpressionError("Invalid second argument.");

if (!v2->getUnit().isEmpty())
throw Exception("Exponent is not allowed to have a unit.");
throw ExpressionError("Exponent is not allowed to have a unit.");

// Compute new unit for exponentation
double exponent = v2->getValue();
if (!v1->getUnit().isEmpty()) {
if (exponent - boost::math::round(exponent) < 1e-9)
unit = v1->getUnit().pow(exponent);
else
throw Exception("Exponent must be an integer when used with a unit");
throw ExpressionError("Exponent must be an integer when used with a unit");
}
break;
}
Expand Down Expand Up @@ -987,7 +987,7 @@ const Property * VariableExpression::getProperty() const
if (prop)
return prop;
else
throw Base::Exception(std::string("Property '") + var.getPropertyName() + std::string("' not found."));
throw ExpressionError(std::string("Property '") + var.getPropertyName() + std::string("' not found."));
}

/**
Expand All @@ -1005,7 +1005,7 @@ Expression * VariableExpression::eval() const
PropertyContainer * parent = prop->getContainer();

if (!parent->isDerivedFrom(App::DocumentObject::getClassTypeId()))
throw Base::Exception("Property must belong to a document object.");
throw ExpressionError("Property must belong to a document object.");

boost::any value = prop->getValue(var);

Expand Down Expand Up @@ -1045,7 +1045,7 @@ Expression * VariableExpression::eval() const
return new StringExpression(owner, svalue);
}

throw Base::Exception("Property is of invalid type.");
throw ExpressionError("Property is of invalid type.");
}

/**
Expand Down Expand Up @@ -1170,7 +1170,7 @@ Expression *ConditionalExpression::eval() const
NumberExpression * v = freecad_dynamic_cast<NumberExpression>(e.get());

if (v == 0)
throw Exception("Invalid expression");
throw ExpressionError("Invalid expression");

if (fabs(v->getValue()) > 0.5)
return trueExpr->eval();
Expand Down Expand Up @@ -1384,10 +1384,10 @@ Expression * App::ExpressionParser::parse(const App::DocumentObject *owner, cons
ExpressionParser::ExpressionParser_delete_buffer (my_string_buffer);

if (result != 0)
throw Base::Exception("Failed to parse expression.");
throw ParserError("Failed to parse expression.");

if (ScanResult == 0)
throw Base::Exception("Unknown error in expression");
throw ParserError("Unknown error in expression");

if (valueExpression)
return ScanResult;
Expand All @@ -1412,10 +1412,10 @@ UnitExpression * ExpressionParser::parseUnit(const App::DocumentObject *owner, c
ExpressionParser::ExpressionParser_delete_buffer (my_string_buffer);

if (result != 0)
throw Base::Exception("Failed to parse expression.");
throw ParserError("Failed to parse expression.");

if (ScanResult == 0)
throw Base::Exception("Unknown error in expression");
throw ParserError("Unknown error in expression");

// Simplify expression
Expression * simplified = ScanResult->simplify();
Expand Down
34 changes: 34 additions & 0 deletions src/Base/Exception.cpp
Expand Up @@ -321,6 +321,40 @@ DivisionByZeroError::DivisionByZeroError(const DivisionByZeroError &inst)

// ---------------------------------------------------------

ExpressionError::ExpressionError(const char * sMessage)
: Exception(sMessage)
{
}

ExpressionError::ExpressionError(const std::string& sMessage)
: Exception(sMessage)
{
}

ExpressionError::ExpressionError(const ExpressionError &inst)
: Exception(inst)
{
}

// ---------------------------------------------------------

ParserError::ParserError(const char * sMessage)
: Exception(sMessage)
{
}

ParserError::ParserError(const std::string& sMessage)
: Exception(sMessage)
{
}

ParserError::ParserError(const ParserError &inst)
: Exception(inst)
{
}

// ---------------------------------------------------------

#if defined(__GNUC__) && defined (FC_OS_LINUX)
#include <stdexcept>
#include <iostream>
Expand Down
33 changes: 33 additions & 0 deletions src/Base/Exception.h
Expand Up @@ -286,6 +286,39 @@ class BaseExport DivisionByZeroError : public Exception
virtual ~DivisionByZeroError() throw() {}
};

/**
* The ExpressionError can be used to indicate erroneous.input
* to the expression engine.
* @author Werner Mayer
*/
class BaseExport ExpressionError : public Exception
{
public:
/// Construction
ExpressionError(const char * sMessage);
ExpressionError(const std::string& sMessage);
/// Construction
ExpressionError(const ExpressionError &inst);
/// Destruction
virtual ~ExpressionError() throw() {}
};

/**
* The ParserError can be used to indicate the parsing error.
* @author Werner Mayer
*/
class BaseExport ParserError : public Exception
{
public:
/// Construction
ParserError(const char * sMessage);
ParserError(const std::string& sMessage);
/// Construction
ParserError(const ParserError &inst);
/// Destruction
virtual ~ParserError() throw() {}
};


inline void Exception::setMessage(const char * sMessage)
{
Expand Down

0 comments on commit e959450

Please sign in to comment.