diff --git a/main.cxx b/main.cxx index a1fdfe7..3dc8e00 100644 --- a/main.cxx +++ b/main.cxx @@ -1,8 +1,16 @@ +// Include necessary C++ standard library headers. #include +#include #include +#include #include #include +// Conditional compilation based on ENABLE_TESTS macro. +#ifdef ENABLE_TESTS +#include +#endif + // Abstract Syntax Tree (AST) Node base class class ASTNode { public: @@ -24,7 +32,7 @@ class ASTNode { // Virtual functions for evaluation and type retrieval. virtual double evaluate() const = 0; virtual ASTNode::Type getType() const = 0; - virtual ~ASTNode() {} + virtual ~ASTNode() = default; }; // Constant Node class @@ -41,6 +49,9 @@ class Constant : public ASTNode { // Implementation of evaluate for Constant node. double evaluate() const override { return value; } + + // Getter function for the constant value. + double getValue() const { return value; } }; // Identifier Node class @@ -76,17 +87,23 @@ class Identifier : public ASTNode { // Unary Node base class class Unary : public ASTNode { protected: - const ASTNode *operand; + std::unique_ptr operand; public: // Constructor for Unary node. - explicit Unary(const ASTNode *operand) : operand(operand) {} + explicit Unary(std::unique_ptr operand) : operand(std::move(operand)) {} // Implementation of getType for Unary node. - ASTNode::Type getType() const override { return ASTNode::Type::Unary; } + ASTNode::Type getType() const = 0; + + // Getter function to access the operand. + const ASTNode &getInput() { return *operand; } + + // Function to release ownership of the operand. + std::unique_ptr releaseInput() { return std::move(operand); } // Virtual destructor for Unary node. - virtual ~Unary() { delete operand; } + virtual ~Unary() = default; }; // UnaryPlus Node class @@ -116,21 +133,27 @@ class UnaryMinus : public Unary { // Binary Node base class class Binary : public ASTNode { protected: - const ASTNode *left; - const ASTNode *right; + std::unique_ptr left; + std::unique_ptr right; public: // Constructor for Binary node. - Binary(const ASTNode *left, const ASTNode *right) : left(left), right(right) {} + Binary(std::unique_ptr left, std::unique_ptr right) + : left(std::move(left)), right(std::move(right)) {} + + // Getter functions to access left and right operands. + const ASTNode &getLeft() { return *left; } + const ASTNode &getRight() { return *right; } + + // Functions to release ownership of left and right operands. + std::unique_ptr releaseLeft() { return std::move(left); } + std::unique_ptr releaseRight() { return std::move(right); } // Implementation of getType for Binary node. ASTNode::Type getType() const override { return ASTNode::Type::Binary; } // Virtual destructor for Binary node. - virtual ~Binary() { - delete left; - delete right; - } + virtual ~Binary() = default; }; // Add Node class @@ -202,23 +225,62 @@ class Power : public Binary { // Static initialization of variableTable in Identifier class. std::unordered_map Identifier::variableTable; -// Main function -int main() { - // Setting variables in the variableTable. - Identifier::setVariable("Num1", 3.0); - Identifier::setVariable("Num2", 7.0); +#ifdef ENABLE_TESTS +// Function to run a test expression evaluation. +void runTest() { + // Test with a complex expression: (2 * (a + b)) / (c - 1) ^ (d + 1) + Identifier::setVariable("a", 3.0); + Identifier::setVariable("b", 1.0); + Identifier::setVariable("c", 5.0); + Identifier::setVariable("d", 2.0); - // Creating an expression tree. - ASTNode *expression = new Add(new UnaryMinus(new Identifier("Num1")), - new Multiply(new Constant(2), new Subtract(new Constant(4), new Identifier("Num2")))); + std::unique_ptr variableA = std::make_unique("a"); + std::unique_ptr variableB = std::make_unique("b"); + std::unique_ptr variableC = std::make_unique("c"); + std::unique_ptr variableD = std::make_unique("d"); - // Evaluating the expression and printing the result. + std::unique_ptr expression = std::make_unique( + std::make_unique(std::make_unique(2.0), + std::make_unique(std::move(variableA), std::move(variableB))), + std::make_unique(std::make_unique(std::move(variableC), std::make_unique(1.0)), + std::make_unique(std::move(variableD), std::make_unique(1.0)))); + + // Evaluate the expression double result = expression->evaluate(); - std::cout << "Result: " << result << std::endl; - // Deleting the expression and clearing variables. - delete expression; + // Expected result: (2 * (3 + 1)) / (5 - 1) ^ (2 + 1) = 8 / 4 ^ 3 = 8 / 64 = + // 0.125 + assert(result == 0.125); + + std::cout << "Test passed successfully. Result: " << result << std::endl; + + // Clear variables for the next test Identifier::clearVariables(); +} +#endif // ENABLE_TESTS + +// Function to print the help message. +void printHelpMessage(const char *programName) { + std::cout << "Usage: " << programName << " [--run-test]\n" + << "Options:\n" + << " --run-test Run the test for the expression evaluation code.\n" + << " This option should be used without any additional " + "arguments.\n" + << " Example: " << programName << " --run-test\n"; +} + +// Main function +int main(int argc, char *argv[]) { + // Check if the "--run-test" argument is provided + if (argc == 2 && std::strcmp(argv[1], "--run-test") == 0) { +#ifdef ENABLE_TESTS + // Run the test if ENABLE_TESTS is defined + runTest(); +#endif // ENABLE_TESTS + } else { + // Print help message if no valid arguments are provided + printHelpMessage(argv[0]); + } return 0; }