Line data Source code
1 : #include <iostream>
2 : #include <cstring>
3 : #include <utility>
4 : #include <vector>
5 : #include <cassert>
6 : #include "common/exprtype.hpp"
7 : #include "common/tables.hpp"
8 : #include "common/obstacle.hpp"
9 : #include "compiler/parser.hpp"
10 : #define C_IS_ALPHA ((c >= 'a') && (c <= 'z') || (c >= 'A') && (c <= 'Z') || (c == '_'))
11 : #define C_IS_NUM ((c >= '0') && (c <= '9'))
12 :
13 : // Быстрый алгоритм возведения x в степень n
14 19 : int Parser::fastPow(int x, int n) {
15 19 : int r = 1;
16 41 : while (n != 0) {
17 22 : if ( (n & 1) == 1) r *= x;
18 22 : x *= x;
19 22 : n >>= 1;
20 : }
21 19 : return r;
22 : }
23 :
24 54 : void Parser::load(std::string name) {
25 54 : code.open(name);
26 54 : if (!code.is_open()) {
27 0 : std::cout << "Файл " << name << " не найден!\n";
28 0 : exit(-1);
29 : }
30 54 : }
31 :
32 51 : Parser::~Parser(void) {
33 51 : code.close();
34 51 : }
35 :
36 51 : bool Parser::parse(void) {
37 51 : code >> c;
38 :
39 51 : IdTable.pushType(_LABEL_);
40 51 : IdentTable * progOffset = IdTable.confirm();
41 51 : poliz.pushVal(progOffset);
42 51 : poliz.pushOp(_NONE_, _LABEL_, JMP);
43 : try {
44 :
45 3 : do {
46 54 : if (fileQueue.size() != 0) {
47 3 : code.swap(*fileQueue.back());
48 3 : fileQueue.back()->close();
49 3 : delete fileQueue.back();
50 3 : fileQueue.pop_back();
51 3 : code >> c;
52 : }
53 :
54 137 : while (!code.eof()) {
55 91 : if (readWord("program")) {
56 45 : progOffset->setVal(new int (poliz.getSize()));
57 45 : program();
58 46 : } else if (readWord("struct"))
59 16 : defStruct();
60 30 : else if (readWord("def"))
61 26 : defFunction();
62 4 : else if (readWord("include"))
63 3 : include();
64 1 : else throw Obstacle(WRONG_SCOPE);
65 83 : code >> c;
66 : }
67 46 : } while (fileQueue.size() != 0);
68 :
69 :
70 : }
71 8 : catch(Obstacle & o) {
72 8 : ok = false;
73 8 : c.where();
74 8 : o.describe();
75 8 : c.cite(code);
76 8 : c.line++;
77 : }
78 51 : return ok;
79 : }
80 :
81 3 : void Parser::include() {
82 6 : std::string incfile;
83 :
84 3 : if ((c == ' ') || (c == '\n')) code >> c;
85 3 : if (c == '\"') {
86 51 : do {
87 53 : code >>= c;
88 53 : incfile.push_back(c.symbol());
89 53 : } while ((c != '\"') && (!code.eof()));
90 2 : incfile.pop_back();
91 2 : code >> c;
92 : } else {
93 26 : do {
94 27 : incfile.push_back(c.symbol());
95 27 : code >>= c;
96 27 : } while ((c != ';') && (!code.eof()));
97 : }
98 :
99 : #ifdef DEBUG
100 : std::cout << "Переключаюсь на файл \"" << incfile << "\"\n";
101 : #endif
102 :
103 3 : std::ifstream * mainFile = new std::ifstream;
104 3 : mainFile->swap(code);
105 3 : fileQueue.push_back(mainFile);
106 3 : load(incfile);
107 3 : if ((c == ' ') || (c == '\n')) code >> c;
108 3 : }
109 :
110 26 : void Parser::defFunction(void) {
111 26 : inFunc = true;
112 26 : IdentTable * thisFunc = IdTable.confirm();
113 26 : thisFunc->setFunc();
114 26 : thisFunc->setOffset( poliz.getSize() );
115 26 : if ((c == ' ') || (c == '\n')) code >> c;
116 26 : char * name = identificator();
117 26 : thisFunc->setId(name);
118 26 : if (c != '(') throw Obstacle(FUNC_OPENBR);
119 25 : code >> c;
120 :
121 25 : IdentTable * formalParams = nullptr;
122 25 : if (c != ')') {
123 20 : IdTable.last()->setOrd(0);
124 20 : type();
125 20 : formalParams = def();
126 :
127 21 : while (c == ';') {
128 1 : code >> c;
129 1 : type();
130 1 : def();
131 : }
132 :
133 20 : if (c != ')') throw Obstacle(FUNC_CLOSEBR);
134 : }
135 :
136 : int paramsNum;
137 24 : if (formalParams != nullptr)
138 19 : paramsNum = IdTable.last()->getOrd() - formalParams->getOrd();
139 5 : else paramsNum = 0;
140 :
141 24 : thisFunc->setParams(paramsNum);
142 :
143 24 : if (paramsNum != 0)
144 19 : thisFunc->setVal(formalParams);
145 :
146 24 : IdentTable * p = formalParams;
147 24 : int paramsSum = 0;
148 48 : for (int i = 0; i < paramsNum; i++) {
149 24 : if (p->isShared()) {
150 4 : int nparamFact = 0;
151 4 : if (p->getType() == _STRUCT_) {
152 1 : IdentTable * fields = reinterpret_cast<IdentTable*>(p->getVal());
153 4 : while (fields->next != nullptr) {
154 3 : nparamFact++;
155 3 : fields = fields->next;
156 : }
157 3 : } else nparamFact = 1;
158 :
159 10 : for (int k = 0; k < nparamFact; k++) {
160 6 : IdTable.pushVal(new int (k + paramsSum));
161 6 : IdTable.pushType(_INT_);
162 6 : poliz.pushVal(IdTable.confirm());
163 6 : poliz.pushOp(_NONE_, _INT_, SHARE);
164 : }
165 :
166 4 : paramsSum += nparamFact;
167 : }
168 24 : if (p->getType() == _STRUCT_) {
169 3 : IdentTable * fields = reinterpret_cast<IdentTable*>(p->getVal());
170 11 : while (fields->next != nullptr) {
171 8 : fields->setReg(true);
172 8 : fields = fields->next;
173 : }
174 21 : } else p->setReg(true);
175 24 : p = p->next;
176 : }
177 :
178 24 : code >> c;
179 :
180 24 : if (c == ':') {
181 23 : code >> c;
182 :
183 23 : if (readWord("shared")) {
184 1 : thisFunc->setShared();
185 1 : code >> c;
186 : }
187 :
188 23 : if (readWord("int"))
189 11 : thisFunc->setType(_INT_);
190 12 : else if (readWord("string"))
191 3 : thisFunc->setType(_STRING_);
192 9 : else if (readWord("real"))
193 6 : thisFunc->setType(_REAL_);
194 3 : else if (readWord("bool"))
195 1 : thisFunc->setType(_BOOLEAN_);
196 2 : else if (readWord("struct")) {
197 1 : code >> c;
198 1 : char * stName = identificator();
199 1 : thisFunc->setType(_STRUCT_);
200 1 : thisFunc->setStruct(stName);
201 : //IdTable.pushStruct(stName);
202 1 : } else throw Obstacle(NO_TYPE);
203 1 : } else throw Obstacle(PROCEDURE);
204 :
205 22 : retTypes.push_back(std::make_pair(thisFunc->getType(), thisFunc->getStruct()));
206 :
207 22 : if ((c == ' ') || (c == '\n')) code >> c;
208 22 : if (c != '{') throw Obstacle(PROG_OPENBR);
209 22 : code >> c;
210 :
211 22 : defs();
212 22 : operations();
213 :
214 22 : retTypes.pop_back();
215 :
216 22 : if (c != '}') throw Obstacle(PROG_CLOSEBR); // никогда не будет исполнено
217 22 : if (inFunc) throw Obstacle(NO_RETURN);
218 :
219 159 : while (formalParams != nullptr) {
220 138 : formalParams->fade();
221 138 : formalParams = formalParams->next;
222 : }
223 21 : inFunc = false;
224 21 : }
225 :
226 22 : void Parser::returnOp(void) {
227 22 : inFunc = false;
228 22 : code >> c;
229 :
230 22 : int fieldSize = 1;
231 22 : char * stName = retTypes.back().second;
232 22 : if (retTypes.back().first == _STRUCT_) {
233 1 : fieldSize = StTable.getStruct(stName)->getFields().last()->getOrd();
234 : }
235 22 : type_t retFact = expr(&fieldSize, stName);
236 :
237 20 : if (retFact != retTypes.back().first)
238 1 : throw Obstacle(RETURN_TYPE_MISMATCH);
239 19 : if (c != ';') throw Obstacle(SEMICOLON);
240 19 : code >> c;
241 19 : poliz.pushOp(_INT_, _LABEL_, RET);
242 19 : }
243 :
244 45 : void Parser::program(void) {
245 45 : if ((c == ' ') || (c == '\n')) code >> c;
246 45 : if (c != '{') throw Obstacle(PROG_OPENBR);
247 45 : code >> c;
248 :
249 45 : defs();
250 43 : operations();
251 :
252 43 : if (c != '}') throw Obstacle(PROG_CLOSEBR);
253 43 : poliz.pushOp(_NONE_, _NONE_, STOP);
254 43 : }
255 :
256 16 : void Parser::defStruct(void) {
257 16 : if ((c == ' ') || (c == '\n')) code >> c;
258 16 : char * name = identificator();
259 16 : StTable.pushName(name);
260 16 : if ((c == ' ') || (c == '\n')) code >> c;
261 16 : if (c != '{')
262 0 : throw Obstacle(BAD_STRUCT);
263 16 : code >> c;
264 5 : do {
265 : type_t field_type;
266 21 : char * struct_name = nullptr;
267 21 : char * field_name = nullptr;
268 21 : bool shared = false;
269 :
270 21 : if (readWord("shared")) {
271 1 : if (c != ' ') throw Obstacle(TYPE_UNKNOWN);
272 1 : shared = true;
273 1 : code >> c;
274 : }
275 :
276 21 : if (readWord("int"))
277 9 : field_type = _INT_;
278 12 : else if (readWord("string"))
279 2 : field_type = _STRING_;
280 10 : else if (readWord("real"))
281 4 : field_type = _REAL_;
282 6 : else if (readWord("bool"))
283 3 : field_type = _BOOLEAN_;
284 3 : else if (readWord("struct")) {
285 3 : if (c != ' ') throw Obstacle(TYPE_UNKNOWN);
286 3 : code >> c;
287 3 : struct_name = identificator();
288 3 : field_type = _STRUCT_;
289 0 : } else throw Obstacle(TYPE_UNKNOWN);
290 :
291 21 : if (c != ' ') throw Obstacle(TYPE_UNKNOWN);
292 :
293 16 : do {
294 37 : code >> c;
295 37 : field_name = identificator();
296 37 : StTable.pushField(field_type, field_name, struct_name, shared);
297 37 : if ((c == ' ') || (c == '\n')) code >> c;
298 37 : } while (c == ',');
299 :
300 21 : if (c != ';') throw Obstacle(SEMICOLON);
301 21 : code >> c;
302 21 : } while (c != '}');
303 16 : StTable.confirm();
304 16 : }
305 :
306 135 : void Parser::defs(void) {
307 135 : while (type()) {
308 68 : def();
309 68 : if (c != ';') throw Obstacle(SEMICOLON);
310 68 : code >> c;
311 : }
312 65 : }
313 :
314 89 : IdentTable * Parser::def(void) {
315 89 : IdentTable * r = nullptr;
316 : try {
317 33 : do {
318 122 : code >> c;
319 122 : if (r == nullptr) {
320 89 : r = variable();
321 84 : r->setMainTable(&IdTable);
322 33 : } else variable()->setMainTable(&IdTable);
323 117 : if ((c == ' ') || (c == '\n')) code >> c;
324 117 : } while (c == ',');
325 10 : } catch(Obstacle & o) {
326 5 : IdTable.last()->setId(nullptr);
327 5 : ok = false;
328 5 : c.where();
329 5 : o.describe();
330 5 : c.cite(code);
331 5 : c.line++;
332 5 : revert(1); // исправление двоеточия
333 : }
334 89 : return r;
335 : }
336 :
337 168 : bool Parser::typeModificator(void) {
338 168 : bool r = true;
339 :
340 168 : if (readWord("shared")) {
341 8 : IdTable.last()->setShared();
342 8 : if (c != ' ') throw Obstacle(BAD_TYPE);
343 7 : code >> c;
344 : }
345 160 : else r = false;
346 :
347 167 : return r;
348 : }
349 :
350 168 : bool Parser::type(void) {
351 168 : bool r = true;
352 168 : bool tmod = typeModificator();
353 :
354 167 : if (readWord("int"))
355 47 : IdTable.pushType(_INT_);
356 120 : else if (readWord("string"))
357 8 : IdTable.pushType(_STRING_);
358 112 : else if (readWord("real"))
359 15 : IdTable.pushType(_REAL_);
360 97 : else if (readWord("bool"))
361 6 : IdTable.pushType(_BOOLEAN_);
362 91 : else if (readWord("struct")) {
363 20 : code >> c;
364 20 : char * stName = identificator();
365 20 : IdTable.pushStruct(stName);
366 20 : IdTable.pushType(_STRUCT_);
367 20 : IdentTable & templateFields = StTable.getStruct(stName)->getFields();
368 20 : IdTable.pushVal(new IdentTable(templateFields));
369 71 : } else r = false;
370 :
371 167 : if (tmod && (!r))
372 1 : throw Obstacle(MODIF_WITHOUT_TYPE);
373 :
374 166 : return r && (c == ' ');
375 : }
376 :
377 : /* Перед выполнением:
378 : * aab bba aca
379 : * ^~~ <= курсор на первой букве слова
380 : * После выполнения:
381 : * aab bba aca
382 : * ^ <= курсор за последней буквой слова (если true)
383 : * Если false, курсор на начальной позиции
384 : */
385 5378 : bool Parser::readWord(const char * word) {
386 5378 : bool r = true;
387 : int i;
388 7875 : for (i = 0; word[i] != '\0'; i++) {
389 7410 : if (c != word[i]) { r = false; break; }
390 2497 : code >>= c;
391 : }
392 : // Каждое слово должно отделяться пробелом или знаком препинания
393 5378 : if (C_IS_NUM || C_IS_ALPHA) r = false;
394 5378 : if (!r) revert(i);
395 5378 : return r;
396 : }
397 :
398 97 : void Parser::assign(IdentTable * lval) {
399 97 : type_t lvtype = lval->getType();
400 :
401 97 : if ((lvtype == _STRUCT_) && (c == '{')) {
402 6 : IdentTable * fields = static_cast<IdentTable *>(lval->getVal());
403 10 : do {
404 16 : code >> c;
405 16 : char * fieldName = identificator();
406 16 : IdentTable * val = fields->getIT(fieldName);
407 :
408 16 : if ((c == ' ') || (c == '\n')) code >> c;
409 :
410 16 : while (c == '.') {
411 0 : code >> c;
412 0 : fieldName = identificator();
413 0 : IdentTable * innerFields = static_cast<IdentTable *>(val->getVal());
414 0 : val = innerFields->getIT(fieldName);
415 0 : if ((c == ' ') || (c == '\n')) code >> c;
416 : }
417 :
418 16 : if (c != '=') throw Obstacle(BAD_EXPR);
419 16 : code >> c;
420 16 : assign(val);
421 16 : } while (c == ',');
422 6 : if (c != '}') throw Obstacle(BAD_EXPR);
423 6 : code >> c;
424 :
425 : } else {
426 91 : int fieldSize = unrollStruct(lval);
427 91 : char * strName = nullptr;
428 :
429 182 : std::vector<type_t> fieldTypes;
430 91 : if (lvtype == _STRUCT_) {
431 11 : strName = lval->getStruct();
432 11 : fieldTypes = StTable.getTypes(lval->getStruct());
433 : }
434 :
435 91 : type_t exop = expr(&fieldSize, strName);
436 85 : expressionType(lvtype, exop, ASSIGN);
437 :
438 85 : if (lvtype == _STRUCT_) {
439 39 : for (int i = 0; i < fieldSize; i++) {
440 30 : type_t t = fieldTypes[i];
441 : // В expr => constExpr проверяется корректность типа
442 30 : poliz.pushOp(t, t, ASSIGN);
443 : }
444 : } else {
445 76 : poliz.pushOp(lvtype, exop, ASSIGN);
446 : }
447 :
448 85 : if (exop == _STRUCT_)
449 9 : repack(fieldSize);
450 :
451 :
452 85 : if ((c == ' ') || (c == '\n')) code >> c;
453 : }
454 91 : }
455 :
456 412 : int Parser::unrollStruct(IdentTable * lval, int ord) {
457 412 : int fieldSize = 0;
458 412 : if (lval->getType() == _STRUCT_){
459 28 : IdentTable * fields = static_cast<IdentTable *>(lval->getVal());
460 107 : while (fields->next != nullptr) {
461 79 : int newOrd = -1;
462 79 : if (fields->isReg())
463 6 : newOrd = fields->getOrd();
464 79 : fieldSize += unrollStruct(fields, newOrd);
465 79 : fields = fields->next;
466 : }
467 : #ifdef DEBUG
468 : std::cout << "РАЗМЕР " << fieldSize << std::endl;
469 : #endif
470 : } else {
471 384 : fieldSize = 1;
472 384 : poliz.pushVal(lval);
473 : }
474 412 : return fieldSize;
475 : }
476 :
477 122 : IdentTable * Parser::variable(void) {
478 122 : IdTable.dupType();
479 122 : char * name = identificator();
480 122 : IdTable.pushId(name);
481 121 : if ((c == ' ') || (c == '\n')) code >> c;
482 121 : if (c == '=') constVal();
483 117 : return IdTable.confirm();
484 : }
485 :
486 742 : char * Parser::identificator(void) {
487 742 : if (!C_IS_ALPHA) throw Obstacle(BAD_IDENT);
488 741 : char * ident = new char[MAXIDENT];
489 741 : int i = 0;
490 742 : do {
491 1483 : ident[i++] = c.symbol();
492 1483 : code >>= c;
493 1483 : } while (C_IS_ALPHA);
494 741 : ident[i] = '\0';
495 741 : return ident;
496 : }
497 :
498 15 : void Parser::constStruct(IdentTable * fields) {
499 :
500 15 : if (c != '{') throw Obstacle(BAD_EXPR);
501 :
502 17 : do {
503 32 : code >> c;
504 32 : char * fieldName = identificator();
505 32 : IdentTable * val = fields->getIT(fieldName);
506 32 : type_t tval = val->getType();
507 32 : if ((c == ' ') || (c == '\n')) code >> c;
508 32 : if (c != '=') throw Obstacle(BAD_EXPR);
509 32 : code >> c;
510 :
511 32 : switch (tval) {
512 8 : case _INT_:
513 8 : val->setVal( new int (constInt()) );
514 8 : break;
515 4 : case _STRING_:
516 4 : val->setVal( constString() );
517 4 : break;
518 7 : case _REAL_:
519 7 : val->setVal( new float (constReal()) );
520 7 : break;
521 10 : case _BOOLEAN_:
522 10 : val->setVal( new bool (constBool()) );
523 10 : break;
524 3 : case _STRUCT_:
525 3 : constStruct(static_cast<IdentTable *>(val->getVal()));
526 3 : break;
527 0 : default:
528 0 : throw Obstacle(PANIC);
529 : }
530 32 : if ((c == ' ') || (c == '\n')) code >> c;
531 32 : } while (c == ',');
532 15 : if (c != '}') throw Obstacle(BAD_EXPR);
533 15 : code >> c;
534 15 : }
535 :
536 41 : void Parser::constVal(void) {
537 41 : IdentTable * val = IdTable.last();
538 41 : type_t tval = val->getType();
539 :
540 41 : code >> c;
541 :
542 41 : switch(tval) {
543 19 : case _INT_:
544 19 : IdTable.pushVal( new int (constInt()) );
545 18 : break;
546 4 : case _STRING_:
547 4 : IdTable.pushVal( constString() );
548 3 : break;
549 4 : case _REAL_:
550 4 : IdTable.pushVal( new float (constReal()) );
551 3 : break;
552 2 : case _BOOLEAN_:
553 2 : IdTable.pushVal( new bool (constBool()) );
554 1 : break;
555 12 : case _STRUCT_:
556 12 : constStruct(static_cast<IdentTable *>(val->getVal()));
557 12 : break;
558 0 : default:
559 0 : throw Obstacle(PANIC);
560 : }
561 37 : }
562 :
563 498 : int Parser::constInt(void) {
564 498 : int x = 0, sign = 1;
565 498 : if (c == '-') {
566 3 : sign = -1;
567 3 : code >> c;
568 495 : } else if (c == '+') code >> c;
569 :
570 498 : if (!C_IS_NUM) throw Obstacle(BAD_INT);
571 :
572 35 : do {
573 256 : x = 10 * x + ( c.symbol() - '0');
574 256 : code >>= c;
575 256 : } while (C_IS_NUM);
576 221 : x = x * sign;
577 :
578 221 : return x;
579 : }
580 :
581 99 : char * Parser::constString(void) {
582 99 : if (c != '\"') throw Obstacle(BAD_STRING);
583 :
584 98 : int start = code.tellg();
585 1503 : do { code >>= c; }
586 1503 : while ((!code.eof()) && (c != '\"'));
587 :
588 98 : if (code.eof()) throw Obstacle(BAD_STRING);
589 :
590 98 : int len = (int)code.tellg() - start - 1;
591 98 : code.seekg(start);
592 :
593 98 : char *x = new char[len + 1];
594 :
595 1503 : for (int i = 0; i < len; i++) {
596 1405 : code >>= c;
597 1405 : x[i] = c.symbol();
598 : }
599 :
600 98 : x[len] = '\0';
601 :
602 98 : code >>= c; // кавычка
603 98 : code >>= c;
604 :
605 98 : return x;
606 : }
607 :
608 379 : float Parser::constReal(void) {
609 379 : int intPart = constInt();
610 :
611 103 : if (c != '.') throw Obstacle(BAD_REAL);
612 16 : code >>= c;
613 :
614 16 : if (!C_IS_NUM) throw Obstacle(BAD_REAL);
615 :
616 16 : int x = 1;
617 16 : float floatPart = 0;
618 3 : do {
619 19 : floatPart += (float)( c.symbol() - '0') / fastPow(10, x++);
620 19 : code >>= c;
621 19 : } while (C_IS_NUM);
622 :
623 16 : if (intPart < 0) floatPart *= -1;
624 :
625 16 : return intPart + floatPart;
626 : }
627 :
628 12 : bool Parser::constBool(void) {
629 : bool r;
630 12 : if (readWord("true")) r = true;
631 6 : else if (readWord("false")) r = false;
632 1 : else throw Obstacle(BAD_BOOL);
633 :
634 11 : return r;
635 : }
636 :
637 285 : void Parser::operations(void) {
638 285 : while (c != '}') {
639 205 : try { operation(); }
640 42 : catch(Obstacle & o) {
641 21 : ok = false;
642 21 : c.where();
643 21 : o.describe();
644 21 : c.cite(code);
645 21 : c.line++;
646 21 : code >> c;
647 : }
648 : }
649 80 : }
650 :
651 251 : void Parser::operation(void) {
652 :
653 251 : if (c.symbol() == '}') return;
654 251 : else if (readWord("if")) condOp();
655 236 : else if (readWord("for")) forOp();
656 224 : else if (readWord("while")) whileOp();
657 218 : else if (readWord("break")) breakOp();
658 215 : else if (readWord("continue")) continueOp();
659 213 : else if (readWord("write")) writeOp();
660 132 : else if (readWord("goto")) gotoOp();
661 127 : else if (readWord("read")) readOp();
662 109 : else if (readWord("bytecode")) bytecodeOp();
663 105 : else if (readWord("return")) returnOp();
664 83 : else if (readWord("thread")) threadOp();
665 77 : else if (readWord("fork")) forkOp();
666 76 : else if (readWord("lock")) lockOp();
667 75 : else if (readWord("{")) {
668 11 : code >> c;
669 11 : operations();
670 11 : if (c != '}')
671 0 : throw Obstacle(OP_CLOSEBR);
672 11 : code >> c;
673 : } else {
674 64 : char * name = identificator();
675 64 : if ((c == ' ') || (c == '\n')) code >> c;
676 :
677 64 : if (c == ':') {
678 6 : code >> c;
679 6 : saveLabel(name, poliz.getSize());
680 6 : operation();
681 : } else {
682 58 : IdentTable * lval = IdTable.getIT(name);
683 66 : while (c == '.') {
684 8 : code >> c;
685 8 : name = identificator();
686 8 : IdentTable * fields = static_cast<IdentTable *>(lval->getVal());
687 8 : lval = fields->getIT(name);
688 8 : if ((c == ' ') || (c == '\n')) code >> c;
689 : }
690 58 : if (c != '=') throw Obstacle(BAD_OPERATOR);
691 58 : code >> c;
692 58 : assign(lval);
693 52 : if (c != ';') throw Obstacle(SEMICOLON);
694 52 : code >> c;
695 : }
696 : }
697 :
698 : }
699 :
700 6 : void Parser::threadOp(void) {
701 6 : if (inThread)
702 1 : throw Obstacle(NESTED_THREADS);
703 :
704 5 : if ((c == ' ') || (c == '\n')) code >> c;
705 :
706 5 : if (c != ':')
707 1 : throw Obstacle(NEED_THREAD_NUMBER);
708 :
709 4 : code >> c;
710 4 : inThread = true;
711 :
712 4 : IdTable.pushType(_LABEL_);
713 4 : IdentTable * progOffset = IdTable.confirm();
714 4 : poliz.pushVal(progOffset);
715 4 : poliz.pushOp(_NONE_, _LABEL_, JMP);
716 :
717 4 : int threadNum = constInt();
718 4 : IdTable.pushType(_LABEL_);
719 4 : IdTable.pushVal( new int (poliz.getSize()) );
720 4 : IdTable.pushId(nullptr);
721 4 : threads[threadNum] = IdTable.confirm();
722 :
723 4 : if ((c == ' ') || (c == '\n')) code >> c;
724 :
725 4 : if (c != '{')
726 0 : throw Obstacle(PROG_OPENBR);
727 4 : code >> c;
728 :
729 4 : operations();
730 :
731 4 : poliz.pushOp(_NONE_, _NONE_, STOP);
732 :
733 4 : if (c != '}')
734 0 : throw Obstacle(PROG_CLOSEBR);
735 :
736 4 : progOffset->setVal(new int (poliz.getSize()));
737 :
738 4 : code >> c;
739 4 : inThread = false;
740 4 : }
741 :
742 1 : void Parser::forkOp(void) {
743 1 : if ((c == ' ') || (c == '\n')) code >> c;
744 1 : if (c != '(')
745 0 : throw Obstacle(FUNC_OPENBR);
746 :
747 1 : do {
748 2 : code >> c;
749 2 : int threadNum = constInt();
750 2 : poliz.pushVal(threads[threadNum]);
751 2 : poliz.pushOp(_NONE_, _INT_, FORK);
752 2 : if ((c == ' ') || (c == '\n')) code >> c;
753 2 : } while (c == ',');
754 :
755 1 : if (c != ')')
756 0 : throw Obstacle(FUNC_CLOSEBR);
757 1 : code >> c;
758 1 : if (c != ';')
759 0 : throw Obstacle(SEMICOLON);
760 :
761 1 : code >> c;
762 1 : }
763 :
764 1 : void Parser::lockOp(void) {
765 1 : if ((c == ' ') || (c == '\n')) code >> c;
766 1 : if (c != '(')
767 0 : throw Obstacle(FUNC_OPENBR);
768 1 : code >> c;
769 1 : if ((c == ' ') || (c == '\n')) code >> c;
770 1 : if (c != ')')
771 0 : throw Obstacle(FUNC_CLOSEBR);
772 1 : code >> c;
773 1 : if (c != ';')
774 0 : throw Obstacle(SEMICOLON);
775 :
776 1 : poliz.pushOp(_NONE_, _NONE_, LOCK);
777 :
778 1 : code >> c;
779 1 : }
780 :
781 9 : IdentTable * Parser::saveLabel(char * label, int addr) {
782 : IdentTable * existinglab;
783 : try {
784 9 : existinglab = IdTable.getIT(label, false);
785 3 : if (existinglab->getType() != _LABEL_)
786 0 : throw Obstacle(LABEL_OR_IDENT);
787 3 : delete static_cast<int *>(existinglab->getVal());
788 3 : existinglab->setVal(new int (addr));
789 : }
790 12 : catch(Obstacle & o) {
791 6 : if (o.r == LABEL_OR_IDENT) {
792 0 : ok = false;
793 0 : c.where();
794 0 : o.describe();
795 0 : c.cite(code);
796 0 : c.line++;
797 0 : code >> c;
798 : } else {
799 6 : IdTable.pushType(_LABEL_);
800 6 : IdTable.pushVal( new int (addr) );
801 6 : IdTable.pushId(label);
802 6 : existinglab = IdTable.confirm();
803 : }
804 : }
805 9 : return existinglab;
806 : }
807 :
808 358 : type_t Parser::expr(int * fieldSize, char * structName) {
809 358 : type_t r = _NONE_;
810 :
811 358 : assert(fieldSize != nullptr);
812 :
813 358 : r = andExpr(fieldSize, structName);
814 :
815 : while (true) {
816 345 : if (readWord("or")) {
817 2 : code >> c;
818 2 : type_t rval = andExpr(fieldSize, structName);
819 :
820 2 : if ((r == _STRUCT_) || (rval == _STRUCT_)) {
821 1 : handleStruct(r, rval, LOR, fieldSize, structName);
822 1 : repack(*fieldSize);
823 : } else
824 1 : poliz.pushOp(r, rval, LOR);
825 :
826 2 : r = expressionType(r, rval, LOR);
827 343 : } else break;
828 2 : }
829 :
830 343 : return r;
831 : }
832 :
833 360 : type_t Parser::andExpr(int * fieldSize, char * structName) {
834 360 : type_t r = _NONE_;
835 :
836 360 : r = boolExpr(fieldSize, structName);
837 :
838 : while (true) {
839 346 : if (readWord("and")) {
840 1 : code >> c;
841 1 : type_t rval = boolExpr(fieldSize, structName);
842 :
843 1 : if ((r == _STRUCT_) || (rval == _STRUCT_)) {
844 1 : handleStruct(r, rval, LAND, fieldSize, structName);
845 1 : repack(*fieldSize);
846 : } else
847 0 : poliz.pushOp(r, rval, LAND);
848 :
849 1 : r = expressionType(r, rval, LAND);
850 345 : } else break;
851 1 : }
852 345 : return r;
853 : }
854 :
855 361 : type_t Parser::boolExpr(int * fieldSize, char * structName) {
856 361 : type_t r = _NONE_;
857 :
858 361 : r = add(fieldSize, structName);
859 :
860 346 : if ( (c == '=') || (c == '<') || (c == '>') || (c == '!')) {
861 28 : operation_t op = NONE;
862 28 : char p = c.symbol();
863 28 : code >>= c;
864 28 : if (c == '=') {
865 18 : switch(p) {
866 3 : case '<': op = LESSEQ; break;
867 3 : case '>': op = GRTREQ; break;
868 3 : case '!': op = NEQ; break;
869 9 : case '=': op = EQ; break;
870 : }
871 18 : code >>= c;
872 : } else {
873 10 : switch(p) {
874 6 : case '<': op = LESS; break;
875 4 : case '>': op = GRTR; break;
876 0 : default: throw Obstacle(BAD_EXPR);
877 : }
878 : }
879 28 : if ((c == ' ') || (c == '\n')) code >> c;
880 28 : type_t rval = add(fieldSize, structName);
881 :
882 28 : if ((r == _STRUCT_) || (rval == _STRUCT_)) {
883 0 : handleStruct(r, rval, op, fieldSize, structName);
884 0 : repack(*fieldSize);
885 : } else
886 28 : poliz.pushOp(r, rval, op);
887 :
888 28 : r = expressionType(r, rval, op);
889 : }
890 :
891 346 : return r;
892 : }
893 :
894 389 : type_t Parser::add(int * fieldSize, char * structName) {
895 389 : bool exit = false;
896 389 : bool inverse = false;
897 389 : if (c == '+') code >> c;
898 389 : if (c == '-') {
899 1 : inverse = true;
900 1 : code >> c;
901 : }
902 389 : type_t r = mul(fieldSize, structName);
903 : operation_t op;
904 :
905 : while (true) {
906 :
907 412 : switch (c.symbol()) {
908 31 : case '+': op = PLUS; break;
909 7 : case '-': op = MINUS; break;
910 374 : default: exit = true;
911 : }
912 412 : if (exit) break;
913 38 : code >> c;
914 38 : type_t rval = mul(fieldSize, structName);
915 :
916 38 : if ((r == _STRUCT_) || (rval == _STRUCT_)) {
917 2 : handleStruct(r, rval, op, fieldSize, structName);
918 2 : repack(*fieldSize);
919 : } else
920 36 : poliz.pushOp(r, rval, op);
921 :
922 38 : r = expressionType(r, rval, op);
923 38 : }
924 :
925 374 : if (inverse) {
926 1 : if (r == _STRUCT_) {
927 0 : handleStruct(_NONE_, r, INV, fieldSize, structName);
928 0 : repack(*fieldSize);
929 0 : r = expressionType(_NONE_, r, INV);
930 : }
931 : }
932 :
933 374 : return r;
934 : }
935 :
936 5 : void Parser::handleStruct(
937 : type_t lval, type_t rval, operation_t op, int * fieldSize, char * structName) {
938 :
939 : /* Если в rval лежит простой тип, то его можно просто скопировать
940 : * для всех остальных полей в lval. В случае, если rval -- структура,
941 : * то нужно аккуратно обойти все её поля. Причём constExpr гарантирует,
942 : * что структуры lval и rval идентичны, поэтому мы можем взять имя
943 : * lval (т.е. structName) для определения структуры rval.
944 : */
945 5 : assert((lval == _STRUCT_) || (rval == _STRUCT_));
946 :
947 10 : std::vector<type_t> types = StTable.getTypes(structName);
948 5 : int newFieldSize = types.size();
949 : type_t ltype, rtype;
950 21 : for (int i = newFieldSize - 1; i >= 0; i--) {
951 16 : if (lval == _STRUCT_) ltype = types[i];
952 3 : else ltype = lval;
953 16 : if (rval == _STRUCT_) rtype = types[i];
954 5 : else rtype = rval;
955 :
956 16 : if ((ltype == _STRUCT_) || (rtype == _STRUCT_))
957 0 : handleStruct(ltype, rtype, op, &newFieldSize, structName);
958 : else
959 16 : poliz.pushOp(ltype, rtype, op);
960 : }
961 5 : }
962 :
963 427 : type_t Parser::mul(int * fieldSize, char * structName) {
964 427 : bool exit = false;
965 427 : type_t r = constExpr(fieldSize, structName);
966 : operation_t op;
967 :
968 : while (true) {
969 :
970 445 : switch (c.symbol()) {
971 21 : case '*': op = MUL; break;
972 10 : case '/': op = DIV; break;
973 2 : case '%': op = MOD; break;
974 412 : default: exit = true;
975 : }
976 445 : if (exit) break;
977 33 : code >> c;
978 33 : type_t rval = constExpr(fieldSize, structName);
979 :
980 33 : if ((r == _STRUCT_) || (rval == _STRUCT_)) {
981 1 : handleStruct(r, rval, op, fieldSize, structName);
982 1 : repack(*fieldSize);
983 : } else
984 32 : poliz.pushOp(r, rval, op);
985 :
986 33 : r = expressionType(r, rval, op);
987 :
988 33 : }
989 :
990 412 : return r;
991 : }
992 :
993 14 : void Parser::repack(int fieldSize) {
994 14 : op_t op = poliz.getProg()[poliz.getSize() - fieldSize - 1];
995 14 : if ((operation_t)(op & 0xFF) == UNPACK)
996 1 : return;
997 :
998 13 : int POLIZsteps[2 * fieldSize];
999 101 : for (int i = 0; i < fieldSize * 2; i++)
1000 88 : POLIZsteps[i] = 1;
1001 :
1002 65 : POLIZ buff[2], opBuff[2];
1003 :
1004 : /* Каков смысл steps? В нём хранится количество элементов ПОЛИЗА,
1005 : * которое нужно достать для каждого поля. Вначале идёт левая,
1006 : * потом правая ветка.
1007 : */
1008 13 : int temp_iter = fieldSize;
1009 : int i;
1010 57 : while (((i = poliz.getSize()) > 0) && poliz.getEB()[i - 1] && temp_iter) {
1011 44 : op_t oper = poliz.getProg()[i - 1];
1012 44 : opBuff[1].push(oper, poliz.getEB()[i - 1]);
1013 44 : poliz.pop();
1014 44 : temp_iter--;
1015 : }
1016 39 : for (int buffIter = 1; buffIter >= 0; buffIter--) {
1017 114 : for (int nfield = fieldSize; nfield > 0; nfield--) {
1018 88 : int stepIdx = buffIter + (nfield - 1) * 2;
1019 88 : int fields = POLIZsteps[stepIdx];
1020 88 : POLIZsteps[stepIdx] = 0;
1021 217 : while (fields) {
1022 129 : i = poliz.getSize();
1023 129 : bool ebit = poliz.getEB()[i - 1];
1024 129 : op_t oper = poliz.getProg()[i - 1];
1025 129 : if (ebit) {
1026 25 : int nops = operands(static_cast<operation_t>(oper & 0xFF));
1027 25 : fields += nops;
1028 : }
1029 :
1030 129 : buff[buffIter].push(oper, ebit);
1031 129 : POLIZsteps[stepIdx] += 1;
1032 :
1033 129 : poliz.pop();
1034 129 : fields--;
1035 : }
1036 : }
1037 : }
1038 :
1039 101 : for (int step = 0; step < fieldSize * 2; step++) {
1040 217 : while (POLIZsteps[step]) {
1041 129 : int bi = buff[step % 2].getSize();
1042 129 : bool ebit = buff[step % 2].getEB()[bi - 1];
1043 129 : op_t oper = buff[step % 2].getProg()[bi - 1];
1044 129 : buff[step % 2].pop();
1045 129 : poliz.push(oper, ebit);
1046 129 : POLIZsteps[step] -= 1;
1047 : }
1048 88 : int bi = opBuff[step % 2].getSize();
1049 88 : if (bi > 0) {
1050 44 : bool ebit = opBuff[step % 2].getEB()[bi - 1];
1051 44 : op_t oper = opBuff[step % 2].getProg()[bi - 1];
1052 44 : opBuff[step % 2].pop();
1053 44 : poliz.push(oper, ebit);
1054 : }
1055 14 : }
1056 : }
1057 :
1058 476 : type_t Parser::constExpr(int * fieldSize, char * structName) {
1059 : type_t r;
1060 :
1061 476 : if (readWord("true")) {
1062 2 : r = _BOOLEAN_;
1063 4 : NEW_IDENT(val, _BOOLEAN_, nullptr, new bool (true), fieldSize)
1064 474 : } else if (readWord("false")) {
1065 1 : r = _BOOLEAN_;
1066 2 : NEW_IDENT(val, _BOOLEAN_, nullptr, new bool (false), fieldSize)
1067 473 : } else if (readWord("not")) {
1068 0 : type_t val = constExpr(fieldSize, structName);
1069 0 : r = expressionType(_NONE_, val, LNOT);
1070 0 : for (int i = 0; i < *fieldSize; i++)
1071 0 : poliz.pushOp(_NONE_, val, LNOT);
1072 473 : } else if (c == '(') {
1073 14 : code >> c;
1074 14 : r = expr(fieldSize, structName);
1075 13 : if (c != ')') throw Obstacle(EXPR_CLOSEBR);
1076 13 : code >>= c;
1077 : } else {
1078 :
1079 459 : if (c == '\"') {
1080 91 : r = _STRING_;
1081 91 : char * x = constString();
1082 182 : NEW_IDENT(val, _STRING_, nullptr, x, fieldSize)
1083 : } else {
1084 368 : int start = code.tellg();
1085 : try {
1086 368 : r = _REAL_;
1087 368 : float x = constReal();
1088 12 : NEW_IDENT(val, _REAL_, nullptr, new float (x), fieldSize)
1089 724 : } catch (Obstacle & o) {
1090 362 : code.seekg(start - 1);
1091 362 : code >>= c;
1092 362 : if (o.r != BAD_INT) {
1093 86 : r = _INT_;
1094 86 : int x = constInt();
1095 177 : NEW_IDENT(val, _INT_, nullptr, new int (x), fieldSize)
1096 : } else {
1097 276 : IdentTable * val = getFieldInStruct();
1098 267 : r = val->getType();
1099 :
1100 267 : if (c == '(') { // Вызов функции
1101 22 : if (! val->isFunc())
1102 0 : throw Obstacle(NOT_CALLABLE);
1103 22 : callIdent(val);
1104 : } else {
1105 245 : if (val->isFunc())
1106 1 : throw Obstacle(CALLABLE);
1107 :
1108 244 : if (r == _STRUCT_) {
1109 15 : if ((structName != nullptr) && (strcmp(val->getStruct(), structName) != 0))
1110 2 : throw Obstacle(EXPR_BAD_TYPE);
1111 : }
1112 :
1113 242 : int fields = unrollStruct(val);
1114 242 : if (*fieldSize != 0) {
1115 242 : *fieldSize = fields;
1116 : }
1117 :
1118 : }
1119 : }
1120 : }
1121 : }
1122 : }
1123 :
1124 460 : if ((c == ' ') || (c == '\n')) code >> c;
1125 :
1126 460 : return r;
1127 : }
1128 :
1129 276 : IdentTable * Parser::getFieldInStruct(void) {
1130 276 : char * name = identificator();
1131 275 : IdentTable * val = IdTable.getIT(name);
1132 268 : if ((c == ' ') || (c == '\n')) code >> c;
1133 :
1134 341 : while (c == '.') { // Добираемся до поля структуры
1135 73 : code >> c;
1136 73 : name = identificator();
1137 73 : IdentTable * fields = static_cast<IdentTable *>(val->getVal());
1138 73 : val = fields->getIT(name);
1139 73 : if ((c == ' ') || (c == '\n')) code >> c;
1140 : }
1141 268 : if (!val->isShared() && inThread)
1142 1 : throw Obstacle(PRIVATE_VAR_IN_THREAD);
1143 :
1144 267 : return val;
1145 : }
1146 :
1147 22 : void Parser::callIdent(IdentTable * val) {
1148 22 : code >> c;
1149 22 : IdentTable * fields = static_cast<IdentTable *>(val->getVal());
1150 22 : int paramCount = 0;
1151 22 : int paramCountFact = 0;
1152 42 : while (c != ')') {
1153 22 : if (fields == nullptr)
1154 0 : throw Obstacle(TOO_MUCH_PARAMS);
1155 22 : if (c == ',') code >> c;
1156 :
1157 22 : int fieldSize = 1;
1158 22 : char * structName = nullptr;
1159 :
1160 22 : if (fields->getType() == _STRUCT_) {
1161 3 : fieldSize = fields->last()->getOrd();
1162 3 : structName = fields->getStruct();
1163 : }
1164 :
1165 22 : type_t exprType = expr(&fieldSize, structName);
1166 21 : if (fields->getType() != exprType)
1167 1 : throw Obstacle(EXPR_BAD_TYPE);
1168 20 : fields = fields->next;
1169 20 : paramCount += fieldSize;
1170 20 : paramCountFact++;
1171 : }
1172 :
1173 20 : code >> c;
1174 20 : if (paramCountFact != val->getParams())
1175 1 : throw Obstacle(BAD_PARAMS_COUNT);
1176 19 : int fieldSize = 1;
1177 38 : NEW_IDENT(params, _INT_, nullptr, new int (paramCount), &fieldSize)
1178 38 : NEW_IDENT(callable, _LABEL_, nullptr, new int (val->getOffset()), &fieldSize)
1179 19 : poliz.pushOp(_INT_, _LABEL_, CALL);
1180 :
1181 19 : if (val->getType() == _STRUCT_) {
1182 1 : int fnum = StTable.getStruct(val->getStruct())->getFields().last()->getOrd();
1183 1 : IdTable.pushType(_INT_);
1184 1 : IdTable.pushVal(new int (fnum));
1185 1 : poliz.pushVal(IdTable.confirm());
1186 1 : poliz.pushOp(_NONE_, _INT_, UNPACK);
1187 : }
1188 19 : }
1189 :
1190 15 : void Parser::condOp(void) {
1191 15 : if ((c == ' ') || (c == '\n')) code >> c;
1192 15 : if (c != '(')
1193 0 : throw Obstacle(BAD_PARAMS_OPBR);
1194 15 : code >> c;
1195 :
1196 15 : int fieldSize = 1;
1197 15 : type_t r = expr(&fieldSize);
1198 :
1199 15 : if (r != _BOOLEAN_)
1200 1 : throw Obstacle(BAD_IF);
1201 :
1202 14 : if (c != ')')
1203 0 : throw Obstacle(BAD_PARAMS_CLBR);
1204 :
1205 14 : code >> c;
1206 :
1207 14 : IdTable.pushType(_LABEL_);
1208 14 : IdentTable * elsecase = IdTable.confirm();
1209 14 : IdTable.pushType(_LABEL_);
1210 14 : IdentTable * endif = IdTable.confirm();
1211 :
1212 14 : poliz.pushOp(_NONE_, _BOOLEAN_, LNOT);
1213 14 : poliz.pushVal(elsecase);
1214 14 : poliz.pushOp(_BOOLEAN_, _LABEL_, JIT);
1215 :
1216 14 : operation();
1217 :
1218 14 : poliz.pushVal(endif);
1219 14 : poliz.pushOp(_NONE_, _LABEL_, JMP);
1220 :
1221 14 : elsecase->setVal( new int (poliz.getSize()) );
1222 :
1223 14 : if (readWord("else")) {
1224 10 : code >> c;
1225 10 : operation();
1226 : }
1227 :
1228 14 : endif->setVal( new int (poliz.getSize()) );
1229 14 : }
1230 :
1231 12 : IdentTable * Parser::cycleparam(void) {
1232 : IdentTable * lval;
1233 : char * name;
1234 :
1235 12 : if (type()) {
1236 : // переменная не описана
1237 7 : code >> c;
1238 7 : name = identificator();
1239 7 : IdTable.pushId(name);
1240 7 : lval = IdTable.confirm();
1241 : } else {
1242 : // переменная описана
1243 5 : name = identificator();
1244 5 : lval = IdTable.getIT(name);
1245 : }
1246 :
1247 12 : if ((c == ' ') || (c == '\n')) code >> c;
1248 :
1249 13 : while (c == '.') {
1250 1 : code >> c;
1251 1 : name = identificator();
1252 1 : IdentTable * fields = static_cast<IdentTable *>(lval->getVal());
1253 1 : lval = fields->getIT(name);
1254 1 : if ((c == ' ') || (c == '\n')) code >> c;
1255 : }
1256 :
1257 12 : if (c != '=') throw Obstacle(BAD_EXPR);
1258 12 : code >> c;
1259 12 : assign(lval);
1260 :
1261 12 : return lval;
1262 : }
1263 :
1264 12 : void Parser::forOp(void) {
1265 12 : IdTable.pushType(_LABEL_);
1266 12 : IdentTable * exit = IdTable.confirm();
1267 12 : exits.push(exit);
1268 12 : IdTable.pushType(_LABEL_);
1269 12 : IdentTable * body = IdTable.confirm();
1270 :
1271 12 : if ((c == ' ') || (c == '\n')) code >> c;
1272 12 : if (c != '(')
1273 0 : throw Obstacle(BAD_PARAMS_OPBR);
1274 12 : code >> c;
1275 :
1276 12 : IdentTable * cp = nullptr;
1277 12 : cp = cycleparam(); // начальное выражение
1278 : /*
1279 : try{ cp = cycleparam(); } // начальное выражение
1280 : catch(Obstacle & o){
1281 : o.describe();
1282 : }
1283 : */
1284 :
1285 12 : if (c != ';')
1286 0 : throw Obstacle(SEMICOLON);
1287 :
1288 12 : IdTable.pushType(_LABEL_);
1289 12 : IdTable.pushVal( new int (poliz.getSize()) );
1290 12 : IdentTable * condexpr = IdTable.confirm();
1291 12 : code >> c;
1292 :
1293 12 : int fieldSize = 1;
1294 12 : type_t e2 = expr(&fieldSize); // условие продолжения
1295 :
1296 12 : if (e2 != _BOOLEAN_) throw Obstacle(BAD_IF);
1297 11 : poliz.pushVal(body);
1298 11 : poliz.pushOp(_BOOLEAN_, _LABEL_, JIT);
1299 : // Здесь машина будет в случае невыполнения условия
1300 11 : poliz.pushVal(exit);
1301 11 : poliz.pushOp(_NONE_, _LABEL_, JMP);
1302 :
1303 11 : if (c != ';')
1304 0 : throw Obstacle(SEMICOLON);
1305 :
1306 11 : IdTable.pushType(_LABEL_);
1307 11 : IdTable.pushVal( new int (poliz.getSize()) );
1308 11 : IdentTable * cyclexpr = IdTable.confirm();
1309 11 : steps.push(cyclexpr);
1310 :
1311 11 : code >> c;
1312 :
1313 11 : char * name = identificator();
1314 11 : IdentTable * cycleLval = IdTable.getIT(name);
1315 11 : if ((c == ' ') || (c == '\n')) code >> c;
1316 11 : if (c != '=') throw Obstacle(BAD_EXPR);
1317 11 : code >> c;
1318 11 : assign(cycleLval);
1319 :
1320 11 : if (c != ')')
1321 0 : throw Obstacle(BAD_PARAMS_CLBR);
1322 :
1323 11 : poliz.pushVal(condexpr);
1324 11 : poliz.pushOp(_NONE_, _LABEL_, JMP);
1325 :
1326 11 : code >> c;
1327 11 : body->setVal(new int (poliz.getSize()) );
1328 11 : operation(); // тело цикла
1329 :
1330 : // Проверяем условие, если правда, то проходим через цикл. выражение
1331 : // и возвращаемся в тело. Иначе выходим из него.
1332 11 : poliz.pushVal(cyclexpr);
1333 11 : poliz.pushOp(_NONE_, _LABEL_, JMP);
1334 :
1335 11 : exit->setVal(new int (poliz.getSize()) );
1336 :
1337 11 : exits.pop();
1338 11 : steps.pop();
1339 :
1340 11 : if ((cp->next->getId() == nullptr)) {
1341 7 : cp->setId(nullptr); // Эта переменная вне цикла не определена.
1342 : }
1343 11 : }
1344 :
1345 4 : void Parser::bytecodeOp(void) {
1346 4 : if ((c == ' ') || (c == '\n')) code >> c;
1347 4 : if (c != '{')
1348 0 : throw Obstacle(PROG_OPENBR);
1349 :
1350 8 : std::vector<type_t> types;
1351 :
1352 23 : do {
1353 27 : bool couldRead = true;
1354 27 : code >> c;
1355 27 : switch (c.symbol()) {
1356 3 : case 'A':
1357 3 : if (readWord("ASSIGN")) {
1358 3 : BYTECODE_OP_BIN(ASSIGN)
1359 0 : } else couldRead = false;
1360 3 : break;
1361 1 : case 'C':
1362 1 : if (readWord("CALL")) {
1363 1 : BYTECODE_OP_BIN(CALL)
1364 0 : } else couldRead = false;
1365 1 : break;
1366 0 : case 'D':
1367 0 : if (readWord("DIV")) {
1368 0 : BYTECODE_OP_BIN(DIV)
1369 0 : } else couldRead = false;
1370 0 : break;
1371 2 : case 'E':
1372 2 : if (readWord("ENDL")) {
1373 0 : BYTECODE_OP_BIN(ENDL)
1374 2 : } else if (readWord("EQ")) {
1375 1 : BYTECODE_OP_BIN(EQ)
1376 1 : } else couldRead = false;
1377 2 : break;
1378 0 : case 'G':
1379 0 : if (readWord("GRTR")) {
1380 0 : BYTECODE_OP_BIN(GRTR)
1381 0 : } else if (readWord("GRTREQ")) {
1382 0 : BYTECODE_OP_BIN(GRTREQ)
1383 0 : } else couldRead = false;
1384 0 : break;
1385 0 : case 'I':
1386 0 : if (readWord("INV")) {
1387 0 : BYTECODE_OP_BIN(INV)
1388 0 : } else couldRead = false;
1389 0 : break;
1390 2 : case 'J':
1391 2 : if (readWord("JIT")) {
1392 1 : BYTECODE_OP_BIN(JIT)
1393 1 : } else if (readWord("JMP")) {
1394 1 : BYTECODE_OP_BIN(JMP)
1395 0 : } else couldRead = false;
1396 2 : break;
1397 0 : case 'L':
1398 0 : if (readWord("LAND")) {
1399 0 : BYTECODE_OP_BIN(LAND)
1400 0 : } else if (readWord("LESS")) {
1401 0 : BYTECODE_OP_BIN(LESS)
1402 0 : } else if (readWord("LESSEQ")) {
1403 0 : BYTECODE_OP_BIN(LESSEQ)
1404 0 : } else if (readWord("LNOT")) {
1405 0 : BYTECODE_OP_BIN(LNOT)
1406 0 : } else if (readWord("LOAD")) {
1407 0 : BYTECODE_OP_BIN(LOAD)
1408 0 : } else if (readWord("LOR")) {
1409 0 : BYTECODE_OP_BIN(LOR)
1410 0 : } else couldRead = false;
1411 0 : break;
1412 2 : case 'M':
1413 2 : if (readWord("MINUS")) {
1414 0 : BYTECODE_OP_BIN(MINUS)
1415 2 : } else if (readWord("MOD")) {
1416 0 : BYTECODE_OP_BIN(MOD)
1417 2 : } else if (readWord("MUL")) {
1418 2 : BYTECODE_OP_BIN(MUL)
1419 0 : } else couldRead = false;
1420 2 : break;
1421 0 : case 'N':
1422 0 : if (readWord("NEQ")) {
1423 0 : BYTECODE_OP_BIN(NEQ)
1424 0 : } else couldRead = false;
1425 0 : break;
1426 0 : case 'P':
1427 0 : if (readWord("PLUS")) {
1428 0 : BYTECODE_OP_BIN(PLUS)
1429 0 : } else couldRead = false;
1430 0 : break;
1431 2 : case 'R':
1432 2 : if (readWord("READ")) {
1433 1 : BYTECODE_OP_BIN(READ)
1434 1 : } else if (readWord("RET")) {
1435 1 : types.push_back(_LABEL_);
1436 1 : BYTECODE_OP_BIN(RET)
1437 0 : } else couldRead = false;
1438 2 : break;
1439 0 : case 'S':
1440 0 : if (readWord("STOP")) {
1441 0 : BYTECODE_OP_BIN(STOP)
1442 0 : } else couldRead = false;
1443 0 : break;
1444 0 : case 'W':
1445 0 : if (readWord("WRITE")) {
1446 0 : BYTECODE_OP_BIN(WRITE)
1447 0 : } else couldRead = false;
1448 0 : break;
1449 :
1450 15 : default:
1451 15 : couldRead = false;
1452 15 : break;
1453 : }
1454 27 : if (!couldRead) {
1455 16 : int fieldSize = 1;
1456 16 : int p = c.pos;
1457 : try {
1458 16 : types.push_back(constExpr(&fieldSize));
1459 2 : } catch (Obstacle & o) {
1460 1 : revert(c.pos - p - 1);
1461 1 : IdentTable * ident = IdTable.getIT(identificator());
1462 1 : if (ident->isFunc()) {
1463 1 : IdTable.pushType(_LABEL_);
1464 1 : IdTable.pushVal( new int (ident->getOffset()) );
1465 1 : IdentTable * label = IdTable.confirm();
1466 1 : poliz.pushVal(label);
1467 1 : types.push_back(_LABEL_);
1468 : } else {
1469 0 : poliz.pushVal(static_cast<IdentTable *>(ident->getVal()));
1470 0 : types.push_back(ident->getType());
1471 : }
1472 : }
1473 : }
1474 :
1475 27 : if ((c == ' ') || (c == '\n')) code >> c;
1476 27 : } while (c == ',');
1477 :
1478 4 : if (c != '}')
1479 0 : throw Obstacle(PROG_CLOSEBR);
1480 :
1481 4 : code >> c;
1482 4 : }
1483 :
1484 6 : void Parser::whileOp(void) {
1485 6 : IdTable.pushType(_LABEL_);
1486 6 : IdentTable * exit = IdTable.confirm();
1487 6 : exits.push(exit);
1488 :
1489 6 : if ((c == ' ') || (c == '\n')) code >> c;
1490 6 : if (c != '(')
1491 0 : throw Obstacle(BAD_PARAMS_OPBR);
1492 :
1493 6 : IdTable.pushType(_LABEL_);
1494 6 : IdTable.pushVal( new int (poliz.getSize()) );
1495 6 : IdentTable * condexpr = IdTable.confirm();
1496 6 : steps.push(condexpr);
1497 6 : code >> c;
1498 :
1499 6 : int fieldSize = 1;
1500 6 : type_t e2 = expr(&fieldSize); // условие продолжения
1501 :
1502 6 : if (e2 != _BOOLEAN_) throw Obstacle(BAD_IF);
1503 5 : poliz.pushOp(_NONE_, _BOOLEAN_, LNOT);
1504 5 : poliz.pushVal(exit);
1505 5 : poliz.pushOp(_BOOLEAN_, _LABEL_, JIT);
1506 :
1507 5 : if ((c == ' ') || (c == '\n')) code >> c;
1508 5 : if (c != ')')
1509 0 : throw Obstacle(BAD_PARAMS_CLBR);
1510 :
1511 5 : code >> c;
1512 5 : operation(); // тело цикла
1513 :
1514 5 : poliz.pushVal(condexpr);
1515 5 : poliz.pushOp(_NONE_, _LABEL_, JMP);
1516 :
1517 5 : exit->setVal(new int (poliz.getSize()) );
1518 5 : exits.pop();
1519 5 : steps.pop();
1520 5 : }
1521 3 : void Parser::breakOp(void) {
1522 3 : if (exits.isEmpty())
1523 1 : throw Obstacle(BREAK_OUTSIDE_CYCLE);
1524 2 : poliz.pushVal(static_cast<IdentTable *>(exits.top()));
1525 2 : poliz.pushOp(_NONE_, _LABEL_, JMP);
1526 2 : if (c != ';')
1527 0 : throw Obstacle(SEMICOLON);
1528 2 : code >> c;
1529 2 : }
1530 :
1531 2 : void Parser::continueOp(void) {
1532 2 : if (exits.isEmpty())
1533 1 : throw Obstacle(CONTINUE_OUTSIDE_CYCLE);
1534 1 : poliz.pushVal(static_cast<IdentTable *>(steps.top()));
1535 1 : poliz.pushOp(_NONE_, _LABEL_, JMP);
1536 1 : if (c != ';')
1537 0 : throw Obstacle(SEMICOLON);
1538 1 : code >> c;
1539 1 : }
1540 :
1541 5 : void Parser::gotoOp(void) {
1542 5 : code >> c;
1543 5 : char * label = identificator();
1544 : IdentTable * labval;
1545 : try {
1546 5 : labval = IdTable.getIT(label, false);
1547 : }
1548 3 : catch(Obstacle & o) {
1549 : // До метки ещё не дошли, но это не повод расстраиваться!
1550 3 : labval = saveLabel(label, 0);
1551 : }
1552 :
1553 5 : if (labval->getType() != _LABEL_)
1554 0 : throw Obstacle(BAD_LABEL);
1555 :
1556 5 : code >> c;
1557 :
1558 5 : poliz.pushVal(labval);
1559 5 : poliz.pushOp(_NONE_, _LABEL_, JMP);
1560 5 : }
1561 :
1562 18 : void Parser::readOp(void) {
1563 18 : if ((c == ' ') || (c == '\n')) code >> c;
1564 18 : if (c != '(')
1565 0 : throw Obstacle(BAD_PARAMS_OPBR);
1566 :
1567 18 : code >> c;
1568 18 : char * operand = identificator();
1569 18 : IdentTable * it = IdTable.getIT(operand);
1570 18 : poliz.pushVal(it);
1571 18 : poliz.pushOp(_NONE_, it->getType(), READ);
1572 :
1573 18 : if ((c == ' ') || (c == '\n')) code >> c;
1574 18 : if (c != ')')
1575 0 : throw Obstacle(BAD_PARAMS_CLBR);
1576 :
1577 18 : code >> c;
1578 :
1579 18 : if (c != ';')
1580 0 : throw Obstacle(SEMICOLON);
1581 :
1582 18 : code >> c;
1583 18 : }
1584 :
1585 81 : void Parser::writeOp(void) {
1586 81 : if ((c == ' ') || (c == '\n')) code >> c;
1587 81 : if (c != '(')
1588 0 : throw Obstacle(BAD_PARAMS_OPBR);
1589 :
1590 95 : do {
1591 176 : code >> c;
1592 176 : int fieldSize = 1;
1593 176 : type_t exop = expr(&fieldSize);
1594 171 : poliz.pushOp(_NONE_, exop, WRITE);
1595 171 : } while (c == ',');
1596 :
1597 76 : poliz.pushOp(_NONE_, _NONE_, ENDL);
1598 :
1599 76 : if (c != ')')
1600 0 : throw Obstacle(BAD_PARAMS_CLBR);
1601 :
1602 76 : code >> c;
1603 :
1604 76 : if (c != ';')
1605 0 : throw Obstacle(SEMICOLON);
1606 :
1607 76 : code >> c;
1608 76 : }
1609 :
1610 29 : void Parser::giveBIN(const char * filename, bool optimize, bool printPoliz, bool verbose) {
1611 29 : bin.open(filename, std::ios_base::binary | std::ios_base::out);
1612 29 : int x = 0;
1613 29 : bin.write((char*)&x, sizeof(int)); // Сюда запишем адрес начала команд
1614 :
1615 29 : IdentTable * ITp = &IdTable;
1616 :
1617 29 : if (optimize) {
1618 29 : Optimizer opt(&IdTable, &poliz, verbose);
1619 29 : ITp = opt.optimize();
1620 : }
1621 :
1622 29 : if (printPoliz) {
1623 0 : ITp->repr();
1624 0 : poliz.repr();
1625 0 : std::cout << std::endl;
1626 : }
1627 :
1628 358 : while (ITp->next != nullptr) {
1629 329 : ITp->setOffset((int)bin.tellp());
1630 329 : ITp->writeValToStream(bin);
1631 329 : ITp = ITp->next;
1632 : }
1633 :
1634 29 : int progStart = bin.tellp();
1635 29 : int b = poliz.getSize();
1636 29 : op_t * prog = poliz.getProg();
1637 29 : bool * execBit = poliz.getEB();
1638 1344 : for (int i = 0; i < b; i++) {
1639 1315 : if (execBit[i]) {
1640 660 : int tempint1 = (int)prog[i];
1641 660 : bin.write((char*)&tempint1, sizeof(int));
1642 : } else {
1643 655 : int tempint2 = IT_FROM_POLIZ(poliz, i)->getOffset();
1644 655 : bin.write((char*)&tempint2, sizeof(int));
1645 : }
1646 1315 : bin.write((char*)&execBit[i], sizeof(bool));
1647 : }
1648 29 : bin.seekp(0, std::ios_base::beg);
1649 29 : bin.write((char*)&progStart, sizeof(int));
1650 :
1651 29 : bin.close();
1652 29 : }
1653 :
1654 4920 : void Parser::revert(int x) {
1655 4920 : code.seekg((int)code.tellg() - x - 1);
1656 4920 : code >>= c;
1657 4920 : c.pos -= x + 1;
1658 4920 : }
|