Started implementation of function parsing
This commit is contained in:
57
function.cpp
Normal file
57
function.cpp
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#include "function.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct t_parameter {
|
||||||
|
std::string name;
|
||||||
|
uint32_t type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct t_function {
|
||||||
|
std::string name;
|
||||||
|
uint32_t address;
|
||||||
|
uint32_t type;
|
||||||
|
std::vector<t_parameter> parameters;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::vector<t_function> functions;
|
||||||
|
static int current_function = -1;
|
||||||
|
|
||||||
|
const bool function_register(const std::string name, const uint32_t address) {
|
||||||
|
for (auto f : functions) if (f.name == name) return false;
|
||||||
|
functions.push_back({name, address});
|
||||||
|
current_function = functions.size()-1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void function_set_type(const uint32_t type) {
|
||||||
|
functions[current_function].type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int function_get_type() {
|
||||||
|
return functions[current_function].type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool function_parameter_add(const std::string name, const uint32_t type) {
|
||||||
|
for (auto p : functions[current_function].parameters) if (p.name == name) return false;
|
||||||
|
functions[current_function].parameters.push_back({name, type});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool function_exists(const std::string name) {
|
||||||
|
for (auto f : functions) if (f.name == name) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t function_get_address(const std::string name) {
|
||||||
|
for (auto f : functions) if (f.name == name) return f.address;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int function_get_num_parameters() {
|
||||||
|
return functions[current_function].parameters.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
const int function_get_parameter_type(const int index) {
|
||||||
|
return functions[current_function].parameters[index].type;
|
||||||
|
}
|
||||||
13
function.h
13
function.h
@@ -5,8 +5,17 @@
|
|||||||
// Register a new function. Returns false if a function with the same name already exists
|
// Register a new function. Returns false if a function with the same name already exists
|
||||||
const bool function_register(const std::string name, const uint32_t address);
|
const bool function_register(const std::string name, const uint32_t address);
|
||||||
|
|
||||||
// Add a parameter to the last registered function
|
// Set the return type of the last searched function
|
||||||
void function_parameter_add(const std::string name, const int type);
|
void function_set_type(const uint32_t type);
|
||||||
|
|
||||||
|
// Get the return type of the last searched function or -1 if none
|
||||||
|
const int function_get_type();
|
||||||
|
|
||||||
|
// Add a parameter to the last registered function, returns false if there's a parameter already named like that
|
||||||
|
const bool function_parameter_add(const std::string name, const uint32_t type);
|
||||||
|
|
||||||
|
// Check if there's a function with that name
|
||||||
|
const bool function_exists(const std::string name);
|
||||||
|
|
||||||
|
|
||||||
// Retrieve the address of the specified function, or zero if there's no such function
|
// Retrieve the address of the specified function, or zero if there's no such function
|
||||||
|
|||||||
89
parser.cpp
89
parser.cpp
@@ -2,11 +2,13 @@
|
|||||||
#include "tokenizer.h"
|
#include "tokenizer.h"
|
||||||
#include "scope.h"
|
#include "scope.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "function.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
#define MAX_CODE_SIZE 65536
|
#define MAX_CODE_SIZE 65536
|
||||||
#define MAX_LABELS 256
|
#define MAX_LABELS 256
|
||||||
@@ -417,6 +419,7 @@ static void parse_expression() {
|
|||||||
static bool identifier_exists(const std::string identifier) {
|
static bool identifier_exists(const std::string identifier) {
|
||||||
if (scope_variable_exists(identifier)) return true;
|
if (scope_variable_exists(identifier)) return true;
|
||||||
if (types_exist(identifier) != -1) return true;
|
if (types_exist(identifier) != -1) return true;
|
||||||
|
if (function_exists(identifier)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,8 +477,7 @@ static void parse_var() {
|
|||||||
|
|
||||||
static void parse_struct() {
|
static void parse_struct() {
|
||||||
EXPECT(TOKEN_IDENTIFIER, "Expected identifier");
|
EXPECT(TOKEN_IDENTIFIER, "Expected identifier");
|
||||||
char struct_name[40];
|
const std::string struct_name = tkn_get_string();
|
||||||
strcpy(struct_name, tkn_get_string());
|
|
||||||
if (identifier_exists(struct_name)) HALT("Identifier already exists");
|
if (identifier_exists(struct_name)) HALT("Identifier already exists");
|
||||||
const int struct_num = types_add(struct_name);
|
const int struct_num = types_add(struct_name);
|
||||||
tkn_next();
|
tkn_next();
|
||||||
@@ -485,7 +487,6 @@ static void parse_struct() {
|
|||||||
char member_name[40];
|
char member_name[40];
|
||||||
strcpy(member_name, tkn_get_string());
|
strcpy(member_name, tkn_get_string());
|
||||||
tkn_next(); EXPECT(TOKEN_AS, "Expected 'as'");
|
tkn_next(); EXPECT(TOKEN_AS, "Expected 'as'");
|
||||||
// TODO [RZC 04/05/2021] Implement support for arrays
|
|
||||||
tkn_next();
|
tkn_next();
|
||||||
if (tkn_get_token() == TOKEN_ARRAY) {
|
if (tkn_get_token() == TOKEN_ARRAY) {
|
||||||
tkn_next(); EXPECT(TOKEN_OF, "Expected 'of'");
|
tkn_next(); EXPECT(TOKEN_OF, "Expected 'of'");
|
||||||
@@ -495,8 +496,7 @@ static void parse_struct() {
|
|||||||
tkn_next();
|
tkn_next();
|
||||||
}
|
}
|
||||||
EXPECT(TOKEN_IDENTIFIER, "Expected type identifier");
|
EXPECT(TOKEN_IDENTIFIER, "Expected type identifier");
|
||||||
char type_name[40];
|
const std::string type_name = tkn_get_string();
|
||||||
strcpy(type_name, tkn_get_string());
|
|
||||||
const int type_num = types_exist(type_name);
|
const int type_num = types_exist(type_name);
|
||||||
if (type_num == -1) HALT("Unknown type");
|
if (type_num == -1) HALT("Unknown type");
|
||||||
types_add_member(struct_num, member_name, type_num, member_length);
|
types_add_member(struct_num, member_name, type_num, member_length);
|
||||||
@@ -505,6 +505,51 @@ static void parse_struct() {
|
|||||||
tkn_next();
|
tkn_next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_function() {
|
||||||
|
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<uint32_t> 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();
|
||||||
|
}
|
||||||
|
parse_statements();
|
||||||
|
scope_close_local();
|
||||||
|
EXPECT(TOKEN_END, "Expected statement or 'end'");
|
||||||
|
tkn_next();
|
||||||
|
}
|
||||||
|
|
||||||
/*static void parse_dim() {
|
/*static void parse_dim() {
|
||||||
EXPECT(TOKEN_IDENTIFIER, "Expected variable");
|
EXPECT(TOKEN_IDENTIFIER, "Expected variable");
|
||||||
char varname[40];
|
char varname[40];
|
||||||
@@ -703,12 +748,19 @@ static void parse_gosub() {
|
|||||||
tkn_next();
|
tkn_next();
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/*
|
|
||||||
static void parse_return() {
|
static void parse_return() {
|
||||||
// TODO [RZC 27/04/2021] Falta afegir paràmetre de retorn
|
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);
|
emmit(OP_RET);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// XXX [RZC 27/04/2021] No hi ha labels
|
// XXX [RZC 27/04/2021] No hi ha labels
|
||||||
/*static void parse_label() {
|
/*static void parse_label() {
|
||||||
@@ -737,21 +789,16 @@ static void parse_call() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
static void parse_statements() {
|
static void parse_statements() {
|
||||||
while (!parser_finished) {
|
while (!parser_finished) {
|
||||||
current_line = tkn_get_line();
|
current_line = tkn_get_line();
|
||||||
switch (tkn_get_token()) {
|
switch (tkn_get_token()) {
|
||||||
case TOKEN_CONST:
|
case TOKEN_CONST:
|
||||||
tkn_next(); parse_const(); break;
|
tkn_next(); parse_const(); break;
|
||||||
case TOKEN_DIM:
|
case TOKEN_VAR:
|
||||||
tkn_next(); parse_dim(); break;
|
tkn_next(); parse_var(); break;
|
||||||
case TOKEN_LET:
|
/*
|
||||||
tkn_next(); parse_let(); break;
|
|
||||||
case TOKEN_INC:
|
|
||||||
tkn_next(); parse_inc(); break;
|
|
||||||
case TOKEN_DEC:
|
|
||||||
tkn_next(); parse_dec(); break;
|
|
||||||
case TOKEN_IF:
|
case TOKEN_IF:
|
||||||
tkn_next(); parse_if(); break;
|
tkn_next(); parse_if(); break;
|
||||||
case TOKEN_FOR:
|
case TOKEN_FOR:
|
||||||
@@ -760,23 +807,25 @@ static void parse_statements() {
|
|||||||
tkn_next(); parse_break(); break;
|
tkn_next(); parse_break(); break;
|
||||||
case TOKEN_CONTINUE:
|
case TOKEN_CONTINUE:
|
||||||
tkn_next(); parse_continue(); break;
|
tkn_next(); parse_continue(); break;
|
||||||
|
*/
|
||||||
case TOKEN_RETURN:
|
case TOKEN_RETURN:
|
||||||
tkn_next(); parse_return(); break;
|
tkn_next(); parse_return(); break;
|
||||||
case TOKEN_REM:
|
case TOKEN_REM:
|
||||||
tkn_next(); break;
|
tkn_next(); break;
|
||||||
|
|
||||||
|
/*
|
||||||
case TOKEN_IDENTIFIER:
|
case TOKEN_IDENTIFIER:
|
||||||
for (int i = 0; i < num_external_functions; i++) {
|
for (int i = 0; i < num_external_functions; i++) {
|
||||||
if (strcmp(external_functions[i].name, tkn_get_string()) == 0) { parse_call(); break; }
|
if (strcmp(external_functions[i].name, tkn_get_string()) == 0) { parse_call(); break; }
|
||||||
}
|
}
|
||||||
parse_let(); break;
|
parse_let(); break;
|
||||||
|
*/
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
|
||||||
static void parse_global_statements() {
|
static void parse_global_statements() {
|
||||||
while (!parser_finished) {
|
while (!parser_finished) {
|
||||||
current_line = tkn_get_line();
|
current_line = tkn_get_line();
|
||||||
@@ -787,8 +836,8 @@ static void parse_global_statements() {
|
|||||||
tkn_next(); parse_var(); break;
|
tkn_next(); parse_var(); break;
|
||||||
case TOKEN_STRUCT:
|
case TOKEN_STRUCT:
|
||||||
tkn_next(); parse_struct(); break;
|
tkn_next(); parse_struct(); break;
|
||||||
/*case TOKEN_FUNCTION:
|
case TOKEN_FUNCTION:
|
||||||
tkn_next(); parse_function(); break;*/
|
tkn_next(); parse_function(); break;
|
||||||
case TOKEN_REM:
|
case TOKEN_REM:
|
||||||
tkn_next(); break;
|
tkn_next(); break;
|
||||||
case TOKEN_ENDFILE:
|
case TOKEN_ENDFILE:
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const bool scope_is_local() {
|
|||||||
|
|
||||||
void scope_open_local() {
|
void scope_open_local() {
|
||||||
are_we_inside_local = true;
|
are_we_inside_local = true;
|
||||||
|
blocks.push(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int scope_close_local() {
|
const int scope_close_local() {
|
||||||
@@ -37,6 +38,7 @@ const int scope_close_local() {
|
|||||||
// Malament, no havem tancat algún block. No se si es detectarà abans per altra part. Per ara anem a deixar este comentari.
|
// Malament, no havem tancat algún block. No se si es detectarà abans per altra part. Per ara anem a deixar este comentari.
|
||||||
}
|
}
|
||||||
const int return_value = local.total_size;
|
const int return_value = local.total_size;
|
||||||
|
while (!blocks.empty()) blocks.pop();
|
||||||
local.variables.clear();
|
local.variables.clear();
|
||||||
local.total_size = 0;
|
local.total_size = 0;
|
||||||
are_we_inside_local = false;
|
are_we_inside_local = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user