AALanguage
The best language for those who have nothing to do
Loading...
Searching...
No Matches
Analyzer.cpp
Go to the documentation of this file.
1#include "Analyzer.h"
2
6
7void Analyzer::execute(std::string path, std::string lib_path) {
8 bool started = false;
9 try {
10 LibParser lib_parser(lib_path);
11 LexicalAnalyzer lex(path, lib_parser);
12
13 printf("\x1B[32mThe lexical analysis was successful\n\033[0m");
14
16 program(lex);
17
18 if (current_token.line != -1) {
19 printf("\x1B[31mUnexpected end of file\n\033[0m");
20 exit(0);
21 }
22
23 printf("\x1B[32mThe syntactic & semantic analysis was successful\n\033[0m");
24 printf("\x1B[32mThe internal representation of the program has been successfully generated\n\033[0m");
25 auto main = semantic.get_function("main", std::vector<Type>());
26 started = true;
27 auto result = prog.execute(main);
28 std::cout << "\nExit code: " << (result.second == nullptr ? "unknown" : *(std::string*)prog.convert(result, Poliz::PolizType::STRING_LITERAL));
29 } catch (std::exception ex) {
30 printf(("\x1B[31m\n" + std::string(ex.what())).c_str());
31 if (current_token.line != -1) {
32 std::cout << " (" << current_token.line << " line)";
33 }
34 printf("\033[0m");
35 if (started)
36 std::cout << "\nExit code: -1";
37 }
38}
39
40void Analyzer::semicolon(LexicalAnalyzer& lex, bool is_important) {
41 if (current_token.line == -1)
42 throw std::exception("Invalid end of line: ';' expected");
43 if (current_token.value != ";")
44 throw std::exception("Invalid token: ';' expected");
45 prog.put_lex({ Poliz::PolizType::SEMICOLON, new std::string(";") });
46 int curr = current_token.line;
47 int prev = lex.prev_token().line;
48 lex.get_token();
49 if (curr != prev) {
51 throw std::exception("Invalid end of line: ';' expected");
52 }
54 if (!is_important) {
56 }
57}
58
60 while (current_token.value == ";") {
61 prog.put_lex({ Poliz::PolizType::SEMICOLON, new std::string(";") });
63 }
64}
65
68 preprocessor(lex);
69 if (current_token.line == -1) return;
70 program_body(lex);
71}
72
74 while (current_token.value == "using") {
77 semicolon(lex);
79 }
81}
82
85 throw std::exception("Invalid token: identifier expected");
86 std::string curr_namespace = current_token.value;
88 while (current_token.value == ".") {
89 curr_namespace.push_back('.');
92 throw std::exception("Invalid token: identifier expected");
93 }
94 curr_namespace += current_token.value;
96 }
97 prog.put_lex({ Poliz::PolizType::USING, new std::string(curr_namespace) });
98}
99
101 if (current_token.line == -1) return;
103 may_be_semicolon(lex);
104 program_body(lex);
105}
106
108 bool is_const = current_token.value == "const";
109 ExprType curr_type;
110 if (is_const) {
111 current_token = lex.get_token();
114 } else
116 type(lex);
118 throw std::exception("Invalid token: identifier expected");
119 std::string name = current_token.value;
120 current_token = lex.get_token();
121 Identifier* ident = nullptr;
122 bool is_array = current_token.value == "[";
123 int size = 0;
124 if (is_array) {
125 current_token = lex.get_token();
126 if (lex.is_literal(current_token.value) != lex.integer)
127 throw std::exception("Invalid token: integer literal expected");
128 size = std::stoi(current_token.value);
129 current_token = lex.get_token();
130 if (current_token.value != "]")
131 throw std::exception("Invalid token: ']' expected");
132 current_token = lex.get_token();
133
134 ident = new Identifier(name, Type(curr_type, is_const, true, size));
135 } else {
136 ident = new Identifier(name, Type(curr_type, is_const, false));
137 }
138 if (current_token.value == "=") {
139 current_token = lex.get_token();
141 expression(lex, true);
142 if (!semantic.is_convertible(semantic.exprs.top().first, ident->type))
143 throw std::exception(("Cannot convert " + semantic.type_to_string(semantic.exprs.top().first) + " to " + semantic.type_to_string(ident->type)).c_str());
144 semantic.exprs.pop();
145 prog.put_lex({ Poliz::PolizType::ASSIGN, new std::string("=") });
146
150 }
151 } else if (semantic.is_in_function_header) {
153 throw std::exception("Parameters with default values cannot be followed by standard ones");
155 }
156 if (current_token.value != "=") {
157 if (is_array) {
158 semantic.init_array(curr_type, size, ident->value, ident->name);
159 } else ident->value = nullptr;
160 }
162}
163
164void Analyzer::var_definitions(LexicalAnalyzer& lex, bool need_semicolon, bool is_program) {
165 bool is_const = current_token.value == "const";
166 ExprType curr_type;
167 if (is_const) {
168 current_token = lex.get_token();
171 } else
173 type(lex);
175 throw std::exception("Invalid token: identifier expected");
176 std::string name = current_token.value;
177 current_token = lex.get_token();
178 Identifier* ident = nullptr;
179 bool is_array = current_token.value == "[";
180 int size = 0;
181 if (is_array) {
182 current_token = lex.get_token();
183 if (lex.is_literal(current_token.value) != lex.integer)
184 throw std::exception("Invalid token: integer literal expected");
185 size = std::stoi(current_token.value);
186 current_token = lex.get_token();
187 if (current_token.value != "]")
188 throw std::exception("Invalid token: ']' expected");
189 current_token = lex.get_token();
190
191 ident = new Identifier(name, Type(curr_type, is_const, true, size));
192 } else {
193 ident = new Identifier(name, Type(curr_type, is_const, false));
194 }
195 if (current_token.value == "=") {
196 current_token = lex.get_token();
198 expression(lex, true);
199 prog.put_lex({ Poliz::PolizType::ASSIGN, new std::string("=") });
200
201 if (!semantic.is_convertible(semantic.exprs.top().first, ident->type))
202 throw std::exception(("Cannot convert " + semantic.type_to_string(semantic.exprs.top().first) + " to " + semantic.type_to_string(ident->type)).c_str());
203 semantic.exprs.pop();
204 } else {
205 if (is_array) semantic.init_array(curr_type, size, ident->value, ident->name);
206 else ident->value = nullptr;
207 }
208 semantic.add_identifier(ident, is_program);
209 while (current_token.value == ",") {
210 current_token = lex.get_token();
212 throw std::exception("Invalid token: identifier expected");
213 name = current_token.value;
214 current_token = lex.get_token();
215 is_array = current_token.value == "[";
216 if (current_token.value == "[") {
217 current_token = lex.get_token();
218 if (lex.is_literal(current_token.value) != lex.integer)
219 throw std::exception("Invalid token: integer literal expected");
220 size = std::stoi(current_token.value);
221 current_token = lex.get_token();
222 if (current_token.value != "]")
223 throw std::exception("Invalid token: ']' expected");
224 current_token = lex.get_token();
225
226 ident = new Identifier(name, Type(curr_type, is_const, true, size));
227 } else {
228 ident = new Identifier(name, Type(curr_type, is_const, false));
229 }
230 if (current_token.value == "=") {
231 current_token = lex.get_token();
233 expression(lex, true);
234 prog.put_lex({ Poliz::PolizType::ASSIGN, new std::string("=") });
235
236 if (!semantic.is_convertible(semantic.exprs.top().first, ident->type))
237 throw std::exception(("Cannot convert " + semantic.type_to_string(semantic.exprs.top().first) + " to " + semantic.type_to_string(ident->type)).c_str());
238 semantic.exprs.pop();
239 } else {
240 if (is_array) semantic.init_array(curr_type, size, ident->value, ident->name);
241 else ident->value = nullptr;
242 }
243 semantic.add_identifier(ident, is_program);
244 }
245 if (need_semicolon) {
246 semicolon(lex);
247 may_be_semicolon(lex);
248 }
249}
250
252 if (current_token.value == "const")
253 current_token = lex.get_token();
254 default_type(lex);
255}
256
258 for (int i = 0; i < service_types.size(); ++i) {
260 current_token = lex.get_token();
261 return;
262 }
263 }
264 throw std::exception("Invalid token: service type expected");
265}
266
267void Analyzer::function(LexicalAnalyzer& lex, bool is_struct) {
269 if (current_token.value == "void")
270 current_token = lex.get_token();
271 else
272 default_type(lex);
273
275 Type func_type;
276 func_type.expr_type = curr_type;
278 throw std::exception("Invalid token: identifier expected");
279 std::string name = current_token.value;
280 current_token = lex.get_token();
281 std::unordered_map<std::string, void*> values;
282
283 semantic.current_function = func_type;
284
285 if (current_token.value == "[" && curr_type != ExprType::Void) {
286 current_token = lex.get_token();
287 if (lex.is_literal(current_token.value) != lex.integer)
288 throw std::exception("Invalid token: integer literal expected");
289 int size = std::stoi(current_token.value);
290 current_token = lex.get_token();
291 if (current_token.value != "]")
292 throw std::exception("Invalid token: ']' expected");
293 current_token = lex.get_token();
294
295 func_type.is_array = true;
296 func_type.array_size = size;
297 }
298
299 if (current_token.value != "(")
300 throw std::exception("Invalid token: '(' expected");
301 current_token = lex.get_token();
302
304 bool was_parameters = false;
305 int ptr = prog.get_size();
307
309 semantic.params_ptrs.clear();
310check_function_brace:
311 if (current_token.value == ")" || was_parameters) {
313 semantic.params_ptrs.clear();
314 current_token = lex.get_token();
315 if (current_token.value != "{")
316 throw std::exception("Invalid token: '{' expected");
317 current_token = lex.get_token();
318 while (current_token.value != "}" && current_token.line != -1)
319 statement(lex);
320 if (current_token.value != "}")
321 throw std::exception("Invalid token: '}' expected");
322 current_token = lex.get_token();
323 if (func_type.expr_type == ExprType::Void)
326 may_be_semicolon(lex);
327 } else {
328 parameter_list(lex);
329 was_parameters = true;
330 goto check_function_brace;
331 }
332}
333
335 if (current_token.value == "const") {
336 var_definitions(lex, true, is_program);
337 return;
338 }
339 if (current_token.value == "void") {
340 function(lex);
341 return;
342 }
343 default_type(lex);
345 throw std::exception("Invalid token: identifier expected");
346 current_token = lex.get_token();
347 std::string str = current_token.value;
348 if (current_token.value == "[") {
349 current_token = lex.get_token();
350 current_token = lex.get_token();
351 current_token = lex.get_token();
352 str = current_token.value;
356 }
357 if (str == "(") {
360 function(lex);
361 } else if (str == "=" || str == "," || str == ";") {
364 var_definitions(lex, true, is_program);
365 } else
366 throw std::exception("Invalid token: '=', ',', ';' or '(' expected");
367}
368
369void Analyzer::expression(LexicalAnalyzer& lex, bool is_vars, bool is_print) {
371 if (is_print)
373
374 while (!is_vars && current_token.value == ",") {
375 semantic.exprs.pop();
376 current_token = lex.get_token();
378 if (is_print)
380 if (!is_print)
381 prog.put_lex({ Poliz::PolizType::COMMA, new std::string(",") });
382 }
383}
384
387 std::vector<std::string> operations;
388 while (current_token.value == "=" || current_token.value == "+=" || current_token.value == "-=" || current_token.value == "*=" ||
389 current_token.value == "/=" || current_token.value == "%=" || current_token.value == ">>=" || current_token.value == "<<=" ||
390 current_token.value == "&=" || current_token.value == "^=" || current_token.value == "|=" || current_token.value == "->=" ||
391 current_token.value == "~=") {
392
393 auto operation = current_token.value;
394 auto full_operation = operation;
395 auto tmp_operation = operation;
396 if (operation != "=")
397 operation = operation.substr(0, operation.size() - 1);
398 if (!semantic.exprs.top().second)
399 throw std::exception("Cannot apply assignment operator to rvalue");
400 if (semantic.exprs.top().first.is_const)
401 throw std::exception("Cannot apply assignment operator to const");
402 auto prev = semantic.exprs.top().first;
403 semantic.exprs.pop();
404 current_token = lex.get_token();
406 operations.push_back(full_operation);
407 if (!semantic.check_operation(prev, semantic.exprs.top().first, operation))
408 throw std::exception(("Cannot apply " + tmp_operation + " operator with " + semantic.type_to_string(prev) +
409 " and " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
410 auto curr = semantic.exprs.top();
411 semantic.exprs.pop();
412 semantic.exprs.push({ semantic.calc_expr_type(prev, curr.first), curr.second });
413 }
414 for (int i = (int)operations.size() - 1; i >= 0; --i) {
415 prog.put_lex({ Poliz::PolizType::ASSIGN, new std::string(operations[i]) });
416 }
417}
418
421 while (current_token.value == "||") {
422 current_token = lex.get_token();
423 auto prev = semantic.exprs.top().first;
424 semantic.exprs.pop();
426 prog.put_lex({ Poliz::PolizType::LOGICAL_OR, new std::string("||") });
427 if (!semantic.check_operation(prev, semantic.exprs.top().first, "||"))
428 throw std::exception(("Cannot apply || operator with " + semantic.type_to_string(prev) + " and " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
429 auto curr = semantic.exprs.top();
430 semantic.exprs.pop();
431 semantic.exprs.push({ Type(ExprType::Bool, false, false), false });
432 }
433}
434
437 while (current_token.value == "&&") {
438 current_token = lex.get_token();
439 auto prev = semantic.exprs.top().first;
440 semantic.exprs.pop();
442 prog.put_lex({ Poliz::PolizType::LOGICAL_AND, new std::string("&&") });
443 if (!semantic.check_operation(prev, semantic.exprs.top().first, "&&"))
444 throw std::exception(("Cannot apply && operator with " + semantic.type_to_string(prev) + " and " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
445 auto curr = semantic.exprs.top();
446 semantic.exprs.pop();
447 semantic.exprs.push({ Type(ExprType::Bool, false, false), false });
448 }
449}
450
453 while (current_token.value == "|") {
454 current_token = lex.get_token();
455 auto prev = semantic.exprs.top().first;
456 semantic.exprs.pop();
458 prog.put_lex({ Poliz::PolizType::BITWISE_OR, new std::string("|") });
459 if (!semantic.check_operation(prev, semantic.exprs.top().first, "|"))
460 throw std::exception(("Cannot apply | operator with " + semantic.type_to_string(prev) + " and " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
461 auto curr = semantic.exprs.top();
462 semantic.exprs.pop();
463 semantic.exprs.push({ semantic.calc_expr_type(prev, curr.first), false });
464 }
465}
466
469 while (current_token.value == "^") {
470 current_token = lex.get_token();
471 auto prev = semantic.exprs.top().first;
472 semantic.exprs.pop();
474 prog.put_lex({ Poliz::PolizType::BITWISE_XOR, new std::string("^") });
475 if (!semantic.check_operation(prev, semantic.exprs.top().first, "^"))
476 throw std::exception(("Cannot apply ^ operator with " + semantic.type_to_string(prev) + " and " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
477 auto curr = semantic.exprs.top();
478 semantic.exprs.pop();
479 semantic.exprs.push({ semantic.calc_expr_type(prev, curr.first), false });
480 }
481}
482
485 while (current_token.value == "->") {
486 current_token = lex.get_token();
487 auto prev = semantic.exprs.top().first;
488 semantic.exprs.pop();
490 prog.put_lex({ Poliz::PolizType::BITWISE_CONS, new std::string("->") });
491 if (!semantic.check_operation(prev, semantic.exprs.top().first, "->"))
492 throw std::exception(("Cannot apply -> operator with " + semantic.type_to_string(prev) + " and " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
493 auto curr = semantic.exprs.top();
494 semantic.exprs.pop();
495 semantic.exprs.push({ semantic.calc_expr_type(prev, curr.first), false });
496 }
497}
498
501 while (current_token.value == "&") {
502 current_token = lex.get_token();
503 auto prev = semantic.exprs.top().first;
504 semantic.exprs.pop();
506 prog.put_lex({ Poliz::PolizType::BITWISE_AND, new std::string("&") });
507 if (!semantic.check_operation(prev, semantic.exprs.top().first, "&"))
508 throw std::exception(("Cannot apply & operator with " + semantic.type_to_string(prev) + " and " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
509 auto curr = semantic.exprs.top();
510 semantic.exprs.pop();
511 semantic.exprs.push({ semantic.calc_expr_type(prev, curr.first), false });
512 }
513}
514
517 while (current_token.value == "==" || current_token.value == "!=") {
518 auto operation = current_token.value;
519 current_token = lex.get_token();
520 auto prev = semantic.exprs.top().first;
521 semantic.exprs.pop();
523 prog.put_lex({ Poliz::PolizType::EQUALITY, new std::string(operation) });
524 if (!semantic.check_operation(prev, semantic.exprs.top().first, operation))
525 throw std::exception(("Cannot apply " + operation + " operator with " + semantic.type_to_string(prev) +
526 " and " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
527 auto curr = semantic.exprs.top();
528 semantic.exprs.pop();
529 semantic.exprs.push({ Type(ExprType::Bool, false, false), false });
530 }
531}
532
535 while (current_token.value == ">" || current_token.value == "<" || current_token.value == ">=" || current_token.value == "<=") {
536 auto operation = current_token.value;
537 current_token = lex.get_token();
538 auto prev = semantic.exprs.top().first;
539 semantic.exprs.pop();
541 prog.put_lex({ Poliz::PolizType::CMP, new std::string(operation) });
542 if (!semantic.check_operation(prev, semantic.exprs.top().first, operation))
543 throw std::exception(("Cannot apply " + operation + " operator with " + semantic.type_to_string(prev) +
544 " and " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
545 auto curr = semantic.exprs.top();
546 semantic.exprs.pop();
547 semantic.exprs.push({ Type(ExprType::Bool, false, false), false });
548 }
549}
550
552 plus_expression(lex);
553 while (current_token.value == ">>" || current_token.value == "<<") {
554 auto operation = current_token.value;
555 current_token = lex.get_token();
556 auto prev = semantic.exprs.top().first;
557 semantic.exprs.pop();
558 plus_expression(lex);
559 prog.put_lex({ Poliz::PolizType::BITWISE_SHIFT, new std::string(operation) });
560 if (!semantic.check_operation(prev, semantic.exprs.top().first, operation))
561 throw std::exception(("Cannot apply " + operation + " operator with " + semantic.type_to_string(prev) +
562 " and " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
563 auto curr = semantic.exprs.top();
564 semantic.exprs.pop();
565 semantic.exprs.push({ semantic.calc_expr_type(prev, curr.first), false });
566 }
567}
568
571 while (current_token.value == "+" || current_token.value == "-") {
572 auto operation = current_token.value;
573 current_token = lex.get_token();
574 auto prev = semantic.exprs.top().first;
575 semantic.exprs.pop();
577 prog.put_lex({ Poliz::PolizType::PLUS, new std::string(operation) });
578 if (!semantic.check_operation(prev, semantic.exprs.top().first, operation))
579 throw std::exception(("Cannot apply " + operation + " operator with " + semantic.type_to_string(prev) +
580 " and " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
581 auto curr = semantic.exprs.top();
582 semantic.exprs.pop();
583 semantic.exprs.push({ semantic.calc_expr_type(prev, curr.first), false });
584 }
585}
586
588 unary_expression(lex);
589 while (current_token.value == "*" || current_token.value == "/" || current_token.value == "%") {
590 auto operation = current_token.value;
591 current_token = lex.get_token();
592 auto prev = semantic.exprs.top().first;
593 semantic.exprs.pop();
594 unary_expression(lex);
595 prog.put_lex({ Poliz::PolizType::MULT, new std::string(operation) });
596 if (!semantic.check_operation(prev, semantic.exprs.top().first, operation))
597 throw std::exception(("Cannot apply " + operation + " operator with " + semantic.type_to_string(prev) +
598 " and " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
599 auto curr = semantic.exprs.top();
600 semantic.exprs.pop();
601 semantic.exprs.push({ semantic.calc_expr_type(prev, curr.first), false });
602 }
603}
604
606 std::vector<std::string> operations;
607 while (current_token.value == "+" || current_token.value == "-" || current_token.value == "!" || current_token.value == "~" ||
608 current_token.value == "++" || current_token.value == "--") {
609 operations.push_back(current_token.value);
610 current_token = lex.get_token();
611 }
613 for (int i = (int)operations.size() - 1; i >= 0; --i) {
614 prog.put_lex({ Poliz::PolizType::UNARY, new std::string(operations[i]) });
615 }
616
617 auto curr = semantic.exprs.top();
618 semantic.exprs.pop();
619 for (int i = operations.size() - 1; i >= 0; --i) {
620 if (curr.first.is_array)
621 throw std::exception(("Cannot apply " + operations[i] + " operator to " + semantic.type_to_string(curr.first)).c_str());
622 if (operations[i] == "+" || operations[i] == "-" || operations[i] == "~") {
623 if (curr.first.expr_type == ExprType::String || curr.first.expr_type == ExprType::Bool || curr.first.expr_type == ExprType::Unknown ||
624 curr.first.expr_type == ExprType::Void)
625 throw std::exception(("Cannot apply " + operations[i] + " operator to " + semantic.type_to_string(curr.first)).c_str());
626 curr.second = false;
627 } else if (operations[i] == "!") {
628 if (curr.first.expr_type != ExprType::Bool)
629 throw std::exception(("Cannot apply " + operations[i] + " operator to " + semantic.type_to_string(curr.first)).c_str());
630 curr.second = false;
631 } else {
632 if (curr.first.expr_type == ExprType::String || curr.first.expr_type == ExprType::Bool || curr.first.expr_type == ExprType::Unknown ||
633 curr.first.expr_type == ExprType::Void)
634 throw std::exception(("Cannot apply " + operations[i] + " operator to " + semantic.type_to_string(curr.first)).c_str());
635 if (!curr.second)
636 throw std::exception(("Cannot apply " + operations[i] + " operator to rvalue").c_str());
637 if (curr.first.is_const)
638 throw std::exception(("Cannot apply " + operations[i] + " operator to const").c_str());
639 }
640 }
641 semantic.exprs.push(curr);
642}
643
646 semantic.exprs.push({ semantic.literal_to_type(lex, current_token), false });
647 prog.put_lex({ Poliz::PolizType::LITERAL, new std::pair<std::string, Type>(current_token.value, semantic.literal_to_type(lex, current_token)) });
648 current_token = lex.get_token();
649 return;
650 }
651 if (current_token.value == "(") {
652 current_token = lex.get_token();
653 expression(lex);
654 if (current_token.value != ")")
655 throw std::exception("Invalid token: ')' expected");
656 current_token = lex.get_token();
657 return;
658 }
659 field(lex);
660}
661
662void Analyzer::field(LexicalAnalyzer& lex, bool only_array) {
664 if (current_token.value == "convert") {
666 if (current_token.value == "[")
667 throw std::exception("Cannot apply operator [] to rvalue string");
668 } else if (current_token.value == "rand")
669 rand_statement(lex);
670 else if (current_token.value == "strlen")
671 strlen_statement(lex);
672 else if (current_token.value == "time")
673 time_statement(lex);
674 else
675 throw std::exception("Invalid token: identifier expected");
676 return;
678 throw std::exception("Invalid token: identifier expected");
679 std::string name = current_token.value;
680 current_token = lex.get_token();
681 Identifier* ident = nullptr;
682 if (current_token.value == "[")
683 ident = semantic.get_identifier(name);
684 while (current_token.value == "[" || current_token.value == "(" && !only_array) { // TODO: field .
685 if (current_token.value == "[") {
686 if (!ident->type.is_array && ident->type.expr_type != ExprType::String)
687 throw std::exception("Cannot apply operator [] to anything other than an array or string");
688 current_token = lex.get_token();
689
691 expression(lex, true);
692 if (!semantic.is_convertible(semantic.exprs.top().first, Type(ExprType::Long, false, false)))
693 throw std::exception("Cannot access index that is not an integer");
694 if (ident->type.is_array)
695 prog.put_lex({ Poliz::PolizType::GETARR, new std::string("[]") });
696 else
697 prog.put_lex({ Poliz::PolizType::GETSTR, new std::string("[]") });
698 semantic.exprs.pop();
699 if (current_token.value != "]")
700 throw std::exception("Invalid token: ']' expected");
701 current_token = lex.get_token();
702 if (current_token.value != "[") {
703 semantic.exprs.push({ Type(ident->type.is_array ? ident->type.expr_type : ExprType::Char, false, false), true });
704 } else if (ident->type.expr_type != ExprType::String)
705 throw std::exception("Cannot apply operator [] to anything other than an array or string");
706 else {
707 current_token = lex.get_token();
708 expression(lex, true);
709 prog.put_lex({ Poliz::PolizType::GETSTR, new std::string("[]") });
710 if (!semantic.is_convertible(semantic.exprs.top().first, Type(ExprType::Long, false, false)))
711 throw std::exception("Cannot access index that is not an integer");
712 semantic.exprs.pop();
713 if (current_token.value != "]")
714 throw std::exception("Invalid token: ']' expected");
715 current_token = lex.get_token();
716 semantic.exprs.push({ Type(ExprType::Char, false, false), true });
717 }
718 return;
719 } /*else if (current_token.value == ".") {
720 current_token = lex.get_token();
721 if (current_token.type != LexicalAnalyzer::token_type::identifier)
722 throw std::exception("Invalid token: identifier expected");
723 current_token = lex.get_token();
724 } */ else { // TODO: check function
725 current_token = lex.get_token();
726 std::vector<Type> idents;
727 if (current_token.value != ")") {
728 expression(lex, true);
729 idents.push_back(semantic.exprs.top().first);
730 semantic.exprs.pop();
731 }
732 while (current_token.value == ",") {
733 current_token = lex.get_token();
734 expression(lex, true);
735 idents.push_back(semantic.exprs.top().first);
736 semantic.exprs.pop();
737 }
738 if (current_token.value != ")")
739 throw std::exception("Invalid token: ')' expected");
740 current_token = lex.get_token();
741
742 auto func = semantic.get_function(name, idents);
744 prog.put_lex({ Poliz::PolizType::CALL, new int(idents.size()) });
745
746 if (current_token.value == "[") {
747 if (!func.type.is_array)
748 throw std::exception("Cannot apply operator [] to anything other than an array or string");
749 current_token = lex.get_token();
750 expression(lex, true);
751 if (func.type.is_array != ExprType::String)
752 prog.put_lex({ Poliz::PolizType::GETARR, new std::string("[]") });
753 else
754 prog.put_lex({ Poliz::PolizType::GETSTR, new std::string("[]") });
755 if (!semantic.is_convertible(semantic.exprs.top().first, Type(ExprType::Long, false, false)))
756 throw std::exception("Cannot access index that is not an integer");
757 semantic.exprs.pop();
758 current_token = lex.get_token();
759
760 if (current_token.value != "[") {
761 semantic.exprs.push({ Type(func.type.expr_type, false, false), false });
762 } else if (func.type.expr_type != ExprType::String)
763 throw std::exception("Cannot apply operator [] to anything other than an array or string");
764 else {
765 current_token = lex.get_token();
766 expression(lex, true);
767 prog.put_lex({ Poliz::PolizType::GETSTR, new std::string("[]") });
768 if (!semantic.is_convertible(semantic.exprs.top().first, Type(ExprType::Long, false, false)))
769 throw std::exception("Cannot access index that is not an integer");
770 semantic.exprs.pop();
771 if (current_token.value != "]")
772 throw std::exception("Invalid token: ']' expected");
773 current_token = lex.get_token();
774 semantic.exprs.push({ Type(ExprType::Char, false, false), true });
775 }
776 } else
777 semantic.exprs.push({ func.type, false });
778 return;
779 }
780 }
781
782 ident = semantic.get_identifier(name);
783 semantic.exprs.push({ ident->type, true });
785}
786
791
792 var_definition(lex);
793 prog.blank();
795
796 while (current_token.value == ",") {
797 current_token = lex.get_token();
798 var_definition(lex);
799 prog.blank();
801 }
803}
804
806 if (current_token.value != "if")
807 throw std::exception("Invalid token: 'if' expected");
808 current_token = lex.get_token();
809 if (current_token.value != "(")
810 throw std::exception("Invalid token: '(' expected");
811 current_token = lex.get_token();
812 expression(lex);
813 if (semantic.exprs.top().first.expr_type != ExprType::Bool || semantic.exprs.top().first.is_array)
814 throw std::exception(("Invalid expression type. bool expected, but found " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
815 semantic.exprs.pop();
817 int ptrF = prog.get_size() - 1;
818 prog.put_lex({ Poliz::PolizType::FGO, new std::string("!F") });
819 if (current_token.value != ")")
820 throw std::exception("Invalid token: ')' expected");
821 current_token = lex.get_token();
822 statement(lex);
823 int* ptrEnd = new int(-1);
825 prog.put_lex({ Poliz::PolizType::GO, new std::string("!") });
826 prog.blank();
827 prog[ptrF].second = new int(prog.get_size() - 1);
828
829 while (current_token.value == "elif") {
830 current_token = lex.get_token();
831
832 if (current_token.value != "(")
833 throw std::exception("Invalid token: '(' expected");
834 current_token = lex.get_token();
835 expression(lex);
836 if (semantic.exprs.top().first.expr_type != ExprType::Bool || semantic.exprs.top().first.is_array)
837 throw std::exception(("Invalid expression type. bool expected, but found " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
838 semantic.exprs.pop();
840 ptrF = prog.get_size() - 1;
841 prog.put_lex({ Poliz::PolizType::FGO, new std::string("!F") });
842
843 if (current_token.value != ")")
844 throw std::exception("Invalid token: ')' expected");
845 current_token = lex.get_token();
846 statement(lex);
847
849 prog.put_lex({ Poliz::PolizType::GO, new std::string("!") });
850 prog.blank();
851 prog[ptrF].second = new int(prog.get_size() - 1);
852 }
853 if (current_token.value == "else") {
854 current_token = lex.get_token();
855 statement(lex);
856 }
857
858 *ptrEnd = prog.get_size() - 1;
859}
860
862 if (current_token.value == "break") {
863 if (semantic.break_ptr.empty())
864 throw std::exception("It is not possible to call break in the current context");
865 current_token = lex.get_token();
867 prog.put_lex({ Poliz::PolizType::GO, new std::string("!") });
868 } else if (current_token.value == "continue") {
869 if (semantic.continue_ptr.empty())
870 throw std::exception("It is not possible to call continue in the current context");
871 current_token = lex.get_token();
873 prog.put_lex({ Poliz::PolizType::GO, new std::string("!") });
874 } /*else if (current_token.value == "goto") { TODO: add goto
875 current_token = lex.get_token();
876 if (current_token.type != LexicalAnalyzer::token_type::identifier)
877 throw std::exception("Invalid token: 'identifier' expected");
878 current_token = lex.get_token();
879 } */else
880 throw std::exception("Invalid token: 'break', 'continue' or 'goto' expected");
881}
882
884 if (current_token.value != "return")
885 throw std::exception("Invalid token: 'return' expected");
886 current_token = lex.get_token();
887 if (current_token.value != ";") {
888 expression(lex);
889 auto type = semantic.exprs.top().first;
890 semantic.exprs.pop();
892 throw std::exception(("Cannot cast " + semantic.type_to_string(type) + " type to " + semantic.type_to_string(semantic.current_function)).c_str());
893 prog.put_lex({ Poliz::PolizType::RET, nullptr });
894 } else {
896 throw std::exception("The function requires a return value.");
898 }
899}
900
902 prog.blank();
903 int* ptrBeg = new int(prog.get_size() - 1);
904 int* ptrEnd = new int(-1);
905 semantic.continue_ptr.push(ptrBeg);
906 semantic.break_ptr.push(ptrEnd);
907 if (current_token.value != "while")
908 throw std::exception("Invalid token: 'while' expected");
909 current_token = lex.get_token();
910 if (current_token.value != "(")
911 throw std::exception("Invalid token: '(' expected");
912 current_token = lex.get_token();
913 expression(lex);
914 if (semantic.exprs.top().first.expr_type != ExprType::Bool || semantic.exprs.top().first.is_array)
915 throw std::exception(("Invalid expression type. bool expected, but found " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
916 semantic.exprs.pop();
918 prog.put_lex({ Poliz::PolizType::FGO, new std::string("!F") });
919
920 if (current_token.value != ")")
921 throw std::exception("Invalid token: ')' expected");
922 current_token = lex.get_token();
923 statement(lex);
924
926 prog.put_lex({ Poliz::PolizType::GO, new std::string("!") });
927
928 prog.blank();
929 *ptrEnd = prog.get_size() - 1;
930
932 semantic.break_ptr.pop();
933}
934
937 if (current_token.value != "for")
938 throw std::exception("Invalid token: 'for' expected");
939 current_token = lex.get_token();
940 if (current_token.value != "(")
941 throw std::exception("Invalid token: '(' expected");
942 current_token = lex.get_token();
943 if (current_token.value != ";") {
945 for (int i = 0; i < service_types.size(); ++i) {
947 var_definitions(lex, false);
948 break;
949 }
950 }
951 } else if (current_token.value == "const")
952 var_definitions(lex, false);
953 else {
955 current_token = lex.get_token();
958 var_definitions(lex, false);
959
960 } else {
962 expression(lex);
963 semantic.exprs.pop();
964 }
965 }
966 }
967 }
968 semicolon(lex, true);
969
970 prog.blank();
971 int* ptrExpr = new int(prog.get_size() - 1);
972 int* ptrEnd = new int(-1);
973 int* ptrAct = new int(-1);
974 int* ptrBody = new int(-1);
975 semantic.break_ptr.push(ptrEnd);
976 semantic.continue_ptr.push(ptrAct);
977
978 if (current_token.value != ";") {
979 expression(lex);
980 if (semantic.exprs.top().first.expr_type != ExprType::Bool || semantic.exprs.top().first.is_array)
981 throw std::exception(("Invalid expression type. bool expected, but found " + semantic.type_to_string(semantic.exprs.top().first)).c_str());
982 semantic.exprs.pop();
983
985 prog.put_lex({ Poliz::PolizType::FGO, new std::string("!F") });
986
988 prog.put_lex({ Poliz::PolizType::GO, new std::string("!") });
989 }
990 semicolon(lex, true);
991 prog.blank();
992 *ptrAct = prog.get_size() - 1;
993 if (current_token.value != ")") {
994 expression(lex);
995 semantic.exprs.pop();
996 }
998 prog.put_lex({ Poliz::PolizType::GO, new std::string("!") });
999 if (current_token.value != ")")
1000 throw std::exception("Invalid token: ')' expected");
1001 current_token = lex.get_token();
1002 prog.blank();
1003 *ptrBody = prog.get_size() - 1;
1004 statement(lex, true);
1006 prog.put_lex({ Poliz::PolizType::GO, new std::string("!") });
1007 prog.blank();
1008 *ptrEnd = prog.get_size() - 1;
1009 semantic.break_ptr.pop();
1010 semantic.continue_ptr.pop();
1011}
1012
1014 if (current_token.value != "switch")
1015 throw std::exception("Invalid token: 'switch' expected");
1016 current_token = lex.get_token();
1017 if (current_token.value != "(")
1018 throw std::exception("Invalid token: '(' expected");
1019 current_token = lex.get_token();
1020 expression(lex);
1021 Type curr_type = semantic.exprs.top().first;
1022 semantic.exprs.pop();
1023 std::unordered_set<std::string> cases;
1024 if (current_token.value != ")")
1025 throw std::exception("Invalid token: ')' expected");
1026 current_token = lex.get_token();
1027 if (current_token.value != "{")
1028 throw std::exception("Invalid token: '{' expected");
1029 current_token = lex.get_token();
1030 int* ptr_end = new int(-1);
1032
1033 while (current_token.value == "case" || current_token.value == "default") {
1034 semantic.break_ptr.push(ptr_end);
1035 if (current_token.value == "default") {
1036 current_token = lex.get_token();
1037 if (cases.count("default") != 0)
1038 throw std::exception("The default case has already been described above");
1039 cases.insert("default");
1040 if (current_token.value != ":")
1041 throw std::exception("Invalid token: ':' expected");
1042 current_token = lex.get_token();
1043
1044 statement(lex);
1045 } else {
1046 current_token = lex.get_token();
1048 throw std::exception("Invalid token: 'literal' expected");
1049
1050 std::string val = current_token.value;
1051 if ((val[0] >= '0' && val[0] <= '9') || val[0] == '-' || val[0] == '+') {
1052 while (val.back() < '0' || val.back() > '9')
1053 val.pop_back();
1054 val = std::to_string(std::stold(val));
1055 }
1056 if (cases.count(val) != 0)
1057 throw std::exception(("The case " + current_token.value + " has already been described above").c_str());
1059 throw std::exception(("Cannot cast " + semantic.type_to_string(semantic.literal_to_type(lex, current_token)) + " type to " + semantic.type_to_string(curr_type)).c_str());
1060
1061 cases.insert(val);
1062 current_token = lex.get_token();
1063 if (current_token.value != ":")
1064 throw std::exception("Invalid token: ':' expected");
1065 current_token = lex.get_token();
1066
1067 int* ptr_case_end = new int(-1);
1068 prog.put_lex({ Poliz::PolizType::LITERAL, new std::pair<std::string, ExprType>(val, curr_type.expr_type) });
1069 prog.put_lex({ Poliz::PolizType::SWITCH_CMP, new std::string("==") });
1070 prog.put_lex({ Poliz::PolizType::POINTER, ptr_case_end });
1071 prog.put_lex({ Poliz::PolizType::FGO, new std::string("!F") });
1072
1073 statement(lex);
1074 prog.blank();
1075 *ptr_case_end = prog.get_size() - 1;
1076 }
1077 semantic.break_ptr.pop();
1078 }
1079 if (current_token.value != "}")
1080 throw std::exception("Invalid token: '}' expected");
1081 current_token = lex.get_token();
1082
1083 prog.put_lex({ Poliz::PolizType::SWITCH_POP, new std::string("POP") });
1084 *ptr_end = prog.get_size() - 1;
1085}
1086
1088 if (current_token.value != "print")
1089 throw std::exception("Invalid token: 'print' expected");
1090 current_token = lex.get_token();
1091 if (current_token.value != "(")
1092 throw std::exception("Invalid token: '(' expected");
1093 current_token = lex.get_token();
1094 expression(lex, false, true);
1095 semantic.exprs.pop();
1096 if (current_token.value != ")")
1097 throw std::exception("Invalid token: ')' expected");
1098 current_token = lex.get_token();
1099}
1100
1102 if (current_token.value != "read")
1103 throw std::exception("Invalid token: 'read' expected");
1104 current_token = lex.get_token();
1105 if (current_token.value != "(")
1106 throw std::exception("Invalid token: '(' expected");
1107 current_token = lex.get_token();
1108 field(lex, true);
1109 semantic.exprs.pop();
1110 prog.put_lex({ Poliz::PolizType::READ, nullptr });
1111 while (current_token.value == ",") {
1112 current_token = lex.get_token();
1113 field(lex, true);
1114 semantic.exprs.pop();
1115 prog.put_lex({ Poliz::PolizType::READ, nullptr });
1116 }
1117 if (current_token.value != ")")
1118 throw std::exception("Invalid token: ')' expected");
1119 current_token = lex.get_token();
1120}
1121
1123 if (current_token.value != "readln")
1124 throw std::exception("Invalid token: 'readln' expected");
1125 current_token = lex.get_token();
1126 if (current_token.value != "(")
1127 throw std::exception("Invalid token: '(' expected");
1128 current_token = lex.get_token();
1129 field(lex, true);
1130 auto type = semantic.exprs.top().first;
1131 if (type.expr_type != ExprType::String)
1132 throw std::exception("Cannot use readln with not a string identifier");
1133 semantic.exprs.pop();
1135 if (current_token.value != ")")
1136 throw std::exception("Invalid token: ')' expected");
1137 current_token = lex.get_token();
1138}
1139
1140void Analyzer::statement(LexicalAnalyzer& lex, bool prev_table) {
1141 if (current_token.value == "{") {
1142 current_token = lex.get_token();
1143 if (!prev_table)
1145 while (current_token.value != "}" && current_token.line != -1)
1146 statement(lex);
1147 if (current_token.value != "}")
1148 throw std::exception("Invalid token: '}' expected");
1149 current_token = lex.get_token();
1151 may_be_semicolon(lex);
1152 return;
1153 }
1154 if (current_token.value == "if") {
1155 if_statement(lex);
1156 may_be_semicolon(lex);
1157 return;
1158 }
1159 if (current_token.value == "goto" || current_token.value == "break" || current_token.value == "continue") {
1160 goto_statement(lex);
1161 semicolon(lex);
1162 may_be_semicolon(lex);
1163 return;
1164 }
1165 if (current_token.value == "return") {
1166 return_statement(lex);
1167 semicolon(lex);
1168 may_be_semicolon(lex);
1169 return;
1170 }
1171 if (current_token.value == "while") {
1172 while_statement(lex);
1173 may_be_semicolon(lex);
1174 return;
1175 }
1176 if (current_token.value == "for") {
1177 for_statement(lex);
1178 may_be_semicolon(lex);
1179 return;
1180 }
1181 if (current_token.value == "switch") {
1182 switch_statement(lex);
1183 may_be_semicolon(lex);
1184 return;
1185 }
1186 if (current_token.value == "read") {
1187 read_statement(lex);
1188 semicolon(lex);
1189 may_be_semicolon(lex);
1190 return;
1191 }
1192 if (current_token.value == "print") {
1193 print_statement(lex);
1194 semicolon(lex);
1195 may_be_semicolon(lex);
1196 return;
1197 }
1198 if (current_token.value == "readln") {
1199 readln_statement(lex);
1200 semicolon(lex);
1201 may_be_semicolon(lex);
1202 return;
1203 }
1204 if (current_token.value == "exit") {
1205 exit_statement(lex);
1206 semicolon(lex);
1207 may_be_semicolon(lex);
1208 return;
1209 }
1210 if (current_token.value == "convert") {
1211 convert_statement(lex);
1212 semicolon(lex);
1213 may_be_semicolon(lex);
1214 return;
1215 }
1217 for (int i = 0; i < service_types.size(); ++i) {
1218 if (service_types[i] == current_token.value) {
1219 var_definitions(lex);
1220 return;
1221 }
1222 }
1223 }
1224 if (current_token.value == "const") {
1225 var_definitions(lex);
1226 return;
1227 }
1229 current_token = lex.get_token();
1231 current_token = lex.prev_token();
1232 var_definitions(lex);
1233 } else {
1234 current_token = lex.prev_token();
1235 expression(lex);
1236 semicolon(lex);
1237 may_be_semicolon(lex);
1238 }
1239 } else {
1240 if (current_token.value != ";") {
1241 expression(lex);
1242 semantic.exprs.pop();
1243 semicolon(lex);
1244 may_be_semicolon(lex);
1245 } else {
1246 may_be_semicolon(lex);
1247 }
1248 }
1249}
1250
1252 current_token = lex.get_token();
1253 if (current_token.value != "(")
1254 throw std::exception("Invalid token: '(' expected");
1255 current_token = lex.get_token();
1256 expression(lex);
1257 prog.put_lex({ Poliz::PolizType::EXIT, nullptr });
1258 if (current_token.value != ")")
1259 throw std::exception("Invalid token: ')' expected");
1260 current_token = lex.get_token();
1261}
1262
1264 current_token = lex.get_token();
1265 if (current_token.value != "(")
1266 throw std::exception("Invalid token: '(' expected");
1267 current_token = lex.get_token();
1268 expression(lex);
1269 if (semantic.exprs.top().first.expr_type != ExprType::String)
1270 throw std::exception("Invalid operand: cannot use strlen function with not a string");
1271 semantic.exprs.pop();
1272 semantic.exprs.push({ Type(ExprType::Int, false, false), false });
1274 if (current_token.value != ")")
1275 throw std::exception("Invalid token: ')' expected");
1276 current_token = lex.get_token();
1277}
1278
1280 current_token = lex.get_token();
1281 if (current_token.value != "(")
1282 throw std::exception("Invalid token: '(' expected");
1283 current_token = lex.get_token();
1284 expression(lex, true);
1285 if (current_token.value != ",")
1286 throw std::exception("Invalid token: ',' expected");
1287 current_token = lex.get_token();
1288 std::string* val = new std::string(current_token.value);
1289 default_type(lex);
1290 semantic.exprs.pop();
1291 semantic.exprs.push({ Type(semantic.string_to_type(*val), false, false), false });
1293 if (current_token.value != ")")
1294 throw std::exception("Invalid token: ')' expected");
1295 current_token = lex.get_token();
1296}
1297
1299 current_token = lex.get_token();
1300 if (current_token.value != "(")
1301 throw std::exception("Invalid token: '(' expected");
1302 current_token = lex.get_token();
1303 if (current_token.value != ")")
1304 throw std::exception("Invalid token: ')' expected");
1305 current_token = lex.get_token();
1306 prog.put_lex({ Poliz::PolizType::RAND, nullptr });
1307 semantic.exprs.push({ Type(ExprType::Int, false, false), false });
1308}
1309
1311 current_token = lex.get_token();
1312 if (current_token.value != "(")
1313 throw std::exception("Invalid token: '(' expected");
1314 current_token = lex.get_token();
1315 if (current_token.value != ")")
1316 throw std::exception("Invalid token: ')' expected");
1317 current_token = lex.get_token();
1318 prog.put_lex({ Poliz::PolizType::TIME, nullptr });
1319 semantic.exprs.push({ Type(ExprType::Long, false, false), false });
1320}