use std::fmt;
#[derive(Debug, Clone, PartialEq)]
pub enum CalcError {
TooMany,
BadLiteral,
ParenNotOpen,
ParenOpen,
Conditional,
Incomplete,
Underflow,
Overflow,
Syntax,
NullArg,
Internal,
DivisionByZero,
BadSeparator,
BadAssignment,
TypeMismatch,
LengthMismatch,
InvalidFormat,
LoopLimitExceeded,
EmptyArray,
InvalidSubrange,
BracketNotOpen,
BraceNotOpen,
}
impl fmt::Display for CalcError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CalcError::TooMany => write!(f, "Too many results returned"),
CalcError::BadLiteral => write!(f, "Badly formed numeric literal"),
CalcError::ParenNotOpen => write!(f, "Close parenthesis found without open"),
CalcError::ParenOpen => write!(f, "Parenthesis still open at end of expression"),
CalcError::Conditional => write!(f, "Unbalanced conditional ?: operators"),
CalcError::Incomplete => write!(f, "Incomplete expression, operand missing"),
CalcError::Underflow => write!(f, "Not enough operands provided"),
CalcError::Overflow => write!(f, "Runtime stack would overflow"),
CalcError::Syntax => write!(f, "Syntax error, unknown operator/operand"),
CalcError::NullArg => write!(f, "NULL or empty input argument"),
CalcError::Internal => write!(f, "Internal error"),
CalcError::DivisionByZero => write!(f, "Division by zero"),
CalcError::BadSeparator => write!(f, "Comma without enclosing parentheses"),
CalcError::BadAssignment => write!(f, "Bad assignment target"),
CalcError::TypeMismatch => write!(f, "Type mismatch: mixed numeric/string operation"),
CalcError::LengthMismatch => write!(f, "Array length mismatch in binary operation"),
CalcError::InvalidFormat => write!(f, "Invalid format string"),
CalcError::LoopLimitExceeded => write!(f, "Loop iteration limit exceeded"),
CalcError::EmptyArray => write!(f, "Operation on empty array"),
CalcError::InvalidSubrange => write!(f, "Invalid subrange specification"),
CalcError::BracketNotOpen => write!(f, "Close bracket found without open"),
CalcError::BraceNotOpen => write!(f, "Close brace found without open"),
}
}
}
impl std::error::Error for CalcError {}
impl CalcError {
pub fn code(&self) -> i16 {
match self {
CalcError::TooMany => 1,
CalcError::BadLiteral => 2,
CalcError::BadAssignment => 3,
CalcError::BadSeparator => 4,
CalcError::ParenNotOpen | CalcError::BracketNotOpen | CalcError::BraceNotOpen => 5,
CalcError::ParenOpen => 6,
CalcError::Conditional => 7,
CalcError::Incomplete => 8,
CalcError::Underflow => 9,
CalcError::Overflow | CalcError::LoopLimitExceeded => 10,
CalcError::Syntax
| CalcError::DivisionByZero
| CalcError::TypeMismatch
| CalcError::LengthMismatch
| CalcError::InvalidFormat
| CalcError::EmptyArray
| CalcError::InvalidSubrange => 11,
CalcError::NullArg => 12,
CalcError::Internal => 13,
}
}
}
pub fn calc_error_str(error: i16) -> Option<&'static str> {
const ERR_STRS: [&str; 14] = [
"No error",
"Too many results returned",
"Badly formed numeric literal",
"Bad assignment target",
"Comma without enclosing parentheses",
"Close parenthesis found without open",
"Parenthesis still open at end of expression",
"Unbalanced conditional ?: operators",
"Incomplete expression, operand missing",
"Not enough operands provided",
"Runtime stack overflow",
"Syntax error, unknown operator/operand",
"NULL or empty input argument to postfix()",
"Internal error, unknown element type",
];
if !(0..=13).contains(&error) {
return None;
}
Some(ERR_STRS[error as usize])
}