A simple scripting language in C++
Ferenc Szontágh
2025-04-19 26263ab9055d2ce4f6b1ec934949bcea240b1f29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <memory>
#include <string>
 
#include "ExpressionNode.hpp"
 
namespace Interpreter {
class BinaryExpressionNode : public ExpressionNode {
    std::unique_ptr<ExpressionNode> lhs_;
    std::unique_ptr<ExpressionNode> rhs_;
    std::string                     op_;
 
  public:
    BinaryExpressionNode(std::unique_ptr<ExpressionNode> lhs, std::string op, std::unique_ptr<ExpressionNode> rhs) :
        lhs_(std::move(lhs)),
        rhs_(std::move(rhs)),
        op_(std::move(op)) {}
 
    Symbols::Value evaluate(Interpreter & interpreter) const override {
        auto leftVal  = lhs_->evaluate(interpreter);
        auto rightVal = rhs_->evaluate(interpreter);
        if (leftVal.getType() != rightVal.getType()) {
            throw std::runtime_error(
                "Unsupported types in binary expression: " + Symbols::Variables::TypeToString(leftVal.getType()) +
                " and " + Symbols::Variables::TypeToString(rightVal.getType()) + " " + toString());
        }
        if (leftVal.getType() == Symbols::Variables::Type::BOOLEAN &&
            rightVal.getType() == Symbols::Variables::Type::BOOLEAN) {
            bool l = leftVal.get<bool>();
            bool r = rightVal.get<bool>();
 
            if (op_ == "&&") {
                return Symbols::Value(l && r);
            }
            if (op_ == "||") {
                return Symbols::Value(l || r);
            }
            if (op_ == "==") {
                return Symbols::Value(l == r);
            }
            if (op_ == "!=") {
                return Symbols::Value(l != r);
            }
 
            throw std::runtime_error("Unknown operator: " + op_);
        }
 
        if (leftVal.getType() == Symbols::Variables::Type::INTEGER &&
            rightVal.getType() == Symbols::Variables::Type::INTEGER) {
            int l = leftVal.get<int>();
            int r = rightVal.get<int>();
 
            if (op_ == "+") {
                return Symbols::Value(l + r);
            }
            if (op_ == "-") {
                return Symbols::Value(l - r);
            }
            if (op_ == "*") {
                return Symbols::Value(l * r);
            }
            if (op_ == "/") {
                return Symbols::Value(l / r);  // TODO: 0 div
            }
            if (op_ == "%") {
                return Symbols::Value(l % r);
            }
            if (op_ == "==") {
                return Symbols::Value(l == r);
            }
            if (op_ == "!=") {
                return Symbols::Value(l != r);
            }
            if (op_ == "<") {
                return Symbols::Value(l < r);
            }
            if (op_ == ">") {
                return Symbols::Value(l > r);
            }
            if (op_ == "<=") {
                return Symbols::Value(l <= r);
            }
            if (op_ == ">=") {
                return Symbols::Value(l >= r);
            }
 
            throw std::runtime_error("Unknown operator: " + op_);
        }
 
        if (leftVal.getType() == Symbols::Variables::Type::STRING &&
            rightVal.getType() == Symbols::Variables::Type::STRING) {
            auto l = leftVal.get<std::string>();
            auto r = rightVal.get<std::string>();
 
            if (op_ == "+") {
                return Symbols::Value(l + r);
            }
            if (op_ == "==") {
                return Symbols::Value(l == r);
            }
            if (op_ == "!=") {
                return Symbols::Value(l != r);
            }
            throw std::runtime_error("Unknown operator: " + op_);
        }
 
        throw std::runtime_error(
            "Unsupported types in binary expression: " + Symbols::Variables::TypeToString(leftVal.getType()) + " and " +
            Symbols::Variables::TypeToString(rightVal.getType()) + " " + toString());
    }
 
    std::string toString() const override { return "(" + lhs_->toString() + " " + op_ + " " + rhs_->toString() + ")"; }
};
 
};  // namespace Interpreter