-
Notifications
You must be signed in to change notification settings - Fork 3
/
atom.h
138 lines (104 loc) · 2.67 KB
/
atom.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
133
134
135
136
137
138
#ifndef __TAB_ATOM_H
#define __TAB_ATOM_H
namespace tab {
typedef long Int;
typedef unsigned long UInt;
typedef double Real;
struct String {
size_t ix;
bool operator==(String b) const { return ix == b.ix; }
};
} // namespace tab
namespace std {
template <> struct hash<tab::String> {
size_t operator()(tab::String x) const { return hash<size_t>()(x.ix); }
};
template <> struct hash< std::pair<tab::String, size_t> > {
size_t operator()(const std::pair<tab::String, size_t>& x) const {
return hash<size_t>()(x.first.ix) + hash<size_t>()(x.second);
}
};
} // namespace std
namespace tab {
struct Strings {
std::unordered_map<std::string,size_t> s2i;
std::unordered_map<size_t,std::string> i2s;
String add(const std::string& s) {
auto i = s2i.find(s);
if (i != s2i.end())
return String{i->second};
size_t n = s2i.size() + 1;
s2i.insert(std::make_pair(s, n));
i2s.insert(std::make_pair(n, s));
return String{n};
}
const std::string& get(String s) {
auto i = i2s.find(s.ix);
if (i == i2s.end())
throw std::runtime_error("Sanity error: uninterned string.");
return i->second;
}
};
Strings& strings() {
static Strings ret;
return ret;
}
struct Atom {
enum {
INT = 0,
UINT = 1,
REAL = 2,
STRING = 3
} which;
union {
Int inte;
UInt uint;
Real real;
String str;
};
Atom(Int i = 0) : which(INT), inte(i) {}
Atom(UInt i) : which(UINT), uint(i) {}
Atom(Real i) : which(REAL), real(i) {}
Atom(String i) : which(STRING), str(i) {}
void copy(const Atom& a) {
switch (a.which) {
case INT:
inte = a.inte;
break;
case UINT:
uint = a.uint;
break;
case REAL:
real = a.real;
break;
case STRING:
str = a.str;
break;
};
which = a.which;
}
Atom(const Atom& a) {
copy(a);
}
~Atom() {}
Atom& operator=(const Atom& a) {
copy(a);
return *this;
}
bool is_string() const { return (which == STRING); }
static std::string print(const Atom& a) {
switch (a.which) {
case INT:
return "INT(" + std::to_string(a.inte) + ")";
case UINT:
return "UINT(" + std::to_string(a.uint) + ")";
case REAL:
return "REAL(" + std::to_string(a.real) + ")";
case STRING:
return "STRING(" + strings().get(a.str) + ")";
}
return ":~(";
}
};
} // namespace tab
#endif