Tests started. Enabling constant declaration
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
|
|
||||||
.vscode
|
.vscode
|
||||||
|
*.exe
|
||||||
|
|||||||
21
main.cpp
Normal file
21
main.cpp
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#include "parser.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static unsigned char mem[65536];
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
|
||||||
|
FILE *f = fopen("test.vb", "rb");
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long fsize = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET); //same as rewind(f);
|
||||||
|
char *program = (char*)malloc(fsize + 1);
|
||||||
|
fread(program, fsize, 1, f);
|
||||||
|
fclose(f);
|
||||||
|
program[fsize] = 0;
|
||||||
|
parser_parse(program, mem);
|
||||||
|
free(program);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
110
parser.cpp
110
parser.cpp
@@ -1,5 +1,7 @@
|
|||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "tokenizer.h"
|
#include "tokenizer.h"
|
||||||
|
#include "scope.h"
|
||||||
|
#include "types.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -159,7 +161,7 @@ static const uint32_t get_current_address() {
|
|||||||
/****************************************************************************************/
|
/****************************************************************************************/
|
||||||
/* LABEL MANAGEMENT */
|
/* LABEL MANAGEMENT */
|
||||||
/****************************************************************************************/
|
/****************************************************************************************/
|
||||||
|
/*
|
||||||
static const word get_label_address(const char* string) {
|
static const word get_label_address(const char* string) {
|
||||||
for (int i = 0; i < num_known_labels; i++) { if (strcmp(known_labels[i].name, string) == 0) return known_labels[i].address; }
|
for (int i = 0; i < num_known_labels; i++) { if (strcmp(known_labels[i].name, string) == 0) return known_labels[i].address; }
|
||||||
//unknown_labels[num_unknown_labels].name = (char*)malloc(strlen(string) + 1);
|
//unknown_labels[num_unknown_labels].name = (char*)malloc(strlen(string) + 1);
|
||||||
@@ -205,54 +207,9 @@ static void register_label_address(const char* string) {
|
|||||||
static void generate_anonymous_labelname(char* dest) {
|
static void generate_anonymous_labelname(char* dest) {
|
||||||
int_to_string(num_anonymous_labels++, dest);
|
int_to_string(num_anonymous_labels++, dest);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/****************************************************************************************/
|
|
||||||
/* STRING MANAGEMENT */
|
|
||||||
/****************************************************************************************/
|
|
||||||
static const bool same_string(const unsigned char* a, const unsigned char*b) {
|
|
||||||
for (int i = 0; i <= a[0]; i++) if (a[i] != b[i]) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
static void copy_string(unsigned char* dest, const unsigned char* src) {
|
|
||||||
memcpy(dest, src, src[0] + 1);
|
|
||||||
//for (int i = 0; i <= src[0]; i++) dest[i] = src[i];
|
|
||||||
}
|
|
||||||
static void to_basic_string(unsigned char* dest, const char* src) {
|
|
||||||
int len = strlen(src);
|
|
||||||
*dest = len; dest++;
|
|
||||||
memcpy(dest, src, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int register_array(const unsigned char* string) {
|
|
||||||
for (int i = 0; i < num_strings; i++) {
|
|
||||||
if (same_string(strings[i].string, string)) { strings[i].references[strings[i].num_references++] = get_current_address(); return 0; }
|
|
||||||
}
|
|
||||||
copy_string(strings[num_strings].string, string);
|
|
||||||
strings[num_strings++].references[0] = get_current_address();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int register_string(const char* string) {
|
|
||||||
unsigned char new_str[255]; to_basic_string(new_str, string);
|
|
||||||
for (int i = 0; i < num_strings; i++) {
|
|
||||||
if (same_string(strings[i].string, new_str)) { strings[i].references[strings[i].num_references++] = get_current_address(); return 0; }
|
|
||||||
}
|
|
||||||
copy_string(strings[num_strings].string, new_str);
|
|
||||||
strings[num_strings++].references[0] = get_current_address();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void append_strings() {
|
|
||||||
code[0] = codepos & 255;
|
|
||||||
code[1] = codepos >> 8;
|
|
||||||
emmit(num_strings);
|
|
||||||
for (int i = 0; i < num_strings; i++) {
|
|
||||||
for (int j = 0; j < strings[i].num_references; j++) { patch(strings[i].references[j], get_current_address()); }
|
|
||||||
//char len = strings[i].string[0];
|
|
||||||
//emmit(len);
|
|
||||||
for (int j = 0; j <= strings[i].string[0]; j++) { emmit(strings[i].string[j]); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************************/
|
/****************************************************************************************/
|
||||||
/* PARSER */
|
/* PARSER */
|
||||||
@@ -274,7 +231,9 @@ static void parse_getcolor();
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define EXPECT(X, Y) if (tkn_get_token() != X) { parser_finished = true; error_raise(Y); return; }
|
#define EXPECT(X, Y) if (tkn_get_token() != X) { parser_finished = true; error_raise(Y); return; }
|
||||||
|
#define HALT(Y) { parser_finished = true; error_raise(Y); return; }
|
||||||
|
|
||||||
|
/*
|
||||||
static void parse_concat_atom() {
|
static void parse_concat_atom() {
|
||||||
if (tkn_get_token() == TOKEN_STRING) {
|
if (tkn_get_token() == TOKEN_STRING) {
|
||||||
emmit(OP_SETX);
|
emmit(OP_SETX);
|
||||||
@@ -316,6 +275,7 @@ static void parse_concatenation() {
|
|||||||
emmit(OP_CONCAT);
|
emmit(OP_CONCAT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
static void parse_expr_atom() {
|
static void parse_expr_atom() {
|
||||||
// NUM, VAR, UNARY, PAREN
|
// NUM, VAR, UNARY, PAREN
|
||||||
@@ -326,6 +286,17 @@ static void parse_expr_atom() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tkn_get_token() == TOKEN_IDENTIFIER) {
|
if (tkn_get_token() == TOKEN_IDENTIFIER) {
|
||||||
|
if (scope_variable_exists(tkn_get_string())) {
|
||||||
|
// [RZC 03/05/2021] TODO: Revisar si hi ha que navegar un struct o array
|
||||||
|
emmit(scope_is_local() ? OP_LDL : OP_LD);
|
||||||
|
emmit(scope_get_variable_address());
|
||||||
|
tkn_next();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// [RZC 03/05/2021] TODO: Revisar funcions
|
||||||
|
parser_finished = true; error_raise("Syntax error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
// [RZC 27/04/2021] Per ara llevem les constants
|
// [RZC 27/04/2021] Per ara llevem les constants
|
||||||
/*int constvalue = get_constant(tkn_get_string());
|
/*int constvalue = get_constant(tkn_get_string());
|
||||||
if (constvalue != -1) {
|
if (constvalue != -1) {
|
||||||
@@ -348,9 +319,6 @@ static void parse_expr_atom() {
|
|||||||
emmit(OP_LOAD);
|
emmit(OP_LOAD);
|
||||||
emmit_w(ivar);
|
emmit_w(ivar);
|
||||||
}*/
|
}*/
|
||||||
// [RZC 27/04/2021] Atenció! Ara les variables han de estar declarades abans, pel que pot haver error ací si no s'ha trobat.
|
|
||||||
tkn_next();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (tkn_get_token() == TOKEN_MINUS) {
|
if (tkn_get_token() == TOKEN_MINUS) {
|
||||||
tkn_next();
|
tkn_next();
|
||||||
@@ -449,14 +417,17 @@ static void parse_const() {
|
|||||||
tkn_next(); EXPECT(TOKEN_IDENTIFIER, "Expected type identifier");
|
tkn_next(); EXPECT(TOKEN_IDENTIFIER, "Expected type identifier");
|
||||||
char type_name[40];
|
char type_name[40];
|
||||||
strcpy(type_name, tkn_get_string());
|
strcpy(type_name, tkn_get_string());
|
||||||
|
const int type_num = types_exist(type_name);
|
||||||
|
if (type_num == -1) HALT("Unknown type");
|
||||||
|
const int var_address = scope_declare_variable(const_name, type_num, 0);
|
||||||
tkn_next(); EXPECT(TOKEN_EQ, "Expected '='");
|
tkn_next(); EXPECT(TOKEN_EQ, "Expected '='");
|
||||||
tkn_next(); EXPECT(TOKEN_NUMBER, "Expected integer constant");
|
tkn_next(); parse_expression();
|
||||||
int constvalue = tkn_get_value();
|
emmit(scope_is_local() ? OP_STL : OP_ST);
|
||||||
parser_register_constant(constname, constvalue);
|
emmit_dw(var_address);
|
||||||
tkn_next();
|
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];
|
||||||
strcpy(varname, tkn_get_string());
|
strcpy(varname, tkn_get_string());
|
||||||
@@ -465,7 +436,7 @@ static void parse_dim() {
|
|||||||
get_variable_index(varname, tkn_get_value()); // register variable with size, no need to keep ival
|
get_variable_index(varname, tkn_get_value()); // register variable with size, no need to keep ival
|
||||||
tkn_next(); EXPECT(TOKEN_RPAR, "Expected ')'");
|
tkn_next(); EXPECT(TOKEN_RPAR, "Expected ')'");
|
||||||
tkn_next();
|
tkn_next();
|
||||||
}
|
}*/
|
||||||
// [RZC 27/04/2021] Desactivat INC i DEC per ara
|
// [RZC 27/04/2021] Desactivat INC i DEC per ara
|
||||||
/*static void parse_inc() {
|
/*static void parse_inc() {
|
||||||
EXPECT(TOKEN_IDENTIFIER, "Expected variable");
|
EXPECT(TOKEN_IDENTIFIER, "Expected variable");
|
||||||
@@ -546,6 +517,7 @@ static void parse_dec() {
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
/*
|
||||||
static void parse_if() {
|
static void parse_if() {
|
||||||
char* previous_breaklabel = breaklabel;
|
char* previous_breaklabel = breaklabel;
|
||||||
parse_expression();
|
parse_expression();
|
||||||
@@ -636,6 +608,7 @@ static void parse_continue() {
|
|||||||
emmit(OP_JMP);
|
emmit(OP_JMP);
|
||||||
emmit_w(get_label_address(contlabel));
|
emmit_w(get_label_address(contlabel));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// [RZC 27/04/2021] Ni GOTO ni GOSUB
|
// [RZC 27/04/2021] Ni GOTO ni GOSUB
|
||||||
/*static void parse_goto() {
|
/*static void parse_goto() {
|
||||||
@@ -652,10 +625,12 @@ static void parse_gosub() {
|
|||||||
tkn_next();
|
tkn_next();
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
/*
|
||||||
static void parse_return() {
|
static void parse_return() {
|
||||||
// [RZC 27/04/2021] [TODO] Falta afegir paràmetre de retorn
|
// [RZC 27/04/2021] [TODO] Falta afegir paràmetre de retorn
|
||||||
emmit(OP_RET);
|
emmit(OP_RET);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// [RZC 27/04/2021] No hi ha labels
|
// [RZC 27/04/2021] No hi ha labels
|
||||||
/*static void parse_label() {
|
/*static void parse_label() {
|
||||||
@@ -663,6 +638,7 @@ static void parse_return() {
|
|||||||
tkn_next();
|
tkn_next();
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
/*
|
||||||
static void parse_call() {
|
static void parse_call() {
|
||||||
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) {
|
if (strcmp(external_functions[i].name, tkn_get_string()) == 0) {
|
||||||
@@ -702,10 +678,10 @@ static void parse_statements() {
|
|||||||
tkn_next(); parse_if(); break;
|
tkn_next(); parse_if(); break;
|
||||||
case TOKEN_FOR:
|
case TOKEN_FOR:
|
||||||
tkn_next(); parse_for(); break;
|
tkn_next(); parse_for(); break;
|
||||||
/*case TOKEN_BREAK:
|
case TOKEN_BREAK:
|
||||||
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:
|
||||||
@@ -722,21 +698,25 @@ static void parse_statements() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
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();
|
||||||
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_VAR:
|
/*case TOKEN_VAR:
|
||||||
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:
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
|
HALT("Syntax error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -767,6 +747,8 @@ static void parse_global_statements() {
|
|||||||
void parser_parse(const char* buffer, byte* mem) {
|
void parser_parse(const char* buffer, byte* mem) {
|
||||||
|
|
||||||
tkn_init(buffer);
|
tkn_init(buffer);
|
||||||
|
scope_init();
|
||||||
|
types_init();
|
||||||
parser_finished = false;
|
parser_finished = false;
|
||||||
//include_labels();
|
//include_labels();
|
||||||
code = mem;
|
code = mem;
|
||||||
@@ -774,7 +756,7 @@ void parser_parse(const char* buffer, byte* mem) {
|
|||||||
tkn_next();
|
tkn_next();
|
||||||
|
|
||||||
parse_global_statements();
|
parse_global_statements();
|
||||||
append_strings(); // [RZC 27/04/2021] [TODO] Encara vull açò? si el bytecode no ha de ser independent, no veig que faça falta
|
//append_strings(); // [RZC 27/04/2021] [TODO] Encara vull açò? si el bytecode no ha de ser independent, no veig que faça falta
|
||||||
|
|
||||||
if (error_raised()) { // [RZC 27/04/2021] Res, per ara que printf el error i pete
|
if (error_raised()) { // [RZC 27/04/2021] Res, per ara que printf el error i pete
|
||||||
error_print(NULL);
|
error_print(NULL);
|
||||||
@@ -790,11 +772,13 @@ void parser_parse(const char* buffer, byte* mem) {
|
|||||||
//return code;
|
//return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int parser_get_codesize() { return codepos; }
|
//const int parser_get_codesize() { return codepos; }
|
||||||
const int parser_get_memory_usage() { return num_variables; }
|
//const int parser_get_memory_usage() { return num_variables; }
|
||||||
unsigned short* parser_get_lines() { return lines; }
|
//unsigned short* parser_get_lines() { return lines; }
|
||||||
|
|
||||||
|
/*
|
||||||
void parser_register_external_function(const char* name, const char* parameters, void (*fun)(void)) {
|
void parser_register_external_function(const char* name, const char* parameters, void (*fun)(void)) {
|
||||||
strcpy(external_functions[num_external_functions].name, name);
|
strcpy(external_functions[num_external_functions].name, name);
|
||||||
external_functions[num_external_functions++].num_parameters = num_parameters;
|
external_functions[num_external_functions++].num_parameters = num_parameters;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|||||||
6
parser.h
6
parser.h
@@ -7,8 +7,10 @@ enum OPS {
|
|||||||
OP_DUP,
|
OP_DUP,
|
||||||
OP_SWAP,
|
OP_SWAP,
|
||||||
|
|
||||||
OP_LOAD,
|
OP_LD,
|
||||||
OP_STORE,
|
OP_ST,
|
||||||
|
OP_LDL,
|
||||||
|
OP_STL,
|
||||||
|
|
||||||
OP_JMP,
|
OP_JMP,
|
||||||
OP_JNT,
|
OP_JNT,
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ void scope_init() {
|
|||||||
are_we_inside_local = false;
|
are_we_inside_local = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool scope_is_local() {
|
||||||
|
return are_we_inside_local;
|
||||||
|
}
|
||||||
|
|
||||||
void scope_open_local() {
|
void scope_open_local() {
|
||||||
are_we_inside_local = true;
|
are_we_inside_local = true;
|
||||||
}
|
}
|
||||||
@@ -49,7 +53,7 @@ void scope_close_block() {
|
|||||||
while (local.variables.size() > size_before_block) local.variables.pop_back();
|
while (local.variables.size() > size_before_block) local.variables.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t scope_declare_variable(const std::string name, const int type, const int length) {
|
const int scope_declare_variable(const std::string name, const int type, const int length) {
|
||||||
t_scope& scope = (are_we_inside_local ? local : global);
|
t_scope& scope = (are_we_inside_local ? local : global);
|
||||||
if (are_we_inside_local) {
|
if (are_we_inside_local) {
|
||||||
for (int i = blocks.top(); i < scope.variables.size(); i++ ) if (scope.variables[i].name == name) return -1;
|
for (int i = blocks.top(); i < scope.variables.size(); i++ ) if (scope.variables[i].name == name) return -1;
|
||||||
@@ -69,6 +73,7 @@ const bool scope_variable_exists(const std::string name) {
|
|||||||
current_var = &v;
|
current_var = &v;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t scope_get_variable_address() {
|
const uint32_t scope_get_variable_address() {
|
||||||
|
|||||||
3
scope.h
3
scope.h
@@ -3,12 +3,13 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void scope_init();
|
void scope_init();
|
||||||
|
const bool scope_is_local();
|
||||||
void scope_open_local();
|
void scope_open_local();
|
||||||
const int scope_close_local();
|
const int scope_close_local();
|
||||||
void scope_open_block();
|
void scope_open_block();
|
||||||
void scope_close_block();
|
void scope_close_block();
|
||||||
|
|
||||||
const uint32_t scope_declare_variable(const std::string name, const int type, const int length);
|
const int scope_declare_variable(const std::string name, const int type, const int length);
|
||||||
|
|
||||||
const bool scope_variable_exists(const std::string name);
|
const bool scope_variable_exists(const std::string name);
|
||||||
const uint32_t scope_get_variable_address();
|
const uint32_t scope_get_variable_address();
|
||||||
|
|||||||
Reference in New Issue
Block a user