Line data Source code
1 : #include <iostream>
2 : #include <cstring>
3 : #include <vector>
4 : #include "config.hpp"
5 : #include "common/tables.hpp"
6 : #include "common/obstacle.hpp"
7 : #include "common/exprtype.hpp"
8 : //#include "common/util.hpp"
9 :
10 236 : bool charEqual(const char* a, const char* b) {
11 236 : bool ret = true;
12 236 : int i = 0;
13 780 : while (ret && (a[i] != '\0') && (b[i] != '\0')) {
14 544 : ret = ret && (a[i] == b[i]);
15 544 : i++;
16 : }
17 236 : ret = ret && (a[i] == '\0') && (b[i] == '\0');
18 236 : return ret;
19 : }
20 :
21 841 : IdentTable::IdentTable(void) {
22 841 : valType = _NONE_;
23 841 : structName = nullptr;
24 841 : name = nullptr;
25 841 : fadedName = nullptr;
26 841 : def = false;
27 841 : func = false;
28 841 : reg = false;
29 841 : val = nullptr;
30 841 : ord = 0;
31 841 : params = 0;
32 841 : offset = 0;
33 841 : next = nullptr;
34 841 : shared = false;
35 841 : mainTable = nullptr;
36 841 : }
37 :
38 96 : IdentTable::IdentTable(const IdentTable & templateIT) {
39 96 : valType = templateIT.valType;
40 96 : def = templateIT.def;
41 96 : ord = templateIT.ord;
42 96 : offset = templateIT.offset;
43 96 : func = templateIT.func;
44 96 : reg = templateIT.reg;
45 96 : params = templateIT.params;
46 96 : shared = templateIT.shared;
47 96 : mainTable = templateIT.mainTable;
48 :
49 96 : if (templateIT.structName != nullptr) {
50 6 : structName = new char[strnlen(templateIT.structName, MAXIDENT) + 1];
51 6 : memccpy(structName, templateIT.structName, '\0', strnlen(templateIT.structName, MAXIDENT) + 1);
52 90 : } else structName = nullptr;
53 :
54 96 : if (templateIT.name != nullptr) {
55 96 : name = new char[strnlen(templateIT.name, MAXIDENT) + 1];
56 96 : memccpy(name, templateIT.name, '\0', strnlen(templateIT.name, MAXIDENT) + 1);
57 0 : } else name = nullptr;
58 :
59 96 : if (templateIT.fadedName != nullptr) {
60 0 : fadedName = new char[strnlen(templateIT.fadedName, MAXIDENT) + 1];
61 0 : memccpy(fadedName, templateIT.fadedName, '\0', strnlen(templateIT.fadedName, MAXIDENT) + 1);
62 96 : } else fadedName = nullptr;
63 :
64 96 : if (templateIT.valType == _STRUCT_)
65 6 : val = new IdentTable( * static_cast<IdentTable *>(templateIT.val));
66 90 : else val = templateIT.val;
67 :
68 96 : if (templateIT.next->getType() != _NONE_)
69 60 : next = new IdentTable(*templateIT.next);
70 36 : else next = new IdentTable;
71 96 : }
72 :
73 0 : IdentTable & IdentTable::operator=(const IdentTable & templateIT) {
74 0 : if (this == &templateIT) return *this;
75 :
76 0 : valType = templateIT.valType;
77 0 : def = templateIT.def;
78 0 : ord = templateIT.ord;
79 0 : offset = templateIT.offset;
80 0 : func = templateIT.func;
81 0 : reg = templateIT.reg;
82 0 : params = templateIT.params;
83 0 : shared = templateIT.shared;
84 0 : mainTable = templateIT.mainTable;
85 :
86 0 : if (templateIT.structName != nullptr) {
87 0 : structName = new char[strnlen(templateIT.structName, MAXIDENT) + 1];
88 0 : memccpy(structName, templateIT.structName, '\0', strnlen(templateIT.structName, MAXIDENT) + 1);
89 0 : } else structName = nullptr;
90 :
91 0 : if (templateIT.name != nullptr) {
92 0 : name = new char[strnlen(templateIT.name, MAXIDENT) + 1];
93 0 : memccpy(name, templateIT.name, '\0', strnlen(templateIT.name, MAXIDENT) + 1);
94 0 : } else name = nullptr;
95 :
96 0 : if (templateIT.fadedName != nullptr) {
97 0 : fadedName = new char[strnlen(templateIT.fadedName, MAXIDENT) + 1];
98 0 : memccpy(fadedName, templateIT.fadedName, '\0', strnlen(templateIT.fadedName, MAXIDENT) + 1);
99 0 : } else fadedName = nullptr;
100 :
101 0 : if (templateIT.valType == _STRUCT_)
102 0 : val = new IdentTable( * static_cast<IdentTable *>(templateIT.val));
103 0 : else val = templateIT.val;
104 :
105 0 : if (templateIT.next->getType() != _NONE_)
106 0 : next = new IdentTable(*templateIT.next);
107 0 : else next = new IdentTable;
108 :
109 0 : return *this;
110 : }
111 :
112 : // Получаем последний объект списка
113 1998 : IdentTable * IdentTable::last(void) {
114 1998 : IdentTable * p = this;
115 19583 : while (p->next != nullptr) p = p->next;
116 1998 : return p;
117 : }
118 :
119 : // Сохраняем идентификатор переменной
120 400 : void IdentTable::pushId(char* ident) {
121 400 : IdentTable * p = this;
122 3912 : while (p->next != nullptr) {
123 3513 : if ((p->name != nullptr) && (ident != nullptr) && (strcmp(p->name, ident) == 0)) {
124 1 : delete [] ident;
125 1 : throw Obstacle(IDENT_DUP);
126 : }
127 3512 : p = p->next;
128 : }
129 399 : p->name = ident;
130 399 : }
131 :
132 : // Сохраняем тип переменной
133 633 : void IdentTable::pushType(type_t t) {
134 633 : last()->valType = t;
135 633 : }
136 :
137 23 : void IdentTable::pushStruct(char * name) {
138 23 : last()->structName = name;
139 23 : }
140 :
141 : // Сохраняем значение переменной
142 435 : void IdentTable::pushVal(void* v) {
143 435 : IdentTable * l = last();
144 435 : l->val = v;
145 435 : l->def = true;
146 435 : }
147 :
148 : // Всё, что могло быть известно, мы узнали. Переключаемся на новый объект.
149 687 : IdentTable * IdentTable::confirm(void) {
150 687 : IdentTable * l = last();
151 :
152 : #ifdef DEBUG
153 : std::cout << "Создан новый объект: ";
154 : l->whoami();
155 : std::cout << std::endl;
156 : #endif
157 :
158 687 : IdentTable * newIdent = new IdentTable;
159 687 : l->next = newIdent;
160 687 : l->next->ord = l->ord + 1;
161 687 : newIdent->mainTable = l->mainTable;
162 :
163 687 : return l;
164 : }
165 :
166 : // Дублирование типа для выражений вида:
167 : // int a, b, c;
168 122 : void IdentTable::dupType(void) {
169 122 : IdentTable * p = this;
170 122 : if (last()->valType == _NONE_) {
171 172 : while (p->next->next != nullptr) p = p->next;
172 33 : p->next->valType = p->valType;
173 33 : p->next->shared = p->shared;
174 33 : if (p->structName != nullptr) {
175 7 : p->next->structName = new char[strnlen(p->structName, MAXIDENT) + 1];
176 7 : memccpy(p->next->structName, p->structName, '\0', strnlen(p->structName, MAXIDENT) + 1);
177 : }
178 33 : if (p->valType == _STRUCT_) {
179 7 : p->next->val = new IdentTable(* static_cast<IdentTable *>(p->val));
180 7 : p = static_cast<IdentTable *>(p->next->val);
181 30 : while (p->next != nullptr) {
182 23 : if (p->valType != _STRUCT_)
183 21 : p->val = nullptr;
184 23 : p->def = false;
185 23 : p = p->next;
186 : }
187 : }
188 : }
189 122 : }
190 :
191 1171 : type_t IdentTable::getType(void) const {
192 1171 : return valType;
193 : }
194 :
195 22 : void IdentTable::setType(type_t newType) {
196 22 : valType = newType;
197 22 : }
198 :
199 65 : char * IdentTable::getStruct(void) const {
200 65 : return structName;
201 : }
202 :
203 26 : void IdentTable::setFunc(void) {
204 26 : func = true;
205 26 : }
206 :
207 268 : bool IdentTable::isFunc(void) const {
208 268 : return func;
209 : }
210 :
211 20 : void IdentTable::setOrd(int x) {
212 20 : ord = x;
213 20 : }
214 :
215 29 : void IdentTable::setReg(bool x) {
216 29 : reg = x;
217 29 : }
218 :
219 903 : bool IdentTable::isReg(void) const {
220 903 : return reg;
221 : }
222 :
223 24 : void IdentTable::setParams(int x) {
224 24 : params = x;
225 24 : }
226 :
227 20 : int IdentTable::getParams(void) const {
228 20 : return params;
229 : }
230 :
231 512 : IdentTable * IdentTable::getIT(char * name, bool autodel) {
232 512 : IdentTable * p = this;
233 :
234 2584 : while ((p->name == nullptr) || (strcmp(p->name, name) != 0)) {
235 2088 : if (p->next->valType != _NONE_) p = p->next;
236 : else {
237 16 : if (autodel) delete [] name;
238 16 : throw Obstacle(IDENT_NOT_DEF);
239 : }
240 : }
241 :
242 496 : delete [] name;
243 :
244 496 : return p;
245 : }
246 :
247 0 : void IdentTable::whoami() {
248 :
249 0 : std::cout << '[' << typetostr(valType) << ' ';
250 0 : if (valType == _STRUCT_) {
251 0 : std::cout << structName << ' ';
252 0 : if (name != nullptr) std::cout << name;
253 0 : else std::cout << "? ";
254 0 : if (func) std::cout << "FUNCTION ";
255 0 : std::cout << " = [";
256 0 : IdentTable * fields = static_cast<IdentTable *>(val);
257 0 : while (fields->next != nullptr) {
258 0 : fields->whoami();
259 0 : fields = fields->next;
260 : }
261 0 : std::cout << " ]";
262 : } else {
263 0 : if (func) std::cout << "FUNCTION ";
264 0 : if (name != nullptr)
265 0 : std::cout << name;
266 0 : if (fadedName != nullptr)
267 0 : std::cout << '(' << fadedName << ") ";
268 0 : if (func) std::cout << " (params num: " << params << ")";
269 0 : else if (def) {
270 0 : std::cout << "= ";
271 0 : switch (valType) {
272 0 : case _INT_: case _LABEL_:
273 0 : std::cout << * static_cast<int *> ( val ); break;
274 0 : case _REAL_:
275 0 : std::cout << * static_cast<float *>( val ); break;
276 0 : case _STRING_:
277 0 : std::cout << static_cast<char *> ( val ); break;
278 0 : case _BOOLEAN_:
279 0 : std::cout << * static_cast<bool *> ( val ); break;
280 0 : default:
281 0 : std::cout << "?"; break;
282 : }
283 0 : } else std::cout << "= ?";
284 : }
285 0 : std::cout << ']';
286 :
287 0 : }
288 :
289 0 : void IdentTable::repr(void) {
290 0 : IdentTable * p = this;
291 0 : std::cout << "IdentTable:" << std::endl;
292 0 : while (p->next != nullptr) {
293 0 : std::cout << p << " ";
294 0 : p->whoami();
295 0 : std::cout << std::endl;
296 0 : p = p->next;
297 : }
298 0 : }
299 :
300 38 : void IdentTable::setId(char * name) {
301 38 : if (this->name != nullptr) delete [] this->name;
302 38 : this->name = name;
303 38 : }
304 :
305 11 : char * IdentTable::getId(void) const {
306 11 : return this->name;
307 : }
308 :
309 292 : void * IdentTable::getVal(void) const {
310 292 : return val;
311 : }
312 :
313 155 : void IdentTable::setVal(void * val) {
314 155 : this->val = val;
315 155 : def = true;
316 155 : }
317 :
318 436 : void IdentTable::setOffset(int x) {
319 436 : offset = x;
320 436 : }
321 :
322 675 : int IdentTable::getOffset(void) const {
323 675 : return offset;
324 : }
325 :
326 87 : int IdentTable::getOrd(void) const {
327 87 : return ord;
328 : }
329 :
330 410 : void IdentTable::writeValToStream(std::ostream & s) {
331 410 : if (func) return;
332 :
333 394 : if (!def) {
334 118 : switch (valType) {
335 58 : case _INT_: case _LABEL_:
336 58 : val = new int (0); break;
337 30 : case _REAL_:
338 30 : val = new float (0); break;
339 9 : case _STRING_:
340 9 : val = new char[1];
341 9 : static_cast<char*>(val)[0] = '\0';
342 9 : break;
343 12 : case _BOOLEAN_:
344 12 : val = new bool (false); break;
345 9 : case _STRUCT_: break;
346 0 : default:
347 0 : throw Obstacle(PANIC);
348 : }
349 118 : def = true;
350 : }
351 : IdentTable * ITp;
352 394 : switch (valType) {
353 225 : case _INT_: case _LABEL_:
354 225 : s.write(static_cast<char*>(val), sizeof(int)); break;
355 44 : case _REAL_:
356 44 : s.write(static_cast<char*>(val), sizeof(float)); break;
357 73 : case _STRING_:
358 73 : s.write("\0\0\0\0\0\0\0\0", sizeof(void*));
359 73 : s.write(static_cast<char*>(val), sizeof(char) * (strlen(static_cast<char*>(val)) + 1));
360 73 : break;
361 24 : case _BOOLEAN_:
362 24 : s.write(static_cast<char*>(val), sizeof(bool)); break;
363 28 : case _STRUCT_:
364 28 : ITp = static_cast<IdentTable*>(val);
365 109 : while (ITp->next != nullptr) {
366 81 : ITp->setOffset((int)s.tellp());
367 81 : ITp->writeValToStream(s);
368 81 : ITp = ITp->next;
369 : }
370 28 : break;
371 0 : default:
372 0 : throw Obstacle(PANIC);
373 : }
374 : }
375 :
376 29 : IdentTable * IdentTable::deleteLabels(void) {
377 29 : IdentTable *p = this, *head = this, *temp;
378 :
379 29 : while ((p->next != nullptr) && (p->next->valType == _LABEL_))
380 0 : p = p->next;
381 :
382 29 : if (head->valType == _LABEL_)
383 29 : head = p->next;
384 :
385 29 : p = head;
386 :
387 29 : if (p == nullptr) return p;
388 :
389 383 : while (p->next != nullptr) {
390 354 : if (p->next->valType == _LABEL_) {
391 103 : temp = p->next;
392 103 : p->next = p->next->next;
393 103 : temp->next = nullptr;
394 103 : delete temp;
395 251 : } else p = p->next;
396 : }
397 :
398 29 : return head;
399 : }
400 :
401 118 : bool IdentTable::isDef(void) const {
402 118 : return def;
403 : }
404 :
405 4104 : bool operator==(IdentTable & a, IdentTable & b) {
406 4104 : if (&a == &b) return true;
407 :
408 4104 : if ((a.name == nullptr) && (b.name == nullptr)) {
409 2777 : if (a.valType != b.valType) return false;
410 929 : if ((a.val == nullptr) && (b.val == nullptr))
411 20 : return true;
412 909 : if ((a.val == nullptr) || (b.val == nullptr))
413 105 : return false;
414 : bool ret;
415 804 : switch (a.valType) {
416 219 : case _INT_:
417 219 : ret = ((*static_cast<int *>(a.val)) == (*static_cast<int *>(b.val)));
418 219 : break;
419 2 : case _REAL_:
420 2 : ret = ((*static_cast<float *>(a.val)) == (*static_cast<float *>(b.val)));
421 2 : break;
422 116 : case _STRING_:
423 116 : ret = charEqual(static_cast<char *>(a.val), static_cast<char *>(b.val));
424 116 : break;
425 1 : case _BOOLEAN_:
426 1 : ret = ((*static_cast<bool *>(a.val)) == (*static_cast<bool *>(b.val)));
427 1 : break;
428 466 : default:
429 466 : ret = false;
430 : }
431 804 : return ret;
432 : }
433 :
434 1327 : if ((a.name != nullptr) && (b.name != nullptr))
435 120 : return charEqual(a.name, b.name);
436 :
437 1207 : return false;
438 : }
439 :
440 138 : void IdentTable::fade(void) {
441 138 : fadedName = name;
442 138 : name = nullptr;
443 138 : }
444 :
445 292 : bool IdentTable::isShared(void) const {
446 292 : return shared;
447 : }
448 :
449 10 : void IdentTable::setShared(void) {
450 10 : shared = true;
451 10 : }
452 :
453 355 : void IdentTable::setMainTable(IdentTable* table) {
454 355 : mainTable = table;
455 355 : if (structName != nullptr) {
456 33 : static_cast<IdentTable*>(val)->setMainTable(table);
457 : }
458 355 : if (next != nullptr) {
459 205 : next->setMainTable(table);
460 : }
461 355 : }
462 :
463 38 : IdentTable* IdentTable::getMainTable(void) {
464 38 : return mainTable;
465 : }
466 :
467 1 : void IdentTable::setStruct(char * name) {
468 1 : structName = name;
469 1 : }
470 :
471 1874 : IdentTable::~IdentTable() {
472 937 : if (name != nullptr) delete [] name;
473 937 : if (fadedName != nullptr) delete [] fadedName;
474 :
475 937 : if ((val != nullptr) && (!func)) {
476 690 : switch (valType) {
477 475 : case _INT_: case _LABEL_:
478 475 : delete static_cast<int *>( val ); break;
479 46 : case _REAL_:
480 46 : delete static_cast<float *>( val ); break;
481 26 : case _BOOLEAN_:
482 26 : delete static_cast<bool *>( val ); break;
483 107 : case _STRING_:
484 107 : delete [] static_cast<char *>( val ); break;
485 36 : case _STRUCT_:
486 36 : delete static_cast<IdentTable*>(val); break;
487 0 : default: break;
488 : }
489 : }
490 937 : if (structName != nullptr) delete [] structName;
491 :
492 937 : if (next != nullptr) delete next;
493 937 : }
494 :
495 69 : StructTable * StructTable::last(void) {
496 69 : StructTable * p = this;
497 92 : while (p->next != nullptr) p = p->next;
498 69 : return p;
499 : }
500 :
501 16 : void StructTable::pushName(char * name) {
502 16 : last()->name = name;
503 16 : }
504 :
505 37 : void StructTable::pushField(type_t type, char * name, char * structName, bool shared) {
506 37 : StructTable * l = last();
507 37 : l->fields.pushType(type);
508 37 : l->fields.pushId(name);
509 37 : if (shared) l->fields.setShared();
510 37 : if (structName != nullptr) {
511 3 : l->fields.pushStruct(structName);
512 3 : IdentTable & templateIT = getStruct(structName)->getFields();
513 3 : l->fields.pushVal(new IdentTable(templateIT));
514 : }
515 37 : l->fields.confirm();
516 37 : }
517 :
518 16 : StructTable * StructTable::confirm(void) {
519 16 : StructTable * p = last();
520 :
521 : #ifdef DEBUG
522 : std::cout << "Описана новая структура: " << p->name << '{';
523 : IdentTable * targetFields = & p->fields;
524 : targetFields->whoami();
525 : while (targetFields->next->next != nullptr) {
526 : std::cout << ", ";
527 : targetFields = targetFields->next;
528 : targetFields->whoami();
529 : }
530 : std::cout << '}' << std::endl;
531 : #endif
532 :
533 16 : p->next = new StructTable;
534 :
535 16 : return p;
536 : }
537 :
538 43 : StructTable * StructTable::getStruct(char * name) {
539 43 : StructTable * p = this;
540 :
541 52 : while (p != nullptr) {
542 52 : if (strcmp(p->name, name) == 0) break;
543 9 : p = p->next;
544 : }
545 :
546 43 : if (p == nullptr)
547 0 : throw Obstacle(STRUCT_UNDEF);
548 :
549 43 : return p;
550 : }
551 :
552 25 : IdentTable & StructTable::getFields(void) {
553 25 : return fields;
554 : }
555 :
556 18 : std::vector<type_t> StructTable::getTypes(char * name) {
557 18 : std::vector<type_t> result;
558 :
559 18 : IdentTable * targetFields = & getStruct(name)->fields;
560 68 : while (targetFields->next != nullptr) {
561 50 : type_t type = targetFields->getType();
562 50 : if (type == _STRUCT_) {
563 2 : std::vector<type_t> part = getTypes(targetFields->getStruct());
564 2 : result.reserve(result.size() + part.size());
565 2 : result.insert(result.end(), part.begin(), part.end());
566 48 : } else result.push_back(type);
567 50 : targetFields = targetFields->next;
568 : }
569 :
570 18 : return result;
571 : }
572 :
573 67 : StructTable::~StructTable(void) {
574 67 : if (name != nullptr) delete [] name;
575 67 : if (next != nullptr) delete next;
576 67 : }
|