From 567710779ac1e65431376b0e401eebebee70650f Mon Sep 17 00:00:00 2001 From: Raimon Zamora Date: Tue, 4 May 2021 10:24:35 +0200 Subject: [PATCH] [BUG] Repaired types on some parameters. [FEAT] Implemented struct, still testing. [FEAT] Implemented var, still testing. --- .gitignore | 1 + parser.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++----- parser.h | 2 +- scope.cpp | 4 +-- scope.h | 2 +- test.vb | 8 +++++- tokenizer.cpp | 2 +- types.cpp | 16 +++++------ types.h | 8 +++--- variables.h | 6 ++--- 10 files changed, 96 insertions(+), 27 deletions(-) diff --git a/.gitignore b/.gitignore index 67fcd98..c07acba 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .vscode *.exe +jb diff --git a/parser.cpp b/parser.cpp index 679a8b7..3c3f150 100644 --- a/parser.cpp +++ b/parser.cpp @@ -218,7 +218,7 @@ static void generate_anonymous_labelname(char* dest) { static void parse_expression(); static void parse_statements(); -/* [RZC 27/04/2021] No usat en JailScript +/* [RZC 27/04/2021] No usat en JailBasic //static void parse_strleft(); static void parse_str(); static void parse_chr(); @@ -339,7 +339,7 @@ static void parse_expr_atom() { tkn_next(); return; } - // [RZC 27/04/2021] No usat en JailScript, pero hi haurà que afegir les funcions + // [RZC 27/04/2021] No usat en JailBasic, pero hi haurà que afegir les funcions /* if (tkn_get_token() == TOKEN_STRLEN) { tkn_next(); parse_strlen(); return; } if (tkn_get_token() == TOKEN_KEYPRESSED) { tkn_next(); parse_keypressed(); return; } @@ -409,17 +409,24 @@ static void parse_expression() { } } +static bool identifier_exists(const std::string identifier) { + if (scope_variable_exists(identifier)) return true; + if (types_exist(identifier) != -1) return true; + return false; +} + static void parse_const() { EXPECT(TOKEN_IDENTIFIER, "Expected identifier"); char const_name[40]; strcpy(const_name, tkn_get_string()); - if (scope_variable_exists(const_name)) HALT("Identifier already exists"); + if (identifier_exists(const_name)) 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); @@ -428,6 +435,61 @@ static void parse_const() { //tkn_next(); } +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)) 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"); // [RZC 04/05/2021] TODO: Només deuria acceptar enters. + var_length = tkn_get_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"); + char struct_name[40]; + strcpy(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) { + EXPECT(TOKEN_IDENTIFIER, "Expected identifier"); + char member_name[40]; + strcpy(member_name, tkn_get_string()); + tkn_next(); EXPECT(TOKEN_AS, "Expected 'as'"); + // [RZC 04/05/2021] TODO: Implement support for arrays + 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"); + types_add_member(struct_num, member_name, type_num, 1); + tkn_next(); + } + tkn_next(); +} + /*static void parse_dim() { EXPECT(TOKEN_IDENTIFIER, "Expected variable"); char varname[40]; @@ -706,11 +768,11 @@ static void parse_global_statements() { switch (tkn_get_token()) { case TOKEN_CONST: tkn_next(); parse_const(); break; - /*case TOKEN_VAR: + case TOKEN_VAR: tkn_next(); parse_var(); break; case TOKEN_STRUCT: tkn_next(); parse_struct(); break; - case TOKEN_FUNCTION: + /*case TOKEN_FUNCTION: tkn_next(); parse_function(); break;*/ case TOKEN_REM: tkn_next(); break; @@ -723,7 +785,7 @@ static void parse_global_statements() { } } -// [RZC 27/04/2021] No usat en JailScript +// [RZC 27/04/2021] No usat en JailBasic /*static void include_labels() { FILE *f = fopen("rom.lbl", "rb"); byte num_labels; diff --git a/parser.h b/parser.h index 9db0b0a..950b496 100644 --- a/parser.h +++ b/parser.h @@ -17,7 +17,7 @@ enum OPS { OP_JTR, OP_RET, OP_CALL, - OP_CALLEX, // AFEGIT PER A JAILSCRIPT + OP_CALLEX, // AFEGIT PER A JAILBASIC OP_ADD, OP_SUB, diff --git a/scope.cpp b/scope.cpp index afe50cd..60f0762 100644 --- a/scope.cpp +++ b/scope.cpp @@ -53,14 +53,14 @@ void scope_close_block() { while (local.variables.size() > size_before_block) local.variables.pop_back(); } -const int scope_declare_variable(const std::string name, const int type, const int length) { +const int scope_declare_variable(const std::string name, const uint32_t type, const uint32_t length) { t_scope& scope = (are_we_inside_local ? local : global); if (are_we_inside_local) { for (int i = blocks.top(); i < scope.variables.size(); i++ ) if (scope.variables[i].name == name) return -1; } else { for (t_variable v : scope.variables) if (v.name == name) return -1; } - const int address = scope.total_size; + const uint32_t address = scope.total_size; const t_variable var {name, type, length, address}; scope.variables.push_back(var); scope.total_size += types_get_length(type) + (length == 0 ? 1 : length); diff --git a/scope.h b/scope.h index 3b8a57a..9679447 100644 --- a/scope.h +++ b/scope.h @@ -9,7 +9,7 @@ const int scope_close_local(); void scope_open_block(); void scope_close_block(); -const int scope_declare_variable(const std::string name, const int type, const int length); +const int scope_declare_variable(const std::string name, const uint32_t type, const uint32_t length); const bool scope_variable_exists(const std::string name); const uint32_t scope_get_variable_address(); diff --git a/test.vb b/test.vb index 893a280..84cdab4 100644 --- a/test.vb +++ b/test.vb @@ -1,2 +1,8 @@ ' Esto es un comentario -const perico as number = 4-perico +struct point + x as number + y as number +end + +var peiv as point +const perico as number = 4-peiv diff --git a/tokenizer.cpp b/tokenizer.cpp index f2a12a8..9499fae 100644 --- a/tokenizer.cpp +++ b/tokenizer.cpp @@ -118,7 +118,7 @@ static void tkn_do_next() { if (CCHR == '%') { NEXT; current_token = TOKEN_MOD; return; } if (CCHR == 39) { NEXT; current_token = TOKEN_REM; while (CCHR != 0 && CCHR != 10) { NEXT; }; return; } - // Per a agafar numeros en hexadecimal o binari, heretat de PaCO, no se si li fa falta a JailScript + // Per a agafar numeros en hexadecimal o binari, heretat de PaCO, no se si li fa falta a JailBasic /*if (CCHR == '&') { NEXT; if ((CCHR | 32) == 'h') { diff --git a/types.cpp b/types.cpp index f7d693e..c817e2f 100644 --- a/types.cpp +++ b/types.cpp @@ -32,7 +32,7 @@ const int types_get_length(const uint32_t type) { return types[type].size; } -const int types_add_variable(const uint32_t type, const std::string name, const int var_type, const int length) { +const int types_add_member(const uint32_t type, const std::string name, const uint32_t var_type, const uint32_t length) { if (type >= types.size()) return -1; // ERROR INTERN: No deuria donar-se mai for (auto m : types[type].members) if (m.name == name) return -1; const t_variable new_var {name, var_type, length}; @@ -41,20 +41,20 @@ const int types_add_variable(const uint32_t type, const std::string name, const return types[type].members.size()-1; } -const int types_variable_exists(const uint32_t type, const std::string name) { +const int types_member_exists(const uint32_t type, const std::string name) { if (type >= types.size()) return -1; // ERROR INTERN: No deuria donar-se mai for (int i = 0; i < types[type].members.size(); i++) if (types[type].members[i].name == name) return i; return -1; } -const int types_get_variable_type(const uint32_t type, const uint32_t variable) { +const int types_get_member_type(const uint32_t type, const uint32_t member) { if (type >= types.size()) return -1; // ERROR INTERN: No deuria donar-se mai - if (variable >= types[type].members.size()) return -1; // ERROR INTERN: No deuria donar-se mai - return types[type].members[variable].type; + if (member >= types[type].members.size()) return -1; // ERROR INTERN: No deuria donar-se mai + return types[type].members[member].type; } -const int types_get_variable_length(const uint32_t type, const uint32_t variable) { +const int types_get_member_length(const uint32_t type, const uint32_t member) { if (type >= types.size()) return -1; // ERROR INTERN: No deuria donar-se mai - if (variable >= types[type].members.size()) return -1; // ERROR INTERN: No deuria donar-se mai - return types[type].members[variable].length; + if (member >= types[type].members.size()) return -1; // ERROR INTERN: No deuria donar-se mai + return types[type].members[member].length; } \ No newline at end of file diff --git a/types.h b/types.h index 7af3e28..a213a0e 100644 --- a/types.h +++ b/types.h @@ -7,7 +7,7 @@ const int types_add(const std::string name); const int types_exist(const std::string name); const int types_get_length(const uint32_t type); -const int types_add_variable(const uint32_t type, const std::string name, const uint32_t var_type, const int length); -const int types_variable_exists(const uint32_t type, const std::string name); -const int types_get_variable_type(const uint32_t type, const uint32_t variable); -const int types_get_variable_length(const uint32_t type, const uint32_t variable); +const int types_add_member(const uint32_t type, const std::string name, const uint32_t var_type, const uint32_t length); +const int types_member_exists(const uint32_t type, const std::string name); +const int types_get_member_type(const uint32_t type, const uint32_t member); +const int types_get_member_length(const uint32_t type, const uint32_t member); diff --git a/variables.h b/variables.h index 3bddd4c..852d21b 100644 --- a/variables.h +++ b/variables.h @@ -2,7 +2,7 @@ struct t_variable { std::string name; - int type; - int length; - int address; + uint32_t type; + uint32_t length; + uint32_t address; };