Ik probeer een simpele interpreter te programmeren. Ik heb een expression-class en enkele afgeleide classes waarmee ik een zogenaamde expression-tree kan opbouwen. Iedere expression bevat een methode evaluate() die ik kan aanroepen, het zogenaamde interpreter-pattern. Deze methode moet in bepaalde gevallen een waarde teruggeven. Deze waarde kan bijvoorbeeld een int, een float of een functionpointer zijn.
Ik twee oplossing bedacht:
Voorbeeld middels expression-pointer:
Ik twee oplossing bedacht:
- De methode evaluate() geeft een expression-pointer terug die ik vervolgens naar de juiste value cast. Deze methode vereist veel downcasts.
- Een andere oplossing is om een union (met pointers naar values) terug te geven.
Voorbeeld middels expression-pointer:
C++:
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
| class expression { public: enum id_type { // a lot of exppression-id's }; ~virtual expression() { } virtual inline const expression::id_type type() const { return expression::EXPRESSION; } virtual void translate(std::ostream& out) { } virtual expression* evaluate(expression* parent, /* some more arguments */) { } }; class int_value : public expression { public: int_value(int v) : value(v) { } virtual ~int_value() { } virtual inline const expression::id_type type() const { return expression::INT; } virtual void translate(std::ostream& out) { } virtual expression* evaluate(expression* parent) { return this; } void set_value(int v) { value = v; } int get_value() { return value; } private: int value; }; class add_operator : expression { public: add_operator(expression* a, expression* b) : operand_a(a), operand(b) { } virtual ~add_operator() { } virtual inline const expression::id_type type() const { return expression::ADD_OPERATOR; } virtual void translate(std::ostream& out) { } virtual expression* evaluate(expression* parent) { // this part is a bit simplified, some typechecks need to be done first. int a = static_cast<int_value*>(operand_a->evaluate(this))->get_value(); int b = static_cast<int_value*>(operand_b->evaluate(this))->get_value(); return new int_value(a+b); } private: expression* operand_a; expression* operand_b; }; void test() { expression* add1 = new add_operator(new int_value(4),new int_value(3)); expression* add2 = new add_operator(add1,new int_value(5)); expression* add3 = new add_operator(add2,new int_value(3)); std::cout << static_cast<int_value*>(add3->evaluate(NULL))->get_value() << std::endl; // output = 15 } |
PC load letter? What the fuck does that mean?