← index
cplusplus17.Examples/examples/tree/tree.cpp
Source: cplusplus17.Examples/examples/tree/tree.cpp
// Practice creating a tree.
// Than moving through the tree and solving the expression

#include<iostream>
#include<string>
#include<unordered_map>

struct Symbol {
    double value;
    std::string name;
};

enum class Var_type { EMPTY, DIGIT, VARIABLE, PLUS, EQUAL};

std::unordered_map<std::string, Symbol> symbols;

template<typename T>
class Node {
public:
    T token;
    double value;
    Var_type id;
    Node<T> *left, *right;
    Node() : id(Var_type::EMPTY), left(nullptr), right(nullptr) {}
    Node(const T &n_token, Var_type n_id, Node<T> *n_left, Node<T> *n_right) {
        token = n_token;
        id = n_id;
        left = n_left;
        right = n_right;
    }
};

template<typename T>
class Tree {
public:
    Node<T> *root;
    
    Tree() {
        root = new Node<T>("Root", Var_type::EMPTY, nullptr, nullptr);
    }
    ~Tree() {
        release(root);
    }
    
    void print() {
        printNodes(root);
    }
    
    double eval(Node<T> *node) {
        if(node == nullptr) return 0;
        std::cout << node->token << " current Node..\n";
        double v = 0;
    
        switch(node->id) {
            case Var_type::EQUAL: {
                v = eval(node->right);
                symbols[node->left->token].value = v;
                std::cout << node->left->token << " = " << v << "\n";
            }
                break;
            case Var_type::PLUS: {
                double op1 = eval(node->left);
                double op2 = eval(node->right);
                std::cout << op1 << "+" << op2 << "\n";
                return op1+op2;
            }
                break;
            case Var_type::VARIABLE:
                v = symbols[node->token].value;
                std::cout << "Var Value: " << v << "\n";
                break;
            case Var_type::DIGIT:
                v = node->value;
                std::cout << "Value: " << v << "\n";
                break;
            case Var_type::EMPTY:
                break;
        }
        return v;
    }
    
private:
    void printNodes(Node<T> *n) {
        if(n != nullptr)
            std::cout << "Node: " << n->token << ":" << static_cast<char>(n->id) << "\n";
        
        if(n->left != nullptr)
            printNodes(n->left);
        
        if(n->right != nullptr)
            printNodes(n->right);
    }
    
    void release(Node<T> *n) {
        if(n->left != nullptr)
            release(n->left);
        if(n->right != nullptr)
            release(n->right);
        if(n != 0) {
            std::cout << "releasing: " << n->token << "\n";
            delete n;
        }
    }
};

void add_token(std::string name, double value) {
    symbols[name].name = name;
    symbols[name].value = value;
}

int main() {
    // add some leaves to the tree
    Tree<std::string> assign;
    Node<std::string> *node;
    assign.root->id = Var_type::EQUAL;
    assign.root->token = "=";
    assign.root->left = new Node<std::string>("x", Var_type::VARIABLE, nullptr, nullptr);
    assign.root->right = new Node<std::string>("+", Var_type::PLUS, nullptr, nullptr);
    node = assign.root->right;
    node->left = new Node<std::string>("10", Var_type::DIGIT, nullptr, nullptr);
    node->left->value = 10;
    node->right = new Node<std::string>("+", Var_type::PLUS, nullptr, nullptr);
    node = node->right;
    node->left = new Node<std::string>("x", Var_type::VARIABLE, nullptr, nullptr);
    node->right = new Node<std::string>("y", Var_type::VARIABLE, nullptr, nullptr);
    // print the leaves
    assign.print();
    // put some variables in symbol table
    add_token("x", 25);
    add_token("y", 50);
    // evaluate 
    double val = assign.eval(assign.root);
    std::cout << "value: " << val << "\n";
    return 0;
}