DEADSOFTWARE

a2acec53a29458d3df6aa63044704f5a20eb847a
[mp3cc.git] / mpc / parser / parser.c
1 /********************************************************************
3 parser.c - recursive-descent parser
5 Niksa Orlic, 2004-04-19
7 ********************************************************************/
10 //#include "../util/message.h"
11 #include "../util/error.h"
12 #include "../util/strings.h"
13 #include "../structures/type_list.h"
14 #include "../structures/string_list.h"
15 #include "../structures/type.h"
16 #include "../structures/identifier.h"
17 #include "../structures/name_table.h"
18 #include "../classgen/bytecode.h"
19 #include "../structures/block.h"
20 #include "../lex/tokens.h"
21 #include "../util/memory.h"
22 #include "../structures/unit.h"
24 #include "../classgen/constant_pool.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #include "../classgen/classgen.h"
32 #include "parser.h"
33 #include "stdpas.h"
35 #pragma warning (disable: 4305)
36 #pragma warning (disable: 4761)
38 extern int procedure_linenum;
40 //extern void (*compile_terminate)();
42 extern FILE* yyin;
45 int current_token;
46 block *root_block;
48 int next_record_ID;
50 /* Scanner variables and functions */
51 extern long int linenum;
52 extern int new_linenum;
53 extern long int integer_constant;
54 extern int error_count;
55 extern float real_constant;
56 extern char boolean_constant;
57 extern char char_constant;
58 extern string *string_constant;
59 extern char *yytext;
60 extern int yylex();
61 extern FILE *yyin;
62 extern void backchar(int c);
63 extern int goverify;
65 extern void VerifyFile(char*);
67 extern int usesFloat;
69 extern char *output_path;
71 extern int detect_units_only;
73 /* Small macro for outputting the yytext value */
74 #define YYTEXT_STRING (current_token == END_OF_INPUT ? "<EOF>" : yytext)
77 /* A macro to explicitly declare we didn't forget break inside
78 the case statement */
79 //#define no_break /* do nothing */;
82 int inside_loop = 0; /* the counter checks if 'break' is located inside a loop */
84 int compiling_unit = 0; /* set to 1 if this is an unit */
85 int inside_interface_part = 0; /* if the compiler is inside the interface part of the unit */
86 int inside_implementation_part = 0; /* if the compiler is inside the implementation part of the unit */
88 int inside_routine = 0;
89 int routine_return_type = void_type;
90 int routine_return_parameters_length = 0;
92 string *str_program_name;
93 string *str_currrent_routine_name;
95 extern int mathType;
97 FILE *symbols_file;
99 //ASM - LABEL TABLE
100 int nam[1024];
101 int lab[1024];
102 int len[1024];
103 //int ofs[1024];
104 int labcount;
106 /*
107 Starts parsing the input file. The grammar rule
108 used is:
110 <parser_start> -> <RD_program_header> <RD_uses_list> <RD_block> . <<EOF>>
111 -> <RD_program_header> <RD_unit_interface> <RD_unit_implementation> <RD_unit_initialization> <RD_unit_finalization> . <<EOF>>
112 */
113 void parser_start()
115 block *program_block;
116 int random_field_index;
117 int random_class_index;
118 int random_method_index;
120 root_block = initialize_root_block();
122 current_token = yylex();
124 compiling_unit = 0;
126 str_program_name = RD_program_header();
128 if (compiling_unit == 0)
130 RD_uses_list();
132 if (str_program_name == NULL)
133 str_program_name = string_from_cstr("");
135 program_block = block_create(root_block, str_program_name);
137 // j-a-s-d
138 if (detect_units_only)
139 goto end_parsing;
141 /* initialize the random number generator */
142 random_field_index = cp_add_fieldref("M", "RNG", "Ljava/util/Random;");
143 random_class_index = cp_add_class("java/util/Random");
144 random_method_index = cp_add_methodref("java/util/Random", "<init>", "()V");
146 bytecode_append(program_block->code, new$);
147 bytecode_append_short_int(program_block->code, random_class_index);
149 bytecode_append(program_block->code, dup$);
151 bytecode_append(program_block->code, invokespecial$);
152 bytecode_append_short_int(program_block->code, random_method_index);
154 bytecode_append(program_block->code, putstatic$);
155 bytecode_append_short_int(program_block->code, random_field_index);
156 /* END initialize the random number generator */
158 /* initialize the index counter field */
159 bytecode_append(program_block->code, bipush$);
160 bytecode_append(program_block->code, 25);
161 bytecode_append(program_block->code, newarray$);
162 bytecode_append(program_block->code, 10);
163 bytecode_append(program_block->code, putstatic$);
164 bytecode_append_short_int(program_block->code, cp_add_fieldref("M", "IC", "[I"));
165 /* END initialize the IC field */
167 /* reset the keyboard buffers */
168 bytecode_append(program_block->code, iconst_0$);
169 bytecode_append(program_block->code, putstatic$);
170 bytecode_append_short_int(program_block->code, cp_add_fieldref("M", "KC", "I"));
171 bytecode_append(program_block->code, iconst_0$);
172 bytecode_append(program_block->code, putstatic$);
173 bytecode_append_short_int(program_block->code, cp_add_fieldref("M", "KP", "I"));
174 /* END reset the keyboard buffers */
176 RD_block(program_block);
178 /* do the 'halt' at the end of program execution */
179 bytecode_append(program_block->code, getstatic$);
180 bytecode_append_short_int(program_block->code, cp_add_fieldref("FW", "fw", "LFW;"));
181 bytecode_append(program_block->code, iconst_1$);
182 bytecode_append(program_block->code, invokevirtual$);
183 bytecode_append_short_int(program_block->code, cp_add_methodref("FW", "destroyApp", "(Z)V"));
185 /* bytecode verififer wants this unnecessary return */
186 bytecode_append(program_block->code, return$);
188 else
190 char *symbols_filename;
191 int filepos;
193 symbols_filename = (char*) mem_alloc(strlen(output_path) + string_length(str_program_name) + 10);
194 #ifdef WIN32
195 sprintf(symbols_filename, "%s\\%s.bsf", output_path, string_get_cstr(str_program_name));
196 #endif
197 #ifdef UNIX
198 sprintf(symbols_filename, "%s/%s.bsf", output_path, string_get_cstr(str_program_name));
199 #endif
200 symbols_file = fopen(symbols_filename, "wb");
201 mem_free(symbols_filename);
203 if (symbols_file == NULL)
204 die(7);
206 program_block = block_create(root_block, str_program_name);
208 lowercase(string_get_cstr(str_program_name));
210 RD_unit_interface(program_block);
211 RD_unit_implementation(program_block);
212 RD_unit_initialization(program_block);
213 RD_unit_finalization(program_block);
215 // j-a-s-d
216 if (detect_units_only) {
217 fclose(symbols_file);
218 goto end_parsing;
221 if (current_token != KWD_END)
222 add_error_message(203, "end", YYTEXT_STRING);
223 else
225 current_token = yylex();
228 fclose(symbols_file);
230 bytecode_append(program_block->code, return$);
233 /* check if there are forward declarations without the body */
234 check_unmatched_forward_declarations(program_block, program_block->names);
236 if (current_token != DOT)
238 add_error_message(200, ".", YYTEXT_STRING);
240 /* Error-recovery: find the end of input */
241 while (current_token != END_OF_INPUT)
242 current_token = yylex();
244 else
245 current_token = yylex();
247 if (current_token != END_OF_INPUT)
249 add_error_message(201, YYTEXT_STRING, "");
252 if (error_count == 0)
254 FILE *fp;
255 char *output_file_name;
256 char *short_file_name;
258 if (compiling_unit == 0)
260 output_file_name = (char*) mem_alloc(strlen(output_path) + 10);
261 short_file_name = (char*) mem_alloc(10);
263 else
265 output_file_name = (char*) mem_alloc(strlen(output_path) + string_length(str_program_name) + 10);
266 short_file_name = (char*) mem_alloc(string_length(str_program_name) + 10);
269 if (output_file_name == NULL)
270 die (1);
272 if (compiling_unit == 0)
274 #ifdef WIN32
275 sprintf(output_file_name, "%s\\M.class", output_path);
276 #endif
277 #ifdef UNIX
278 sprintf(output_file_name, "%s/M.class", output_path);
279 #endif
280 sprintf(short_file_name, "M");
282 else
284 #ifdef WIN32
285 sprintf(output_file_name, "%s\\%s.class", output_path, string_get_cstr(str_program_name));
286 #endif
287 #ifdef UNIX
288 sprintf(output_file_name, "%s/%s.class", output_path, string_get_cstr(str_program_name));
289 #endif
290 sprintf(short_file_name, "%s", string_get_cstr(str_program_name));
293 fp = fopen(output_file_name, "wb");
294 mem_free(output_file_name);
295 if (fp == NULL)
297 die (4);
299 create_class_file(program_block, fp);
300 fclose(fp);
302 if (goverify!=0) VerifyFile(short_file_name);
304 // j-a-s-d
305 end_parsing:
306 string_destroy(str_program_name);
308 block_destroy(program_block);
309 block_destroy(root_block);
313 /*
314 Program header, uses the grammar rule:
316 <RD_program_header> -> [program IDENTIFIER ;]
317 */
318 string* RD_program_header()
320 string *program_name = NULL;
322 if ((current_token == KWD_PROGRAM)
323 || (current_token == KWD_UNIT))
325 if (current_token == KWD_UNIT)
326 compiling_unit = 1;
328 current_token = yylex();
330 if (current_token != IDENTIFIER)
332 add_error_message(202, "", "");
334 else
335 program_name = string_from_cstr(YYTEXT_STRING);
337 if ((compiling_unit) && (string_length(program_name) < 3))
338 add_error_message(454, "", "");
340 current_token = yylex();
342 if (current_token != SEMI_COLON)
345 add_error_message(200, ";", YYTEXT_STRING);
347 /* Error-recovery: find any of the following:
348 CONST, TYPE, VAR, PROCEDURE, FUNCTION, BEGIN, ., EOF
349 */
350 while ( (current_token != KWD_CONST)
351 && (current_token != KWD_TYPE)
352 && (current_token != KWD_VAR)
353 && (current_token != KWD_PROCEDURE)
354 && (current_token != KWD_FUNCTION)
355 && (current_token != KWD_BEGIN)
356 && (current_token != DOT)
357 && (current_token != END_OF_INPUT))
359 current_token = yylex();
362 else
363 current_token = yylex();
366 return program_name;
369 /*
370 the interface part of the unit source
372 <RD_unit_interface> -> [interface [;] <RD_block> ]
374 special rules apply to declarations inside the interface; global variable inside_interface_part is used to denote the special cases
375 */
376 void RD_unit_interface(block *current_block)
378 if (current_token != KWD_INTERFACE)
380 if ((current_token == KWD_IMPLEMENTATION)
381 || (current_token == KWD_INITIALIZATION))
382 return;
384 add_error_message(203, "interface", YYTEXT_STRING);
386 do
388 current_token = yylex();
390 while ((current_token != KWD_IMPLEMENTATION) && (current_token != END_OF_INPUT));
392 return;
395 current_token = yylex();
397 if (current_token == SEMI_COLON)
398 current_token = yylex();
400 inside_interface_part = 1;
401 RD_block(current_block);
402 inside_interface_part = 0;
405 /*
406 the implementation part of the unit source
408 <RD_unit_implementation> -> implementation [;] <RD_uses_list> <RD_block>
409 */
410 void RD_unit_implementation(block *current_block)
412 if (current_token == END_OF_INPUT)
413 return;
415 if (current_token != KWD_IMPLEMENTATION)
417 add_error_message(203, "implementation", YYTEXT_STRING);
419 do
421 current_token = yylex();
423 while (current_token != END_OF_INPUT);
425 return;
428 current_token = yylex();
430 if (current_token == SEMI_COLON)
431 current_token = yylex();
433 RD_uses_list();
435 // j-a-s-d
436 if (detect_units_only)
437 return;
439 inside_implementation_part = 1;
440 RD_block(current_block);
441 inside_implementation_part = 0;
444 /*
445 the initialization part of the unit
447 <RD_unit_initialization> -> [initialization [;] <RD_block_body> ]
448 */
449 void RD_unit_initialization(block* current_block)
451 if (current_token == KWD_INITIALIZATION)
453 current_token = yylex();
455 if (current_token == SEMI_COLON)
456 current_token = yylex();
458 RD_block_body(current_block);
462 /*
463 the finalization part of the unit is not supported by the compiler
464 */
465 void RD_unit_finalization(block *current_block)
467 if (current_token == KWD_FINALIZATION)
469 add_error_message(220, "", "");
470 current_token = yylex();
471 return;
475 /*
476 The list of 'uses' directives.
477 <RD_uses_list> -> ( uses NAME; )*
478 */
479 void RD_uses_list()
481 while (current_token == KWD_USES)
483 following_unit:
484 current_token = yylex();
486 if (current_token != IDENTIFIER)
488 add_error_message(202, "", "");
490 /* do error recovery */
491 while ((current_token != END_OF_INPUT)
492 && (current_token != SEMI_COLON))
494 current_token = yylex();
495 return;
499 /* process the library */
500 load_extern_library(string_from_cstr(YYTEXT_STRING));
502 current_token = yylex();
504 if (current_token == COMMA)
505 goto following_unit;
507 if (current_token != SEMI_COLON)
509 add_error_message(200, ";", YYTEXT_STRING);
511 /* do error recovery */
512 while ((current_token != END_OF_INPUT)
513 && (current_token != SEMI_COLON))
515 current_token = yylex();
516 return;
519 else
520 current_token = yylex();
523 if (current_token == SEMI_COLON)
524 current_token = yylex();
526 if (detect_units_only)
528 mem_close();
530 fclose(yyin);
532 // j-a-s-d
533 //compile_terminate();
534 exit(0);
539 /*
540 Program block with declarations and code.
541 The grammar rule used:
543 <RD_block> -> const <RD_const_declaration>
544 | type <RD_type_declaration>
545 | var <RD_var_declaration>
546 | procedure <RD_procedure_declaration>
547 | function <RD_function_declaration>
548 | begin <RD_block_body> end
549 */
550 block* RD_block(block *current_block)
552 switch (current_token)
554 case KWD_CONST:
556 current_token = yylex();
557 RD_const_declaration(current_block);
558 break;
561 case KWD_TYPE:
563 current_token = yylex();
564 RD_type_declaration(current_block);
565 break;
568 case KWD_VAR:
570 current_token = yylex();
571 RD_var_declaration(current_block);
572 break;
575 case KWD_PROCEDURE:
577 if (current_block->parent_block != root_block)
578 add_error_message(431, "", "");
580 current_token = yylex();
581 RD_procedure_declaration(current_block);
582 break;
585 case KWD_FUNCTION:
587 if (current_block->parent_block != root_block)
588 add_error_message(431, "", "");
590 current_token = yylex();
591 RD_function_declaration(current_block);
592 break;
595 case KWD_BEGIN:
597 if ((inside_interface_part) || (inside_implementation_part))
599 add_error_message(204, YYTEXT_STRING, "");
601 do
603 current_token = yylex();
604 } while (current_token != END_OF_INPUT);
606 break;
609 current_token = yylex();
611 RD_block_body(current_block);
613 if (current_token != KWD_END)
615 add_error_message(203, "end", YYTEXT_STRING);
617 else
618 current_token = yylex();
620 break;
623 default:
625 if ((inside_interface_part)
626 && ( (current_token == KWD_IMPLEMENTATION)
627 || (current_token == KWD_INITIALIZATION)
628 || (current_token == KWD_FINALIZATION)
629 || (current_token == KWD_END)
630 ))
632 return current_block;
635 if ((inside_implementation_part)
636 && ( (current_token == KWD_INITIALIZATION)
637 || (current_token == KWD_FINALIZATION)
638 || (current_token == KWD_END)
639 ))
641 return current_block;
645 add_error_message(204, YYTEXT_STRING, "");
647 /* Error-recovery: find any of the following:
648 CONST, TYPE, VAR, PROCEDURE, FUNCTION, BEGIN, ., EOF
649 */
650 while ( (current_token != KWD_CONST)
651 && (current_token != KWD_TYPE)
652 && (current_token != KWD_VAR)
653 && (current_token != KWD_PROCEDURE)
654 && (current_token != KWD_FUNCTION)
655 && (current_token != KWD_BEGIN)
656 && (current_token != DOT)
657 && (current_token != END_OF_INPUT))
659 current_token = yylex();
662 break;
666 return current_block;
670 /*
671 Constant declarations, the grammar rule used is:
673 <RD_constant_declaration> -> ( IDN = CONST ; )+ <RD_block>
674 */
675 void RD_const_declaration(block *current_block)
677 int first_pass = 1;
678 string *constant_name;
680 do
682 if (first_pass)
683 first_pass = 0;
684 else
685 current_token = yylex();
687 if (current_token != IDENTIFIER)
689 break;
692 if (!block_check_name(current_block, YYTEXT_STRING))
694 add_error_message(400, YYTEXT_STRING, "");
697 constant_name = string_from_cstr(YYTEXT_STRING);
699 current_token = yylex();
701 if (current_token != OP_EQUAL)
703 add_error_message(200, "=", YYTEXT_STRING);
705 /* Error-recovery: find the first SEMI_COLON */
706 while ((current_token != SEMI_COLON)
707 && (current_token != END_OF_INPUT))
709 current_token = yylex();
712 if (current_token == END_OF_INPUT)
714 add_error_message(207, "", "");
715 string_destroy(constant_name);
716 return;
719 continue;
722 current_token = yylex();
724 // j-a-s-d: quick fix to support negative integer constants
725 int sign_factor = 1;
726 if (current_token == OP_MINUS) {
727 sign_factor = -1;
728 current_token = yylex();
729 if (current_token != CST_INTEGER) {
730 add_error_message(206, "", "");
731 return;
735 switch (current_token)
737 case CST_INTEGER:
739 add_integer_constant(current_block,
740 integer_constant*sign_factor, string_get_cstr(constant_name));
742 if (inside_interface_part)
743 bsf_write_integer_constant(integer_constant, string_get_cstr(constant_name));
745 current_token = yylex();
746 break;
749 case CST_REAL:
751 add_real_constant(current_block,
752 real_constant, string_get_cstr(constant_name));
754 if (inside_interface_part)
755 bsf_write_real_constant(real_constant, string_get_cstr(constant_name));
757 current_token = yylex();
758 break;
761 case CST_BOOLEAN:
763 add_boolean_constant(current_block,
764 boolean_constant, string_get_cstr(constant_name));
766 if (inside_interface_part)
767 bsf_write_boolean_constant(boolean_constant, string_get_cstr(constant_name));
769 current_token = yylex();
770 break;
773 case CST_CHAR:
775 add_char_constant(current_block,
776 char_constant, string_get_cstr(constant_name));
778 if (inside_interface_part)
779 bsf_write_char_constant(char_constant, string_get_cstr(constant_name));
781 current_token = yylex();
782 break;
785 case CST_STRING:
787 add_string_constant(current_block,
788 string_constant, string_get_cstr(constant_name));
790 if (inside_interface_part)
791 bsf_write_string_constant(string_constant, string_get_cstr(constant_name));
793 current_token = yylex();
794 break;
797 default:
799 /* TODO:: ovo nije dobro, ovdje bi mogao pisati bilo kakav
800 konstantni izraz */
801 add_error_message(206, "", "");
803 /* Error-recovery: find the first semi-colon */
804 while ( (current_token != SEMI_COLON)
805 && (current_token != END_OF_INPUT))
807 current_token = yylex();
810 if (current_token == END_OF_INPUT)
812 add_error_message(207, "", "");
813 return;
816 break;
820 string_destroy(constant_name);
822 } while (current_token == SEMI_COLON);
824 RD_block(current_block);
828 /*
829 Handles variable declarations field. The grammar rule used is:
831 <RD_var_declaration> -> (<RD_identifier_list> : <RD_type> ;)+ <RD_block>
832 */
833 void RD_var_declaration(block *current_block)
835 string_list *identifier_list;
836 type *var_type;
838 do
840 identifier_list = RD_identifier_list(current_block, 1);
842 if (current_token != COLON)
844 add_error_message(200, ":", YYTEXT_STRING);
846 /* Error-recovery: find any of the following:
847 CONST, TYPE, VAR, PROCEDURE, FUNCTION, BEGIN, ., EOF
848 */
849 while ( (current_token != KWD_CONST)
850 && (current_token != KWD_TYPE)
851 && (current_token != KWD_VAR)
852 && (current_token != KWD_PROCEDURE)
853 && (current_token != KWD_FUNCTION)
854 && (current_token != KWD_BEGIN)
855 && (current_token != DOT)
856 && (current_token != END_OF_INPUT))
858 current_token = yylex();
861 if ((current_token == END_OF_INPUT)
862 || (current_token == DOT))
864 add_error_message(207, "", "");
865 return;
868 break;
871 current_token = yylex();
873 var_type = RD_type(current_block);
875 if (var_type->type_class == interval_type)
877 add_error_message(440, "", "");
878 var_type->type_class = integer_type;
881 add_variables(current_block, identifier_list, var_type);
883 if (inside_interface_part)
884 bsf_write_variables(identifier_list, var_type);
886 type_destroy(var_type);
887 string_list_destroy(identifier_list);
889 if (current_token != SEMI_COLON)
891 add_error_message(200, ";", YYTEXT_STRING);
893 /* Error-recovery: find any of the following:
894 CONST, TYPE, VAR, PROCEDURE, FUNCTION, BEGIN, ., EOF
895 */
896 while ( (current_token != KWD_CONST)
897 && (current_token != KWD_TYPE)
898 && (current_token != KWD_VAR)
899 && (current_token != KWD_PROCEDURE)
900 && (current_token != KWD_FUNCTION)
901 && (current_token != KWD_BEGIN)
902 && (current_token != DOT)
903 && (current_token != END_OF_INPUT))
905 current_token = yylex();
908 if ((current_token == END_OF_INPUT)
909 || (current_token == DOT))
911 add_error_message(207, "", "");
912 return;
915 break;
918 current_token = yylex();
920 if (((inside_implementation_part) || (inside_interface_part))
921 && ( (current_token == KWD_INITIALIZATION)
922 || (current_token == KWD_IMPLEMENTATION)
923 || (current_token == KWD_INTERFACE)
924 || (current_token == KWD_END)
925 ))
927 break;
930 } while ( (current_token != KWD_CONST)
931 && (current_token != KWD_TYPE)
932 && (current_token != KWD_VAR)
933 && (current_token != KWD_PROCEDURE)
934 && (current_token != KWD_FUNCTION)
935 && (current_token != KWD_BEGIN)
936 && (current_token != DOT)
937 && (current_token != END_OF_INPUT));
939 if ((current_token == END_OF_INPUT)
940 || (current_token == DOT))
942 add_error_message(207, "", "");
943 return;
946 RD_block(current_block);
950 /*
951 The list of identifiers, the rule used is:
953 <RD_identifier_list> -> IDN (, IDN)*
955 param check_valid_names should be nonzero if the function
956 should call block_check_name() for each identifier
957 */
958 string_list* RD_identifier_list(block *current_block,
959 int check_valid_names)
961 string_list *return_list;
962 string *identifier;
964 return_list = string_list_create();
966 if (current_token != IDENTIFIER)
968 add_error_message(444, "", "");
970 /* Error-recovery: find the first : or EOF */
971 while ((current_token != COLON)
972 && (current_token != DOT)
973 && (current_token != END_OF_INPUT))
975 current_token = yylex();
978 return return_list;
981 if ((check_valid_names)
982 && (!block_check_name(current_block, YYTEXT_STRING)))
984 add_error_message(400, YYTEXT_STRING, "");
987 identifier = string_from_cstr(YYTEXT_STRING);
988 string_list_append(return_list, identifier);
989 string_destroy(identifier);
991 current_token = yylex();
993 while (current_token == COMMA)
995 current_token = yylex();
997 if (current_token != IDENTIFIER)
999 add_error_message(202, "", "");
1001 /* Error-recovery: find the first : or EOF */
1002 while ((current_token != COLON)
1003 && (current_token != DOT)
1004 && (current_token != END_OF_INPUT))
1006 current_token = yylex();
1009 return return_list;
1012 if ((check_valid_names)
1013 && (!block_check_name(current_block, YYTEXT_STRING)))
1015 add_error_message(400, YYTEXT_STRING, "");
1018 identifier = string_from_cstr(YYTEXT_STRING);
1019 string_list_append(return_list, identifier);
1020 string_destroy(identifier);
1022 current_token = yylex();
1025 return return_list;
1029 /*
1030 Handles the declaration of a new type. The grammar
1031 rule used is:
1033 <RD_type_declaration> -> ( IDN = <RD_type> ; )+ <RD_block>
1034 */
1035 void RD_type_declaration(block *current_block)
1037 string *type_name;
1038 type *type_type;
1040 do
1042 if (current_token != IDENTIFIER)
1044 if (((inside_implementation_part) || (inside_interface_part))
1045 && ( (current_token == KWD_INITIALIZATION)
1046 || (current_token == KWD_IMPLEMENTATION)
1047 || (current_token == KWD_INTERFACE)
1048 || (current_token == KWD_END)
1049 ))
1051 return;
1054 add_error_message(202, "", "");
1056 /* Error-recovery: find the first ; or EOF */
1057 while ((current_token != SEMI_COLON)
1058 && (current_token != DOT)
1059 && (current_token != END_OF_INPUT))
1061 current_token = yylex();
1064 if (current_token == SEMI_COLON)
1065 RD_block(current_block);
1067 return;
1070 type_name = string_from_cstr(YYTEXT_STRING);
1071 if (!block_check_name(current_block, YYTEXT_STRING))
1072 add_error_message(400, YYTEXT_STRING, "");
1074 current_token = yylex();
1076 if (current_token != OP_EQUAL)
1078 add_error_message(205, YYTEXT_STRING, "");
1080 /* Error-recovery: find the first ; or EOF */
1081 while ((current_token != SEMI_COLON)
1082 && (current_token != DOT)
1083 && (current_token != END_OF_INPUT))
1085 current_token = yylex();
1088 if (current_token == SEMI_COLON)
1089 RD_block(current_block);
1091 string_destroy(type_name);
1093 return;
1096 current_token = yylex();
1098 type_type = RD_type(current_block);
1100 add_type(current_block, type_name, type_type);
1102 if (inside_interface_part)
1103 bsf_write_type(type_name, type_type);
1105 if (current_token != SEMI_COLON)
1107 add_error_message(200, ";", YYTEXT_STRING);
1109 /* Error-recovery: find the first ; or EOF */
1110 while ((current_token != SEMI_COLON)
1111 && (current_token != DOT)
1112 && (current_token != END_OF_INPUT))
1114 current_token = yylex();
1117 if (current_token == SEMI_COLON)
1118 RD_block(current_block);
1120 return;
1123 current_token = yylex();
1124 } while ( (current_token != KWD_CONST)
1125 && (current_token != KWD_TYPE)
1126 && (current_token != KWD_VAR)
1127 && (current_token != KWD_PROCEDURE)
1128 && (current_token != KWD_FUNCTION)
1129 && (current_token != KWD_BEGIN)
1130 && (current_token != DOT)
1131 && (current_token != END_OF_INPUT));
1133 if ((current_token == END_OF_INPUT)
1134 || (current_token == DOT))
1136 add_error_message(207, "", "");
1137 return;
1140 RD_block(current_block);
1145 /*
1146 Handles the procedure declaration. The grammar
1147 rule used is:
1149 <RD_procedure_declaration> -> IDN <RD_param_list> ;
1150 <RD_proc_block> ; <RD_block>
1151 */
1152 void RD_procedure_declaration(block *current_block)
1154 string *procedure_name;
1155 block *procedure_block;
1156 type_list *parameters;
1157 int forward_declaration;
1158 type *void_return_type;
1159 int procedure_linenum = linenum;
1161 int old_inside_implementation = inside_implementation_part;
1163 inside_implementation_part = 0;
1165 if (!block_check_name(current_block, YYTEXT_STRING))
1167 add_error_message(400, YYTEXT_STRING, "");
1170 procedure_name = string_from_cstr(YYTEXT_STRING);
1171 str_currrent_routine_name = string_from_cstr(YYTEXT_STRING);
1173 if (current_token != IDENTIFIER)
1175 add_error_message(202, "", "");
1177 /* Error-recovery: find the first ; */
1178 while ((current_token != SEMI_COLON)
1179 && (current_token != END_OF_INPUT))
1181 current_token = yylex();
1184 if (current_token == END_OF_INPUT)
1185 return;
1187 else
1189 current_token = yylex();
1192 if (STRING_COMPARE(procedure_name->cstr, "run") == 0)
1193 add_error_message(433, "", "");
1195 /* create a new block for the procedure */
1196 procedure_block = block_create(current_block, string_duplicate(procedure_name));
1198 parameters = RD_param_list(procedure_block);
1200 if (current_token != SEMI_COLON)
1202 add_error_message(200, ";", YYTEXT_STRING);
1204 /* Error-recovery: do nothing */
1206 else
1207 current_token = yylex();
1209 void_return_type = type_create();
1210 void_return_type->type_class = void_type;
1212 add_procedure(current_block, procedure_name, parameters, -1, procedure_linenum);
1214 if (inside_interface_part)
1215 bsf_write_procedure(procedure_name, parameters);
1217 forward_declaration = RD_proc_block(procedure_block, void_return_type, parameters);
1219 type_destroy(void_return_type);
1221 add_procedure(current_block, procedure_name, parameters, forward_declaration, procedure_linenum);
1223 if (current_token != SEMI_COLON)
1225 if (inside_interface_part == 0)
1226 add_error_message(200, ";", YYTEXT_STRING);
1228 /* Error-recovery: do nothing */
1230 else
1231 current_token = yylex();
1233 inside_implementation_part = old_inside_implementation;
1235 RD_block(current_block);
1239 /*
1240 Handles the function declaration. The grammar
1241 rule used is:
1243 <RD_function_declaration> -> IDN <RD_param_list> : IDN ;
1244 <RD_proc_block> ; <RD_block>
1245 */
1246 void RD_function_declaration(block *current_block)
1248 string *function_name;
1249 block *function_block;
1250 type_list *parameters;
1251 int forward_declaration;
1252 type *return_type;
1253 identifier *return_value;
1254 int function_linenum = linenum;
1256 int old_inside_implementation = inside_implementation_part;
1258 inside_implementation_part = 0;
1260 if (!block_check_name(current_block, YYTEXT_STRING))
1262 add_error_message(400, YYTEXT_STRING, "");
1265 function_name = string_from_cstr(YYTEXT_STRING);
1266 str_currrent_routine_name = string_from_cstr(YYTEXT_STRING);
1268 if (current_token != IDENTIFIER)
1270 add_error_message(202, "", "");
1272 /* Error-recovery: find the first ; */
1273 while ((current_token != SEMI_COLON)
1274 && (current_token != END_OF_INPUT))
1276 current_token = yylex();
1279 if (current_token == END_OF_INPUT)
1280 return;
1282 else
1283 current_token = yylex();
1285 if (STRING_COMPARE(function_name->cstr, "run") == 0)
1286 add_error_message(433, "", "");
1288 /* create a new block for the function */
1289 function_block = block_create(current_block, string_duplicate(function_name));
1291 /* parameters start at index 0, variables follow after the return value */
1292 function_block->next_parameter_index = 0;
1293 function_block->next_variable_index = 0;
1295 parameters = RD_param_list(function_block);
1297 function_block->next_variable_index ++;
1299 if (current_token != COLON)
1301 add_error_message(200, ":", YYTEXT_STRING);
1303 else
1304 current_token = yylex();
1306 return_type = type_from_name(current_block, YYTEXT_STRING);
1308 if (return_type->type_class == error_type)
1309 add_error_message(406, YYTEXT_STRING, "");
1311 if (return_type->type_class == interval_type)
1313 add_error_message(440, "", "");
1314 return_type->type_class = integer_type;
1317 if (current_token != IDENTIFIER)
1319 add_error_message(202, "", "");
1321 else
1322 current_token = yylex();
1324 if (current_token != SEMI_COLON)
1326 add_error_message(200, ";", YYTEXT_STRING);
1328 /* Error-recovery: do nothing */
1330 else
1331 current_token = yylex();
1333 /* initialize the return value */
1334 return_value = identifier_create();
1335 return_value->identifier_class = variable_name;
1336 return_value->variable_index = type_list_length(parameters);
1337 return_value->variable_type = type_duplicate(return_type);
1338 return_value->belongs_to_program_block = 0;
1339 if (compiling_unit == 0)
1340 initialize_variable(function_block, return_value, NULL, 1, "M");
1341 else
1342 initialize_variable(function_block, return_value, NULL, 1, string_get_cstr(str_program_name));
1344 identifier_destroy(return_value);
1346 add_function(current_block, function_name, parameters,
1347 return_type, -1, function_linenum);
1349 forward_declaration = RD_proc_block(function_block, return_type, parameters);
1351 add_function(current_block, function_name, parameters,
1352 return_type, forward_declaration, function_linenum);
1354 if (inside_interface_part)
1355 bsf_write_function(function_name, parameters, return_type);
1357 if (current_token != SEMI_COLON)
1359 if (inside_interface_part == 0)
1360 add_error_message(200, ";", YYTEXT_STRING);
1362 /* Error-recovery: do nothing */
1364 else
1365 current_token = yylex();
1367 inside_implementation_part = old_inside_implementation;
1369 RD_block(current_block);
1373 /*
1374 Allows forward declarations. The rule used is:
1376 <RD_proc_block> -> forward | <RD_block>
1378 Return nonzero value if the declaration is forward
1379 declaration.
1380 */
1381 int RD_proc_block(block *current_block, type *return_type, type_list *parameters)
1383 routine_return_type = return_type->type_class;
1384 routine_return_parameters_length = type_list_length(parameters);
1385 inside_routine = 1;
1386 int forward_declaration = 0;
1388 if ((current_token == KWD_FORWARD)
1389 || (inside_interface_part))
1391 forward_declaration = 1;
1393 if (inside_interface_part == 0)
1394 current_token = yylex();
1396 block_destroy(current_block);
1398 else
1400 if (inside_interface_part)
1401 add_error_message(221, "", "");
1403 RD_block(current_block);
1405 /* insert current_block into it's parents block list */
1406 if (current_block->parent_block->children_count == 0)
1408 current_block->parent_block->children = (block**) mem_alloc(sizeof(block*));
1410 else
1412 current_block->parent_block->children = (block**) mem_realloc(current_block->parent_block->children,
1413 (current_block->parent_block->children_count + 1) * sizeof(block*));
1416 current_block->parent_block->children_count ++;
1418 if (current_block->parent_block->children == NULL)
1419 die(20);
1421 switch(return_type->type_class)
1423 case void_type:
1424 bytecode_append(current_block->code, return$);
1425 break;
1427 case real_type:
1428 usesFloat=1;
1429 if (mathType == 1)
1431 bytecode_append(current_block->code, iload$);
1432 bytecode_append(current_block->code, type_list_length(parameters));
1433 bytecode_append(current_block->code, ireturn$);
1435 else
1437 switch(type_list_length(parameters))
1439 case 0:
1440 bytecode_append(current_block->code, aload_0$);
1441 break;
1442 case 1:
1443 bytecode_append(current_block->code, aload_1$);
1444 break;
1445 case 2:
1446 bytecode_append(current_block->code, aload_2$);
1447 break;
1448 case 3:
1449 bytecode_append(current_block->code, aload_3$);
1450 break;
1451 default:
1452 bytecode_append(current_block->code, aload$);
1453 bytecode_append(current_block->code, type_list_length(parameters));
1456 bytecode_append(current_block->code, areturn$);
1458 break;
1460 case integer_type:
1461 case boolean_type:
1462 case char_type:
1463 bytecode_append(current_block->code, iload$);
1464 bytecode_append(current_block->code, type_list_length(parameters));
1465 bytecode_append(current_block->code, ireturn$);
1466 break;
1468 case string_type:
1469 case array_type:
1470 case record_type:
1471 case image_type:
1472 case command_type:
1473 case stream_type:
1474 case record_store_type:
1475 case http_type:
1476 switch(type_list_length(parameters))
1478 case 0:
1479 bytecode_append(current_block->code, aload_0$);
1480 break;
1481 case 1:
1482 bytecode_append(current_block->code, aload_1$);
1483 break;
1484 case 2:
1485 bytecode_append(current_block->code, aload_2$);
1486 break;
1487 case 3:
1488 bytecode_append(current_block->code, aload_3$);
1489 break;
1490 default:
1491 bytecode_append(current_block->code, aload$);
1492 bytecode_append(current_block->code, type_list_length(parameters));
1495 bytecode_append(current_block->code, areturn$);
1497 break;
1500 current_block->parent_block->children[current_block->parent_block->children_count-1] = current_block;
1502 inside_routine = 0;
1503 return forward_declaration;
1507 /*
1508 Handles the declarations of parameters to a
1509 procedure/function. The grammar rule used is:
1511 <RD_param_list> -> empty
1512 | "(" [var] <RD_identifier_list> : [IDN.]IDN (; [var] <RD_identifier_list> : [IDN.]IDN )+ ")"
1513 */
1514 type_list* RD_param_list(block *current_block)
1516 type_list *parameter_list;
1517 string_list *identifier_list;
1518 type *parameters_type;
1519 int is_parameter_variable;
1521 int i, len;
1523 parameter_list = type_list_create();
1525 if (current_token == OPEN_BR)
1527 do
1529 current_token = yylex();
1531 if (current_token == END_OF_INPUT)
1533 add_error_message(207, "", "");
1534 return parameter_list;
1537 if (current_token == CLOSE_BR)
1538 break;
1540 is_parameter_variable = 0;
1542 if (current_token == KWD_VAR)
1544 is_parameter_variable = 1;
1545 current_token = yylex();
1546 add_warning_message(436, "", "");
1549 identifier_list = RD_identifier_list(current_block, 0);
1551 if (current_token != COLON)
1553 add_error_message(200, ":", YYTEXT_STRING);
1555 /* Error-recovery, find the ")" */
1556 while (current_token != CLOSE_BR)
1558 current_token = yylex();
1561 if (current_token == END_OF_INPUT)
1562 return parameter_list;
1564 break;
1567 else
1568 current_token = yylex();
1570 parameters_type = type_from_name(current_block, YYTEXT_STRING);
1572 if (parameters_type->type_class == error_type)
1574 /* check if the name is an unit name */
1575 identifier *unit;
1577 lowercase(YYTEXT_STRING);
1579 unit = get_identifier(current_block, YYTEXT_STRING);
1581 if (unit->identifier_class == unit_name)
1583 identifier *type_identifier;
1585 current_token = yylex();
1587 if (current_token != DOT)
1588 add_error_message(200, ".", YYTEXT_STRING);
1589 else
1590 current_token = yylex();
1592 type_identifier = name_table_find(unit->unit_block->names, string_from_cstr(YYTEXT_STRING));
1594 if (type_identifier == NULL)
1595 add_error_message(455, YYTEXT_STRING, "");
1596 else
1597 parameters_type = type_identifier->defined_type;
1600 identifier_destroy(unit);
1603 if (parameters_type->type_class == interval_type)
1605 add_error_message(440, "", "");
1606 parameters_type->type_class = integer_type;
1609 /* add the types into parameter_list */
1610 len = string_list_length(identifier_list);
1611 for(i=0; i<len; i++)
1612 type_list_append(parameter_list, type_duplicate(parameters_type));
1614 add_parameters(current_block, identifier_list, parameters_type,
1615 is_parameter_variable);
1617 if (current_token != IDENTIFIER)
1619 add_error_message(202, "", "");
1621 /* Error-recovery */
1622 if ((current_token != COMMA)
1623 && (current_token != CLOSE_BR))
1624 current_token = yylex();
1626 else
1627 current_token = yylex();
1629 } while (current_token == SEMI_COLON);
1631 if (current_token != CLOSE_BR)
1633 add_error_message(208, YYTEXT_STRING, "");
1635 /* Error-recovery: find the first ; */
1636 while ((current_token != CLOSE_BR)
1637 && (current_token != END_OF_INPUT))
1639 current_token = yylex();
1643 current_token = yylex();
1646 return parameter_list;
1649 /*
1650 Handles the block of code. The grammar rule used is:
1652 <RD_block_body> -> (<RD_statement> ; )+
1653 */
1654 void RD_block_body(block *current_block)
1656 short int first_pass = 1;
1658 do
1660 if (first_pass)
1661 first_pass = 0;
1662 else
1663 current_token = yylex();
1665 RD_statement(current_block);
1667 } while (current_token == SEMI_COLON);
1671 /*
1672 The statements rule:
1674 <RD_statement> -> begin <RD_block_body> end
1675 | empty (if current_token == end || current_token == until)
1676 | if <RD_if_statement>
1677 | case <RD_case_statement>
1678 | while <RD_while_statement>
1679 | repeat <RD_repeat_statement>
1680 | for <RD_for_statement>
1681 | with <RD_with_statement>
1682 | <RD_assignment_or_procedure_call>
1683 | break
1684 */
1685 void RD_statement(block *current_block)
1687 switch (current_token)
1689 case KWD_BEGIN:
1691 current_token = yylex();
1692 RD_block_body(current_block);
1694 if (current_token != KWD_END)
1696 add_error_message(203, "end", YYTEXT_STRING);
1699 current_token = yylex();
1701 break;
1704 case KWD_END: case KWD_UNTIL: case KWD_FOREVER:
1706 return;
1709 case KWD_EXIT:
1711 if (inside_routine == 0) { // j-a-s-d: in the main block treat it as a Halt()
1712 char *halt_text;
1713 halt_text = malloc(strlen("halt") + 1);
1714 strcpy(halt_text, "halt");
1715 create_std_function_code(current_block->code, halt_text);
1716 string_destroy(halt_text);
1717 } else switch (routine_return_type) {
1718 case void_type:
1719 bytecode_append(current_block->code, return$);
1720 break;
1722 case real_type:
1723 if (mathType == 1)
1725 bytecode_append(current_block->code, iload$);
1726 bytecode_append(current_block->code, routine_return_parameters_length);
1727 bytecode_append(current_block->code, ireturn$);
1729 else
1731 switch(routine_return_parameters_length)
1733 case 0:
1734 bytecode_append(current_block->code, aload_0$);
1735 break;
1736 case 1:
1737 bytecode_append(current_block->code, aload_1$);
1738 break;
1739 case 2:
1740 bytecode_append(current_block->code, aload_2$);
1741 break;
1742 case 3:
1743 bytecode_append(current_block->code, aload_3$);
1744 break;
1745 default:
1746 bytecode_append(current_block->code, aload$);
1747 bytecode_append(current_block->code, routine_return_parameters_length);
1750 bytecode_append(current_block->code, areturn$);
1752 break;
1754 case integer_type:
1755 case boolean_type:
1756 case char_type:
1757 bytecode_append(current_block->code, iload$);
1758 bytecode_append(current_block->code, routine_return_parameters_length);
1759 bytecode_append(current_block->code, ireturn$);
1760 break;
1762 case string_type:
1763 case array_type:
1764 case record_type:
1765 case image_type:
1766 case command_type:
1767 case stream_type:
1768 case record_store_type:
1769 case http_type:
1770 switch(routine_return_parameters_length)
1772 case 0:
1773 bytecode_append(current_block->code, aload_0$);
1774 break;
1775 case 1:
1776 bytecode_append(current_block->code, aload_1$);
1777 break;
1778 case 2:
1779 bytecode_append(current_block->code, aload_2$);
1780 break;
1781 case 3:
1782 bytecode_append(current_block->code, aload_3$);
1783 break;
1784 default:
1785 bytecode_append(current_block->code, aload$);
1786 bytecode_append(current_block->code, routine_return_parameters_length);
1788 bytecode_append(current_block->code, areturn$);
1789 break;
1791 current_token = yylex();
1792 break;
1794 case KWD_IF:
1796 current_token = yylex();
1797 RD_if_statement(current_block);
1798 break;
1801 case KWD_CASE:
1803 current_token = yylex();
1804 RD_case_statement(current_block);
1805 break;
1808 case KWD_WHILE:
1810 current_token = yylex();
1811 RD_while_statement(current_block);
1812 break;
1815 case KWD_REPEAT:
1817 current_token = yylex();
1818 RD_repeat_statement(current_block);
1819 break;
1822 case KWD_FOR:
1824 current_token = yylex();
1825 RD_for_statement(current_block);
1826 break;
1829 case KWD_WITH:
1831 add_error_message(215, "", "");
1832 current_token = yylex();
1833 RD_with_statement(current_block);
1834 break;
1837 case IDENTIFIER:
1838 case KWD_RESULT: // j-a-s-d
1840 RD_assignment_or_procedure_call(current_block);
1841 break;
1844 case KWD_BREAK:
1846 current_token = yylex();
1848 if (inside_loop <= 0)
1849 add_error_message(219, "", "");
1850 else
1852 bytecode_append(current_block->code, break_stmt$);
1853 bytecode_append_short_int(current_block->code, 0);
1855 break;
1858 case KWD_BYTECODE:
1860 RD_inline_body(current_block);
1861 if (current_token != KWD_END) {
1862 add_error_message(200, "end ", YYTEXT_STRING);
1863 while ((current_token != SEMI_COLON) && (current_token != END_OF_INPUT))
1864 current_token = yylex();
1865 } else current_token = yylex();
1866 break;
1869 case KWD_INLINE:
1871 add_warning_message(464, "", "");
1872 current_token = yylex();
1873 if (current_token == OPEN_BR) {
1874 RD_inline_body(current_block);
1875 if (current_token != CLOSE_BR) {
1876 add_error_message(200, "<inline>) ", YYTEXT_STRING);
1877 while ((current_token != SEMI_COLON) && (current_token != END_OF_INPUT))
1878 current_token = yylex();
1879 } else current_token = yylex();
1880 } else {
1881 add_error_message(200, "<inline>(", YYTEXT_STRING);
1882 while ((current_token != SEMI_COLON) && (current_token != END_OF_INPUT))
1883 current_token = yylex();
1885 break;
1888 default:
1890 add_error_message(204, YYTEXT_STRING, "");
1891 break;
1899 ///////////////////////////////////////////////////////////////////////////////////////////////////
1900 ////////////////////////////////////// JAVA - ASM /////////////////////////////////////////////////
1901 ///////////////////////////////////////////////////////////////////////////////////////////////////
1902 /*
1903 Handles the inline statement. The grammar rule
1904 is:
1905 <inline (byte)>
1906 <inline (opcode)>
1907 <inline (opcode int)>
1908 <inline (opcode [[cp_type] 'param1', 'param2', 'param3'])>
1909 */
1910 int RD_opcodes() {
1911 if (strcmp(yytext, "nop") == 0) return 0x00; // íè÷åãî íå äåëàåò
1912 if (strcmp(yytext, "aconst_null") == 0) return 0x01; // çàãðóçêà â ñòåê null ( ïóñòîé ññûëêè íà îáúåêò)
1913 if (strcmp(yytext, "iconst_m1") == 0) return 0x02; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû -1
1914 if (strcmp(yytext, "iconst_0") == 0) return 0x03; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû 0}
1915 if (strcmp(yytext, "iconst_1") == 0) return 0x04; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû 1}
1916 if (strcmp(yytext, "iconst_2") == 0) return 0x05; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû 2}
1917 if (strcmp(yytext, "iconst_3") == 0) return 0x06; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû 3}
1918 if (strcmp(yytext, "iconst_4") == 0) return 0x07; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû 4}
1919 if (strcmp(yytext, "iconst_5") == 0) return 0x08; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû 5}
1920 if (strcmp(yytext, "lconst_0") == 0) return 0x09; // çàãðóçêà äëèííîé öåëî÷èñëåííîé êîíñòàíòû 0}
1921 if (strcmp(yytext, "lconst_1") == 0) return 0x0A; // çàãðóçêà äëèííîé öåëî÷èñëåííîé êîíñòàíòû 1}
1922 if (strcmp(yytext, "fconst_0") == 0) return 0x0B; // çàãðóçêà âåùåñòâåííîãî ÷èñëà îäèíàðíîé òî÷íîñòè 0}
1923 if (strcmp(yytext, "fconst_1") == 0) return 0x0C; // çàãðóçêà âåùåñòâåííîãî ÷èñëà îäèíàðíîé òî÷íîñòè 1}
1924 if (strcmp(yytext, "fconst_2") == 0) return 0x0D; // çàãðóçêà âåùåñòâåííîãî ÷èñëà îäèíàðíîé òî÷íîñòè 2}
1925 if (strcmp(yytext, "dconst_0") == 0) return 0x0E; // çàãðóçêà âåùåñòâåííîãî ÷èñëà äâîéíîé òî÷íîñòè 0}
1926 if (strcmp(yytext, "dconst_1") == 0) return 0x0F; // çàãðóçêà âåùåñòâåííîãî ÷èñëà äâîéíîé òî÷íîñòè 1}
1927 if (strcmp(yytext, "bipush") == 0) return 0x10; // [1]çàãðóçêà â ñòåê îäíîáàéòîâîãî öåëîãî ñî çíàêîì}
1928 if (strcmp(yytext, "sipush") == 0) return 0x11; // [2+-]çàãðóçêà â ñòåê äâóõáàéòîâîãî öåëîãî ñî çíàêîì}
1929 if (strcmp(yytext, "ldc1") == 0) return 0x12; // [1]çàãðóçêà â ñòåê ýëåìåíòà èç êîíñòàíòíîãî ïóëà}
1930 if (strcmp(yytext, "ldc2") == 0) return 0x13; // [2]çàãðóçêà â ñòåê ýëåìåíòà èç êîíñòàíòíîãî ïóëà}
1931 if (strcmp(yytext, "ldc2w") == 0) return 0x14; // [2]çàãðóçêà â ñòåê äëèííîãî öåëîãî èëè äâîéíîãî âåùåñòâåííîãî çíà÷åíèÿ èç êîíñòàíòíîãî ïóëà}
1932 if (strcmp(yytext, "iload") == 0) return 0x15; // [1]çàãðóçêà öåëîãî èç ëîêàëüíîé ïåðåìåííîé}
1933 if (strcmp(yytext, "lload") == 0) return 0x16; // [1]çàãðóçêà äëèííîãî öåëîãî èç ëîêàëüíîé ïåðåìåííîé}
1934 if (strcmp(yytext, "fload") == 0) return 0x17; // [1]çàãðóçêà âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé}
1935 if (strcmp(yytext, "dload") == 0) return 0x18; // [1]çàãðóçêà âåùåñòâåííîãî äâîéíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé}
1936 if (strcmp(yytext, "aload") == 0) return 0x19; // [1]çàãðóçêà îáúåêòíîé ññûëêè èç ëîêàëüíîé ïåðåìåííîé}
1937 if (strcmp(yytext, "iload_0") == 0) return 0x1A; // çàãðóçêà öåëîãî èç ëîêàëüíîé ïåðåìåííîé 0}
1938 if (strcmp(yytext, "iload_1") == 0) return 0x1B; // çàãðóçêà öåëîãî èç ëîêàëüíîé ïåðåìåííîé 1}
1939 if (strcmp(yytext, "iload_2") == 0) return 0x1C; // çàãðóçêà öåëîãî èç ëîêàëüíîé ïåðåìåííîé 2}
1940 if (strcmp(yytext, "iload_3") == 0) return 0x1D; // çàãðóçêà öåëîãî èç ëîêàëüíîé ïåðåìåííîé 3}
1941 if (strcmp(yytext, "lload_0") == 0) return 0x1E; // çàãðóçêà äëèííîãî öåëîãî èç ëîêàëüíîé ïåðåìåííîé 0}
1942 if (strcmp(yytext, "lload_1") == 0) return 0x1F; // çàãðóçêà äëèííîãî öåëîãî èç ëîêàëüíîé ïåðåìåííîé 1}
1943 if (strcmp(yytext, "lload_2") == 0) return 0x20; // çàãðóçêà äëèííîãî öåëîãî èç ëîêàëüíîé ïåðåìåííîé 2}
1944 if (strcmp(yytext, "lload_3") == 0) return 0x21; // çàãðóçêà äëèííîãî öåëîãî èç ëîêàëüíîé ïåðåìåííîé 3}
1945 if (strcmp(yytext, "fload_0") == 0) return 0x22; // çàãðóçêà âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 0}
1946 if (strcmp(yytext, "fload_1") == 0) return 0x23; // çàãðóçêà âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 1}
1947 if (strcmp(yytext, "fload_2") == 0) return 0x24; // çàãðóçêà âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 2}
1948 if (strcmp(yytext, "fload_3") == 0) return 0x25; // çàãðóçêà âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 3}
1949 if (strcmp(yytext, "dload_0") == 0) return 0x26; // çàãðóçêà âåùåñòâåííîãî äâîéíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 0}
1950 if (strcmp(yytext, "dload_1") == 0) return 0x27; // çàãðóçêà âåùåñòâåííîãî äâîéíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 1}
1951 if (strcmp(yytext, "dload_2") == 0) return 0x28; // çàãðóçêà âåùåñòâåííîãî äâîéíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 2}
1952 if (strcmp(yytext, "dload_3") == 0) return 0x29; // çàãðóçêà âåùåñòâåííîãî äâîéíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 3}
1953 if (strcmp(yytext, "aload_0") == 0) return 0x2A; // çàãðóçêà îáúåêòíîé ññûëêè èç ëîêàëüíîé ïåðåìåííîé 0}
1954 if (strcmp(yytext, "aload_1") == 0) return 0x2B; // çàãðóçêà îáúåêòíîé ññûëêè èç ëîêàëüíîé ïåðåìåííîé 1}
1955 if (strcmp(yytext, "aload_2") == 0) return 0x2C; // çàãðóçêà îáúåêòíîé ññûëêè èç ëîêàëüíîé ïåðåìåííîé 2}
1956 if (strcmp(yytext, "aload_3") == 0) return 0x2D; // çàãðóçêà îáúåêòíîé ññûëêè èç ëîêàëüíîé ïåðåìåííîé 3}
1957 if (strcmp(yytext, "iaload") == 0) return 0x2E; // çàãðóçêà öåëîãî èç ìàññèâà}
1958 if (strcmp(yytext, "laload") == 0) return 0x2F; // çàãðóçêà äëèííîãî öåëîãî èç ìàññèâà}
1959 if (strcmp(yytext, "faload") == 0) return 0x30; // çàãðóçêà âåùåñòâåííîãî èç ìàññèâà}
1960 if (strcmp(yytext, "daload") == 0) return 0x31; // çàãðóçêà äâîéíîãî âåùåñòâåííîãî èç ìàññèâà}
1961 if (strcmp(yytext, "aaload") == 0) return 0x32; // çàãðóçêà îáúåêòíîé ññûëêè èç ìàññèâà}
1962 if (strcmp(yytext, "baload") == 0) return 0x33; // çàãðóçêà áàéòà ñî çíàêîì èç ìàññèâà}
1963 if (strcmp(yytext, "caload") == 0) return 0x34; // çàãðóçêà ñèìâîëà èç ìàññèâà}
1964 if (strcmp(yytext, "saload") == 0) return 0x35; // çàãðóçêà êîðîòêîãî èç ìàññèâà}
1965 if (strcmp(yytext, "istore") == 0) return 0x36; // [1]ñîõðàíåíèå öåëîãî çíà÷åíèÿ â ëîêàëüíîé ïåðåìåííîé}
1966 if (strcmp(yytext, "lstore") == 0) return 0x37; // [1]ñîõðàíåíèå äëèííîãî öåëîãî â ëîêàëüíîé ïåðåìåííîé}
1967 if (strcmp(yytext, "fstore") == 0) return 0x38; // [1]ñîõðàíåíèå âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè â ëîêàëüíîé ïåðåìåííîé}
1968 if (strcmp(yytext, "dstore") == 0) return 0x39; // [1]ñîõðàíåíèå äâîéíîãî âåùåñòâåííîãî â ëîêàëüíîé ïåðåìåííîé}
1969 if (strcmp(yytext, "astore") == 0) return 0x3A; // [1]ñîõðàíåíèå îáúåêòíîé ññûëêè â ëîêàëüíîé ïåðåìåííîé}
1970 if (strcmp(yytext, "istore_0") == 0) return 0x3B; // ñîõðàíåíèå öåëîãî â ëîêàëüíîé ïåðåìåííîé 0}
1971 if (strcmp(yytext, "istore_1") == 0) return 0x3C; // ñîõðàíåíèå öåëîãî â ëîêàëüíîé ïåðåìåííîé 1}
1972 if (strcmp(yytext, "istore_2") == 0) return 0x3D; // ñîõðàíåíèå öåëîãî â ëîêàëüíîé ïåðåìåííîé 2}
1973 if (strcmp(yytext, "istore_3") == 0) return 0x3E; // ñîõðàíåíèå öåëîãî â ëîêàëüíîé ïåðåìåííîé 3}
1974 if (strcmp(yytext, "lstore_0") == 0) return 0x3F; // ñîõðàíåíèå äëèííîãî öåëîãî â ëîêàëüíîé ïåðåìåííîé 0}
1975 if (strcmp(yytext, "lstore_1") == 0) return 0x40; // ñîõðàíåíèå äëèííîãî öåëîãî â ëîêàëüíîé ïåðåìåííîé 1}
1976 if (strcmp(yytext, "lstore_2") == 0) return 0x41; // ñîõðàíåíèå äëèííîãî öåëîãî â ëîêàëüíîé ïåðåìåííîé 2}
1977 if (strcmp(yytext, "lstore_3") == 0) return 0x42; // ñîõðàíåíèå äëèííîãî öåëîãî â ëîêàëüíîé ïåðåìåííîé 3}
1978 if (strcmp(yytext, "fstore_0") == 0) return 0x43; // ñîõðàíåíèå âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè â ëîêàëüíîé ïåðåìåííîé 0}
1979 if (strcmp(yytext, "fstore_1") == 0) return 0x44; // ñîõðàíåíèå âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè â ëîêàëüíîé ïåðåìåííîé 1}
1980 if (strcmp(yytext, "fstore_2") == 0) return 0x45; // ñîõðàíåíèå âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè â ëîêàëüíîé ïåðåìåííîé 2}
1981 if (strcmp(yytext, "fstore_3") == 0) return 0x46; // ñîõðàíåíèå âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè â ëîêàëüíîé ïåðåìåííîé 3}
1982 if (strcmp(yytext, "dstore_0") == 0) return 0x47; // ñîõðàíåíèå äâîéíîãî âåùåñòâåííîãî â ëîêàëüíîé ïåðåìåííîé 0}
1983 if (strcmp(yytext, "dstore_1") == 0) return 0x48; // ñîõðàíåíèå äâîéíîãî âåùåñòâåííîãî â ëîêàëüíîé ïåðåìåííîé 1}
1984 if (strcmp(yytext, "dstore_2") == 0) return 0x49; // ñîõðàíåíèå äâîéíîãî âåùåñòâåííîãî â ëîêàëüíîé ïåðåìåííîé 2}
1985 if (strcmp(yytext, "dstore_3") == 0) return 0x4A; // ñîõðàíåíèå äâîéíîãî âåùåñòâåííîãî â ëîêàëüíîé ïåðåìåííîé 3}
1986 if (strcmp(yytext, "astore_0") == 0) return 0x4B; // ñîõðàíåíèå îáúåêòíîé ññûëêè â ëîêàëüíîé ïåðåìåííîé 0}
1987 if (strcmp(yytext, "astore_1") == 0) return 0x4C; // ñîõðàíåíèå îáúåêòíîé ññûëêè â ëîêàëüíîé ïåðåìåííîé 1}
1988 if (strcmp(yytext, "astore_2") == 0) return 0x4D; // ñîõðàíåíèå îáúåêòíîé ññûëêè â ëîêàëüíîé ïåðåìåííîé 2}
1989 if (strcmp(yytext, "astore_3") == 0) return 0x4E; // ñîõðàíåíèå îáúåêòíîé ññûëêè â ëîêàëüíîé ïåðåìåííîé 3}
1990 if (strcmp(yytext, "iastore") == 0) return 0x4F; // ñîõðàíåíèå â öåëî÷èñëåííîì ìàññèâå}
1991 if (strcmp(yytext, "lastore") == 0) return 0x50; // ñîõðàíåíèå â ìàññèâå èç äëèííûõ öåëûõ}
1992 if (strcmp(yytext, "fastore") == 0) return 0x51; // ñîõðàíåíèå â ìàññèâå èç îäèíàðíûõ âåùåñòâåííûõ}
1993 if (strcmp(yytext, "dastore") == 0) return 0x52; // ñîõðàíåíèå â ìàññèâå èç äâîéíûõ âåùåñòâåííûõ}
1994 if (strcmp(yytext, "aastore") == 0) return 0x53; // ñîõðàíåíèå â ìàññèâå èç îáúåêòíûõ ññûëîê}
1995 if (strcmp(yytext, "bastore") == 0) return 0x54; // ñîõðàíåíèå â ìàññèâå áàéòîâ ñî çíàêîì}
1996 if (strcmp(yytext, "castore") == 0) return 0x55; // ñîõðàíåíèå â ñèìâîëüíîì ìàññèâå}
1997 if (strcmp(yytext, "sastore") == 0) return 0x56; // ñîõðàíåíèå â ìàññèâå èç êîðîòêèõ öåëûõ}
1998 if (strcmp(yytext, "pop") == 0) return 0x57; // èçâëå÷åíèå ñëîâà ñ âåðøèíû ñòåêà}
1999 if (strcmp(yytext, "pop2") == 0) return 0x58; // èçâëå÷åíèå äâóõ ñëîâ ñ âåðøèíû ñòåêà}
2000 if (strcmp(yytext, "dup") == 0) return 0x59; // äóáëèðîâàíèå ñëîâà íà âåðøèíå ñòåêà}
2001 if (strcmp(yytext, "dup_x1") == 0) return 0x5A; // äóáëèðîâàíèå ñëîâî íà âåðøèíå ñòåêà è ïîìåùåíèå êîïèè â ñòåê íà äâà ñëîâà íèæå}
2002 if (strcmp(yytext, "dup_x2") == 0) return 0x5B; // äóáëèðîâàíèå âåðøèíû ñòåêà è ïîìåùåíèå êîïèè íà òðè ñëîâà íèæå}
2003 if (strcmp(yytext, "dup2") == 0) return 0x5C; // äóáëèðîâàíèå äâóõ ñëîâ íà âåðøèíå ñòåêà}
2004 if (strcmp(yytext, "dup2_x1") == 0) return 0x5D; // äóáëèðîâàíèå äâóõ ñëîâ íà âåðøèíå ñòåêà è ïîìåùåíèå êîïèé íà äâà ñëîâà íèæå}
2005 if (strcmp(yytext, "dup2_x2") == 0) return 0x5E; // äóáëèðîâàíèå äâóõ ñëîâ íà âåðøèíå ñòåêà è ïîìåùåíèå êîïèé íà òðè ñëîâà íèæå}
2006 if (strcmp(yytext, "swap") == 0) return 0x5F; // îáìåí äâóõ ñëîâ íà âåðøèíå ñòåêà}
2007 if (strcmp(yytext, "iadd") == 0) return 0x60; // ñëîæåíèå öåëûõ}
2008 if (strcmp(yytext, "ladd") == 0) return 0x61; // ñëîæåíèå äëèííûõ öåëûõ}
2009 if (strcmp(yytext, "fadd") == 0) return 0x62; // ñëîæåíèå îäèíàðíûõ âåùåñòâåííûõ}
2010 if (strcmp(yytext, "dadd") == 0) return 0x63; // ñëîæåíèå äâîéíûõ âåùåñòâåííûõ}
2011 if (strcmp(yytext, "isub") == 0) return 0x64; // âû÷èòàíèå öåëûõ}
2012 if (strcmp(yytext, "lsub") == 0) return 0x65; // âû÷èòàíèå äëèííûõ öåëûõ}
2013 if (strcmp(yytext, "fsub") == 0) return 0x66; // âû÷èòàíèå îäèíàðíûõ âåùåñòâåííûõ}
2014 if (strcmp(yytext, "dsub") == 0) return 0x67; // âû÷èòàíèå äâîéíûõ âåùåñòâåííûõ}
2015 if (strcmp(yytext, "imul") == 0) return 0x68; // óìíîæåíèå öåëûõ}
2016 if (strcmp(yytext, "lmul") == 0) return 0x69; // óìíîæåíèå äëèííûõ öåëûõ}
2017 if (strcmp(yytext, "fmul") == 0) return 0x6A; // óìíîæåíèå îäèíàðíûõ âåùåñòâåííûõ}
2018 if (strcmp(yytext, "dmul") == 0) return 0x6B; // óìíîæåíèå äâîéíûõ âåùåñòâåííûõ}
2019 if (strcmp(yytext, "idiv") == 0) return 0x6C; // äåëåíèå öåëûõ}
2020 if (strcmp(yytext, "ldiv") == 0) return 0x6D; // äåëåíèå äëèííûõ öåëûõ}
2021 if (strcmp(yytext, "fdiv") == 0) return 0x6E; // äåëåíèå îäèíàðíûõ âåùåñòâåííûõ}
2022 if (strcmp(yytext, "ddiv") == 0) return 0x6F; // äåëåíèå äâîéíûõ âåùåñòâåííûõ}
2023 if (strcmp(yytext, "irem") == 0) return 0x70; // îñòàòîê îò äåëåíèÿ öåëûõ}
2024 if (strcmp(yytext, "lrem") == 0) return 0x71; // îñòàòîê îò äåëåíèÿ äëèííûõ öåëûõ}
2025 if (strcmp(yytext, "frem") == 0) return 0x72; // îñòàòîê îò äåëåíèÿ îäèíàðíûõ âåùåñòâåííûõ}
2026 if (strcmp(yytext, "drem") == 0) return 0x73; // îñòàòîê îò äåëåíèÿ äâîéíûõ âåùåñòâåííûõ}
2027 if (strcmp(yytext, "ineg") == 0) return 0x74; // îòðèöàíèå öåëîãî}
2028 if (strcmp(yytext, "leg") == 0) return 0x75; // îòðèöàíèå äëèííîãî öåëîãî}
2029 if (strcmp(yytext, "fneg") == 0) return 0x76; // îòðèöàíèå îäèíàðíîãî âåùåñòâåííîãî}
2030 if (strcmp(yytext, "dneg") == 0) return 0x77; // îòðèöàíèå äâîéíîãî âåùåñòâåííîãî ÷èñëà}
2031 if (strcmp(yytext, "ishl") == 0) return 0x78; // ñäâèã öåëîãî âëåâî}
2032 if (strcmp(yytext, "lshl") == 0) return 0x79; // ñäâèã äëèííîãî öåëîãî âëåâî}
2033 if (strcmp(yytext, "ishr") == 0) return 0x7A; // àðèôìåòè÷åñêèé ñäâèã öåëîãî âïðàâî}
2034 if (strcmp(yytext, "lshr") == 0) return 0x7B; // àðèôìåòè÷åñêèé ñäâèã äëèííîãî öåëîãî âïðàâî}
2035 if (strcmp(yytext, "iushr") == 0) return 0x7C; // ëîãè÷åñêèé ñäâèã öåëîãî âïðàâî}
2036 if (strcmp(yytext, "lushr") == 0) return 0x7D; // ëîãè÷åñêèé ñäâèã äëèííîãî öåëîãî âïðàâî}
2037 if (strcmp(yytext, "iand") == 0) return 0x7E; // ëîãè÷åñêîå È ñ îïåðàíäàìè öåëîãî òèïà}
2038 if (strcmp(yytext, "land") == 0) return 0x7F; // ëîãè÷åñêîå È ñ îïåðàíäàìè äëèííîãî öåëîãî òèïà}
2039 if (strcmp(yytext, "ior") == 0) return 0x80; // ëîãè÷åñêîå ÈËÈ ñ öåëî÷èñëåííûìè îïåðàíäàìè}
2040 if (strcmp(yytext, "lor") == 0) return 0x81; // ëîãè÷åñêîå ÈËÈ ñ îïåðàíäàìè äëèííîãî öåëîãî òèïà}
2041 if (strcmp(yytext, "ixor") == 0) return 0x82; // èñêëþ÷àþùåå ÈËÈ ñ öåëî÷èñëåííûìè îïåðàíäàìè}
2042 if (strcmp(yytext, "lxor") == 0) return 0x83; // èñêëþ÷àþùåå ÈËÈ ñ îïåðàíäàìè äëèííîãî öåëîãî òèïà}
2043 if (strcmp(yytext, "iinc") == 0) return 0x84; // [1,1+-]óâåëè÷åíèå ëîêàëüíîé ïåðåìåííîé íà êîíñòàíòó}
2044 if (strcmp(yytext, "i2l") == 0) return 0x85; // ïðåîáðàçîâàíèå öåëîãî â äëèííîå öåëîå}
2045 if (strcmp(yytext, "i2f") == 0) return 0x86; // öåëîå â âåùåñòâåííîå}
2046 if (strcmp(yytext, "i2d") == 0) return 0x87; // öåëîå â äâîéíîå âåùåñòâåííîå}
2047 if (strcmp(yytext, "l2i") == 0) return 0x88; // äëèííîå öåëîå â öåëîå}
2048 if (strcmp(yytext, "l2f") == 0) return 0x89; // äëèííîå öåëîå â âåùåñòâåííîå}
2049 if (strcmp(yytext, "l2d") == 0) return 0x8A; // äëèííîå öåëîå â äâîéíîå âåùåñòâåííîå}
2050 if (strcmp(yytext, "f2i") == 0) return 0x8B; // âåùåñòâåííîå â öåëîå}
2051 if (strcmp(yytext, "f2l") == 0) return 0x8C; // âåùåñòâåííîå â äëèííîå öåëîå}
2052 if (strcmp(yytext, "f2d") == 0) return 0x8D; // âåùåñòâåííîå â äâîéíîå âåùåñòâåííîå}
2053 if (strcmp(yytext, "d2i") == 0) return 0x8E; // äâîéíîå âåùåñòâåííîå â öåëîå}
2054 if (strcmp(yytext, "d2l") == 0) return 0x8F; // äâîéíîå âåùåñòâåííîå â äëèííîå öåëîå}
2055 if (strcmp(yytext, "d2f") == 0) return 0x90; // äâîéíîå âåùåñòâåííîå â âåùåñòâåííîå}
2056 if (strcmp(yytext, "int2byte") == 0) return 0x91; // öåëîå â çíàêîâûé áàéò}
2057 if (strcmp(yytext, "int2char") == 0) return 0x92; // öåëîå â ñèìâîë}
2058 if (strcmp(yytext, "int2short") == 0) return 0x93; // öåëîå â êîðîòêîå}
2059 if (strcmp(yytext, "lcmp") == 0) return 0x94; // ñðàâíåíèå äëèííûõ öåëûõ}
2060 if (strcmp(yytext, "fcmpl") == 0) return 0x95; // ñðàâíåíèå âåùåñòâåííûõ îäèíàðíîé òî÷íîñòè (-1 ïðè NaN)}
2061 if (strcmp(yytext, "fcmpg") == 0) return 0x96; // ñðàâíåíèå âåùåñòâåííûõ îäèíàðíîé òî÷íîñòè (1 ïðè NaN)}
2062 if (strcmp(yytext, "dcmpl") == 0) return 0x97; // ñðàâíåíèå âåùåñòâåííûõ äâîéíîé òî÷íîñòè(-1 ïðè NaN)}
2063 if (strcmp(yytext, "dcmpg") == 0) return 0x98; // ñðàâíåíèå âåùåñòâåííûõ äâîéíîé òî÷íîñòè(1 ïðè NaN)}
2064 if (strcmp(yytext, "ifeq") == 0) return 0x99; // [2]ïåðåõîä, åñëè ðàâíî 0}
2065 if (strcmp(yytext, "ifne") == 0) return 0x9A; // [2]ïåðåõîä, åñëè íå ðàâíî 0}
2066 if (strcmp(yytext, "iflt") == 0) return 0x9B; // [2]ïåðåõîä, åñëè ìåíüøå 0}
2067 if (strcmp(yytext, "ifge") == 0) return 0x9C; // [2]ïåðåõîä, åñëè áîëüøå èëè ðàâíî 0}
2068 if (strcmp(yytext, "ifgt") == 0) return 0x9D; // [2]ïåðåõîä, åñëè áîëüøå 0}
2069 if (strcmp(yytext, "ifle") == 0) return 0x9E; // [2]ïåðåõîä, åñëè ìåíüøå èëè ðàâíî 0}
2070 if (strcmp(yytext, "if_icmpeq") == 0) return 0x9F; // [2]ïåðåõîä, åñëè öåëûå ðàâíû}
2071 if (strcmp(yytext, "if_icmpne") == 0) return 0xA0; // [2]ïåðåõîä, åñëè öåëûå íå ðàâíû}
2072 if (strcmp(yytext, "if_icmplt") == 0) return 0xA1; // [2]ïåðåõîä, åñëè öåëîå ìåíüøå 0}
2073 if (strcmp(yytext, "if_icmpge") == 0) return 0xA2; // [2]ïåðåõîä, åñëè öåëîå áîëüøå èëè ðàâíî}
2074 if (strcmp(yytext, "if_icmpgt") == 0) return 0xA3; // [2]ïåðåõîä, åñëè öåëîå áîëüøå 0}
2075 if (strcmp(yytext, "if_icmple") == 0) return 0xA4; // [2]ïåðåõîä, åñëè öåëîå ìåíüøå èëè ðàâíî}
2076 if (strcmp(yytext, "if_acmpeq") == 0) return 0xA5; // [2]ïåðåõîä, åñëè ññûëêè íà îáúåêò ðàâíû}
2077 if (strcmp(yytext, "if_acmpne") == 0) return 0xA6; // [2]ïåðåõîä, åñëè ññûëêè íà îáúåêò íå ðàâíû}
2078 if (strcmp(yytext, "goto") == 0) return 0xA7; // [2]ïåðåõîä íà}
2079 if (strcmp(yytext, "jsr") == 0) return 0xA8; // [2]ïåðåõîä íà ïîäïðîãðàììó}
2080 if (strcmp(yytext, "ret") == 0) return 0xA9; // [1]âîçâðàò èç ïîäïðîãðàììû}
2081 if (strcmp(yytext, "tableswitch") == 0) return 0xAA; // [tbs] äîñòóï ê òàáëèöå ïåðåõîäà ïî èíäåêñó è ïåðåõîä}
2082 if (strcmp(yytext, "lookupswitch") == 0) return 0xAB; // [lks] äîñòóï ê òàáëèöå ïåðåõîäà ïî ñðàâíåíèþ ñ êëþ÷îì è ïåðåõîä}
2083 if (strcmp(yytext, "ireturn") == 0) return 0xAC; // âîçâðàò öåëîãî çíà÷åíèÿ ôóíêöèè}
2084 if (strcmp(yytext, "lreturn") == 0) return 0xAD; // âîçâðàò äëèííîãî öåëîãî çíà÷åíèÿ ôóíêöèè}
2085 if (strcmp(yytext, "freturn") == 0) return 0xAE; // âîçâðàò îäèíàðíîãî âåùåñòâåííîãî çíà÷åíèÿ ôóíêöèè}
2086 if (strcmp(yytext, "dreturn") == 0) return 0xAF; // âîçâðàò äâîéíîãî âåùåñòâåííîãî çíà÷åíèÿ ôóíêöèè}
2087 if (strcmp(yytext, "areturn") == 0) return 0xB0; // âîçâðàò îáúåêòíîé ññûëêè èç ôóíêöèè}
2088 if (strcmp(yytext, "return") == 0) return 0xB1; // âîçâðàò(îïóñòîøàþùèé) èç ïðîöåäóðû}
2089 if (strcmp(yytext, "getstatic") == 0) return 0xB2; // [2fld]ïîëó÷åíèå ñòàòè÷åñêîãî ïîëÿ êëàññà}
2090 if (strcmp(yytext, "putstatic") == 0) return 0xB3; // [2fld]óñòàíîâêà ñòàòè÷åñêîãî ïîëÿ â êëàññå}
2091 if (strcmp(yytext, "getfield") == 0) return 0xB4; // [2fld]ïåðåíîñ ïîëÿ èç îáúåêòà}
2092 if (strcmp(yytext, "putfield") == 0) return 0xB5; // [2fld]óñòàíîâêà ïîëÿ â îáúåêòå}
2093 if (strcmp(yytext, "invokevirtual") == 0) return 0xB6; // [2mtd],âûçûâàåò ìåòîä ýêçåìïëÿðà, îñíîâûâàÿñü íà òèïå âðåìåíè âûïîëíåíèÿ}
2094 if (strcmp(yytext, "invokenonvirtual") == 0) return 0xB7; // [2mtd],âûçûâàåò ìåòîä ýêçåìïëÿðà, îñíîâûâàÿñü íà íå âèðòóàëüíîì òèïå}
2095 if (strcmp(yytext, "invokestatic") == 0) return 0xB8; // [2mtd]âûçîâ ìåòîäà êëàññà (ñòàòè÷åñêîãî ìåòîäà)}
2096 if (strcmp(yytext, "invokeinterface") == 0) return 0xB9; // [2,1,1]âûçûâàåò ìåòîä èíòåðôåéñà}
2097 if (strcmp(yytext, "new") == 0) return 0xBB; // [2]ñîçäàåò íîâûé îáúåêò}
2098 if (strcmp(yytext, "newarray") == 0) return 0xBC; // [1]atype> T_BOOLEAN=4,T_CHAR=5,T_FLOAT=6,T_DOUBLE=7,T_BYTE=8, T_SHORT=9,T_INT=9,T_LONG=11}
2099 if (strcmp(yytext, "anewarray") == 0) return 0xBD; // [2class]îáúÿâëåíèå íîâîãî ìàññèâà èç ññûëîê íà îáúåêòû}
2100 if (strcmp(yytext, "arraylength") == 0) return 0xBE; // âîçâðàùàåò äëèíó ìàññèâà}
2101 if (strcmp(yytext, "athrow") == 0) return 0xBF; // ãåíåðàöèÿ îáðàáîòêè èëè îøèáêè}
2102 if (strcmp(yytext, "checkcast") == 0) return 0xC0; // cs 2,ïðîâåðÿåò, ÷òî îáúåêò èìååò äàííûé òèï}
2103 if (strcmp(yytext, "instanceof") == 0) return 0xC1; // [2class]îïðåäåëÿåò, èìååò ëè îáúåêò äàííûé òèï}
2104 if (strcmp(yytext, "monitorenter") == 0) return 0xC2; // âõîä â êîíòðîëèðóåìóþ îáëàñòü êîäà}
2105 if (strcmp(yytext, "monitorexit") == 0) return 0xC3; // âûõîä èç êîíòðîëèðóåìîé îáëàñòè êîäà}
2106 if (strcmp(yytext, "wide") == 0) return 0xC4; // ðàñøèðåííûé èíäåêñ äëÿ äîñòóïà ê ëîêàëüíûì ïåðåìåííûì äëÿ êîìàíä çàãðóçêè, ñîõðàíåíèÿ è ïðèðàùåíè}
2107 if (strcmp(yytext, "multianewarray") == 0) return 0xC5; // [2cp-index,1b]ðàçìåùåíèå íîâîãî ìíîãîìåðíîãî ìàññèâà}
2108 if (strcmp(yytext, "ifnull") == 0) return 0xC6; // [2ofs]ïåðåõîä, åñëè ïóñòîé óêàçàòåëü}
2109 if (strcmp(yytext, "ifnonnull") == 0) return 0xC7; // [2ofs]ïåðåõîä, åñëè íå ïóñòîé óêàçàòåëü}
2110 if (strcmp(yytext, "goto_w") == 0) return 0xC8; // [4ofs]ïåðåõîä íà (ðàñøèðåííûé èíäåêñ)}
2111 if (strcmp(yytext, "jsr_w") == 0) return 0xC9; // [4ofs]ïåðåõîä íà ïîäïðîãðàììó (ðàñøèðåííûé èíäåêñ)}
2112 if (strcmp(yytext, "breakpoint") == 0) return 0xCA; // îñòàíîâêà è ïåðåäà÷à êîíòðîëÿ îáðàáîò÷èêó ïðåðûâàíèé}
2113 if (strcmp(yytext, "ret_w") == 0) return 0xD1; // [2]âîçâðàò èç ïîäïðîãðàììû (ðàñøèðåííûé èíäåêñ)}
2114 return 0xFF;
2115 //0x10,0xBC 1b;
2116 //0x11 2b+-;
2117 //0x12 1b constpool-index;
2118 //0x13 2b constpool-index(2byte-const);
2119 //0x14 2b constpool-index(4byte-const);
2120 //0xB2,0xB3,0xB4,0xB5 2b constpool-field;
2121 //0xB6,0xB7,0xB8 2b constpool-method;
2122 //0xB9 2b constpool-method; 1b; 1b;
2123 //0xBB 2b constpool-index;
2124 //0xC5 2b constpool-index; 1b;
2125 //0xBD,0xC1 2b constpool-class;
2126 //0xC0 2b constpool-string;
2127 //0x15,0x16,0x17,0x18,0x19 1b locvar-index;
2128 //0x36,0x37,0x38,0x39,0x3A 1b locvar-index;
2129 //0x84 1b; 1b+-(locvar-add-const);
2130 //0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xC6,0xC7 2b offs;
2131 //0xC8 4b offs;
2132 //0xC9 4b call;
2133 //0xA8 2b call;
2134 //0xA9 1b ret;
2135 //0xD1 2b ret;
2136 //0xC4 wide...;
2137 //0xAA tableswitch...;
2138 //0xAB loookupswitch...;
2139 //îñòàëüíûå êîäû ïàðàìåòðîâ íå èìåþò...
2142 int cp_index_body()
2143 { //ðàçáîð ìîäèôèêàöèé ññûëîê íà ïàðàìåòðû êîíñòàíòíîãî ïóëà
2144 char p1[512];
2145 char p2[512];
2146 if (current_token == IDENTIFIER)
2148 if (strcmp(yytext, "int") == 0)
2150 current_token = yylex();
2151 if (current_token == CST_INTEGER) return cp_add_integer(integer_constant);
2153 else if (strcmp(yytext, "utf8") == 0)
2155 current_token = yylex();
2156 if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_utf8(yytext);
2158 else if (strcmp(yytext, "str") == 0)
2160 current_token = yylex();
2161 if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_string(yytext);
2163 else if (strcmp(yytext, "class") == 0)
2165 current_token = yylex();
2166 if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_class(yytext);
2168 else if (strcmp(yytext, "nametype") == 0)
2170 current_token = yylex();
2171 if ((current_token == CST_STRING)||(current_token == CST_CHAR))
2173 strcpy(&p1,yytext);
2174 current_token = yylex();
2175 if (current_token == COMMA)
2177 current_token = yylex();
2178 if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_nameandtype(p1, yytext);
2181 } else if (strcmp(yytext, "field") == 0)
2183 current_token = yylex();
2184 if ((current_token == CST_STRING)||(current_token == CST_CHAR))
2186 strcpy(&p1,yytext);
2187 current_token = yylex();
2188 if (current_token == COMMA)
2190 current_token = yylex();
2191 if ((current_token == CST_STRING)||(current_token == CST_CHAR))
2193 strcpy(&p2,yytext);
2194 current_token = yylex();
2195 if (current_token == COMMA)
2197 current_token = yylex();
2198 if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_fieldref(p1,p2,yytext);
2204 else if (strcmp(yytext, "method") == 0)
2206 current_token = yylex();
2207 if ((current_token == CST_STRING)||(current_token == CST_CHAR))
2209 strcpy(&p1,yytext);
2210 current_token = yylex();
2211 if (current_token == COMMA)
2213 current_token = yylex();
2214 if ((current_token == CST_STRING)||(current_token == CST_CHAR))
2216 strcpy(&p2,yytext);
2217 current_token = yylex();
2218 if (current_token == COMMA)
2220 current_token = yylex();
2221 if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_methodref(p1,p2,yytext);
2228 else if (current_token == KWD_INTERFACE) //if (strcmp(yytext, "interface") == 0)
2230 current_token = yylex();
2231 if ((current_token == CST_STRING)||(current_token == CST_CHAR))
2233 strcpy(&p1,yytext);
2234 current_token = yylex();
2235 if (current_token == COMMA)
2237 current_token = yylex();
2238 if ((current_token == CST_STRING)||(current_token == CST_CHAR))
2240 strcpy(&p2,yytext);
2241 current_token = yylex();
2242 if (current_token == COMMA)
2244 current_token = yylex();
2245 if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_interface(p1,p2,yytext);
2251 return -1; //îøèáêà ðàçáîðà ïàðàìåòðîâ
2255 int RD_inline_offs(block *current_block, int n, int addr)
2257 current_token = yylex();
2258 if (current_token == CST_INTEGER) return (short)integer_constant; //NUMBER
2259 if (current_token == COLON) //FIND LABEL
2261 current_token = yylex();
2262 if (current_token == CST_INTEGER)
2264 int i = labcount;
2265 nam[0] = integer_constant;
2266 if (integer_constant==111)
2267 integer_constant=111;
2268 len[0] = 0;
2269 while ((nam[i] != integer_constant) || (len[i] != 0)) i--;
2270 if (i>0) return lab[i]-addr;
2271 //add find block
2272 labcount++;
2273 nam[labcount] = integer_constant;
2274 len[labcount] = n; //offs-type: 2bytes / 4bytes
2275 lab[labcount] = current_block->code->bytecode_pos;
2276 return addr; //label no found
2279 return 0; //error!
2283 void RD_inline_body(block *current_block)
2285 int cp_index,opcode,err,addr,offs,i,j;
2286 labcount=0;
2287 err=0;
2288 do {
2289 current_token = yylex();
2290 if (current_token == IDENTIFIER)
2292 opcode=RD_opcodes();
2293 bytecode_append(current_block->code, opcode);
2294 ///////
2295 switch (opcode)
2297 case 0x10: //1byte;
2298 case 0xBC:
2299 case 0x15: //1b locvar-index;
2300 case 0x16:
2301 case 0x17:
2302 case 0x18:
2303 case 0x19:
2304 case 0x36: //1b locvar-index;
2305 case 0x37:
2306 case 0x38:
2307 case 0x39:
2308 case 0x3A:
2309 case 0xA9: //1b ret;
2310 err=1;
2311 current_token = yylex();
2312 if ((current_token == CST_INTEGER) && (integer_constant>=0) && (integer_constant<=255))
2314 bytecode_append(current_block->code, (char)integer_constant);
2315 err=0;
2317 break;
2318 case 0x84: //1b; 1b+-(locvar-add-const);
2319 err=1;
2320 current_token = yylex();
2321 if ((current_token == CST_INTEGER) && (integer_constant>=0) && (integer_constant<=255))
2323 bytecode_append(current_block->code, (char)integer_constant);
2324 current_token = yylex();
2325 if (current_token == COMMA)
2327 current_token = yylex();
2328 if ((current_token == CST_INTEGER) && (integer_constant>=0)&&(integer_constant<=255))
2330 bytecode_append(current_block->code, (char)integer_constant);
2331 err=0;
2335 break;
2336 case 0x11: //2b+-;
2337 err=1;
2338 current_token = yylex();
2339 if ((current_token == CST_INTEGER) && (integer_constant>=0) && (integer_constant<=65535))
2341 bytecode_append_short_int(current_block->code, (short)integer_constant);
2342 err=0;
2344 break;
2345 case 0x99: //2b offs;
2346 case 0x9A:
2347 case 0x9B:
2348 case 0x9C:
2349 case 0x9D:
2350 case 0x9E:
2351 case 0x9F:
2352 case 0xA0:
2353 case 0xA1:
2354 case 0xA2:
2355 case 0xA3:
2356 case 0xA4:
2357 case 0xA5:
2358 case 0xA6:
2359 case 0xA7:
2360 case 0xC6:
2361 case 0xC7:
2362 case 0xA8: //2b call;
2363 case 0xD1: //2b ret;
2364 err=1;
2365 addr = current_block->code->bytecode_pos-1;
2366 offs = RD_inline_offs(current_block, 2, addr);
2367 if (offs != 0)
2369 if ((offs>=-32768) && (offs<=32767))
2371 bytecode_append_short_int(current_block->code, (short)offs);
2372 err=0;
2375 //current_token = yylex();
2376 //if ((current_token == CST_INTEGER) && (integer_constant>=0) && (integer_constant<=65535))
2377 //{
2378 // bytecode_append_short_int(current_block->code, (short)integer_constant);
2379 // err=0;
2380 //}
2381 break;
2382 case 0xC8: //4b offs;
2383 case 0xC9: //4b call;
2384 err=1;
2385 addr = current_block->code->bytecode_pos-1;
2386 offs = RD_inline_offs(current_block, 4, addr);
2387 if (offs != 0)
2389 bytecode_append_long_int(current_block->code, offs);
2390 err=0;
2392 //current_token = yylex();
2393 //if (current_token == CST_INTEGER)
2394 //{
2395 // bytecode_append_long_int(current_block->code, integer_constant);
2396 // err=0;
2397 //}
2398 break;
2399 case 0x12: //1b constpool-index;
2400 err=1;
2401 current_token = yylex();
2402 cp_index=cp_index_body();
2403 if ((cp_index>=0) && (cp_index<=255))
2405 bytecode_append(current_block->code, cp_index);
2406 err=0;
2408 break;
2409 case 0xBB: //2b constpool-index;
2410 err=1;
2411 current_token = yylex();
2412 cp_index=cp_index_body();
2413 if (cp_index>=0)
2415 bytecode_append_short_int(current_block->code, cp_index);
2416 err=0;
2418 break;
2419 case 0xC5: //2b constpool-index; 1b;
2420 err=1;
2421 current_token = yylex();
2422 cp_index=cp_index_body();
2423 if (cp_index>=0)
2425 bytecode_append_short_int(current_block->code, cp_index);
2426 current_token = yylex();
2427 if (current_token == COMMA)
2429 current_token = yylex();
2430 if (current_token == CST_INTEGER)
2432 if ((integer_constant>=0) && (integer_constant<=255))
2434 bytecode_append(current_block->code, (char)integer_constant);
2435 err=0;
2440 break;
2441 case 0xBD: //2b constpool-class;
2442 case 0xC1:
2443 err=1;
2444 current_token = yylex();
2445 if ((current_token == IDENTIFIER) && (strcmp(yytext, "class") == 0))
2447 cp_index=cp_index_body();
2448 if (cp_index>=0)
2450 bytecode_append_short_int(current_block->code, cp_index);
2451 err=0;
2454 break;
2455 case 0xC0: //2b constpool-string;
2456 err=1;
2457 current_token = yylex();
2458 if (current_token == IDENTIFIER) //&& (strcmp(yytext, "str") == 0))
2460 cp_index=cp_index_body();
2461 if (cp_index>=0)
2463 bytecode_append_short_int(current_block->code, cp_index);
2464 err=0;
2467 break;
2468 case 0x13: //2b constpool-index(2byte-const);
2469 case 0x14: //2b constpool-index(4byte-const);
2470 err=1;
2471 current_token = yylex();
2472 //if ((current_token == IDENTIFIER) && (strcmp(yytext, "int") == 0))
2473 //{
2474 cp_index=cp_index_body();
2475 if (cp_index>=0)
2477 bytecode_append_short_int(current_block->code, cp_index);
2478 err=0;
2480 //}
2481 break;
2482 case 0xB2: //2b constpool-field;
2483 case 0xB3:
2484 case 0xB4:
2485 case 0xB5:
2486 err=1;
2487 current_token = yylex();
2488 if ((current_token == IDENTIFIER) && (strcmp(yytext, "field") == 0))
2490 cp_index=cp_index_body();
2491 if (cp_index>=0)
2493 bytecode_append_short_int(current_block->code, cp_index);
2494 err=0;
2497 break;
2498 case 0xB6: //2b constpool-method;
2499 case 0xB7:
2500 case 0xB8:
2501 err=1;
2502 current_token = yylex();
2503 if ((current_token == IDENTIFIER) && (strcmp(yytext, "method") == 0))
2505 cp_index=cp_index_body();
2506 if (cp_index>=0)
2508 bytecode_append_short_int(current_block->code, cp_index);
2509 err=0;
2512 break;
2513 case 0xB9: //2b constpool-method; 1b; 1b;
2514 err=1;
2515 current_token = yylex();
2516 if (current_token == KWD_INTERFACE) //&& (strcmp(yytext, "interface") != 0))
2518 cp_index=cp_index_body();
2519 if (cp_index>=0)
2521 bytecode_append_short_int(current_block->code, cp_index);
2522 current_token = yylex();
2523 if (current_token == COMMA)
2525 current_token = yylex();
2526 if (current_token == CST_INTEGER) {
2527 if ((integer_constant>=0) && (integer_constant<=255))
2529 bytecode_append(current_block->code, (char)integer_constant);
2530 current_token = yylex();
2531 if (current_token == COMMA)
2533 current_token = yylex();
2534 if (current_token == CST_INTEGER)
2536 if ((integer_constant>=0) && (integer_constant<=255))
2538 bytecode_append(current_block->code, (char)integer_constant);
2539 err=0;
2548 break;
2549 case 0xAA: //tableswitch...;
2551 err=1;
2552 addr = current_block->code->bytecode_pos-1;
2553 while (current_block->code->bytecode_pos%4!=0) //4byte-align
2554 bytecode_append(current_block->code, 0);
2555 offs = RD_inline_offs(current_block, 4, addr);
2556 if (offs != 0)
2558 bytecode_append_long_int(current_block->code, offs); //default-offs
2559 current_token = yylex();
2560 if (current_token == COMMA)
2562 current_token = yylex();
2563 if (current_token == CST_INTEGER)
2565 bytecode_append_long_int(current_block->code, integer_constant); //low-index
2566 i=integer_constant;
2567 current_token = yylex();
2568 if (current_token == COMMA)
2570 current_token = yylex();
2571 if (current_token == CST_INTEGER)
2573 bytecode_append_long_int(current_block->code, integer_constant); //high-index Length=high-low+1
2574 j=integer_constant;
2575 current_token = yylex();
2576 if (current_token == COMMA)
2578 err=0;
2579 for (; i<=j; i++)
2581 offs = RD_inline_offs(current_block, 4, addr);
2582 if (i<j)
2584 current_token = yylex();
2585 if (current_token != COMMA) offs = 0;
2587 if (offs == 0) //bad label
2589 add_error_message(462, 0, current_block->code->bytecode_pos);
2590 err=1;
2591 break;
2593 bytecode_append_long_int(current_block->code, offs); //i-offs
2602 break;
2604 case 0xAB: //loookupswitch...;
2606 err=1;
2607 addr = current_block->code->bytecode_pos-1;
2608 while (current_block->code->bytecode_pos%4!=0) //4byte-align
2609 bytecode_append(current_block->code, 0);
2610 offs = RD_inline_offs(current_block, 4, addr);
2611 if (offs != 0)
2613 bytecode_append_long_int(current_block->code, offs); //default-offs
2614 current_token = yylex();
2615 if (current_token == COMMA)
2617 current_token = yylex();
2618 if (current_token == CST_INTEGER)
2620 bytecode_append_long_int(current_block->code, integer_constant); //length
2621 i=integer_constant;
2622 current_token = yylex();
2623 if (current_token == COMMA)
2625 err=0;
2626 for (; i>0; i--)
2628 offs = 0;
2629 current_token = yylex();
2630 if (current_token == CST_INTEGER)
2632 bytecode_append_long_int(current_block->code, integer_constant);
2633 offs = RD_inline_offs(current_block, 4, addr);
2634 if (i>1)
2636 current_token = yylex();
2637 if (current_token != COMMA) offs = 0;
2640 if (offs == 0) //bad label
2642 add_error_message(462, 0, current_block->code->bytecode_pos);
2643 err=1;
2644 break;
2646 bytecode_append_long_int(current_block->code, offs); //i-offs
2653 break;
2654 /*
2655 case 0xC4: //wide;
2656 break;
2657 */
2658 case 0xFF:
2659 err=1;
2660 break;
2663 else if (current_token == CST_INTEGER)
2665 if (integer_constant<=255) bytecode_append(current_block->code, (char)integer_constant);
2666 else if (integer_constant<=65535) bytecode_append_short_int(current_block->code, (short)integer_constant);
2667 else bytecode_append_long_int(current_block->code, integer_constant);
2668 err=0;
2670 else if (current_token == COLON) //SET LABEL
2672 err=1;
2673 current_token = yylex();
2674 if (current_token == CST_INTEGER)
2676 nam[0]=integer_constant;
2677 len[0]=0;
2678 i=labcount;
2679 while ((nam[i]!=integer_constant) || (len[i]!=0)) i--;
2680 if (i==0)
2682 labcount++;
2683 nam[labcount] = integer_constant;
2684 len[labcount] = 0;
2685 lab[labcount] = current_block->code->bytecode_pos;
2686 err=0;
2688 else
2690 add_error_message(461, nam[i], current_block->code->bytecode_pos);
2691 labcount=0;
2696 else err=1;
2697 /////////
2698 if (err==0)
2700 current_token = yylex();
2701 if (current_token != SEMI_COLON) err=1;
2703 } while (err==0);
2704 //modify old label
2705 for (i=labcount; i>0; i--) if (len[i]>0)
2707 for (j=labcount; j>i; j--) if (len[j]==0) if (nam[i]==nam[j]) break;
2708 if (j>i)
2710 int k;
2711 offs = 0;
2712 for (k = lab[i]; k<lab[i]+len[i]; k++)
2713 offs = (offs << 8) + (current_block->code->bytecode[k] & 0xff);
2714 offs = lab[j]-offs;
2715 for (k--; k>=lab[i]; k--)
2717 current_block->code->bytecode[k] = (char)offs;
2718 offs = offs>>8;
2721 else add_error_message(460, nam[i], lab[i]);
2724 ///////////////////////////////////////////////////////////////////////////////////////////////////
2725 //////////////////////////////////// END JAVA - ASM ///////////////////////////////////////////////
2726 ///////////////////////////////////////////////////////////////////////////////////////////////////
2731 /*
2732 Handles the if-then-[else] statement. The grammar rule
2733 is:
2735 <RD_if_statement> -> <RD_expression> then <RD_statement>
2736 [ else <RD_statement> ]
2738 */
2739 void RD_if_statement(block *current_block)
2741 type *expression_type;
2742 long int jump_offset_position;
2743 signed short int offset;
2745 expression_type = RD_expression(current_block);
2747 if ((expression_type->type_class != error_type) /* a simple error-recovery */
2748 && (expression_type->type_class != boolean_type))
2750 add_error_message(407, "boolean", "");
2753 type_destroy(expression_type);
2755 if (current_token != KWD_THEN)
2757 add_error_message(216, YYTEXT_STRING, "");
2760 current_token = yylex();
2762 /* generate the code */
2763 bytecode_append(current_block->code, ifeq$); /* branch if comparison with zero succedd */
2764 jump_offset_position = current_block->code->bytecode_pos;
2765 bytecode_append(current_block->code, 0); /* the place for offset of where to jump */
2766 bytecode_append(current_block->code, 0);
2768 RD_statement(current_block);
2770 while (current_token == SEMI_COLON)
2771 current_token = yylex();
2773 if (current_token == KWD_ELSE)
2775 /* set the address of the next instruction */
2776 offset = (short) (current_block->code->bytecode_pos + 4 - jump_offset_position);
2777 current_block->code->bytecode[jump_offset_position] = (char) (offset>>8);
2778 current_block->code->bytecode[jump_offset_position+1] = (char) offset;
2780 bytecode_append(current_block->code, goto$);
2781 jump_offset_position = current_block->code->bytecode_pos;
2782 bytecode_append(current_block->code, 0);
2783 bytecode_append(current_block->code, 0);
2785 current_token = yylex();
2787 RD_statement(current_block);
2789 /* set the adress of the next instruction */
2790 offset = (short) (current_block->code->bytecode_pos - jump_offset_position + 1);
2791 current_block->code->bytecode[jump_offset_position] = (char) (offset>>8);
2792 current_block->code->bytecode[jump_offset_position+1] = (char) offset;
2794 else
2796 char *yycopy;
2797 int i;
2799 /* set the address of the next instruction */
2800 offset = (short) (current_block->code->bytecode_pos - jump_offset_position + 1);
2801 current_block->code->bytecode[jump_offset_position] = (char) (offset>>8);
2802 current_block->code->bytecode[jump_offset_position+1] = (char) offset;
2804 /* put the current token back to stream and preceed it with ';' */
2805 yycopy = strdup(yytext);
2807 for(i = strlen(yytext) - 1; i >= 0; i--)
2808 backchar(yycopy[i]);
2809 backchar(';');
2810 free(yycopy);
2812 current_token = yylex();
2816 /*
2817 The case-of statement. The rule used is:
2819 <RD_case_statement> -> <RD_expression> OF
2820 <RD_case_list> end
2821 */
2822 void RD_case_statement(block *current_block)
2824 type *expression_type;
2825 expression_type = RD_expression(current_block);
2827 add_error_message(442, "", "");
2829 if ((expression_type->type_class != error_type) /* a simple error-recovery */
2830 && (expression_type->type_class != integer_type)
2831 && (expression_type->type_class != char_type)
2832 && (expression_type->type_class != string_type))
2834 add_error_message(408, "", "");
2837 if (current_token != KWD_OF)
2839 add_error_message(203, "of", YYTEXT_STRING);
2842 current_token = yylex();
2844 RD_case_list(current_block, expression_type);
2846 if (current_token != KWD_END)
2848 add_error_message(203, "end", YYTEXT_STRING);
2851 current_token = yylex();
2852 type_destroy(expression_type);
2856 /*
2857 The case expression's list.
2859 <RD_case_list> -> ( CONST (, CONST)* : <RD_statement> )+
2860 */
2861 void RD_case_list(block *current_block, type *case_type)
2863 short int first_pass = 1;
2865 do
2867 if (first_pass)
2868 first_pass = 0;
2869 else
2870 current_token = yylex();
2872 switch(current_token)
2874 case CST_INTEGER:
2876 if (case_type->type_class != integer_type)
2878 string *expected_type_name;
2879 expected_type_name = type_get_name(case_type);
2880 add_error_message(409, string_get_cstr(expected_type_name), "integer");
2881 string_destroy(expected_type_name);
2883 current_token = yylex();
2884 break;
2887 case CST_REAL:
2889 string *expected_type_name;
2890 expected_type_name = type_get_name(case_type);
2891 add_error_message(409, string_get_cstr(expected_type_name), "real");
2892 string_destroy(expected_type_name);
2894 current_token = yylex();
2895 break;
2898 case CST_BOOLEAN:
2901 string *expected_type_name;
2902 expected_type_name = type_get_name(case_type);
2903 add_error_message(409, string_get_cstr(expected_type_name), "boolean");
2904 string_destroy(expected_type_name);
2906 current_token = yylex();
2907 break;
2910 case CST_CHAR:
2912 if (case_type->type_class != char_type)
2914 string *expected_type_name;
2915 expected_type_name = type_get_name(case_type);
2916 add_error_message(409, string_get_cstr(expected_type_name), "char");
2917 string_destroy(expected_type_name);
2919 current_token = yylex();
2920 break;
2923 case CST_STRING:
2925 if (case_type->type_class != string_type)
2927 string *expected_type_name;
2928 expected_type_name = type_get_name(case_type);
2929 add_error_message(409, string_get_cstr(expected_type_name), "string");
2930 string_destroy(expected_type_name);
2932 current_token = yylex();
2933 break;
2936 case IDENTIFIER:
2938 /* find the constant type for the given identifier */
2939 type *constant_type;
2941 constant_type = get_constant_type(current_block, YYTEXT_STRING);
2943 if (constant_type->type_class == error_type)
2944 add_error_message(410, YYTEXT_STRING, "");
2945 else
2946 if (!type_equal(constant_type, case_type))
2948 string *expected_type_name;
2949 string *constant_type_name;
2951 expected_type_name = type_get_name(case_type);
2952 constant_type_name = type_get_name(constant_type);
2954 add_error_message(409, string_get_cstr(expected_type_name), string_get_cstr(constant_type_name));
2956 string_destroy(expected_type_name);
2957 string_destroy(constant_type_name);
2960 type_destroy(constant_type);
2962 current_token = yylex();
2963 break;
2966 default:
2968 add_error_message(206, "", "");
2970 /* Error-recovery: find the first : */
2971 while ((current_token != COLON)
2972 && (current_token != END_OF_INPUT))
2974 current_token = yylex();
2977 if (current_token == END_OF_INPUT)
2978 return;
2980 break;
2985 } while (current_token == COMMA);
2987 current_token = yylex();
2989 if (current_token != COLON)
2991 add_error_message(200, ":", YYTEXT_STRING);
2993 /* Error-recovery: find the first : */
2994 while ((current_token != COLON)
2995 && (current_token != END_OF_INPUT))
2997 current_token = yylex();
3000 if (current_token == END_OF_INPUT)
3001 return;
3004 current_token = yylex();
3006 RD_statement(current_block);
3010 /*
3011 The while-do statement.
3013 <RD_while_statement> -> <RD_expression> do <RD_statement>
3014 */
3015 void RD_while_statement(block *current_block)
3017 type *expression_type;
3018 int pos1, pos2;
3019 int jump_offset_position;
3020 int jump_offset;
3021 int break_pos1, break_pos2;
3023 pos1 = current_block->code->bytecode_pos;
3025 expression_type = RD_expression(current_block);
3027 pos2 = current_block->code->bytecode_pos;
3028 bytecode_append(current_block->code, ifeq$);
3029 jump_offset_position = current_block->code->bytecode_pos;
3030 bytecode_append_short_int(current_block->code, 0); /* make place for offset value */
3032 if ((expression_type->type_class != error_type) /* a simple error-recovery */
3033 && (expression_type->type_class != boolean_type))
3035 add_error_message(407, "boolean", "");
3038 type_destroy(expression_type);
3040 if (current_token != KWD_DO)
3042 add_error_message(203, "do", YYTEXT_STRING);
3044 else
3045 current_token = yylex();
3047 inside_loop++;
3048 break_pos1 = current_block->code->bytecode_pos;
3049 RD_statement(current_block);
3050 break_pos2 = current_block->code->bytecode_pos;
3051 inside_loop --;
3053 bytecode_append(current_block->code, goto$);
3054 bytecode_append_short_int(current_block->code, pos1 - current_block->code->bytecode_pos + 1);
3056 jump_offset = current_block->code->bytecode_pos - pos2;
3057 current_block->code->bytecode[jump_offset_position] = (char)(jump_offset >> 8);
3058 current_block->code->bytecode[jump_offset_position + 1] = (char) jump_offset;
3060 transform_break_stmts(current_block->code, break_pos1, break_pos2, current_block->code->bytecode_pos);
3064 // j-a-s-d: besides
3065 //
3066 // current_token = yylex();
3067 //
3068 // bytecode_append(current_block->code, goto$);
3069 // bytecode_append_short_int(current_block->code, pos1 - current_block->code->bytecode_pos + 1);
3070 //
3071 // transform_break_stmts(current_block->code, break_pos1, break_pos2, current_block->code->bytecode_pos);
3072 //
3073 // is the exact implementation of forever,
3074 // the lesser impact implementation of repeat/forever to this MP compiler seems to be an "until false"
3076 type* RD_forever(block *current_block)
3078 type *return_type;
3079 return_type = type_create();
3080 bytecode_append(current_block->code, iconst_0$);
3081 current_token = yylex();
3082 return_type->type_class = boolean_type;
3083 return return_type;
3086 /*
3087 The repeat-until statement.
3089 <RD_repeat_statement> -> <RD_block_body> until <RD_expression>
3090 */
3092 void RD_repeat_statement(block *current_block)
3094 type *expression_type;
3096 int pos1;
3097 int break_pos1, break_pos2;
3099 pos1 = current_block->code->bytecode_pos;
3100 inside_loop ++;
3101 break_pos1 = current_block->code->bytecode_pos;
3102 RD_block_body(current_block);
3103 break_pos2 = current_block->code->bytecode_pos;
3104 inside_loop --;
3106 if (current_token == KWD_FOREVER)
3108 expression_type = RD_forever(current_block);
3109 } else {
3110 if (current_token != KWD_UNTIL)
3112 add_error_message(203, "until", YYTEXT_STRING);
3115 current_token = yylex();
3117 expression_type = RD_expression(current_block);
3119 /* generate the code */
3120 bytecode_append(current_block->code, ifeq$);
3121 bytecode_append_short_int(current_block->code, pos1 - current_block->code->bytecode_pos + 1);
3123 if ((expression_type->type_class != error_type) /* a simple error-recovery */
3124 && (expression_type->type_class != boolean_type))
3126 add_error_message(407, "boolean", "");
3129 transform_break_stmts(current_block->code, break_pos1, break_pos2, current_block->code->bytecode_pos);
3131 type_destroy(expression_type);
3136 /*
3137 The for statement.
3139 <RD_for_statement> -> IDN := <RD_expression> (to | downto)
3140 <RD_expression> do <RD_statement>
3141 */
3142 void RD_for_statement(block *current_block)
3144 type *iterator_type;
3145 type *expression1_type;
3146 type *expression2_type;
3147 identifier *iterator;
3148 string *iterator_name;
3149 int is_field;
3150 int check_bytecode_pos;
3151 int direction;
3152 int evaluate_pos;
3153 int break_pos1, break_pos2;
3155 iterator_type = get_variable_type(current_block, YYTEXT_STRING);
3156 iterator = get_identifier(current_block, YYTEXT_STRING);
3157 iterator_name = string_from_cstr(YYTEXT_STRING);
3159 if (iterator->identifier_class == unit_name)
3161 add_error_message(456, "", "");
3162 current_token = yylex();
3163 current_token = yylex();
3166 if ((iterator_type->type_class != integer_type)
3167 && (iterator_type->type_class != char_type))
3169 add_error_message(411, "", "");
3172 if (current_token != IDENTIFIER)
3174 add_error_message(202, "", "");
3176 /* Error-recovery: find the first := */
3177 while ((current_token != OP_ASSIGN)
3178 && (current_token != END_OF_INPUT))
3180 current_token = yylex();
3183 if (current_token == END_OF_INPUT)
3185 type_destroy(iterator_type);
3186 string_destroy(iterator_name);
3187 return;
3190 else
3191 current_token = yylex();
3193 if (current_token != OP_ASSIGN)
3195 add_error_message(209, YYTEXT_STRING, "");
3197 else
3198 current_token = yylex();
3200 expression1_type = RD_expression(current_block);
3202 is_field = iterator->belongs_to_program_block;
3203 create_put_variable_bytecode(iterator, current_block->code, iterator_name->cstr, is_field);
3205 if (!type_equal(iterator_type, expression1_type))
3207 string *name1, *name2;
3208 name1 = type_get_name(iterator_type);
3209 name2 = type_get_name(expression1_type);
3211 add_error_message(412, string_get_cstr(name1), string_get_cstr(name2));
3213 string_destroy(name1);
3214 string_destroy(name2);
3217 switch (current_token)
3219 case KWD_TO:
3221 direction = 1;
3222 current_token = yylex();
3223 break;
3226 case KWD_DOWNTO:
3228 direction = -1;
3229 current_token = yylex();
3230 break;
3233 default:
3235 add_error_message(204, YYTEXT_STRING, "");
3236 break;
3240 evaluate_pos = current_block->code->bytecode_pos;
3241 expression2_type = RD_expression(current_block);
3243 create_variable_bytecode(iterator, current_block->code, iterator_name->cstr, iterator->belongs_to_program_block);
3245 check_bytecode_pos = current_block->code->bytecode_pos;
3246 if (direction == 1)
3247 bytecode_append(current_block->code, if_icmplt$);
3248 else
3249 bytecode_append(current_block->code, if_icmpgt$);
3251 bytecode_append_short_int(current_block->code, 0);
3253 if (!type_equal(iterator_type, expression2_type))
3255 string *name1, *name2;
3256 name1 = type_get_name(iterator_type);
3257 name2 = type_get_name(expression2_type);
3259 add_error_message(412, string_get_cstr(name1), string_get_cstr(name2));
3261 string_destroy(name1);
3262 string_destroy(name2);
3265 if (current_token != KWD_DO)
3267 add_error_message(203, "do", YYTEXT_STRING);
3269 else
3270 current_token = yylex();
3272 inside_loop ++;
3273 break_pos1 = current_block->code->bytecode_pos;
3274 RD_statement(current_block);
3275 break_pos2 = current_block->code->bytecode_pos;
3276 inside_loop --;
3279 // TODO:: moguca optimizacija za neke slucajeve sa iinc$ naredbom
3280 create_variable_bytecode(iterator, current_block->code, iterator_name->cstr, iterator->belongs_to_program_block);
3282 if (direction == 1)
3283 bytecode_append(current_block->code, iconst_1$);
3284 else
3285 bytecode_append(current_block->code, iconst_m1$);
3287 bytecode_append(current_block->code, iadd$);
3289 create_put_variable_bytecode(iterator, current_block->code, iterator_name->cstr, iterator->belongs_to_program_block);
3291 bytecode_append(current_block->code, goto$);
3292 bytecode_append_short_int(current_block->code, evaluate_pos - current_block->code->bytecode_pos + 1);
3294 current_block->code->bytecode[check_bytecode_pos + 1] = (char) ((current_block->code->bytecode_pos - check_bytecode_pos)>>8);
3295 current_block->code->bytecode[check_bytecode_pos + 2] = (char) (current_block->code->bytecode_pos - check_bytecode_pos);
3298 transform_break_stmts(current_block->code, break_pos1, break_pos2, current_block->code->bytecode_pos);
3300 type_destroy(iterator_type);
3301 type_destroy(expression1_type);
3302 type_destroy(expression2_type);
3303 string_destroy(iterator_name);
3307 /*
3308 Type declaration:
3310 <RD_type> -> <RD_basic_type>
3311 | [packed] array <RD_array_declaration>
3312 | record <RD_record_declaration>
3313 | file <RD_file_declaration>
3314 | set <RD_set_declaration> currently unsupported !!!
3315 */
3316 type* RD_type(block *current_block)
3318 switch (current_token)
3320 case KWD_PACKED:
3322 add_warning_message(210, "", "");
3323 current_token = yylex();
3324 if (current_token != KWD_ARRAY)
3325 add_error_message(203, "array", YYTEXT_STRING);
3326 //no_break;
3329 case KWD_ARRAY:
3331 current_token = yylex();
3332 return RD_array_declaration(current_block);
3335 case KWD_RECORD:
3337 current_token = yylex();
3338 return RD_record_declaration(current_block);
3341 case KWD_FILE:
3343 current_token = yylex();
3344 return RD_file_declaration(current_block);
3347 case KWD_SET:
3349 type *error;
3350 error = type_create();
3351 error->type_class = error_type;
3352 add_error_message(211, "", "");
3353 current_token = yylex();
3354 RD_set_declaration(current_block);
3355 return error;
3358 default:
3360 return RD_basic_type(current_block);
3361 break;
3367 /*
3368 Basic type:
3370 <RD_basic_type> -> [IDN .] IDN
3371 | CONST .. CONST
3372 | "(" IDN (, IDN)* ")" enumerated types are not supported
3373 */
3374 type* RD_basic_type(block *current_block)
3376 type *return_type;
3377 return_type = type_create();
3378 return_type->type_class = error_type;
3380 switch (current_token)
3382 case IDENTIFIER:
3384 identifier* name;
3385 type *declared_type;
3386 declared_type = type_from_name(current_block, YYTEXT_STRING);
3388 lowercase(YYTEXT_STRING);
3390 name = get_identifier(current_block, YYTEXT_STRING);
3392 if (name->identifier_class == unit_name)
3394 identifier* type_identifier;
3396 current_token = yylex();
3398 if (current_token != DOT)
3399 add_error_message(200, ".", YYTEXT_STRING);
3400 else
3401 current_token = yylex();
3403 type_identifier = name_table_find_cstr(name->unit_block->names, YYTEXT_STRING);
3405 if (type_identifier == NULL)
3406 add_error_message(455, YYTEXT_STRING, "");
3407 else
3408 declared_type = type_duplicate(type_identifier->defined_type);
3411 identifier_destroy(name);
3413 if (declared_type->type_class != error_type)
3415 type_destroy(return_type);
3416 return_type = type_duplicate(declared_type);
3417 current_token = yylex();
3418 type_destroy(declared_type);
3420 else
3422 identifier *constant_identifier;
3423 constant_identifier = get_constant_identifier(current_block, YYTEXT_STRING);
3425 type_destroy(declared_type);
3427 if ((constant_identifier->identifier_class == constant_name)
3428 && ((constant_identifier->constant_type->type_class == integer_type)
3429 || (constant_identifier->constant_type->type_class == char_type)))
3431 return_type->type_class = interval_type;
3432 return_type->interval_base_type = constant_identifier->constant_type->type_class;
3434 if (constant_identifier->constant_type->type_class == integer_type)
3435 return_type->first_element = constant_identifier->constant_int_value;
3436 else
3437 return_type->first_element = constant_identifier->constant_int_value;
3439 return_type->last_element = return_type->first_element + 1;
3441 identifier_destroy(constant_identifier);
3443 current_token = yylex();
3445 if (current_token != DOTDOT)
3447 add_error_message(213, YYTEXT_STRING, "");
3449 /* Error-recovery */
3450 while ((current_token != CLOSE_SQ_BR)
3451 && (current_token != SEMI_COLON)
3452 && (current_token != KWD_END)
3453 && (current_token != END_OF_INPUT))
3455 current_token = yylex();
3458 break;
3461 current_token = yylex();
3463 if (current_token == IDENTIFIER)
3465 constant_identifier = get_constant_identifier(current_block, YYTEXT_STRING);
3467 if ((constant_identifier->identifier_class != constant_name)
3468 || (constant_identifier->constant_type->type_class != return_type->interval_base_type))
3470 add_error_message(416, "", "");
3472 else
3474 if (return_type->interval_base_type == integer_type)
3475 return_type->last_element = constant_identifier->constant_int_value;
3476 else
3477 return_type->last_element = constant_identifier->constant_int_value;
3480 identifier_destroy(constant_identifier);
3482 else if (current_token == CST_INTEGER)
3484 if (return_type->interval_base_type != integer_type)
3485 add_error_message(416, "", "");
3487 return_type->last_element = integer_constant;
3489 else if (current_token == CST_CHAR)
3491 if (return_type->interval_base_type != char_type)
3492 add_error_message(416, "", "");
3494 return_type->last_element = char_constant;
3496 else
3498 add_error_message(416, "", "");
3501 current_token = yylex();
3504 else
3506 add_error_message(415, YYTEXT_STRING, "");
3507 current_token = yylex();
3508 identifier_destroy(constant_identifier);
3514 break;
3517 case CST_INTEGER:
3518 case CST_CHAR:
3520 return_type->type_class = interval_type;
3522 if (current_token == CST_INTEGER)
3524 return_type->interval_base_type = integer_type;
3525 return_type->first_element = integer_constant;
3527 else
3529 return_type->interval_base_type = char_type;
3530 return_type->first_element = (long int) char_constant;
3533 return_type->last_element = return_type->first_element + 1;
3535 current_token = yylex();
3537 if (current_token != DOTDOT)
3539 add_error_message(213, YYTEXT_STRING, "");
3542 current_token = yylex();
3544 if ((current_token != IDENTIFIER)
3545 && (current_token != CST_INTEGER)
3546 && (current_token != CST_CHAR))
3548 add_error_message(217, "", "");
3550 else
3552 if (current_token == IDENTIFIER)
3554 type *constant_type;
3555 identifier *constant_identifier;
3557 constant_type = get_constant_type(current_block, YYTEXT_STRING);
3559 if (constant_type->type_class != return_type->interval_base_type)
3561 add_error_message(413, "", "");
3564 type_destroy(constant_type);
3566 constant_identifier = get_constant_identifier(current_block, YYTEXT_STRING);
3568 if (constant_identifier->identifier_class != constant_name)
3570 add_error_message(414, YYTEXT_STRING, "");
3572 else
3574 if (return_type->interval_base_type == integer_type)
3575 return_type->last_element = constant_identifier->constant_int_value;
3576 else
3577 return_type->last_element = constant_identifier->constant_int_value;
3580 identifier_destroy(constant_identifier);
3583 else if (current_token == CST_INTEGER)
3585 return_type->last_element = integer_constant;
3587 else
3589 return_type->last_element = (long int) char_constant;
3593 current_token = yylex();
3595 break;
3598 case OPEN_BR:
3600 int brack_count = 1;
3601 add_error_message(212, "", "");
3603 while (brack_count > 0)
3605 current_token = yylex();
3607 if (current_token == OPEN_BR)
3608 brack_count ++;
3610 if (current_token == CLOSE_BR)
3611 brack_count --;
3613 if (current_token == END_OF_INPUT)
3614 return return_type;
3617 current_token = yylex();
3619 break;
3622 default:
3624 add_error_message(204, YYTEXT_STRING, "");
3625 while ((current_token != CLOSE_SQ_BR)
3626 && (current_token != SEMI_COLON)
3627 && (current_token != END_OF_INPUT)
3628 && (current_token != KWD_END))
3630 current_token = yylex();
3633 break;
3637 return return_type;
3641 /*
3642 The declaration of an array.
3644 <RD_array_declaration> -> "[" (<RD_basic_type> (, <RD_basic_type>)* )+ "]" of <RD_type>
3645 */
3646 type* RD_array_declaration(block *current_block)
3648 type *new_type;
3649 type *dimension;
3651 new_type = type_create();
3652 new_type->type_class = array_type;
3654 new_type->dimensions_list = type_list_create();
3656 if (current_token != OPEN_SQ_BR)
3658 add_error_message(200, "[", YYTEXT_STRING);
3661 do
3663 current_token = yylex();
3665 dimension = RD_basic_type(current_block);
3667 if (dimension->type_class != interval_type)
3669 add_error_message(430, "", "");
3672 type_list_append(new_type->dimensions_list, dimension);
3673 type_destroy(dimension);
3675 if ((current_token != CLOSE_SQ_BR)
3676 && (current_token != COMMA))
3678 add_error_message(200, ",", YYTEXT_STRING);
3681 if (current_token == END_OF_INPUT)
3683 add_error_message(207, "", "");
3684 type_destroy(new_type);
3685 new_type = type_create();
3686 new_type->type_class = error_type;
3687 return new_type;
3690 } while (current_token != CLOSE_SQ_BR);
3692 current_token = yylex();
3694 if (current_token != KWD_OF)
3696 add_error_message(203, "of", YYTEXT_STRING);
3699 current_token = yylex();
3701 new_type->element_type = RD_type(current_block);
3703 return new_type;
3707 /*
3708 The declaration of a record.
3710 <RD_record_declaration> -> <RD_identifier_list> ":" <RD_type>
3711 ( <RD_identifier_list> ":" <RD_type> )* end
3712 */
3713 type* RD_record_declaration(block *current_block)
3715 type *new_type;
3716 string_list *identifier_list;
3717 type *element_type;
3718 int old_linenum, tmp;
3720 short int first_pass = 1;
3722 new_type = type_create();
3723 new_type->type_class = record_type;
3724 new_type->elements_name_list = string_list_create();
3725 new_type->elements_type_list = type_list_create();
3726 new_type->unique_record_ID = next_record_ID;
3728 next_record_ID ++;
3730 do
3732 if (first_pass)
3733 first_pass = 0;
3734 else
3735 current_token = yylex();
3737 if ((current_token == KWD_END)
3738 || (current_token == END_OF_INPUT))
3739 break;
3741 identifier_list = RD_identifier_list(current_block, 0);
3743 if (current_token != COLON)
3745 add_error_message(200, ":", YYTEXT_STRING);
3748 old_linenum = linenum;
3749 current_token = yylex();
3751 element_type = RD_type(current_block);
3753 if (element_type->type_class == interval_type)
3755 add_error_message(440, "", "");
3756 element_type->type_class = integer_type;
3759 tmp = linenum;
3760 linenum = old_linenum;
3762 type_add_record(new_type, identifier_list, element_type);
3764 linenum = tmp;
3766 string_list_destroy(identifier_list);
3767 type_destroy(element_type);
3769 } while (current_token == SEMI_COLON);
3771 if (current_token != KWD_END)
3773 add_error_message(214, YYTEXT_STRING, "");
3776 current_token = yylex();
3778 create_record_class(new_type);
3780 return new_type;
3784 /*
3785 The declaration of a file
3787 <RD_file_declaration> -> of IDN
3788 */
3789 type* RD_file_declaration(block *current_block)
3791 type *file_type;
3792 file_type = type_create();
3793 file_type->type_class = error_type;
3794 if (current_token != KWD_OF)
3796 add_error_message(203, "of", YYTEXT_STRING);
3799 current_token = yylex();
3800 // !!!! TODO:: dodati podrsku za fajlove
3801 current_token = yylex();
3802 add_error_message(435, "", "");
3803 return file_type;
3807 /*
3808 Sets are not supported yet, however, this rule is used
3809 as an error-recovery rule if someone tries to use sets.
3811 <RD_set_declaration> -> of <RD_basic_type>
3812 */
3813 void RD_set_declaration(block *current_block)
3815 current_token = yylex();
3817 RD_basic_type(current_block);
3821 /*
3822 Handle the expressions, the relational operators.
3824 <RD_expression> -> <RD_sum> [<rel_operator> <RD_sum>]
3825 */
3826 type* RD_expression(block *current_block)
3828 int old_linenum;
3829 int old_token;
3830 type *type1, *type2;
3832 type1 = RD_sum(current_block);
3834 if ((current_token == OP_LESS)
3835 || (current_token == OP_LESS_EQUAL)
3836 || (current_token == OP_GREATER_EQUAL)
3837 || (current_token == OP_GREATER)
3838 || (current_token == OP_EQUAL)
3839 || (current_token == OP_NOT_EQUAL))
3841 old_token = current_token;
3842 current_token = yylex();
3844 old_linenum = linenum;
3845 type2 = RD_sum(current_block);
3847 if ((type2->type_class != integer_type)
3848 && (type2->type_class != real_type)
3849 && (type2->type_class != char_type)
3850 && (type2->type_class != string_type)
3851 && (type2->type_class != boolean_type)
3852 && (type2->type_class != error_type)
3853 && (type2->type_class != command_type))
3855 new_linenum=old_linenum;
3856 add_error_message(417, "", "");
3858 else
3860 int cast;
3861 cast = type_equal_cast(type1, type2);
3863 if (cast == 0){
3864 new_linenum=old_linenum;
3865 add_error_message(417, "", "");
3868 /* if operands need to be casted */
3869 if ((type1->type_class == integer_type)
3870 || (type2->type_class == integer_type))
3872 if (cast != 1)
3874 usesFloat=1;
3876 if (cast == 3)
3877 bytecode_append(current_block->code, swap$);
3879 if (mathType == 1)
3881 bytecode_append(current_block->code, invokestatic$);
3882 bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(I)I"));
3884 else
3886 bytecode_append(current_block->code, new$);
3887 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
3888 bytecode_append(current_block->code, dup_x1$);
3889 bytecode_append(current_block->code, swap$);
3890 bytecode_append(current_block->code, invokespecial$);
3891 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(I)V"));
3894 if (cast == 3)
3895 bytecode_append(current_block->code, swap$);
3899 else
3901 if ((cast == 2) || (cast == 3))
3903 int method_index = cp_add_methodref("java/lang/String", "valueOf", "(C)Ljava/lang/String;");
3905 if (cast == 3)
3906 bytecode_append(current_block->code, swap$);
3908 /* string cast */
3909 bytecode_append(current_block->code, invokestatic$);
3910 bytecode_append_short_int(current_block->code, method_index);
3912 if (cast == 3)
3913 bytecode_append(current_block->code, swap$);
3917 if (cast == 3) /* return the real type if cast happened */
3919 type *tmp;
3920 tmp = type2;
3921 type2 = type1;
3922 type1 = tmp;
3925 /* create the code */
3926 if ((type1->type_class == integer_type)
3927 || (type1->type_class == boolean_type)
3928 || (type1->type_class == char_type)
3929 || ((type1->type_class == real_type) && (mathType == 1)))
3931 if (type1->type_class == real_type)
3932 usesFloat = 1;
3934 switch (old_token)
3936 case OP_LESS:
3937 bytecode_append(current_block->code, if_icmplt$);
3938 break;
3939 case OP_LESS_EQUAL:
3940 bytecode_append(current_block->code, if_icmple$);
3941 break;
3942 case OP_GREATER_EQUAL:
3943 bytecode_append(current_block->code, if_icmpge$);
3944 break;
3945 case OP_GREATER:
3946 bytecode_append(current_block->code, if_icmpgt$);
3947 break;
3948 case OP_EQUAL:
3949 bytecode_append(current_block->code, if_icmpeq$);
3950 break;
3951 case OP_NOT_EQUAL:
3952 bytecode_append(current_block->code, if_icmpne$);
3953 break;
3956 /* create the rest of the jumping and setting the whatever code */
3957 bytecode_append_short_int(current_block->code, 7);
3958 bytecode_append(current_block->code, iconst_0$);
3959 bytecode_append(current_block->code, goto$);
3960 bytecode_append_short_int(current_block->code, 4);
3961 bytecode_append(current_block->code, iconst_m1$);
3964 if ((type1->type_class == real_type) && (mathType != 1))
3966 usesFloat = 1;
3967 bytecode_append(current_block->code, invokevirtual$);
3969 switch (old_token)
3971 case OP_LESS:
3972 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "lessThan", "(LReal;)Z"));
3973 break;
3974 case OP_LESS_EQUAL:
3975 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "lessEqual", "(LReal;)Z"));
3976 break;
3977 case OP_GREATER_EQUAL:
3978 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "greaterEqual", "(LReal;)Z"));
3979 break;
3980 case OP_GREATER:
3981 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "greaterThan", "(LReal;)Z"));
3982 break;
3983 case OP_EQUAL:
3984 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "equalTo", "(LReal;)Z"));
3985 break;
3986 case OP_NOT_EQUAL:
3987 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "notEqualTo", "(LReal;)Z"));
3988 break;
3991 /* create the rest of the jumping and setting the whatever code */
3992 bytecode_append(current_block->code, ifne$);
3993 bytecode_append_short_int(current_block->code, 7);
3994 bytecode_append(current_block->code, iconst_0$);
3995 bytecode_append(current_block->code, goto$);
3996 bytecode_append_short_int(current_block->code, 4);
3997 bytecode_append(current_block->code, iconst_m1$);
4000 if (type1->type_class == command_type)
4002 if (old_token == OP_EQUAL)
4004 bytecode_append(current_block->code, if_acmpeq$);
4006 else if (old_token == OP_NOT_EQUAL)
4008 bytecode_append(current_block->code, if_acmpne$);
4010 else
4012 new_linenum=old_linenum;
4013 add_error_message(417, "", "");
4016 /* create the rest of the jumping and setting the whatever code */
4017 bytecode_append_short_int(current_block->code, 7);
4018 bytecode_append(current_block->code, iconst_0$);
4019 bytecode_append(current_block->code, goto$);
4020 bytecode_append_short_int(current_block->code, 4);
4021 bytecode_append(current_block->code, iconst_m1$);
4026 if (type1->type_class == string_type)
4028 int method_index = cp_add_methodref("java/lang/String", "compareTo", "(Ljava/lang/String;)I");
4029 bytecode_append(current_block->code, invokevirtual$);
4030 bytecode_append_short_int(current_block->code, method_index);
4032 switch (old_token)
4034 case OP_LESS:
4035 bytecode_append(current_block->code, iflt$);
4036 break;
4037 case OP_LESS_EQUAL:
4038 bytecode_append(current_block->code, ifle$);
4039 break;
4040 case OP_GREATER_EQUAL:
4041 bytecode_append(current_block->code, ifge$);
4042 break;
4043 case OP_GREATER:
4044 bytecode_append(current_block->code, ifgt$);
4045 break;
4046 case OP_EQUAL:
4047 bytecode_append(current_block->code, ifeq$);
4048 break;
4049 case OP_NOT_EQUAL:
4050 bytecode_append(current_block->code, ifne$);
4051 break;
4054 /* create the rest of the jumping and setting the whatever code */
4055 bytecode_append_short_int(current_block->code, 7);
4056 bytecode_append(current_block->code, iconst_0$);
4057 bytecode_append(current_block->code, goto$);
4058 bytecode_append_short_int(current_block->code, 4);
4059 bytecode_append(current_block->code, iconst_m1$);
4062 type_destroy(type2);
4063 type_destroy(type1);
4064 /* the type of comparison is boolean */
4065 type1 = type_create();
4066 type1->type_class = boolean_type;
4069 return type1;
4073 /*
4074 Handle +, -, or, xor operators.
4076 <RD_sum> -> <RD_mult> (<sum_operator> <RD_mult>)*
4077 */
4078 type* RD_sum(block *current_block)
4080 int old_linenum;
4081 int old_token;
4083 type *type1, *type2;
4085 type1 = RD_mult(current_block);
4087 while ((current_token == OP_PLUS)
4088 || (current_token == OP_MINUS)
4089 || (current_token == OP_OR)
4090 || (current_token == OP_XOR))
4092 old_token = current_token;
4094 current_token = yylex();
4096 old_linenum = linenum;
4098 type2 = RD_mult(current_block);
4100 if (((type2->type_class != integer_type)
4101 && (type2->type_class != real_type)
4102 && (type2->type_class != char_type)
4103 && (type2->type_class != string_type)
4104 && (type2->type_class != boolean_type)
4105 && (type2->type_class != error_type))
4106 || ((type1->type_class == string_type)
4107 && (old_token != OP_PLUS)))
4109 new_linenum=old_linenum;
4110 add_error_message(417, "", "");
4112 else
4114 int cast;
4116 /* if first type is char, cast it to string */
4117 if (type1->type_class == char_type)
4119 int method_index = cp_add_methodref("java/lang/String", "valueOf", "(C)Ljava/lang/String;");
4121 bytecode_append(current_block->code, swap$);
4122 bytecode_append(current_block->code, invokestatic$);
4123 bytecode_append_short_int(current_block->code, method_index);
4124 bytecode_append(current_block->code, swap$);
4126 type1->type_class = string_type;
4129 cast = type_equal_cast(type1, type2);
4131 if ((cast == 0) && (type1->type_class != string_type)){
4132 new_linenum=old_linenum;
4133 add_error_message(417, "", "");
4136 /* if operands need to be casted */
4137 if ((type1->type_class != string_type)
4138 && (cast != 1))
4140 usesFloat=1;
4142 if (cast == 3)
4143 bytecode_append(current_block->code, swap$);
4145 if (mathType == 1)
4147 bytecode_append(current_block->code, invokestatic$);
4148 bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(I)I"));
4150 else
4152 bytecode_append(current_block->code, new$);
4153 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
4154 bytecode_append(current_block->code, dup_x1$);
4155 bytecode_append(current_block->code, swap$);
4156 bytecode_append(current_block->code, invokespecial$);
4157 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(I)V"));
4161 if (cast == 3)
4162 bytecode_append(current_block->code, swap$);
4164 if (cast == 3) /* return the real type if cast happened */
4166 type *tmp;
4167 tmp = type2;
4168 type2 = type1;
4169 type1 = tmp;
4176 if ((type1->type_class != integer_type)
4177 && (type1->type_class != boolean_type)
4178 && (type1->type_class != error_type)
4179 && ((old_token == OP_OR) || (old_token == OP_XOR)))
4181 new_linenum=old_linenum;
4182 add_error_message(417, "", "");
4185 /* create the code */
4186 if ((type1->type_class == integer_type)
4187 || (type1->type_class == boolean_type)
4188 || ((type1->type_class == real_type) && (mathType == 1)))
4190 if (type1->type_class == real_type)
4191 usesFloat = 1;
4193 switch (old_token)
4195 case OP_PLUS:
4196 bytecode_append(current_block->code, iadd$);
4197 break;
4198 case OP_MINUS:
4199 bytecode_append(current_block->code, isub$);
4200 break;
4201 case OP_OR:
4202 bytecode_append(current_block->code, ior$);
4203 break;
4204 case OP_XOR:
4205 bytecode_append(current_block->code, ixor$);
4206 break;
4210 if ((type1->type_class == real_type) && (mathType != 1))
4212 usesFloat = 1;
4213 if (old_token == OP_PLUS)
4215 bytecode_append(current_block->code, new$);
4216 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
4217 bytecode_append(current_block->code, dup_x1$);
4218 bytecode_append(current_block->code, swap$);
4219 bytecode_append(current_block->code, invokespecial$);
4220 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
4222 bytecode_append(current_block->code, swap$);
4224 bytecode_append(current_block->code, new$);
4225 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
4226 bytecode_append(current_block->code, dup_x1$);
4227 bytecode_append(current_block->code, swap$);
4228 bytecode_append(current_block->code, invokespecial$);
4229 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
4231 bytecode_append(current_block->code, dup_x1$);
4232 bytecode_append(current_block->code, swap$);
4234 bytecode_append(current_block->code, invokevirtual$);
4235 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "add", "(LReal;)V"));
4239 if (old_token == OP_MINUS)
4241 bytecode_append(current_block->code, new$);
4242 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
4243 bytecode_append(current_block->code, dup_x1$);
4244 bytecode_append(current_block->code, swap$);
4245 bytecode_append(current_block->code, invokespecial$);
4246 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
4248 bytecode_append(current_block->code, swap$);
4250 bytecode_append(current_block->code, new$);
4251 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
4252 bytecode_append(current_block->code, dup_x1$);
4253 bytecode_append(current_block->code, swap$);
4254 bytecode_append(current_block->code, invokespecial$);
4255 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
4257 bytecode_append(current_block->code, dup_x1$);
4258 bytecode_append(current_block->code, swap$);
4260 bytecode_append(current_block->code, invokevirtual$);
4261 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "sub", "(LReal;)V"));
4266 if ((type1->type_class == string_type)
4267 && (old_token == OP_PLUS))
4269 int class_index;
4270 int init_index;
4271 int append_index;
4272 int append2_index;
4273 int toString_index;
4275 if (type2->type_class == real_type)
4277 usesFloat = 1;
4279 if (mathType == 1)
4281 bytecode_append(current_block->code, invokestatic$);
4282 bytecode_append_short_int(current_block->code, cp_add_methodref("F", "tS", "(I)Ljava/lang/String;"));
4284 else
4286 bytecode_append(current_block->code, invokevirtual$);
4287 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "toString", "()Ljava/lang/String;"));
4291 class_index = cp_add_class("java/lang/StringBuffer");
4292 init_index = cp_add_methodref("java/lang/StringBuffer", "<init>", "()V");
4293 append_index = cp_add_methodref("java/lang/StringBuffer", "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
4294 toString_index = cp_add_methodref("java/lang/StringBuffer", "toString", "()Ljava/lang/String;");
4296 switch(type2->type_class)
4298 case string_type:
4299 case real_type:
4300 append2_index = cp_add_methodref("java/lang/StringBuffer", "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
4301 break;
4302 case integer_type:
4303 append2_index = cp_add_methodref("java/lang/StringBuffer", "append", "(I)Ljava/lang/StringBuffer;");
4304 break;
4305 case char_type:
4306 bytecode_append(current_block->code, i2c$);
4307 append2_index = cp_add_methodref("java/lang/StringBuffer", "append", "(C)Ljava/lang/StringBuffer;");
4308 break;
4309 case boolean_type:
4310 bytecode_append(current_block->code, i2b$);
4311 append2_index = cp_add_methodref("java/lang/StringBuffer", "append", "(Z)Ljava/lang/StringBuffer;");
4312 break;
4313 default:
4314 add_error_message(434, "", "");
4317 bytecode_append(current_block->code, swap$);
4319 /* create new string buffer */
4320 bytecode_append(current_block->code, new$);
4321 bytecode_append_short_int(current_block->code, class_index);
4322 bytecode_append(current_block->code, dup$);
4323 bytecode_append(current_block->code, invokespecial$);
4324 bytecode_append_short_int(current_block->code, init_index);
4326 /* append the first argument */
4327 bytecode_append(current_block->code, swap$);
4328 bytecode_append(current_block->code, invokevirtual$);
4329 bytecode_append_short_int(current_block->code, append_index);
4331 /* append the second argument */
4332 bytecode_append(current_block->code, swap$);
4334 bytecode_append(current_block->code, invokevirtual$);
4335 bytecode_append_short_int(current_block->code, append2_index);
4337 /* convert StringBuffer into the String */
4338 bytecode_append(current_block->code, invokevirtual$);
4339 bytecode_append_short_int(current_block->code, toString_index);
4343 type_destroy(type2);
4348 return type1;
4352 /*
4353 Handle * / div mod and operators.
4355 <RD_mult> -> <RD_not> (<mult_operator> <RD_not>)*
4356 */
4357 type* RD_mult(block *current_block)
4359 int old_linenum;
4360 int old_token;
4361 type *type1, *type2;
4363 type1 = RD_not(current_block);
4365 while ((current_token == OP_MULT)
4366 || (current_token == OP_SLASH)
4367 || (current_token == OP_DIV)
4368 || (current_token == OP_MOD)
4369 || (current_token == OP_AND)
4370 || (current_token == OP_SHR)
4371 || (current_token == OP_SHL)
4372 || (current_token == OP_USHR))
4374 old_token = current_token;
4376 current_token = yylex();
4378 old_linenum = linenum;
4380 type2 = RD_not(current_block);
4382 if ((type2->type_class != integer_type)
4383 && (type2->type_class != real_type)
4384 && (type2->type_class != boolean_type)
4385 && (type2->type_class != error_type))
4387 new_linenum=old_linenum;
4388 add_error_message(417, "", "");
4390 else
4392 int cast;
4393 cast = type_equal_cast(type1, type2);
4395 if (cast == 0){
4396 new_linenum=old_linenum;
4397 add_error_message(417, "", "");
4400 if (cast != 1)
4402 /* if operands need to be casted */
4403 usesFloat=1;
4405 if (cast == 3)
4406 bytecode_append(current_block->code, swap$);
4408 if (mathType == 1)
4410 bytecode_append(current_block->code, invokestatic$);
4411 bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(I)I"));
4413 else
4415 bytecode_append(current_block->code, new$);
4416 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
4417 bytecode_append(current_block->code, dup_x1$);
4418 bytecode_append(current_block->code, swap$);
4419 bytecode_append(current_block->code, invokespecial$);
4420 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(I)V"));
4423 if (cast == 3)
4424 bytecode_append(current_block->code, swap$);
4426 if (cast == 3) /* return the real type if cast happened */
4428 type *tmp;
4429 tmp = type2;
4430 type2 = type1;
4431 type1 = tmp;
4436 type_destroy(type2);
4438 if ((type1->type_class == real_type)
4439 && (old_token != OP_MULT)
4440 && (old_token != OP_SLASH))
4442 new_linenum=old_linenum;
4443 add_error_message(417, "", "");
4446 if ((type1->type_class == boolean_type)
4447 && (old_token != OP_AND))
4449 new_linenum=old_linenum;
4450 add_error_message(417, "", "");
4453 /* generate the code */
4454 if (type1->type_class == integer_type)
4456 switch(old_token)
4458 case OP_MULT:
4459 bytecode_append(current_block->code, imul$);
4460 break;
4461 case OP_SLASH:
4462 case OP_DIV:
4463 bytecode_append(current_block->code, idiv$);
4464 break;
4465 case OP_MOD:
4466 bytecode_append(current_block->code, irem$);
4467 break;
4468 case OP_AND:
4469 bytecode_append(current_block->code, iand$);
4470 break;
4471 ///////////
4472 case OP_SHR:
4473 bytecode_append(current_block->code, ishr$);
4474 break;
4475 case OP_SHL:
4476 bytecode_append(current_block->code, ishl$);
4477 break;
4478 // j-a-s-d
4479 case OP_USHR:
4480 bytecode_append(current_block->code, iushr$);
4481 break;
4485 if (type1->type_class == real_type)
4487 usesFloat = 1;
4488 switch(old_token)
4490 case OP_MULT:
4492 if (mathType == 1)
4494 bytecode_append(current_block->code, invokestatic$);
4495 bytecode_append_short_int(current_block->code,
4496 cp_add_methodref("F", "M", "(II)I"));
4498 else
4500 bytecode_append(current_block->code, new$);
4501 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
4502 bytecode_append(current_block->code, dup_x1$);
4503 bytecode_append(current_block->code, swap$);
4504 bytecode_append(current_block->code, invokespecial$);
4505 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
4507 bytecode_append(current_block->code, swap$);
4509 bytecode_append(current_block->code, new$);
4510 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
4511 bytecode_append(current_block->code, dup_x1$);
4512 bytecode_append(current_block->code, swap$);
4513 bytecode_append(current_block->code, invokespecial$); ///
4514 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
4516 bytecode_append(current_block->code, dup_x1$);
4517 bytecode_append(current_block->code, swap$);
4519 bytecode_append(current_block->code, invokevirtual$);
4520 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "mul", "(LReal;)V"));
4523 break;
4524 case OP_SLASH:
4526 if (mathType == 1)
4528 bytecode_append(current_block->code, invokestatic$);
4529 bytecode_append_short_int(current_block->code,
4530 cp_add_methodref("F", "D", "(II)I"));
4532 else
4534 bytecode_append(current_block->code, new$);
4535 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
4536 bytecode_append(current_block->code, dup_x1$);
4537 bytecode_append(current_block->code, swap$);
4538 bytecode_append(current_block->code, invokespecial$);
4539 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
4541 bytecode_append(current_block->code, swap$);
4543 bytecode_append(current_block->code, new$);
4544 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
4545 bytecode_append(current_block->code, dup_x1$);
4546 bytecode_append(current_block->code, swap$);
4547 bytecode_append(current_block->code, invokespecial$);
4548 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
4550 bytecode_append(current_block->code, dup_x1$);
4551 bytecode_append(current_block->code, swap$);
4553 bytecode_append(current_block->code, invokevirtual$);
4554 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "div", "(LReal;)V"));
4557 break;
4561 if ((type1->type_class == boolean_type)
4562 && (old_token == OP_AND))
4564 bytecode_append(current_block->code, iand$);
4568 return type1;
4572 /*
4573 The not operator.
4575 <RD_not> -> [not] <RD_neg>
4576 */
4577 type* RD_not(block *current_block)
4579 type *type1;
4580 int is_not = 0;
4581 int old_linenum;
4583 if (current_token == OP_NOT)
4585 current_token = yylex();
4586 is_not = 1;
4589 old_linenum = linenum;
4591 type1 = RD_neg(current_block);
4593 /* generate the code */
4594 if (is_not)
4596 bytecode_append(current_block->code, iconst_m1$);
4597 bytecode_append(current_block->code, ixor$);
4600 if ((is_not)
4601 && (type1->type_class != integer_type)
4602 && (type1->type_class != boolean_type)
4603 && (type1->type_class != error_type))
4605 new_linenum=old_linenum;
4606 add_error_message(417, "", "");
4609 return type1;
4613 /*
4614 The - sign operator.
4616 <RD_neg> -> ["-"] <RD_value>
4617 */
4618 type* RD_neg(block *current_block)
4620 type *type1;
4621 int is_neg = 0;
4622 int old_linenum;
4624 if (current_token == OP_MINUS)
4626 current_token = yylex();
4627 is_neg = 1;
4630 old_linenum = linenum;
4632 type1 = RD_value(current_block);
4634 /* generate the code */
4635 if (is_neg)
4637 if ((type1->type_class == integer_type)
4638 || ((type1->type_class == real_type) && (mathType == 1)))
4639 bytecode_append(current_block->code, ineg$);
4641 if ((type1->type_class == real_type) && (mathType != 1))
4643 usesFloat = 1;
4645 bytecode_append(current_block->code, new$);
4646 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
4647 bytecode_append(current_block->code, dup_x1$);
4648 bytecode_append(current_block->code, swap$);
4649 bytecode_append(current_block->code, invokespecial$);
4650 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
4651 bytecode_append(current_block->code, dup$);
4652 bytecode_append(current_block->code, invokevirtual$);
4653 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "neg", "()V"));
4657 if ((type1->type_class != real_type)
4658 && (type1->type_class != integer_type)
4659 && (type1->type_class != error_type)
4660 && (is_neg))
4662 new_linenum=old_linenum;
4663 add_error_message(417, "", "");
4666 return type1;
4670 /*
4671 The expression that calls a procedure or
4672 assigns a value to a variable.
4674 <RD_assignment_or_procedure_call>
4676 -> IDN ["[" <RD_expression_list> "]" ] (. IDN ["[" <RD_expression_list> "]" ])* := <RD_expression>
4677 -> IDN ["(" <RD_expression_list> ")"]
4679 */
4680 void RD_assignment_or_procedure_call(block *current_block)
4682 identifier *name;
4683 string *element_name;
4684 char *identifier_text;
4686 if (current_token == KWD_RESULT) { // j-a-s-d
4687 if (inside_routine == 0) // result in main block
4689 add_error_message(463, "result", "");
4690 current_token = yylex();
4691 return;
4693 name = get_identifier(current_block, string_get_cstr(str_currrent_routine_name));
4694 element_name = str_currrent_routine_name;
4695 if (name->identifier_class == procedure_name) // result in procedure
4697 add_error_message(463, "result", "");
4698 current_token = yylex();
4699 identifier_destroy(name);
4700 string_destroy(element_name);
4701 return;
4703 } else {
4704 name = get_identifier(current_block, YYTEXT_STRING);
4705 element_name = string_from_cstr(YYTEXT_STRING);
4708 procedure_linenum = linenum;
4710 if ((current_token != IDENTIFIER) && (current_token != KWD_RESULT)) // j-a-s-d
4712 add_error_message(202, "", "");
4714 /* Error-recovery: find the first ";", end, "." or <<EOF>> */
4715 while ((current_token != SEMI_COLON)
4716 && (current_token != DOT)
4717 && (current_token != KWD_END)
4718 && (current_token != END_OF_INPUT))
4720 current_token = yylex();
4723 string_destroy(element_name);
4724 return;
4728 if ((name->identifier_class == none)
4729 || (name->identifier_class == program_name)
4730 || (name->identifier_class == constant_name)
4731 || (name->identifier_class == type_name))
4734 add_error_message(428, YYTEXT_STRING, "");
4735 current_token = yylex();
4736 identifier_destroy(name);
4737 string_destroy(element_name);
4738 return;
4741 current_token = yylex();
4743 if (name->identifier_class == unit_name)
4745 identifier *unit_name;
4746 type_list *params;
4747 if (current_token != DOT)
4749 add_error_message(200, ".", YYTEXT_STRING);
4750 while (current_token != SEMI_COLON)
4751 current_token = yylex();
4752 return;
4755 current_token = yylex();
4756 unit_name = name_table_find(name->unit_block->names, string_from_cstr(YYTEXT_STRING));
4757 identifier_text = malloc(strlen(YYTEXT_STRING) + 1);
4758 strcpy(identifier_text, YYTEXT_STRING);
4759 string_destroy(element_name);
4760 element_name = string_from_cstr(YYTEXT_STRING);
4762 if (unit_name == NULL)
4764 add_error_message(453, YYTEXT_STRING, "");
4765 add_error_message(200, ".", YYTEXT_STRING);
4766 while (current_token != SEMI_COLON)
4767 current_token = yylex();
4768 return;
4771 name = identifier_duplicate(unit_name);
4772 current_token = yylex();
4774 if (name->identifier_class == procedure_name)
4775 goto procedure_call;
4776 if (name->identifier_class == variable_name)
4777 goto variable_lvalue;
4779 add_error_message(457, YYTEXT_STRING, "");
4783 /* the name belongs to a procedure */
4784 if (name->identifier_class == procedure_name)
4786 procedure_call:
4787 if (name->standard_function)
4789 create_std_function_prefix(current_block->code, element_name->cstr);
4792 if (type_list_length(name->parameters) == 0)
4794 int br_depth = 0;
4795 if (current_token == OPEN_BR)
4797 add_error_message(419, "", "");
4798 br_depth = 1;
4799 while (br_depth > 0)
4801 if ((current_token == END_OF_INPUT)
4802 || (current_token == KWD_END))
4804 identifier_destroy(name);
4805 string_destroy(element_name);
4806 return;
4809 current_token = yylex();
4811 if (current_token == OPEN_BR)
4812 br_depth ++;
4814 if (current_token == CLOSE_BR)
4815 br_depth --;
4818 current_token = yylex();
4821 else
4823 if (current_token != OPEN_BR)
4825 add_error_message(420, "", "");
4827 else
4829 int compare_result;
4830 int old_linenum;
4831 type_list *parameter_list;
4832 current_token = yylex();
4834 old_linenum = linenum;
4836 parameter_list = RD_expression_list_cast(current_block, name->parameters);
4838 compare_result = type_list_different_parameter_cast(parameter_list, name->parameters);
4840 if (compare_result == -1) {
4841 new_linenum=old_linenum;
4842 add_error_message(421, "", "");
4845 if (compare_result > 0)
4847 char par_num[4];
4848 sprintf(par_num, "%d", compare_result);
4849 new_linenum=old_linenum;
4850 add_error_message(422, par_num, "");
4853 type_list_destroy(parameter_list);
4855 if (current_token != CLOSE_BR)
4857 add_error_message(200, ")", YYTEXT_STRING);
4859 else
4860 current_token = yylex();
4864 /* create the bytecode */
4865 if (!name->standard_function)
4867 /* the procedure is user-defined */
4868 int methodref_index;
4869 identifier *block_identifier;
4870 type_list *it;
4871 int pos;
4873 char* descriptor = (char*) mem_alloc(5*1024);
4874 if (descriptor == NULL)
4875 die(1);
4876 descriptor[0] = '(';
4878 if (!name->unit_function)
4880 block_identifier = name_table_find(current_block->names, element_name);
4882 if (block_identifier == NULL)
4883 block_identifier = name_table_find(current_block->parent_block->names, element_name);
4885 else
4887 block_identifier = name;
4890 it = block_identifier->parameters;
4891 pos = 1;
4893 while(it != NULL)
4895 if (it->data == NULL)
4896 break;
4898 get_field_descriptor(it->data, descriptor + pos);
4899 pos = strlen(descriptor);
4900 it = it->next;
4903 descriptor[pos] = ')';
4904 pos ++;
4905 descriptor[pos] = '\0';
4907 if (block_identifier->identifier_class == procedure_name)
4908 strcat(descriptor, "V");
4909 else
4910 get_field_descriptor(block_identifier->return_type, descriptor + pos);
4913 lowercase(element_name->cstr);
4914 if (name->unit_function)
4916 string *full_unit_name;
4918 if (name->container_unit->is_library)
4919 full_unit_name = string_from_cstr("Lib_");
4920 else
4921 full_unit_name = string_create();
4922 string_append(full_unit_name, name->container_unit->unit_name);
4923 methodref_index = cp_add_methodref(full_unit_name->cstr, element_name->cstr, descriptor);
4924 string_destroy(full_unit_name);
4926 else
4928 if (compiling_unit == 0)
4929 methodref_index = cp_add_methodref("M", element_name->cstr, descriptor);
4930 else
4931 methodref_index = cp_add_methodref(string_get_cstr(str_program_name), element_name->cstr, descriptor);
4933 bytecode_append(current_block->code, invokestatic$); /* call */
4934 bytecode_append_short_int(current_block->code, methodref_index);
4936 mem_free(descriptor);
4938 else
4940 /* handle standard functions and procedures */
4941 create_std_function_code(current_block->code, element_name->cstr);
4945 /* if the identifier is the function name and that is not the name of the current
4946 block, report an error */
4947 if (name->identifier_class == function_name)
4949 if (STRING_COMPARE(element_name->cstr, current_block->block_name->cstr) != 0)
4951 add_error_message(432, element_name->cstr, "");
4955 /* if an identifier is a valid l-value */
4956 if ((name->identifier_class == variable_name)
4957 || (name->identifier_class == parameter_name)
4958 || (name->identifier_class == function_name)) /* function names are treated as variables for return values */
4960 type *current_type;
4961 type *new_type;
4962 type *expression_type;
4963 int assign_linenum;
4964 int is_field = 0;
4965 bytecode *get_bytecode;
4966 bytecode *put_bytecode;
4967 variable_lvalue:
4968 is_field = 0;
4969 get_bytecode = bytecode_create();
4970 put_bytecode = bytecode_create();
4972 if (name->identifier_class == variable_name)
4973 current_type = type_duplicate(name->variable_type);
4975 if (name->identifier_class == parameter_name)
4976 current_type = type_duplicate(name->parameter_type);
4978 if (name->identifier_class == function_name)
4979 current_type = type_duplicate(name->return_type);
4981 /* create the get and put bytecodes */
4982 is_field = name->belongs_to_program_block;
4984 if (name->identifier_class == function_name)
4985 is_field = 0;
4987 create_variable_bytecode(name, get_bytecode, element_name->cstr, is_field);
4988 create_put_variable_bytecode(name, put_bytecode, element_name->cstr, is_field);
4990 identifier_destroy(name);
4991 name = NULL;
4992 string_destroy(element_name);
4993 element_name = NULL;
4995 while (current_token != OP_ASSIGN)
4997 if ((current_token == SEMI_COLON)
4998 || (current_token == KWD_END)
4999 || (current_token == END_OF_INPUT))
5001 add_error_message(218, "", "");
5002 type_destroy(current_type);
5003 bytecode_destroy(get_bytecode);
5004 bytecode_destroy(put_bytecode);
5005 return;
5008 if (current_token == DOT)
5010 int fieldref_index;
5011 char record_name[15];
5012 char field_descriptor[128];
5014 current_token = yylex();
5016 /* append the old get bytecode */
5017 bytecode_append_bytecode(current_block->code, get_bytecode);
5019 /* reset the bytecodes */
5020 put_bytecode->bytecode_pos = 0;
5021 get_bytecode->bytecode_pos = 0;
5023 if (current_type->type_class != record_type)
5025 add_error_message(424, "", "");
5027 /* Error-recovery */
5028 while ((current_token != SEMI_COLON)
5029 && (current_token != KWD_END)
5030 && (current_token != END_OF_INPUT))
5032 current_token = yylex();
5035 type_destroy(current_type);
5036 bytecode_destroy(get_bytecode);
5037 bytecode_destroy(put_bytecode);
5038 return;
5041 new_type = type_find_record_element(current_type, YYTEXT_STRING);
5043 if (new_type == NULL)
5045 add_error_message(447, YYTEXT_STRING, "");
5047 else
5049 /* create the new put and get bytecodes */
5050 sprintf(record_name, "R_%d", current_type->unique_record_ID);
5051 get_field_descriptor(new_type, field_descriptor);
5052 lowercase(YYTEXT_STRING);
5053 fieldref_index = cp_add_fieldref(record_name, YYTEXT_STRING, field_descriptor);
5055 bytecode_append(get_bytecode, getfield$);
5056 bytecode_append_short_int(get_bytecode, fieldref_index);
5058 bytecode_append(put_bytecode, putfield$);
5059 bytecode_append_short_int(put_bytecode, fieldref_index);
5062 type_destroy(current_type);
5063 current_type = new_type;
5067 if (current_type == NULL)
5069 add_error_message(425, YYTEXT_STRING, "");
5071 /* Error-recovery */
5072 while ((current_token != SEMI_COLON)
5073 && (current_token != KWD_END)
5074 && (current_token != END_OF_INPUT))
5076 current_token = yylex();
5079 type_destroy(current_type);
5080 bytecode_destroy(get_bytecode);
5081 bytecode_destroy(put_bytecode);
5082 return;
5085 current_token = yylex();
5087 else if (current_token == OPEN_SQ_BR)
5089 type_list *array_elements;
5090 bytecode *tmp_code;
5091 tmp_code = bytecode_create();
5093 // ako je [, a zadnji je array, procitaj listu, usporedi, vrati slijedeci, skoci gore
5094 if (current_type->type_class != array_type)
5096 add_error_message(426, "", "");
5098 /* Error-recovery */
5099 while ((current_token != SEMI_COLON)
5100 && (current_token != KWD_END)
5101 && (current_token != END_OF_INPUT))
5103 current_token = yylex();
5106 type_destroy(current_type);
5107 bytecode_destroy(get_bytecode);
5108 bytecode_destroy(put_bytecode);
5109 return;
5112 current_token = yylex();
5114 array_elements = RD_expression_list_array(current_block, tmp_code, current_type);
5116 bytecode_append_bytecode(get_bytecode, tmp_code);
5117 //bytecode_append_bytecode(put_bytecode, tmp_code);
5118 bytecode_destroy(put_bytecode);
5119 put_bytecode = bytecode_duplicate(get_bytecode);
5121 replace_aaload_instruction(get_bytecode, current_type->element_type);
5123 /* remove the last aaload from put bytecode, adjust the stack and create the
5124 put bytecode */
5125 put_bytecode->bytecode_pos --;
5126 bytecode_append(put_bytecode, dup2_x1$);
5127 bytecode_append(put_bytecode, pop2$);
5129 switch(current_type->element_type->type_class)
5131 case integer_type:
5132 case boolean_type:
5133 case char_type:
5134 bytecode_append(put_bytecode, iastore$);
5135 break;
5137 case real_type:
5138 if (mathType == 1)
5139 bytecode_append(put_bytecode, iastore$);
5140 else
5141 bytecode_append(put_bytecode, aastore$);
5142 break;
5145 case image_type:
5146 case string_type:
5147 case record_type:
5148 case command_type:
5149 case record_store_type:
5150 case http_type:
5151 case alert_type:
5152 case stream_type:
5153 bytecode_append(put_bytecode, aastore$);
5154 break;
5158 bytecode_destroy(tmp_code);
5160 if (type_list_different_parameter_array(array_elements, current_type->dimensions_list) != 0)
5162 char num1[6], num2[6];
5164 sprintf(num1, "%d", type_list_length(current_type->dimensions_list));
5165 sprintf(num2, "%d", type_list_length(array_elements));
5166 add_error_message(427, num1, num2);
5168 /* Error-recovery */
5169 while ((current_token != SEMI_COLON)
5170 && (current_token != KWD_END)
5171 && (current_token != END_OF_INPUT))
5173 current_token = yylex();
5176 type_destroy(current_type);
5177 bytecode_destroy(get_bytecode);
5178 bytecode_destroy(put_bytecode);
5179 return;
5182 if (current_token != CLOSE_SQ_BR)
5184 add_error_message(200, "]", YYTEXT_STRING);
5186 /* Error-recovery */
5187 while ((current_token != SEMI_COLON)
5188 && (current_token != KWD_END)
5189 && (current_token != END_OF_INPUT))
5191 current_token = yylex();
5194 type_destroy(current_type);
5195 bytecode_destroy(get_bytecode);
5196 bytecode_destroy(put_bytecode);
5197 return;
5200 current_token = yylex();
5202 new_type = type_duplicate(current_type->element_type);
5203 type_destroy(current_type);
5205 current_type = new_type;
5207 type_list_destroy(array_elements);
5209 else
5211 add_error_message(204, YYTEXT_STRING, "");
5213 /* Error-recovery */
5214 while ((current_token != SEMI_COLON)
5215 && (current_token != KWD_END)
5216 && (current_token != END_OF_INPUT))
5218 current_token = yylex();
5220 bytecode_destroy(get_bytecode);
5221 bytecode_destroy(put_bytecode);
5222 return;
5226 assign_linenum = linenum;
5228 current_token = yylex();
5230 expression_type = RD_expression(current_block);
5232 if ((type_equal_cast(current_type, expression_type) != 1)
5233 && (current_type->type_class == real_type))
5235 usesFloat = 1;
5237 if (mathType == 1)
5239 bytecode_append(current_block->code, invokestatic$);
5240 bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(I)I"));
5242 else
5244 bytecode_append(current_block->code, new$);
5245 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
5246 bytecode_append(current_block->code, dup_x1$);
5247 bytecode_append(current_block->code, swap$);
5248 bytecode_append(current_block->code, invokespecial$);
5249 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(I)V"));
5253 if ((type_equal_cast(current_type, expression_type) == 2)
5254 && (current_type->type_class == string_type))
5256 int method_index = cp_add_methodref("java/lang/String", "valueOf", "(C)Ljava/lang/String;");
5258 /* string cast */
5259 bytecode_append(current_block->code, invokestatic$);
5260 bytecode_append_short_int(current_block->code, method_index);
5263 bytecode_append_bytecode(current_block->code, put_bytecode);
5265 if ((type_equal_cast(current_type, expression_type) != 1)
5266 && (type_equal_cast(current_type, expression_type) != 2))
5268 new_linenum=assign_linenum;
5269 add_error_message(423, "", "");
5271 else
5272 if (current_type->type_class == array_type)
5274 new_linenum=assign_linenum;
5275 add_error_message(443, "", "");
5280 type_destroy(expression_type);
5281 type_destroy(current_type);
5282 bytecode_destroy(get_bytecode);
5283 bytecode_destroy(put_bytecode);
5286 if (name != NULL)
5287 identifier_destroy(name);
5289 if (element_name != NULL)
5290 string_destroy(element_name);
5294 /*
5295 The list of expressions, used when calling the function
5296 or procedure.
5298 <RD_expression_list> -> <RD_expression> (, <RD_expression>)*
5299 */
5300 type_list* RD_expression_list(block *current_block)
5302 type_list *return_list;
5303 type *expression_type;
5305 return_list = type_list_create();
5307 expression_type = RD_expression(current_block);
5309 type_list_append(return_list, expression_type);
5311 type_destroy(expression_type);
5313 while (current_token == COMMA)
5315 current_token = yylex();
5317 expression_type = RD_expression(current_block);
5319 type_list_append(return_list, expression_type);
5321 type_destroy(expression_type);
5324 return return_list;
5327 /*
5328 Same as the above, only the types are casted according to the second parameter
5329 */
5330 type_list* RD_expression_list_cast(block *current_block, type_list *formal_params)
5332 type_list *return_list;
5333 type *expression_type;
5334 type_list *it;
5336 it = formal_params;
5338 return_list = type_list_create();
5340 expression_type = RD_expression(current_block);
5342 if ((it != NULL) && (it->data != NULL))
5344 int cast;
5346 cast = type_equal_cast(it->data, expression_type);
5348 if ((cast == 2) && (it->data->type_class == string_type))
5350 int method_index = cp_add_methodref("java/lang/String", "valueOf", "(C)Ljava/lang/String;");
5352 bytecode_append(current_block->code, invokestatic$);
5353 bytecode_append_short_int(current_block->code, method_index);
5356 if ((cast == 2) && (it->data->type_class == real_type))
5358 usesFloat = 1;
5360 if (mathType == 1)
5362 bytecode_append(current_block->code, invokestatic$);
5363 bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(I)I"));
5365 else
5367 bytecode_append(current_block->code, new$);
5368 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
5369 bytecode_append(current_block->code, dup_x1$);
5370 bytecode_append(current_block->code, swap$);
5371 bytecode_append(current_block->code, invokespecial$);
5372 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(I)V"));
5376 it = it->next;
5379 type_list_append(return_list, expression_type);
5381 type_destroy(expression_type);
5383 while (current_token == COMMA)
5385 current_token = yylex();
5387 expression_type = RD_expression(current_block);
5389 if ((it != NULL) && (it->data != NULL))
5391 int cast;
5393 cast = type_equal_cast(it->data, expression_type);
5395 if ((cast == 2) && (it->data->type_class == string_type))
5397 int method_index = cp_add_methodref("java/lang/String", "valueOf", "(C)Ljava/lang/String;");
5399 bytecode_append(current_block->code, invokestatic$);
5400 bytecode_append_short_int(current_block->code, method_index);
5403 if ((cast == 2) && (it->data->type_class == real_type))
5405 usesFloat = 1;
5407 if (mathType == 1)
5409 bytecode_append(current_block->code, invokestatic$);
5410 bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(I)I"));
5412 else
5414 bytecode_append(current_block->code, new$);
5415 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
5416 bytecode_append(current_block->code, dup_x1$);
5417 bytecode_append(current_block->code, swap$);
5418 bytecode_append(current_block->code, invokespecial$);
5419 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(I)V"));
5423 it = it->next;
5426 type_list_append(return_list, expression_type);
5428 type_destroy(expression_type);
5431 return return_list;
5434 /*
5435 Same as RD_expression_list, only aaload is generated after each element and the indices
5436 are adjusted.For example, if array is [a..b], the a value must be substracted from the index
5437 */
5438 type_list* RD_expression_list_array(block *current_block, bytecode *code, type *array_type)
5440 type_list *return_list;
5441 type *expression_type;
5442 bytecode *oldBytecode;
5444 type_list *it;
5445 it = array_type->dimensions_list;
5447 oldBytecode = current_block->code;
5448 current_block->code = code;
5450 return_list = type_list_create();
5452 expression_type = RD_expression(current_block);
5453 adjust_indices(code, it->data);
5455 if(it != NULL)
5456 it = it->next;
5458 bytecode_append(code, aaload$);
5460 type_list_append(return_list, expression_type);
5462 type_destroy(expression_type);
5464 while (current_token == COMMA)
5466 current_token = yylex();
5468 expression_type = RD_expression(current_block);
5469 adjust_indices(code, it->data);
5471 if(it != NULL)
5472 it = it->next;
5473 bytecode_append(code, aaload$);
5475 type_list_append(return_list, expression_type);
5477 type_destroy(expression_type);
5480 current_block->code = oldBytecode;
5482 return return_list;
5486 /*
5487 The with statement, currently not supported. This
5488 function is used as an error recovery function.
5490 <RD_with_statement> -> IDN (. IDN)* do <RD_statement>
5491 */
5492 void RD_with_statement(block *current_block)
5494 /* simplified parsing */
5495 while (current_token != KWD_DO)
5497 if (current_token == END_OF_INPUT)
5498 return;
5500 current_token = yylex();
5503 current_token = yylex();
5505 RD_statement(current_block);
5509 /*
5510 Anything that has value: constant, identifier, identifier inside
5511 a record or a function call.
5513 <RD_value> -> CONST
5514 | IDN [ "[" <RD_expression_list> "]" ] ( . IDN [ "[" <RD_expression_list> "]" ])*
5515 | IDN [ "(" <RD_expression_list> ")"]
5516 | "(" <RD_expression> ")"
5517 */
5518 type* RD_value(block *current_block)
5520 type *return_type;
5521 return_type = type_create();
5523 return_type->type_class = error_type;
5525 if (current_token == CST_INTEGER)
5527 switch(integer_constant)
5529 case -1:
5530 bytecode_append(current_block->code, iconst_m1$);
5531 break;
5532 case 0:
5533 bytecode_append(current_block->code, iconst_0$);
5534 break;
5535 case 1:
5536 bytecode_append(current_block->code, iconst_1$);
5537 break;
5538 case 2:
5539 bytecode_append(current_block->code, iconst_2$);
5540 break;
5541 case 3:
5542 bytecode_append(current_block->code, iconst_3$);
5543 break;
5544 case 4:
5545 bytecode_append(current_block->code, iconst_4$);
5546 break;
5547 case 5:
5548 bytecode_append(current_block->code, iconst_5$);
5549 break;
5550 default:
5552 if (abs(integer_constant) < 127)
5554 bytecode_append(current_block->code, bipush$);
5555 bytecode_append(current_block->code, (char)(integer_constant));
5557 else if (abs(integer_constant) < 16000)
5559 bytecode_append(current_block->code, sipush$);
5560 bytecode_append_short_int(current_block->code, (short)(integer_constant));
5562 else
5564 int cp_index;
5565 cp_index = cp_add_integer(integer_constant);
5566 if (cp_index <= 255)
5568 bytecode_append(current_block->code, ldc$);
5569 bytecode_append(current_block->code, (char) cp_index);
5571 else
5573 bytecode_append(current_block->code, ldc_w$);
5574 bytecode_append_short_int(current_block->code, (short) cp_index);
5577 break;
5581 current_token = yylex();
5582 return_type->type_class = integer_type;
5583 return return_type;
5586 if (current_token == CST_REAL)
5588 float cst;
5589 int csti; /* the integer part */
5590 int cstf; /* the fraction part */
5592 /* calculate the exponent and the integer part */
5593 cst = real_constant;
5595 csti = (int)cst;
5596 cstf = (cst - (int)cst)*100000;
5598 usesFloat = 1;
5600 if (mathType == 1)
5602 /* put the integer part on the stack */
5603 if (abs(csti) < 127)
5605 bytecode_append(current_block->code, bipush$);
5606 bytecode_append(current_block->code, csti);
5608 else if (abs(csti) < 15000)
5610 bytecode_append(current_block->code, sipush$);
5611 bytecode_append_short_int(current_block->code, csti);
5613 else
5615 bytecode_append(current_block->code, ldc_w$);
5616 bytecode_append_short_int(current_block->code, cp_add_integer(csti));
5619 /* put the fraction part to the stack */
5620 if (abs(cstf) < 127)
5622 bytecode_append(current_block->code, bipush$);
5623 bytecode_append(current_block->code, cstf);
5625 else if (abs(cstf) < 15000)
5627 bytecode_append(current_block->code, sipush$);
5628 bytecode_append_short_int(current_block->code, cstf);
5630 else
5632 bytecode_append(current_block->code, ldc_w$);
5633 bytecode_append_short_int(current_block->code, cp_add_integer(cstf));
5636 bytecode_append(current_block->code, invokestatic$);
5637 bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(II)I"));
5639 else
5641 char number[64];
5643 bytecode_append(current_block->code, new$);
5644 bytecode_append_short_int(current_block->code, cp_add_class("Real"));
5645 bytecode_append(current_block->code, dup$);
5647 sprintf(number, "%f", real_constant);
5648 bytecode_append(current_block->code, ldc_w$);
5649 bytecode_append_short_int(current_block->code, cp_add_string(number));
5651 bytecode_append(current_block->code, invokespecial$);
5652 bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(Ljava/lang/String;)V"));
5655 current_token = yylex();
5656 return_type->type_class = real_type;
5657 return return_type;
5660 if (current_token == CST_BOOLEAN)
5662 if (boolean_constant)
5664 bytecode_append(current_block->code, iconst_m1$);
5666 else
5668 bytecode_append(current_block->code, iconst_0$);
5671 current_token = yylex();
5672 return_type->type_class = boolean_type;
5673 return return_type;
5676 if (current_token == CST_CHAR)
5678 bytecode_append(current_block->code, bipush$);
5679 bytecode_append(current_block->code, char_constant);
5681 current_token = yylex();
5682 return_type->type_class = char_type;
5683 return return_type;
5686 if (current_token == CST_STRING)
5688 int cp_index;
5689 cp_index = cp_add_string(string_constant->cstr);
5690 if (cp_index <= 255)
5692 bytecode_append(current_block->code, ldc$);
5693 bytecode_append(current_block->code, (char) cp_index);
5695 else
5697 bytecode_append(current_block->code, ldc_w$);
5698 bytecode_append_short_int(current_block->code, (short) cp_index);
5701 current_token = yylex();
5702 return_type->type_class = string_type;
5703 return return_type;
5706 if (current_token == IDENTIFIER)
5708 identifier *name;
5709 char *identifier_text;
5710 identifier_text = (char*) mem_alloc(strlen(YYTEXT_STRING) + 1);
5711 strcpy(identifier_text, YYTEXT_STRING);
5712 lowercase(identifier_text);
5714 name = get_identifier(current_block, identifier_text);
5716 if ((name->identifier_class == none)
5717 || (name->identifier_class == program_name)
5718 || (name->identifier_class == type_name)
5719 || (name->identifier_class == procedure_name))
5721 add_error_message(429, YYTEXT_STRING, "");
5722 current_token = yylex();
5723 identifier_destroy(name);
5724 mem_free(identifier_text);
5725 return return_type;
5729 current_token = yylex();
5731 if (name->identifier_class == constant_name)
5733 constant_value:
5734 create_constant_bytecode(name, current_block->code);
5735 type_destroy(return_type);
5736 return_type = type_duplicate(name->constant_type);
5737 identifier_destroy(name);
5738 mem_free(identifier_text);
5739 return return_type;
5742 /*
5743 Parse the unit functions.
5744 */
5745 if (name->identifier_class == unit_name)
5747 identifier *unit_name;
5749 if (current_token != DOT)
5751 add_error_message(200, ".", YYTEXT_STRING);
5752 while (current_token != SEMI_COLON)
5753 current_token = yylex();
5754 return return_type;
5757 current_token = yylex();
5758 unit_name = name_table_find(name->unit_block->names, string_from_cstr(YYTEXT_STRING));
5759 identifier_text = malloc(strlen(YYTEXT_STRING) + 1);
5760 strcpy(identifier_text, YYTEXT_STRING);
5762 if (unit_name == NULL)
5764 add_error_message(453, YYTEXT_STRING, "");
5765 add_error_message(200, ".", YYTEXT_STRING);
5766 while (current_token != SEMI_COLON)
5767 current_token = yylex();
5768 return return_type;
5771 name = identifier_duplicate(unit_name);
5772 current_token = yylex();
5774 if (name->identifier_class == function_name)
5775 goto function_call;
5777 if (name->identifier_class == constant_name)
5778 goto constant_value;
5780 if (name->identifier_class == variable_name)
5781 goto variable_value;
5783 add_error_message(458, YYTEXT_STRING, "");
5786 if ((name->identifier_class == variable_name)
5787 || (name->identifier_class == parameter_name))
5789 type *current_type;
5790 type *new_type;
5791 int is_field;
5792 variable_value:
5793 is_field = name->belongs_to_program_block;
5795 if (name->identifier_class == variable_name)
5797 create_variable_bytecode(name, current_block->code, identifier_text, is_field);
5798 current_type = type_duplicate(name->variable_type);
5802 if(name->identifier_class == parameter_name)
5804 create_variable_bytecode(name, current_block->code, identifier_text, is_field);
5805 current_type = type_duplicate(name->parameter_type);
5808 mem_free(identifier_text);
5810 identifier_destroy(name);
5812 name = NULL;
5814 while ((current_token == DOT)
5815 || (current_token == OPEN_SQ_BR))
5817 /* get an element from the record */
5818 if (current_token == DOT)
5820 char record_name[5];
5821 char field_descriptor[128];
5822 int fieldref_index;
5824 if (current_type->type_class != record_type)
5826 add_error_message(424, "", "");
5828 /* Error-recovery */
5829 while ((current_token != SEMI_COLON)
5830 && (current_token != KWD_END)
5831 && (current_token != END_OF_INPUT))
5833 current_token = yylex();
5836 type_destroy(current_type);
5837 return return_type;
5840 current_token = yylex();
5842 new_type = type_find_record_element(current_type, YYTEXT_STRING);
5843 sprintf(record_name, "R_%d", current_type->unique_record_ID);
5844 type_destroy(current_type);
5845 current_type = new_type;
5847 if (current_type == NULL)
5849 add_error_message(425, YYTEXT_STRING, "");
5851 /* Error-recovery */
5852 while ((current_token != SEMI_COLON)
5853 && (current_token != KWD_END)
5854 && (current_token != END_OF_INPUT))
5856 current_token = yylex();
5859 type_destroy(current_type);
5860 return return_type;
5863 lowercase(YYTEXT_STRING);
5864 get_field_descriptor(new_type, field_descriptor);
5865 fieldref_index = cp_add_fieldref(record_name, YYTEXT_STRING, field_descriptor);
5867 bytecode_append(current_block->code, getfield$);
5868 bytecode_append_short_int(current_block->code, fieldref_index);
5870 current_token = yylex();
5872 /* get an element from an array */
5873 else if (current_token == OPEN_SQ_BR)
5875 type_list *array_elements;
5877 if (current_type->type_class != array_type)
5879 add_error_message(426, "", "");
5881 /* Error-recovery */
5882 while ((current_token != SEMI_COLON)
5883 && (current_token != KWD_END)
5884 && (current_token != END_OF_INPUT))
5886 current_token = yylex();
5889 type_destroy(current_type);
5890 return return_type;
5893 current_token = yylex();
5895 array_elements = RD_expression_list_array(current_block, current_block->code, current_type);
5897 /* replace the last aaload in the bytecode with the proper loading instruction */
5898 replace_aaload_instruction(current_block->code, current_type->element_type);
5900 if (type_list_different_parameter_array(array_elements, current_type->dimensions_list) != 0)
5902 char num1[6], num2[6];
5904 sprintf(num1, "%d", type_list_length(current_type->dimensions_list));
5905 sprintf(num2, "%d", type_list_length(array_elements));
5906 add_error_message(427, num1, num2);
5908 /* Error-recovery */
5909 while ((current_token != SEMI_COLON)
5910 && (current_token != KWD_END)
5911 && (current_token != END_OF_INPUT))
5913 current_token = yylex();
5916 type_destroy(current_type);
5917 return return_type;
5920 if (current_token != CLOSE_SQ_BR)
5922 add_error_message(200, "]", YYTEXT_STRING);
5924 /* Error-recovery */
5925 while ((current_token != SEMI_COLON)
5926 && (current_token != KWD_END)
5927 && (current_token != END_OF_INPUT))
5929 current_token = yylex();
5932 type_destroy(current_type);
5933 return return_type;
5936 current_token = yylex();
5938 new_type = type_duplicate(current_type->element_type);
5939 type_destroy(current_type);
5941 current_type = new_type;
5943 type_list_destroy(array_elements);
5948 type_destroy(return_type);
5950 return_type = current_type;
5952 return return_type;
5955 function_call:
5957 /* a function call */
5958 if (name->identifier_class == function_name)
5960 int methodref_index;
5961 char *method_type;
5962 int method_index;
5963 method_type = (char*) mem_alloc(1024*5);
5965 if (name->standard_function)
5967 create_std_function_prefix(current_block->code, identifier_text);
5970 if (type_list_length(name->parameters) == 0)
5972 int br_depth = 0;
5973 if (current_token == OPEN_BR)
5975 add_error_message(419, "", "");
5976 br_depth = 1;
5977 while (br_depth > 0)
5979 if ((current_token == END_OF_INPUT)
5980 || (current_token == KWD_END))
5982 identifier_destroy(name);
5983 return return_type;
5986 current_token = yylex();
5988 if (current_token == OPEN_BR)
5989 br_depth ++;
5991 if (current_token == CLOSE_BR)
5992 br_depth --;
5995 current_token = yylex();
5998 /* create the bytecode */
5999 if (name->unit_function)
6001 string *full_unit_name;
6002 if (name->container_unit->is_library == 1)
6003 full_unit_name = string_from_cstr("Lib_");
6004 else
6005 full_unit_name = string_create();
6006 string_append(full_unit_name, name->container_unit->unit_name);
6008 lowercase(identifier_text);
6009 strcpy(method_type, "()");
6010 get_field_descriptor(name->return_type, method_type + 2);
6011 method_index = cp_add_methodref(full_unit_name->cstr,
6012 identifier_text, method_type);
6013 bytecode_append(current_block->code, invokestatic$);
6014 bytecode_append_short_int(current_block->code, method_index);
6015 string_destroy(full_unit_name);
6017 else if (!name->standard_function)
6019 /* the function is user-defined */
6020 strcpy(method_type, "()");
6021 get_field_descriptor(name->return_type, method_type + 2);
6022 if (compiling_unit == 0)
6023 methodref_index = cp_add_methodref("M", identifier_text, method_type);
6024 else
6025 methodref_index = cp_add_methodref(string_get_cstr(str_program_name), identifier_text, method_type);
6026 bytecode_append(current_block->code, invokestatic$); /* call */
6027 bytecode_append_short_int(current_block->code, methodref_index);
6029 else
6031 /* handle standard functions and procedures */
6032 create_std_function_code(current_block->code, identifier_text);
6035 type_destroy(return_type);
6037 mem_free(identifier_text);
6038 mem_free(method_type);
6040 return_type = type_duplicate(name->return_type);
6042 identifier_destroy(name);
6044 return return_type;
6046 else
6048 int compare_result;
6049 int old_linenum;
6050 type_list *parameter_list;
6052 if (current_token != OPEN_BR)
6054 add_error_message(200, "(", YYTEXT_STRING);
6057 current_token = yylex();
6059 old_linenum = linenum;
6061 parameter_list = RD_expression_list_cast(current_block, name->parameters);
6063 compare_result = type_list_different_parameter_cast(parameter_list, name->parameters);
6065 if (compare_result == -1){
6066 new_linenum=old_linenum;
6067 add_error_message(421, "", "");
6070 if (compare_result > 0)
6072 char par_num[4];
6073 sprintf(par_num, "%d", compare_result);
6074 new_linenum=old_linenum;
6075 add_error_message(422, par_num, "");
6078 type_list_destroy(parameter_list);
6080 if (current_token != CLOSE_BR)
6082 add_error_message(200, ")", YYTEXT_STRING);
6084 else
6085 current_token = yylex();
6087 type_destroy(return_type);
6089 /* create the bytecode */
6090 if (!name->standard_function)
6093 int pos = 1;
6094 type_list *it;
6096 it = name->parameters;
6098 method_type[0] = '(';
6100 while (it != NULL)
6102 if (it->data == NULL)
6103 break;
6106 get_field_descriptor(it->data, method_type + pos);
6107 pos = strlen(method_type);
6109 it = it->next;
6112 strcat(method_type, ")");
6116 get_field_descriptor(name->return_type, method_type + strlen(method_type));
6118 if (name->unit_function)
6120 string *full_unit_name;
6121 if (name->container_unit->is_library == 1)
6122 full_unit_name = string_from_cstr("Lib_");
6123 else
6124 full_unit_name = string_create();
6125 string_append(full_unit_name, name->container_unit->unit_name);
6126 lowercase(identifier_text);
6127 methodref_index = cp_add_methodref(full_unit_name->cstr, identifier_text, method_type);
6128 string_destroy(full_unit_name);
6130 else
6132 if (compiling_unit == 0)
6133 methodref_index = cp_add_methodref("M", identifier_text, method_type);
6134 else
6135 methodref_index = cp_add_methodref(string_get_cstr(str_program_name), identifier_text, method_type);
6138 bytecode_append(current_block->code, invokestatic$); /* call */
6139 bytecode_append_short_int(current_block->code, methodref_index);
6141 else
6143 /* handle standard functions and procedures */
6144 create_std_function_code(current_block->code, identifier_text);
6146 /* END create the bytecode */
6148 return_type = type_duplicate(name->return_type);
6150 mem_free(identifier_text);
6151 mem_free(method_type);
6153 identifier_destroy(name);
6155 return return_type;
6159 mem_free(identifier_text);
6161 return return_type;
6164 /* brackets, priority change, no code generated in here */
6165 if (current_token == OPEN_BR)
6167 current_token = yylex();
6169 type_destroy(return_type);
6170 return_type = RD_expression(current_block);
6172 if (current_token != CLOSE_BR)
6174 add_error_message(200, ")", YYTEXT_STRING);
6177 current_token = yylex();
6179 return return_type;
6182 add_error_message(204, YYTEXT_STRING, "");
6184 return return_type;
6188 /*
6189 Create the bytecode that loads the given constant
6190 */
6191 void create_constant_bytecode(identifier *item, bytecode *code)
6193 int cp_index;
6195 switch(item->constant_type->type_class)
6197 case integer_type:
6198 cp_index = cp_add_integer(item->constant_int_value);
6199 if (cp_index <= 255)
6201 bytecode_append(code, ldc$);
6202 bytecode_append(code, (char) cp_index);
6204 else
6206 bytecode_append(code, ldc_w$);
6207 bytecode_append_short_int(code, (short) cp_index);
6209 break;
6211 case real_type:
6213 float cst;
6214 int csti; /* the integer part */
6215 int cstf; /* the fraction part */
6217 /* calculate the exponent and the integer part */
6218 cst = item->constant_real_value;
6220 csti = (int)cst;
6221 cstf = (cst - (int)cst)*100000;
6223 usesFloat = 1;
6225 if (mathType == 1)
6227 /* put the integer part on the stack */
6228 if (abs(csti) < 127)
6230 bytecode_append(code, bipush$);
6231 bytecode_append(code, csti);
6233 else if (abs(csti) < 15000)
6235 bytecode_append(code, sipush$);
6236 bytecode_append_short_int(code, csti);
6238 else
6240 bytecode_append(code, ldc_w$);
6241 bytecode_append_short_int(code, cp_add_integer(csti));
6244 /* put the fraction part to the stack */
6245 if (abs(cstf) < 127)
6247 bytecode_append(code, bipush$);
6248 bytecode_append(code, cstf);
6250 else if (abs(cstf) < 15000)
6252 bytecode_append(code, sipush$);
6253 bytecode_append_short_int(code, cstf);
6255 else
6257 bytecode_append(code, ldc_w$);
6258 bytecode_append_short_int(code, cp_add_integer(cstf));
6261 bytecode_append(code, invokestatic$);
6262 bytecode_append_short_int(code, cp_add_methodref("F", "fI", "(II)I"));
6264 else
6266 char number[64];
6268 bytecode_append(code, new$);
6269 bytecode_append_short_int(code, cp_add_class("Real"));
6270 bytecode_append(code, dup$);
6272 sprintf(number, "%f", real_constant);
6273 bytecode_append(code, ldc_w$);
6274 bytecode_append_short_int(code, cp_add_string(number));
6276 bytecode_append(code, invokespecial$);
6277 bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(Ljava/lang/String;)V"));
6284 break;
6286 case char_type:
6287 cp_index = cp_add_integer(item->constant_int_value);
6288 if (cp_index <= 255)
6290 bytecode_append(code, ldc$);
6291 bytecode_append(code, (char) cp_index);
6293 else
6295 bytecode_append(code, ldc_w$);
6296 bytecode_append_short_int(code, (short) cp_index);
6298 break;
6300 case boolean_type:
6301 if (item->constant_int_value)
6303 bytecode_append(code, iconst_m1$);
6305 else
6307 bytecode_append(code, iconst_0$);
6309 break;
6311 case string_type:
6312 cp_index = cp_add_string(item->constant_string_value->cstr);
6313 if (cp_index <= 255)
6315 bytecode_append(code, ldc$);
6316 bytecode_append(code, (char) cp_index);
6318 else
6320 bytecode_append(code, ldc_w$);
6321 bytecode_append_short_int(code, (short) cp_index);
6323 break;
6328 /*
6329 Creates the code that loads the variable or parameter value to the stack
6330 */
6331 void create_variable_bytecode(identifier *item, bytecode *code, char *name, int is_field)
6333 int index;
6334 type *item_type;
6336 /* if the block is program block, load field instead of variable */
6337 if ((is_field) || (item->unit_function == 1))
6339 if (item->identifier_class == variable_name)
6341 char type_descriptor[128];
6343 lowercase(name);
6344 bytecode_append(code, getstatic$);
6345 get_field_descriptor(item->variable_type, type_descriptor);
6347 if (item->unit_function == 0)
6349 if (compiling_unit == 0)
6350 bytecode_append_short_int(code, cp_add_fieldref("M", name, type_descriptor));
6351 else
6352 bytecode_append_short_int(code, cp_add_fieldref(string_get_cstr(str_program_name), name, type_descriptor));
6354 else
6356 string *unit_name;
6358 if (item->container_unit->is_library == 0)
6359 unit_name = string_create();
6360 else
6361 unit_name = string_from_cstr("Lib_");
6363 lowercase(string_get_cstr(item->container_unit->unit_name));
6365 string_append(unit_name, item->container_unit->unit_name);
6367 bytecode_append_short_int(code, cp_add_fieldref(string_get_cstr(unit_name), name, type_descriptor));
6369 string_destroy(unit_name);
6373 return;
6376 if (item->identifier_class == variable_name)
6378 index = item->variable_index;
6379 item_type = item->variable_type;
6381 else if (item->identifier_class == function_name)
6383 /* this is used for error recovery and returning values form functions */
6384 index = type_list_length(item->parameters);
6385 item_type = item->return_type;
6387 else if (item->identifier_class == parameter_name)
6389 index = item->parameter_index;
6390 item_type = item->parameter_type;
6392 else
6394 add_error_message(444, "", "");
6395 return 0;
6398 switch (item_type->type_class)
6400 case integer_type:
6401 case char_type:
6402 case boolean_type:
6403 switch(index)
6405 case 0:
6406 bytecode_append(code, iload_0$);
6407 break;
6408 case 1:
6409 bytecode_append(code, iload_1$);
6410 break;
6411 case 2:
6412 bytecode_append(code, iload_2$);
6413 break;
6414 case 3:
6415 bytecode_append(code, iload_3$);
6416 break;
6417 default:
6418 bytecode_append(code, iload$);
6419 bytecode_append(code, index);
6420 break;
6423 break;
6425 case real_type:
6426 if (mathType == 1)
6428 switch(index)
6430 case 0:
6431 bytecode_append(code, iload_0$);
6432 break;
6433 case 1:
6434 bytecode_append(code, iload_1$);
6435 break;
6436 case 2:
6437 bytecode_append(code, iload_2$);
6438 break;
6439 case 3:
6440 bytecode_append(code, iload_3$);
6441 break;
6442 default:
6443 bytecode_append(code, iload$);
6444 bytecode_append(code, index);
6445 break;
6448 else
6450 switch(index)
6452 case 0:
6453 bytecode_append(code, aload_0$);
6454 break;
6455 case 1:
6456 bytecode_append(code, aload_1$);
6457 break;
6458 case 2:
6459 bytecode_append(code, aload_2$);
6460 break;
6461 case 3:
6462 bytecode_append(code, aload_3$);
6463 break;
6464 default:
6465 bytecode_append(code, aload$);
6466 bytecode_append(code, index);
6467 break;
6470 break;
6472 case string_type:
6473 case record_type:
6474 case array_type:
6475 case image_type:
6476 case command_type:
6477 case stream_type:
6478 case record_store_type:
6479 case http_type:
6480 case alert_type:
6481 switch(index)
6483 case 0:
6484 bytecode_append(code, aload_0$);
6485 break;
6486 case 1:
6487 bytecode_append(code, aload_1$);
6488 break;
6489 case 2:
6490 bytecode_append(code, aload_2$);
6491 break;
6492 case 3:
6493 bytecode_append(code, aload_3$);
6494 break;
6495 default:
6496 bytecode_append(code, aload$);
6497 bytecode_append(code, index);
6498 break;
6501 break;
6503 default:
6504 die(15);
6508 /*
6509 Creates the code that puts the variable or parameter value from the stack into memory
6510 */
6511 void create_put_variable_bytecode(identifier *item, bytecode *code, char *name, int is_field)
6513 int index;
6514 type *item_type;
6516 if (item->identifier_class == variable_name)
6518 index = item->variable_index;
6519 item_type = item->variable_type;
6521 else if (item->identifier_class == parameter_name)
6523 index = item->parameter_index;
6524 item_type = item->parameter_type;
6526 else if (item->identifier_class == function_name)/* function name, it is return value variable */
6528 index = type_list_length(item->parameters);
6529 is_field = 0;
6530 item_type = item->return_type;
6532 else
6534 add_error_message(444, "", "");
6535 return;
6538 /* if the value on the top of the stack is string, copy it */
6539 if (item_type->type_class == string_type)
6541 int class_index;
6542 int method_index;
6544 class_index = cp_add_class("java/lang/String");
6545 method_index = cp_add_methodref("java/lang/String", "<init>", "(Ljava/lang/String;)V");
6547 bytecode_append(code, new$);
6548 bytecode_append_short_int(code, class_index);
6549 bytecode_append(code, dup_x1$);
6550 bytecode_append(code, swap$);
6551 bytecode_append(code, invokespecial$);
6552 bytecode_append_short_int(code, method_index);
6555 if ((item_type->type_class == real_type) && (mathType != 1))
6557 int class_index;
6558 int method_index;
6560 usesFloat = 1;
6562 class_index = cp_add_class("Real");
6563 method_index = cp_add_methodref("Real", "<init>", "(LReal;)V");
6565 bytecode_append(code, new$);
6566 bytecode_append_short_int(code, class_index);
6567 bytecode_append(code, dup_x1$);
6568 bytecode_append(code, swap$);
6569 bytecode_append(code, invokespecial$);
6570 bytecode_append_short_int(code, method_index);
6573 /* if the value on the top of the stack is record type, copy it */
6574 if (item_type->type_class == record_type)
6576 int class_index;
6577 int constructor_index;
6578 int copy_index;
6580 char type_name[16];
6581 char copy_sig[64];
6583 sprintf(type_name, "R_%d", item_type->unique_record_ID);
6584 sprintf(copy_sig, "(L%s;)L%s;", type_name, type_name);
6586 class_index = cp_add_class(type_name);
6587 constructor_index = cp_add_methodref(type_name, "<init>", "()V");
6588 copy_index = cp_add_methodref(type_name, "Copy", copy_sig);
6590 bytecode_append(code, new$);
6591 bytecode_append_short_int(code, class_index);
6592 bytecode_append(code, dup_x1$);
6593 bytecode_append(code, invokespecial$);
6594 bytecode_append_short_int(code, constructor_index);
6595 bytecode_append(code, invokevirtual$);
6596 bytecode_append_short_int(code, copy_index);
6599 /* if the block is program block, load field instead of variable */
6600 if ((is_field) || (item->unit_function == 1))
6602 if (item->identifier_class == variable_name)
6604 char type_descriptor[128];
6606 lowercase(name);
6607 bytecode_append(code, putstatic$);
6608 get_field_descriptor(item->variable_type, type_descriptor);
6610 if (item->unit_function == 0)
6612 if (compiling_unit == 0)
6613 bytecode_append_short_int(code, cp_add_fieldref("M", name, type_descriptor));
6614 else
6615 bytecode_append_short_int(code, cp_add_fieldref(string_get_cstr(str_program_name), name, type_descriptor));
6617 else
6619 string *unit_name;
6621 if (item->container_unit->is_library == 0)
6622 unit_name = string_create();
6623 else
6624 unit_name = string_from_cstr("Lib_");
6626 lowercase(string_get_cstr(item->container_unit->unit_name));
6628 string_append(unit_name, item->container_unit->unit_name);
6630 bytecode_append_short_int(code, cp_add_fieldref(string_get_cstr(unit_name), name, type_descriptor));
6632 string_destroy(unit_name);
6636 return;
6639 switch (item_type->type_class)
6641 case integer_type:
6642 case char_type:
6643 case boolean_type:
6644 switch(index)
6646 case 0:
6647 bytecode_append(code, istore_0$);
6648 break;
6649 case 1:
6650 bytecode_append(code, istore_1$);
6651 break;
6652 case 2:
6653 bytecode_append(code, istore_2$);
6654 break;
6655 case 3:
6656 bytecode_append(code, istore_3$);
6657 break;
6658 default:
6659 bytecode_append(code, istore$);
6660 bytecode_append(code, index);
6661 break;
6664 break;
6666 case real_type:
6667 if (mathType == 1)
6669 switch(index)
6671 case 0:
6672 bytecode_append(code, istore_0$);
6673 break;
6674 case 1:
6675 bytecode_append(code, istore_1$);
6676 break;
6677 case 2:
6678 bytecode_append(code, istore_2$);
6679 break;
6680 case 3:
6681 bytecode_append(code, istore_3$);
6682 break;
6683 default:
6684 bytecode_append(code, istore$);
6685 bytecode_append(code, index);
6686 break;
6689 else
6691 switch(index)
6693 case 0:
6694 bytecode_append(code, astore_0$);
6695 break;
6696 case 1:
6697 bytecode_append(code, astore_1$);
6698 break;
6699 case 2:
6700 bytecode_append(code, astore_2$);
6701 break;
6702 case 3:
6703 bytecode_append(code, astore_3$);
6704 break;
6705 default:
6706 bytecode_append(code, astore$);
6707 bytecode_append(code, index);
6708 break;
6711 break;
6713 case string_type:
6714 case record_type:
6715 case array_type:
6716 case image_type:
6717 case command_type:
6718 case stream_type:
6719 case record_store_type:
6720 case http_type:
6721 case alert_type:
6722 switch(index)
6724 case 0:
6725 bytecode_append(code, astore_0$);
6726 break;
6727 case 1:
6728 bytecode_append(code, astore_1$);
6729 break;
6730 case 2:
6731 bytecode_append(code, astore_2$);
6732 break;
6733 case 3:
6734 bytecode_append(code, astore_3$);
6735 break;
6736 default:
6737 bytecode_append(code, astore$);
6738 bytecode_append(code, index);
6739 break;
6742 break;
6744 default:
6745 die(15);
6749 /*
6750 The last instruction in the bytecode is aaload; it should be replaced with
6751 the iaload, faload, aload or something like that.
6752 */
6753 void replace_aaload_instruction(bytecode *code, type *element_type)
6755 /* delete the last instruction */
6756 code->bytecode_pos --;
6758 /* create the new instruction */
6759 switch(element_type->type_class)
6761 case integer_type:
6762 case boolean_type:
6763 case char_type:
6764 bytecode_append(code, iaload$);
6765 break;
6767 case real_type:
6768 if (mathType == 1)
6770 bytecode_append(code, iaload$);
6772 else
6774 bytecode_append(code, aaload$);
6776 break;
6778 case record_type:
6779 case string_type:
6780 case image_type:
6781 case command_type:
6782 case stream_type:
6783 case record_store_type:
6784 case http_type:
6785 case alert_type:
6786 bytecode_append(code, aaload$);
6787 break;
6789 default:
6790 die(24);
6794 /*
6795 Creates the code that adjustes array indices
6796 */
6797 void adjust_indices(bytecode *code, type *dimension)
6799 if (dimension == NULL)
6800 return;
6802 switch(dimension->first_element)
6804 case -1:
6805 bytecode_append(code, iconst_m1$);
6806 break;
6807 case 0:
6808 //bytecode_append(code, iconst_0$);
6809 break;
6810 case 1:
6811 bytecode_append(code, iconst_1$); break;
6812 case 2:
6813 bytecode_append(code, iconst_2$); break;
6814 case 3:
6815 bytecode_append(code, iconst_3$); break;
6816 case 4:
6817 bytecode_append(code, iconst_4$); break;
6818 case 5:
6819 bytecode_append(code, iconst_5$); break;
6820 default:
6821 if (dimension->first_element < 128)
6823 bytecode_append(code, bipush$);
6824 bytecode_append(code, dimension->first_element);
6826 else
6828 bytecode_append(code, sipush$);
6829 bytecode_append_short_int(code, dimension->first_element);
6832 if (dimension->first_element != 0)
6833 bytecode_append(code, isub$);