-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcalculate.h
132 lines (115 loc) · 3.73 KB
/
calculate.h
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#ifndef CALCULATE_H
#define CALCULATE_H
#include "syntaxnodes.h"
class SymTable;
template <class T>
class CalculateConstExpr {
private:
Position Pos;
SymTable* Table;
string TypeName;
T CalculateUnarConstExpr(ExprUnarOp* Exp);
T CalculateBinConstExpr(ExprBinOp* Exp);
T CalculateArrayIndex(ExprArrayIndex* Exp);
template <class X_1, class X_2 = T> void CheckType();
public:
T Ans;
T Calculate(Expr* Exp);
CalculateConstExpr(SymTable* Table, string TypeName, Position Pos);
};
template <class T> CalculateConstExpr<T>::CalculateConstExpr(SymTable* Table, string TypeName, Position Pos) : Table(Table), TypeName(TypeName), Pos(Pos){}
template <class T> T CalculateConstExpr<T>::Calculate(Expr* Exp) {
switch (Exp->TypeExp) {
case VarExp:
return Calculate(((SymVar*)Table->GetSymbol(((ExprIdent*)Exp)->Sym->Name.c_str(), Pos))->InitExp);
case ConstIntExp:
CheckType<int>();
return atoi(((ExprIntConst*)Exp)->Value.Source.c_str());
case ConstDoubleExp:
CheckType<int, double>();
return atof(((ExprDoubleConst*)Exp)->Value.Source.c_str());
case ConstBoolExp:
CheckType<bool>();
return _strnicmp(((ExprBoolConst*)Exp)->Value.Source.c_str(), "true", 4) == 0 ? true : false;
case ConstStringExp:
if (((ExprStringConst*)Exp)->Value.Source.size() > 1) {
throw BadType("DOUBLE\" || \"INTEGER\" || \"BOOL", Pos);
}
else {
return atoi(((ExprStringConst*)Exp)->Value.Source.c_str());
}
case BinExp:
return CalculateBinConstExpr((ExprBinOp*)Exp);
case UnarExp:
return CalculateUnarConstExpr((ExprUnarOp*)Exp);
case ArrayExp:
return CalculateArrayIndex((ExprArrayIndex*)Exp);
}
}
template <class T> T CalculateConstExpr<T>::CalculateUnarConstExpr(ExprUnarOp* Exp) {
switch (Exp->Op.Type) {
case TK_MINUS:
CheckType<int, double>();
return - Calculate(Exp->Exp);
case TK_PLUS:
CheckType<int, double>();
return + Calculate(Exp->Exp);
case TK_NOT:
return ! Calculate(Exp->Exp);
}
}
template <class T> T CalculateConstExpr<T>::CalculateBinConstExpr(ExprBinOp* Exp) {
switch (Exp->Op.Type) {
case TK_PLUS:
CheckType<int, double>();
return Calculate(Exp->Left) + Calculate(Exp->Right);
case TK_MINUS:
CheckType<int, double>();
return Calculate(Exp->Left) - Calculate(Exp->Right);
case TK_MUL:
CheckType<int, double>();
return Calculate(Exp->Left) * Calculate(Exp->Right);
case TK_DIV_INT:
CheckType<int>();
case TK_DIV:
return Calculate(Exp->Left) / Calculate(Exp->Right);
case TK_MOD:
CheckType<int>();
return (int)Calculate(Exp->Left) % (int)Calculate(Exp->Right);
case TK_XOR:
CheckType<int>();
return (int)Calculate(Exp->Left) ^ (int)Calculate(Exp->Right);
case TK_AND:
CheckType<int>();
return (int)Calculate(Exp->Left) & (int)Calculate(Exp->Right);
case TK_OR:
CheckType<int>();
return (int)Calculate(Exp->Left) | (int)Calculate(Exp->Right);
case TK_SHL:
CheckType<int>();
return (int)Calculate(Exp->Left) << (int)Calculate(Exp->Right);
case TK_SHR:
CheckType<int>();
return (int)Calculate(Exp->Left) >> (int)Calculate(Exp->Right);
}
}
template <class T> T CalculateConstExpr<T>::CalculateArrayIndex(ExprArrayIndex* Exp) {
Expr* IdentExp = Exp;
vector<int> idxs;
while (IdentExp->TypeExp != VarExp) {
idxs.push_back(Calculate(((ExprArrayIndex*)IdentExp)->Right));
IdentExp = ((ExprArrayIndex*)IdentExp)->Left;
}
ExprInitList* ExpList = (ExprInitList*)((SymConst*)Table->GetSymbol(((ExprIdent*)IdentExp)->Sym->Name.c_str(), Pos))->InitExp;
IdentExp = Exp;
for (int i = idxs.size() - 1; i >= 0; --i) {
ExpList = (ExprInitList*)ExpList->List[idxs[i]];
}
return Calculate(ExpList);
}
template <class T> template <class X_1, class X_2 = T> void CalculateConstExpr<T>::CheckType() {
if (!is_same<X_1, T>::value && !is_same<X_2, T>::value) {
throw BadType(TypeName, Pos);
}
}
#endif