#include "parser.h" #include "tokenizer.h" #include "scope.h" #include "types.h" #include "function.h" #include "error.h" #include #include #include #include #include #include #include #include "decompiler.h" #define MAX_CODE_SIZE 65536 #define MAX_LABELS 256 #define MAX_FUNCTIONS 256 #define MAX_EXTERNAL_FUNCTIONS 256 #define MAX_IDENTIFIER_LENGTH 40 #define MAX_CONSTANTS 256 #define MAX_STRUCT_MEMBERS 10 struct t_label { std::string name; uint32_t address; }; /* struct t_external_function { char name[MAX_IDENTIFIER_LENGTH]; int num_parameters = 0; }; struct t_string { unsigned char string[256]; word references[256]; int num_references = 1; }; */ static byte* code; // [MAX_CODE_SIZE]; static uint32_t codepos = 0; static uint32_t lines[32768]; static uint32_t current_line; static std::vector known_labels; //static int num_known_labels = 0; static std::vector unknown_labels; //static int num_unknown_labels = 0; static int num_anonymous_labels = 0; static std::string breaklabel = ""; static std::string contlabel = ""; /* static t_variable* variables = nullptr; static int num_variables = 0; static bool variable_is_array = false; static t_external_function external_functions[MAX_EXTERNAL_FUNCTIONS]; static int num_external_functions = 0; static t_string strings[256]; static int num_strings = 0; static t_constant constants[MAX_CONSTANTS]; static int num_constants; */ static bool parser_finished = false; static bool global_closed = false; /****************************************************************************************/ /* GENERIC FUNCTIONS */ /****************************************************************************************/ static const std::string int_to_string(int value) { std::string label = "0000000"; //for (int i = 0; i < 7; i++) label[i] = '0'; int i = 6; while (value > 0) { label[i] = 48 + (value % 10); value = value / 10; i--; } return label; } /****************************************************************************************/ /* BYTECODE GENERATOR */ /****************************************************************************************/ static void emmit(const byte value) { lines[codepos] = current_line; code[codepos++] = value; } static void emmit_w(const word value) { lines[codepos] = current_line; code[codepos++] = value & 255; lines[codepos] = current_line; code[codepos++] = value >> 8; } static void emmit_dw(const uint32_t value) { byte *v = (byte*)&value; lines[codepos] = current_line; code[codepos++] = *(v++); lines[codepos] = current_line; code[codepos++] = *(v++); lines[codepos] = current_line; code[codepos++] = *(v++); lines[codepos] = current_line; code[codepos++] = *(v++); } static void emmit_f(const float value) { byte *v = (byte*)&value; lines[codepos] = current_line; code[codepos++] = *(v++); lines[codepos] = current_line; code[codepos++] = *(v++); lines[codepos] = current_line; code[codepos++] = *(v++); lines[codepos] = current_line; code[codepos++] = *(v++); } static void patch(const uint32_t address, const word dest) { code[address] = dest & 255; code[address + 1] = dest >> 8; } static void patch_dw(const uint32_t address, const uint32_t dest) { byte *v = (byte*)&dest; code[address] = v[0]; code[address+1] = v[1]; code[address+2] = v[2]; code[address+3] = v[3]; } static const uint32_t get_current_address() { return codepos; } #define EXPECT(X, Y) if (tkn_get_token() != X) { parser_finished = true; error_raise(Y); return; } #define EXPECT2(X, Y) if (tkn_get_token() != X) { parser_finished = true; error_raise(Y); return -1; } #define HALT(Y) { parser_finished = true; error_raise(Y); return; } #define HALT2(Y) { parser_finished = true; error_raise(Y); return -1; } /****************************************************************************************/ /* LABEL MANAGEMENT */ /****************************************************************************************/ static const uint32_t get_label_address(const std::string name) { for (auto label : known_labels) if (label.name == name) return label.address; unknown_labels.push_back({name, get_current_address()}); return 0; } static void register_label_address(const std::string name) { // If the label already exists, vomit an error for (auto label : known_labels) if (label.name == name) HALT("Duplicate label"); // register new label known_labels.push_back({name, get_current_address()}); // patch and remove any references awaiting for this label auto i = std::begin(unknown_labels); while (i != std::end(unknown_labels)) { if ((*i).name == name) { patch_dw((*i).address, get_current_address()); i = unknown_labels.erase(i); } else { ++i; } } } static const std::string generate_anonymous_labelname() { return int_to_string(num_anonymous_labels++); } /****************************************************************************************/ /* PARSER */ /****************************************************************************************/ static void parse_expression(); static const bool parse_statements(); /* XXX [RZC 27/04/2021] No usat en JailBasic //static void parse_strleft(); static void parse_str(); static void parse_chr(); static void parse_strlen(); static void parse_keypressed(); static void parse_anykey(); static void parse_getchar(); static void parse_getcolor(); */ /* static void parse_concat_atom() { if (tkn_get_token() == TOKEN_STRING) { emmit(OP_SETX); emmit_w(register_string(tkn_get_string())); emmit(OP_JSR); emmit_w(get_label_address("_sys_string_load")); tkn_next(); return; } if (tkn_get_token() == TOKEN_HEXSTRING) { emmit(OP_SETX); emmit_w(register_array(tkn_get_array())); emmit(OP_JSR); emmit_w(get_label_address("_sys_string_load")); tkn_next(); return; } if (tkn_get_token() == TOKEN_IDENTIFIER) { int ivar = get_variable_index(tkn_get_string()); if (!is_variable_array()) { parser_finished = true; error_raise("Expected string constant or variable"); return; } emmit(OP_SETX); emmit_w(ivar); emmit(OP_JSR); emmit_w(get_label_address("_sys_string_load")); tkn_next(); return; } if (tkn_get_token() == TOKEN_STRLEFT) { tkn_next(); parse_strleft(); return; } if (tkn_get_token() == TOKEN_STR) { tkn_next(); parse_str(); return; } if (tkn_get_token() == TOKEN_CHR) { tkn_next(); parse_chr(); return; } parser_finished = true; error_raise("Syntax error"); return; } static void parse_concatenation() { parse_concat_atom(); while (tkn_get_token() == TOKEN_COMMA) { tkn_next(); parse_concat_atom(); emmit(OP_CONCAT); } } */ static int get_variable_address() { int address = scope_get_variable_address(); uint32_t var_length = scope_get_variable_size(); uint32_t var_type = scope_get_variable_type(); while (true) { // Si es un array... if (var_length > 1) { tkn_next(); EXPECT2(TOKEN_LBRACKET, "Expected '['"); tkn_next(); EXPECT2(TOKEN_NUMBER, "Expected number"); const int index = (int)tkn_get_value(); if (tkn_get_value() > index) HALT2("Expected integer value"); if (index >= var_length) HALT2("Index out of bounds"); tkn_next(); EXPECT2(TOKEN_RBRACKET, "Expected ']'"); address += index * types_get_length(var_type); } // Si es un struct... if (var_type >= 2) { tkn_next(); EXPECT2(TOKEN_DOT, "Expected '.'"); tkn_next(); EXPECT2(TOKEN_IDENTIFIER, "Expected identifier"); const std::string member_name = tkn_get_string(); const int member_num = types_member_exists(var_type, member_name); if (member_num == -1) HALT2("Unknown member"); address += types_get_member_offset(var_type, member_num); var_length = types_get_member_length(var_type, member_num); var_type = types_get_member_type(var_type, member_num); } else { return address; } } } static void parse_expr_atom() { // NUM, VAR, UNARY, PAREN if (tkn_get_token() == TOKEN_NUMBER) { emmit(OP_PUSH); emmit_f(tkn_get_value()); tkn_next(); return; } if (tkn_get_token() == TOKEN_IDENTIFIER) { if (scope_variable_exists(tkn_get_string())) { const int address = get_variable_address(); if (address == -1) return; emmit(scope_is_local() ? OP_LDL : OP_LD); emmit_dw(address); tkn_next(); return; } else { // TODO [RZC 03/05/2021] Revisar funcions parser_finished = true; error_raise("Unknown identifier"); return; } } if (tkn_get_token() == TOKEN_MINUS) { tkn_next(); parse_expr_atom(); emmit(OP_NEG); return; } if (tkn_get_token() == TOKEN_NOT) { tkn_next(); parse_expr_atom(); emmit(OP_NOT); return; } if (tkn_get_token() == TOKEN_LPAR) { tkn_next(); parse_expression(); EXPECT(TOKEN_RPAR, "Expected ')'"); tkn_next(); return; } parser_finished = true; error_raise("Syntax error"); return; } static void parse_expr_mul() { parse_expr_atom(); while (tkn_get_token() == TOKEN_ASTERISC || tkn_get_token() == TOKEN_SLASH || tkn_get_token() == TOKEN_MOD) { t_tokentype operat = tkn_get_token(); tkn_next(); parse_expr_atom(); switch (operat) { case TOKEN_ASTERISC: emmit(OP_MUL); break; case TOKEN_SLASH: emmit(OP_DIV); break; case TOKEN_MOD: emmit(OP_MOD); break; default: /* Impossible */ break; } } } static void parse_expr_sum() { parse_expr_mul(); while (tkn_get_token() == TOKEN_PLUS || tkn_get_token() == TOKEN_MINUS) { t_tokentype operat = tkn_get_token(); tkn_next(); parse_expr_mul(); switch (operat) { case TOKEN_PLUS: emmit(OP_ADD); break; case TOKEN_MINUS: emmit(OP_SUB); break; default: /* Impossible */ break; } } } static void parse_expr_bool() { parse_expr_sum(); while (tkn_get_token() == TOKEN_AND || tkn_get_token() == TOKEN_OR) { t_tokentype operat = tkn_get_token(); tkn_next(); parse_expr_sum(); switch (operat) { case TOKEN_AND: emmit(OP_AND); break; case TOKEN_OR: emmit(OP_OR); break; default: /* Impossible */ break; } } } static void parse_expression() { parse_expr_bool(); while (tkn_get_token() == TOKEN_EQ || tkn_get_token() == TOKEN_NEQ || tkn_get_token() == TOKEN_LT || tkn_get_token() == TOKEN_GT || tkn_get_token() == TOKEN_LEQ || tkn_get_token() == TOKEN_GEQ) { t_tokentype operat = tkn_get_token(); tkn_next(); parse_expr_bool(); switch (operat) { case TOKEN_EQ: emmit(OP_EQ); break; case TOKEN_NEQ: emmit(OP_NEQ); break; case TOKEN_LT: emmit(OP_LT); break; case TOKEN_GT: emmit(OP_GT); break; case TOKEN_LEQ: emmit(OP_LEQ); break; case TOKEN_GEQ: emmit(OP_GEQ); break; default: /* Impossible */ break; } } } static bool identifier_exists(const std::string identifier, const bool can_shadow=false) { if (scope_variable_exists(identifier, can_shadow)) return true; if (types_exist(identifier) != -1) return true; if (function_exists(identifier)) return true; return false; } static void parse_const() { EXPECT(TOKEN_IDENTIFIER, "Expected identifier"); char const_name[40]; strcpy(const_name, tkn_get_string()); if (identifier_exists(const_name, true)) HALT("Identifier already exists"); tkn_next(); EXPECT(TOKEN_AS, "Expected 'as'"); tkn_next(); EXPECT(TOKEN_IDENTIFIER, "Expected type identifier"); char type_name[40]; strcpy(type_name, tkn_get_string()); const int type_num = types_exist(type_name); if (type_num == -1) HALT("Unknown type"); if (type_num >= 2) HALT("Only 'number' or 'string' constants allowed"); tkn_next(); EXPECT(TOKEN_EQ, "Expected '='"); tkn_next(); parse_expression(); const int var_address = scope_declare_variable(const_name, type_num, 0); emmit(scope_is_local() ? OP_STL : OP_ST); emmit_dw(var_address); } static void parse_var() { int var_length = 1; EXPECT(TOKEN_IDENTIFIER, "Expected identifier"); const std::string var_name = tkn_get_string(); if (identifier_exists(var_name, true)) HALT("Identifier already exists"); tkn_next(); EXPECT(TOKEN_AS, "Expected 'as'"); tkn_next(); if (tkn_get_token() == TOKEN_ARRAY) { tkn_next(); EXPECT(TOKEN_OF, "Expected 'of'"); tkn_next(); EXPECT(TOKEN_NUMBER, "Expected number"); const float length = tkn_get_value(); var_length = (int)length; if (length > var_length) HALT("Expected integer value"); tkn_next(); } EXPECT(TOKEN_IDENTIFIER, "Expected type identifier"); const std::string type_name = tkn_get_string(); const int type_num = types_exist(type_name); if (type_num == -1) HALT("Unknown type"); tkn_next(); if (tkn_get_token() == TOKEN_EQ) { if (type_num >= 2) HALT("Only 'number' or 'string' variables can be initialized on declaration") if (var_length > 1) HALT("Array variables cannot be initialized on declaration") tkn_next(); parse_expression(); const int var_address = scope_declare_variable(var_name, type_num, var_length); emmit(scope_is_local() ? OP_STL : OP_ST); emmit_dw(var_address); } else { scope_declare_variable(var_name, type_num, var_length); //tkn_next(); } } static void parse_struct() { EXPECT(TOKEN_IDENTIFIER, "Expected identifier"); const std::string struct_name = tkn_get_string(); if (identifier_exists(struct_name)) HALT("Identifier already exists"); const int struct_num = types_add(struct_name); tkn_next(); while (tkn_get_token() != TOKEN_END) { int member_length = 1; EXPECT(TOKEN_IDENTIFIER, "Expected identifier"); char member_name[40]; strcpy(member_name, tkn_get_string()); tkn_next(); EXPECT(TOKEN_AS, "Expected 'as'"); tkn_next(); if (tkn_get_token() == TOKEN_ARRAY) { tkn_next(); EXPECT(TOKEN_OF, "Expected 'of'"); tkn_next(); EXPECT(TOKEN_NUMBER, "Expected number"); member_length = (int)tkn_get_value(); if (tkn_get_value() > member_length) HALT("Expected integer value"); tkn_next(); } EXPECT(TOKEN_IDENTIFIER, "Expected type identifier"); const std::string type_name = tkn_get_string(); const int type_num = types_exist(type_name); if (type_num == -1) HALT("Unknown type"); types_add_member(struct_num, member_name, type_num, member_length); tkn_next(); } tkn_next(); } static void parse_function() { if (!global_closed) { emmit(OP_RET); global_closed = true; } EXPECT(TOKEN_IDENTIFIER, "Expected identifier"); const std::string function_name = tkn_get_string(); if (identifier_exists(function_name)) HALT("Identifier already exists"); function_register(function_name, codepos); tkn_next(); EXPECT(TOKEN_LPAR, "Expected '('"); tkn_next(); scope_open_local(); std::stack addresses; while (tkn_get_token() != TOKEN_RPAR) { if (function_get_num_parameters() != 0) { EXPECT(TOKEN_COMMA, "Expected ',' or ')'"); tkn_next(); } EXPECT(TOKEN_IDENTIFIER, "Expected identifier"); const std::string param_name = tkn_get_string(); tkn_next(); EXPECT(TOKEN_AS, "Expected 'as'"); tkn_next(); EXPECT(TOKEN_IDENTIFIER, "Expected type identifier"); const std::string type_name = tkn_get_string(); const int type_num = types_exist(type_name); if (type_num == -1) HALT("Unknown type"); if (!function_parameter_add(param_name, type_num)) HALT("Parameter name already used"); addresses.push(scope_declare_variable(param_name, type_num, 1)); tkn_next(); } while (!addresses.empty()) { emmit(OP_STL); emmit_dw(addresses.top()); addresses.pop(); } tkn_next(); if (tkn_get_token() == TOKEN_AS) { tkn_next(); EXPECT(TOKEN_IDENTIFIER, "Expected type identifier"); const std::string type_name = tkn_get_string(); const int type_num = types_exist(type_name); if (type_num == -1) HALT("Unknown type"); function_set_type(type_num); tkn_next(); } if (!parse_statements() && (function_get_type() != -1)) HALT("Not all paths return a value"); scope_close_local(); EXPECT(TOKEN_END, "Expected statement or 'end'"); tkn_next(); } /*static void parse_dim() { EXPECT(TOKEN_IDENTIFIER, "Expected variable"); char varname[40]; strcpy(varname, tkn_get_string()); tkn_next(); EXPECT(TOKEN_LPAR, "Expected array size"); tkn_next(); EXPECT(TOKEN_NUMBER, "Expected integer constant as array size"); get_variable_index(varname, tkn_get_value()); // register variable with size, no need to keep ival tkn_next(); EXPECT(TOKEN_RPAR, "Expected ')'"); tkn_next(); }*/ // XXX [RZC 27/04/2021] Desactivat INC i DEC per ara /*static void parse_inc() { EXPECT(TOKEN_IDENTIFIER, "Expected variable"); int ivar = get_variable_index(tkn_get_string()); if (is_variable_array()) { tkn_next(); EXPECT(TOKEN_LPAR, "Expected array index"); tkn_next(); parse_expr_atom(); EXPECT(TOKEN_RPAR, "Expected ')'"); emmit(OP_SETY); emmit(OP_LOADI); emmit_w(ivar); emmit(OP_INC); emmit(OP_STOREI); emmit_w(ivar); } else { emmit(OP_LOAD); emmit_w(ivar); emmit(OP_INC); emmit(OP_STORE); emmit_w(ivar); } tkn_next(); } static void parse_dec() { EXPECT(TOKEN_IDENTIFIER, "Expected variable"); int ivar = get_variable_index(tkn_get_string()); if (is_variable_array()) { tkn_next(); EXPECT(TOKEN_LPAR, "Expected array index"); tkn_next(); parse_expr_atom(); EXPECT(TOKEN_RPAR, "Expected ')'"); emmit(OP_SETY); emmit(OP_LOADI); emmit_w(ivar); emmit(OP_DEC); emmit(OP_STOREI); emmit_w(ivar); } else { emmit(OP_LOAD); emmit_w(ivar); emmit(OP_DEC); emmit(OP_STORE); emmit_w(ivar); } tkn_next(); }*/ // XXX [RZC 27/04/2021] Desactivat, no se molt be ni què es /*static void parse_let() { EXPECT(TOKEN_IDENTIFIER, "Expected variable"); int ivar = get_variable_index(tkn_get_string()); if (is_variable_array()) { tkn_next(); if (tkn_get_token() == TOKEN_COLON) { tkn_next(); parse_concatenation(); emmit(OP_SETX); emmit_w(ivar); emmit(OP_JSR); emmit_w(get_label_address("_sys_string_store")); return; } else { EXPECT(TOKEN_LPAR, "Expected ':' or '('"); tkn_next(); parse_expr_atom(); EXPECT(TOKEN_RPAR, "Expected ')'"); emmit(OP_SETY); } } tkn_next(); EXPECT(TOKEN_EQ, "Expected '='"); tkn_next(); parse_expression(); if (is_variable_array()) { emmit(OP_STOREI); emmit_w(ivar); } else { emmit(OP_STORE); emmit_w(ivar); } }*/ static const bool parse_if() { bool ret_at_else = true; const std::string previous_breaklabel = breaklabel; parse_expression(); EXPECT2(TOKEN_THEN, "Expected 'THEN'"); tkn_next(); emmit(OP_JNT); const std::string elselabel = generate_anonymous_labelname(); const std::string endlabel = generate_anonymous_labelname(); breaklabel = endlabel; bool else_visited = false; emmit_dw(get_label_address(elselabel)); scope_open_block(); const bool ret_at_then = parse_statements(); scope_close_block(); if (tkn_get_token() == TOKEN_ELSE) { else_visited = true; emmit(OP_JMP); emmit_dw(get_label_address(endlabel)); register_label_address(elselabel); tkn_next(); scope_open_block(); ret_at_else = parse_statements(); scope_close_block(); } if (tkn_get_token() == TOKEN_END) { if (!else_visited) register_label_address(elselabel); register_label_address(endlabel); tkn_next(); breaklabel = previous_breaklabel; return ret_at_else && ret_at_then; } parser_finished = true; if (!else_visited) error_raise("Expected 'ELSE', 'END' or a statement"); else error_raise("Expected 'END' or a statement"); return false; } /* static void parse_for() { char* previous_breaklabel = breaklabel; char* previous_contlabel = contlabel; EXPECT(TOKEN_IDENTIFIER, "Expected variable"); int ivar = get_variable_index(tkn_get_string()); tkn_next(); EXPECT(TOKEN_EQ, "Expected '='"); tkn_next(); parse_expression(); emmit(OP_STORE); emmit_w(ivar); char forlabel[8]; generate_anonymous_labelname(forlabel); char endlabel[8]; generate_anonymous_labelname(endlabel); char continuelabel[8]; generate_anonymous_labelname(continuelabel); breaklabel = endlabel; contlabel = continuelabel; register_label_address(forlabel); EXPECT(TOKEN_TO, "Expected 'TO'"); tkn_next(); parse_expression(); emmit(OP_LOAD); emmit_w(ivar); emmit(OP_EQ); emmit(OP_JTR); emmit_w(get_label_address(endlabel)); //int endLabel = GetCurrentAddress(); parse_statements(); EXPECT(TOKEN_END, "Expected 'END'"); tkn_next(); register_label_address(continuelabel); emmit(OP_LOAD); emmit_w(ivar); emmit(OP_INC); emmit(OP_STORE); emmit_w(ivar); emmit(OP_JMP); emmit_w(get_label_address(forlabel)); register_label_address(endlabel); //Patch(endLabel, GetCurrentAddress()); breaklabel = previous_breaklabel; contlabel = previous_contlabel; } static void parse_break() { if (breaklabel == nullptr) { parser_finished = true; error_raise("Can't break outside of a loop or condition"); return; } emmit(OP_JMP); emmit_w(get_label_address(breaklabel)); } static void parse_continue() { if (contlabel == nullptr) { parser_finished = true; error_raise("Can't continue outside of a loop"); return; } emmit(OP_JMP); emmit_w(get_label_address(contlabel)); } */ // XXX [RZC 27/04/2021] Ni GOTO ni GOSUB /*static void parse_goto() { emmit(OP_JMP); EXPECT(TOKEN_IDENTIFIER, "Expected label name"); emmit_w(get_label_address(tkn_get_string())); tkn_next(); } static void parse_gosub() { emmit(OP_JSR); EXPECT(TOKEN_IDENTIFIER, "Expected label name"); emmit_w(get_label_address(tkn_get_string())); tkn_next(); }*/ static void parse_return() { const int return_type = function_get_type(); if (return_type != -1) { if (return_type == 0) { parse_expression(); } else if (return_type == 1) { // TODO [RZC 04/05/2021] Falta gestionar tipus string } } emmit(OP_RET); } // XXX [RZC 27/04/2021] No hi ha labels /*static void parse_label() { register_label_address(tkn_get_string()); tkn_next(); }*/ /* static void parse_call() { for (int i = 0; i < num_external_functions; i++) { if (strcmp(external_functions[i].name, tkn_get_string()) == 0) { if (external_functions[i].num_parameters == -1) { tkn_next(); EXPECT(TOKEN_STRING, "Expected string"); emmit(OP_PUSH); emmit(register_string(tkn_get_string())); } else { tkn_next(); for (int j = 0; j < external_functions[i].num_parameters; j++) { //if (j != 0) EXPECT(TOKEN_COMMA, "Expected comma"); parse_expression(); } } emmit(OP_CALL); emmit(i); } } } */ static const bool parse_statements() { bool return_called = false; bool local_return = false; bool already_warned = false; while (!parser_finished) { current_line = tkn_get_line(); switch (tkn_get_token()) { case TOKEN_CONST: tkn_next(); if (local_return && !already_warned) { error_warning("Unreachable code"); already_warned = true; } parse_const(); break; case TOKEN_VAR: tkn_next(); if (local_return && !already_warned) { error_warning("Unreachable code"); already_warned = true; } parse_var(); break; case TOKEN_IF: tkn_next(); if (local_return && !already_warned) { error_warning("Unreachable code"); already_warned = true; } if (parse_if()) { return_called = true; } break; /* case TOKEN_FOR: tkn_next(); parse_for(); break; case TOKEN_BREAK: tkn_next(); parse_break(); break; case TOKEN_CONTINUE: tkn_next(); parse_continue(); break; */ case TOKEN_RETURN: tkn_next(); if (local_return && !already_warned) { error_warning("Unreachable code"); already_warned = true; } parse_return(); local_return = return_called = true; break; case TOKEN_REM: tkn_next(); break; /* case TOKEN_IDENTIFIER: for (int i = 0; i < num_external_functions; i++) { if (strcmp(external_functions[i].name, tkn_get_string()) == 0) { parse_call(); break; } } parse_let(); break; */ default: return return_called; } } return return_called; } static void parse_global_statements() { while (!parser_finished) { current_line = tkn_get_line(); switch (tkn_get_token()) { case TOKEN_CONST: tkn_next(); if (!global_closed) { parse_const(); } else { HALT("Global constants must be defined before functions"); } break; case TOKEN_VAR: tkn_next(); if (!global_closed) { parse_var(); } else { HALT("Global variables must be defined before functions"); } break; case TOKEN_STRUCT: tkn_next(); if (!global_closed) { parse_struct(); } else { HALT("Structs must be defined before functions") } break; case TOKEN_FUNCTION: tkn_next(); parse_function(); break; case TOKEN_REM: tkn_next(); break; case TOKEN_ENDFILE: return; default: HALT("Syntax error"); return; } } } // XXX [RZC 27/04/2021] No usat en JailBasic /*static void include_labels() { FILE *f = fopen("rom.lbl", "rb"); byte num_labels; fread(&num_labels, 1, 1, f); for (int i = 0; i < num_labels; i++) { word address; fread(&address, 2, 1, f); byte len; fread(&len, 1, 1, f); char label[50]; fread(label, len, 1, f); label[len] = 0; strcpy(known_labels[num_known_labels].name, label); known_labels[num_known_labels++].address = address; } fclose(f); }*/ /****************************************************************************************/ /* INTERFACE */ /****************************************************************************************/ void parser_parse(const char* buffer, byte* mem) { tkn_init(buffer); scope_init(); types_init(); parser_finished = false; //include_labels(); code = mem; codepos = 2; // XXX [RZC 27/04/2021] Perquè 2? tkn_next(); parse_global_statements(); //append_strings(); // XXX [RZC 27/04/2021] Encara vull açò? si el bytecode no ha de ser independent, no veig que faça falta if (error_raised()) { // XXX [RZC 27/04/2021] Res, per ara que printf el error i pete error_print(NULL); //codepos = 0xA000; //emmit(OP_JMP); //emmit_w(0xA000); } else { error_print_warnings(); decompiler_save(code, codepos); } //FILE *f = fopen("test.bin", "wb"); //fwrite(mem, codepos, 1, f); //fclose(f); //return code; } //const int parser_get_codesize() { return codepos; } //const int parser_get_memory_usage() { return num_variables; } //unsigned short* parser_get_lines() { return lines; } /* void parser_register_external_function(const char* name, const char* parameters, void (*fun)(void)) { strcpy(external_functions[num_external_functions].name, name); external_functions[num_external_functions++].num_parameters = num_parameters; } */