1 /*
2 * (C) Copyright 2001-2015 Diomidis Spinellis
3 *
4 * This file is part of CScout.
5 *
6 * CScout is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * CScout is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with CScout. If not, see <http://www.gnu.org/licenses/>.
18 *
19 *
20 * A token identifier.
21 * This uniquelly identifies any token (part).
22 * It is used to compose input tokens, symbol table antries,
23 * as a map source for equivalence classes, and as a member in
24 * equivalence classes.
25 *
26 * Rationale: the program works by assigning tokens to equivalence
27 * classes. Each class must know its tokens, and each token its
28 * equivalence class. Because equivalence classes can be merged and split
29 * it is easier, instead of maintaining two-way relationships between ECs
30 * and their tokens, to have a fixed way to represent EC contents,
31 * and identifier EC membership. Tokids satisfy this property, because
32 * they remain constant and with the same meaining throughout the program's
33 * lifetime.
34 *
35 */
36
37 #ifndef TOKID_
38 #define TOKID_
39
40 #include <deque>
41 #include <map>
42
43 using namespace std;
44
45 #include "cpp.h"
46 #include "fileid.h"
47
48 class Eclass;
49
50 class Tokid;
51 class Tpart;
52 typedef deque <Tokid> dequeTokid;
53 typedef deque <Tpart> dequeTpart;
54
55 class Tokid;
56 typedef map <Tokid, Eclass *> mapTokidEclass;
57
58 class Tokid {
59 #ifdef PICO_QL
60 public:
61 #else
62 private:
63 #endif
64 static mapTokidEclass tm; // Map from tokens to their equivalence
65 private:
66 // classes
67 Fileid fi; // File
68 cs_offset_t offs; // Offset
69 public:
70 // Construct it, based on the fileid and offset in that file
Tokid(Fileid i,streampos l)71 Tokid(Fileid i, streampos l) : fi(i), offs((cs_offset_t)l) {};
72 // Construct it uninitialised to be filled-in later
Tokid()73 Tokid() {}
74 // Return a tokid that uniquely represents all same tokids coming from identical files
75 // (The first element of the identical files set is invariant)
76 Tokid unique() const;
77 // Print it (for debugging)
78 friend ostream& operator<<(ostream& o,const Tokid t);
79 inline friend bool operator ==(const class Tokid a, const class Tokid b);
80 inline friend bool operator !=(const class Tokid a, const class Tokid b);
81 inline friend bool operator <(const class Tokid a, const class Tokid b);
82 inline friend bool operator <=(const class Tokid a, const class Tokid b);
83 inline friend bool operator >=(const class Tokid a, const class Tokid b);
84 // Advance i character positions
85 inline Tokid& operator +=(int i);
86 inline friend Tokid operator +(const Tokid& a, int i);
87 // Advance one position
88 inline Tokid operator ++(int); // Int signifies postfix (Str97 11.11 p. 292)
89 // Return offset distance
90 inline friend int operator -(const Tokid& a, const Tokid& b);
91 // Return its equivalence class
92 inline Eclass *get_ec() const;
93 // Return its equivalence class or NULL if none
94 inline Eclass *check_ec() const;
95 // Set its equivalence class to ec (done when adding it to an Eclass)
96 // use Eclass:add_tokid, not this method in all other contexts
97 inline void set_ec(Eclass *ec) const;
98 // Return an iterator for accessing the map or the end_ec() value
99 inline mapTokidEclass::iterator find_ec() const;
100 // The not-found value
101 inline mapTokidEclass::iterator end_ec();
102 // Erase the tokid's EC from the map
103 inline void erase_ec(mapTokidEclass::iterator i) const;
104 inline void erase_ec(Eclass *e) const;
105 // Returns the Tokids participating in all ECs for a token of length l
106 dequeTpart constituents(int l);
107 // Set the Tokid's equivalence class attribute
108 void set_ec_attribute(enum e_attribute a, int len) const;
109 // Return true if one of the tokid's ECs has the specified attribute
110 bool has_ec_attribute(enum e_attribute a, int l) const;
111 // Clear the map of tokid equivalence classes
112 static void clear();
113 // Print the contents of the class map
114 friend ostream& operator<<(ostream& o,const map <Tokid, Eclass *>& dummy);
115 // Return true if the underlying file is read-only
get_readonly()116 bool get_readonly() const { return fi.get_readonly(); }
117 // Accessor functions
get_path()118 inline const string& get_path() const { return fi.get_path(); }
get_fileid()119 inline Fileid get_fileid() const { return fi; }
get_streampos()120 inline streampos get_streampos() const { return (streampos)offs; }
map_size()121 static map <Tokid, Eclass *>::size_type map_size() { return tm.size(); }
122 };
123
124 // Print dequeTokid sequences
125 ostream& operator<<(ostream& o,const dequeTokid& dt);
126
127 extern mapTokidEclass tokid_map; // Dummy; used for printing
128
129 inline Tokid
130 operator +(const Tokid& a, int i)
131 {
132 Tokid r = a;
133
134 return (r += i);
135 }
136
137 inline int
138 operator -(const Tokid& a, const Tokid &b)
139 {
140 return (a.offs - b.offs);
141 }
142
143 inline Tokid&
144 Tokid::operator +=(int i)
145 {
146 offs += i;
147 return (*this);
148 }
149
150 inline Tokid
151 Tokid::operator ++(int dummy)
152 {
153 offs++;
154 return (*this);
155 }
156
157 inline bool
158 operator ==(const class Tokid a, const class Tokid b)
159 {
160 return (a.fi == b.fi && a.offs == b.offs);
161 }
162
163 inline bool
164 operator !=(const class Tokid a, const class Tokid b)
165 {
166 return (!(a == b));
167 }
168
169
170 inline bool
171 operator <(const class Tokid a, const class Tokid b)
172 {
173 if (a.fi == b.fi)
174 return (a.offs < b.offs);
175 else
176 return (a.fi < b.fi);
177 }
178
179 inline bool
180 operator <=(const class Tokid a, const class Tokid b)
181 {
182 return a < b || a == b;
183 }
184
185 inline bool
186 operator >=(const class Tokid a, const class Tokid b)
187 {
188 return b < a || a == b;
189 }
190
191 inline Eclass *
get_ec()192 Tokid::get_ec() const
193 {
194 return tm[*this];
195 }
196
197 inline Eclass *
check_ec()198 Tokid::check_ec() const
199 {
200 mapTokidEclass::const_iterator i = tm.find(*this);
201 if (i == tm.end())
202 return NULL;
203 else
204 return ((*i).second);
205 }
206
207 inline void
set_ec(Eclass * ec)208 Tokid::set_ec(Eclass *ec) const
209 {
210 /*
211 * tm[*this] = ec;
212 * Efficiently implement the functionality we need.
213 * See Meyers Effective STL, Item 24.
214 */
215 mapTokidEclass::iterator i = tm.lower_bound(*this);
216 if (i != tm.end() && i->first == *this)
217 i->second = ec;
218 else
219 tm.insert(i, mapTokidEclass::value_type(*this, ec));
220 }
221
222 inline void
erase_ec(mapTokidEclass::iterator i)223 Tokid::erase_ec(mapTokidEclass::iterator i) const
224 {
225 tm.erase(i);
226 }
227
228 inline void
erase_ec(Eclass * e)229 Tokid::erase_ec(Eclass *e) const
230 {
231 mapTokidEclass::iterator i = tm.find(*this);
232 csassert(i != tm.end());
233 tm.erase(i);
234 }
235
236 inline mapTokidEclass::iterator
find_ec()237 Tokid::find_ec() const
238 {
239 return tm.find(*this);
240 }
241
242 inline mapTokidEclass::iterator
end_ec()243 Tokid::end_ec()
244 {
245 return tm.end();
246 }
247 #endif /* TOKID_ */
248