cliard24 0.1.2

cliard24 is a command-line 24-point card game. It provides two main functions: the game mode allows you to play the classic 24-point game interactively in the terminal, where you randomly draw 4 cards and use addition, subtraction, multiplication, division, and parentheses to reach 24; the solve mode lets you input any combination of numbers and a target value to calculate all possible expression solutions. The tool supports customizable attempt limits, endless mode, solution count limits, and mixed input of card letters (A/J/Q/K) and numbers.
Documentation
//! Error types for the expression Abstract Syntax Tree module.
//!
//! Comprehensive error handling covering parsing failures, invalid expression structures,
//! arithmetic errors (division by zero, precision loss), and evaluation issues.

use std::num::ParseFloatError;
use thiserror::Error;

use crate::expression::ast::ExprNum;

/// All possible errors that can occur during AST operations.
#[derive(Error, Debug)]
pub enum AstError<'a> {
    // Expression parsing errors
    /// Failed to parse a string as a numeric literal.
    ///
    /// # Fields
    ///
    /// * `input` - The invalid input string
    /// * `source` - Underlying ParseFloatError
    #[error("Failed to parse '{input}' as a number: {source}")]
    ParseLiteralError {
        /// The input string that failed to parse
        input: &'a str,
        /// The underlying parse error from the standard library
        #[source]
        source: ParseFloatError,
    },

    /// Encountered an unknown operator symbol.
    #[error("Unknown operator: '{0}'")]
    UnknownOperator(&'a str),

    /// Syntax error with unexpected token at specific position.
    #[error("Syntax error: unexpected token '{token}' at position {position}")]
    SyntaxError {
        /// The unexpected token encountered
        token: &'a str,
        /// Character position where the error occurred
        position: usize,
    },

    /// Attempted to access a node with invalid index.
    #[error("Invalid node index: {index} (total nodes: {total_nodes})")]
    InvalidNodeIndex {
        /// The invalid index that was requested
        index: usize,
        /// Total number of nodes available
        total_nodes: usize,
    },

    /// Attempted to access a precomputed value with invalid index.
    #[error("Invalid pre-value index: {index} (total pre-value: {total_nodes})")]
    InvalidPrecalcIndex {
        /// The invalid index that was requested
        index: usize,
        /// Total number of pre-calculated values available
        total_nodes: usize,
    },

    // Expression structure errors
    /// Unmatched parentheses in expression.
    #[error("Unmatched parentheses")]
    UnmatchedParentheses,

    /// Operator received incorrect number of operands.
    ///
    /// # Fields
    ///
    /// * `operator` - The operator symbol
    /// * `expected` - Expected operand count (always 2 for binary operators)
    /// * `actual` - Actual operand count received
    #[error("Operator '{operator}' expects {expected} operands, but received {actual}")]
    InvalidOperandCount {
        /// The operator that caused the error
        operator: &'a str,
        /// Expected number of operands
        expected: usize,
        /// Actual number of operands available
        actual: usize,
    },

    /// Expression tree is empty.
    #[error("Empty expression")]
    EmptyExpression,

    /// General error during expression evaluation.
    #[error("Expression evaluation error: {0}")]
    ExpressionEvaluationError(&'a str),

    /// Invalid structure detected in expression.
    #[error("Invalid expression structure: {0}")]
    InvalidExpressionStructure(&'a str),

    // Arithmetic computation errors
    /// Division by zero attempted.
    #[error("Division by zero")]
    DivisionByZero,

    /// Calculation result is a subnormal number (precision loss).
    #[error("The calculation result '{0}' is abnormal")]
    CalculationResultError(ExprNum),

    // Variable errors
    /// Variable was not provided a value during evaluation.
    #[error("The evaluated variable '{0}' has not been initialized")]
    UninitializedVariable(&'a str),
}