From a724ddbe1c8c53acd8b2836e437237cf17c57043 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 22 Jan 2020 03:03:37 +0100 Subject: Use macro return_if_error instead of if-statement everywhere --- Makefile | 4 +- include/parser.h | 8 ++- src/bytecode.c | 4 +- src/parser.c | 198 +++++++++++++++++++++++++++-------------------------- src/std/hash_map.c | 5 -- 5 files changed, 111 insertions(+), 108 deletions(-) diff --git a/Makefile b/Makefile index 399128b..15de48f 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -CFLAGS = -Wall -Wextra -g3 -ansi -pedantic -fPIE -LIBS = -Wl,-Bdynamic -lcurl +CFLAGS = -Wall -Wextra -Werror -g3 -std=c89 -pedantic -fPIE +LIBS = -lgc OBJ = build/main.o build/tokenizer.o build/parser.o build/bytecode.o build/buffer.o build/hash_map.o CC = cc diff --git a/include/parser.h b/include/parser.h index d130597..b915dfd 100644 --- a/include/parser.h +++ b/include/parser.h @@ -3,7 +3,11 @@ #include "tokenizer.h" -/* Returns 0 on success */ -int tsl_parse(const char *code, size_t code_size); +typedef enum { + TSL_PARSE_RESULT_ERR, + TSL_PARSE_RESULT_OK +} TslParseResult; + +TslParseResult tsl_parse(const char *code, size_t code_size); #endif /* TSL_PARSER_H */ diff --git a/src/bytecode.c b/src/bytecode.c index a0b5406..9406852 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -1,5 +1,6 @@ #include "../include/bytecode.h" #include +#include void tsl_bytecode_writer_init(TslBytecodeWriter *self) { tsl_buffer_init(&self->buffer); @@ -17,6 +18,7 @@ void tsl_bytecode_writer_reset_register_counter(TslBytecodeWriter *self) { TslRegister tsl_bytecode_writer_get_unique_register(TslBytecodeWriter *self) { if(self->register_counter < INT16_MAX) return self->register_counter++; + fprintf(stderr, "Error: Too many variables in the same scope\n"); return -1; } @@ -28,7 +30,7 @@ int tsl_bytecode_writer_load_number(TslBytecodeWriter *self, TslRegister dst, do return tsl_buffer_append(&self->buffer, &instruction, sizeof(instruction)); } -tsl_bytecode_writer_mov_reg(TslBytecodeWriter *self, TslRegister dst, TslRegister src) { +int tsl_bytecode_writer_mov_reg(TslBytecodeWriter *self, TslRegister dst, TslRegister src) { TslInstructionType2 instruction; instruction.opcode = TSL_OPCODE_MOV_REG; instruction.dst_reg = dst; diff --git a/src/parser.c b/src/parser.c index be3461c..bad630e 100644 --- a/src/parser.c +++ b/src/parser.c @@ -2,6 +2,13 @@ #include "../include/bytecode.h" #include "../include/std/hash_map.h" #include +#include + +#define return_if_error(expr) \ + { \ + if(!(expr)) \ + return TSL_PARSE_RESULT_ERR;\ + } typedef struct { TslTokenizer tokenizer; @@ -9,8 +16,8 @@ typedef struct { TslHashMap variables; } TslParser; -static int tsl_parser_parse_rhs(TslParser *self); -static int tsl_parser_parse_expressions(TslParser *self, TslToken end_token); +static TslParseResult tsl_parser_parse_rhs(TslParser *self, TslRegister *reg_result); +static TslParseResult tsl_parser_parse_expressions(TslParser *self, TslToken end_token); static void tsl_parser_init(TslParser *self, const char *code, size_t code_size) { tsl_tokenizer_init(&self->tokenizer, code, code_size); @@ -23,6 +30,7 @@ static void tsl_parser_deinit(TslParser *self) { tsl_hash_map_deinit(&self->variables); } +#if 0 static uint64_t hash_string_view(const void *data, size_t size) { uint64_t result = 0xdec05eba; const uint8_t *p = data; @@ -33,27 +41,27 @@ static uint64_t hash_string_view(const void *data, size_t size) { } return result; } +#endif -static int tsl_parser_parse_map(TslParser *self) { - #define parse_map_element_separator \ - if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_COLON)) \ - return -1; \ - if(tsl_parser_parse_rhs(self) != 0) \ - return -1; \ - token = tsl_tokenizer_next(&self->tokenizer); \ - if(token == TSL_TOKEN_COMMA) { \ - continue; \ - } else if(token == TSL_TOKEN_RBRACE) { \ - return 0; \ - } else { \ - fprintf(stderr, "Error: Expected ',' or '}', got TODO\n"); \ - return -1; \ +static TslParseResult tsl_parser_parse_map(TslParser *self) { + TslRegister src_reg; + #define parse_map_element_separator \ + return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_COLON)); \ + return_if_error(tsl_parser_parse_rhs(self, &src_reg)); \ + token = tsl_tokenizer_next(&self->tokenizer); \ + if(token == TSL_TOKEN_COMMA) { \ + continue; \ + } else if(token == TSL_TOKEN_RBRACE) { \ + return TSL_PARSE_RESULT_OK; \ + } else { \ + fprintf(stderr, "Error: Expected ',' or '}', got TODO\n"); \ + return TSL_PARSE_RESULT_ERR; \ } for(;;) { TslToken token = tsl_tokenizer_next(&self->tokenizer); if(token == TSL_TOKEN_NUM) { - printf("rhs num: %ld\n", self->tokenizer.number_value); + printf("rhs num: %f\n", self->tokenizer.number_value); parse_map_element_separator } else if(token == TSL_TOKEN_BOOL) { printf("rhs bool: %s\n", self->tokenizer.bool_value ? "true" : "false"); @@ -62,37 +70,37 @@ static int tsl_parser_parse_map(TslParser *self) { printf("rhs null\n"); parse_map_element_separator } else if(token == TSL_TOKEN_STRING) { - printf("rhs string: |%.*s|\n", self->tokenizer.string.size, self->tokenizer.string.data); + printf("rhs string: |%.*s|\n", (int)self->tokenizer.string.size, self->tokenizer.string.data); parse_map_element_separator } else if(token == TSL_TOKEN_RBRACE) { /* '}' after trailing ',' or an empty map */ - return 0; + return TSL_PARSE_RESULT_OK; } else { fprintf(stderr, "Error: Expected '}', got TODO\n"); - return -1; + return TSL_PARSE_RESULT_ERR; } token = tsl_tokenizer_next(&self->tokenizer); } } -static int tsl_parser_parse_list(TslParser *self) { +static TslParseResult tsl_parser_parse_list(TslParser *self) { #define parse_list_element_separator \ token = tsl_tokenizer_next(&self->tokenizer); \ if(token == TSL_TOKEN_COMMA) { \ continue; \ } else if(token == TSL_TOKEN_RBRACKET) { \ - return 0; \ + return TSL_PARSE_RESULT_OK; \ } else { \ fprintf(stderr, "Error: Expected ',' or ']', got TODO\n"); \ - return -1; \ + return TSL_PARSE_RESULT_ERR; \ } for(;;) { /* TODO: Use tsl_parser_parse_rhs instead */ TslToken token = tsl_tokenizer_next(&self->tokenizer); if(token == TSL_TOKEN_NUM) { - printf("rhs num: %ld\n", self->tokenizer.number_value); + printf("rhs num: %f\n", self->tokenizer.number_value); parse_list_element_separator } else if(token == TSL_TOKEN_BOOL) { printf("rhs bool: %s\n", self->tokenizer.bool_value ? "true" : "false"); @@ -101,36 +109,34 @@ static int tsl_parser_parse_list(TslParser *self) { printf("rhs null\n"); parse_list_element_separator } else if(token == TSL_TOKEN_STRING) { - printf("rhs string: |%.*s|\n", self->tokenizer.string.size, self->tokenizer.string.data); + printf("rhs string: |%.*s|\n", (int)self->tokenizer.string.size, self->tokenizer.string.data); parse_list_element_separator } else if(token == TSL_TOKEN_RBRACKET) { /* ']' after trailing ',' or an empty list */ - return 0; + return TSL_PARSE_RESULT_OK; } else { fprintf(stderr, "Error: Expected '}', got TODO\n"); - return -1; + return TSL_PARSE_RESULT_ERR; } } } /* FN_BODY = '{' EXPRS '}' */ -static int tsl_parser_parse_fn_body(TslParser *self) { - if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LBRACE)) - return -1; +static TslParseResult tsl_parser_parse_fn_body(TslParser *self) { + return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LBRACE)); return tsl_parser_parse_expressions(self, TSL_TOKEN_RBRACE); } /* FN = '(' (IDENTIFIER ',')* ')' FN_BODY */ -static int tsl_parser_parse_fn(TslParser *self) { - if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LPAREN)) - return -1; - +static TslParseResult tsl_parser_parse_fn(TslParser *self) { + return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LPAREN)); for(;;) { TslToken token = tsl_tokenizer_next(&self->tokenizer); if(token == TSL_TOKEN_RPAREN) { return tsl_parser_parse_fn_body(self); } else if(token == TSL_TOKEN_IDENTIFIER) { TslStringView param_name = self->tokenizer.identifier; + printf("function parameter: |%.*s|\n", (int)param_name.size, param_name.data); token = tsl_tokenizer_next(&self->tokenizer); if(token == TSL_TOKEN_COMMA) { continue; @@ -138,50 +144,42 @@ static int tsl_parser_parse_fn(TslParser *self) { return tsl_parser_parse_fn_body(self); } else { fprintf(stderr, "Error: Expected ',' or ')', got TODO\n"); - return -1; + return TSL_PARSE_RESULT_ERR; } } else { fprintf(stderr, "Error: Expected parameter name or ')', got TODO\n"); - return -1; + return TSL_PARSE_RESULT_ERR; } } } /* VAR_INDEX = '[' RHS ']' */ -static int tsl_parser_parse_var_indexing(TslParser *self) { - if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LBRACKET)) - return -1; - - if(tsl_parser_parse_rhs(self) != 0) - return -1; - - if(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_RBRACKET)) - return 0; - else - return -1; +static TslParseResult tsl_parser_parse_var_indexing(TslParser *self) { + TslRegister src_reg; + return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LBRACKET)); + return_if_error(tsl_parser_parse_rhs(self, &src_reg)); + return tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_RBRACKET); } /* FUNC_CALL = '(' (RHS ',')* ')' */ -static int tsl_parser_parse_func_call(TslParser *self) { - if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LPAREN)) - return -1; - +static TslParseResult tsl_parser_parse_func_call(TslParser *self) { + return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LPAREN)); for(;;) { TslToken token = tsl_tokenizer_peek(&self->tokenizer); if(token == TSL_TOKEN_RPAREN) { tsl_tokenizer_consume_peek(&self->tokenizer); /* consume previous TSL_TOKEN_RPAREN */ - return 0; + return TSL_PARSE_RESULT_OK; } else { - if(tsl_parser_parse_rhs(self) != 0) - return -1; + TslRegister src_reg; + return_if_error(tsl_parser_parse_rhs(self, &src_reg)); token = tsl_tokenizer_next(&self->tokenizer); if(token == TSL_TOKEN_COMMA) { continue; } else if(token == TSL_TOKEN_RPAREN) { - return 0; + return TSL_PARSE_RESULT_OK; } else { fprintf(stderr, "Error: Expected ',' or ')', got TODO\n"); - return -1; + return TSL_PARSE_RESULT_ERR; } } } @@ -190,140 +188,144 @@ static int tsl_parser_parse_func_call(TslParser *self) { /* TODO: Do not allow empty command */ /* TODO: Allow command inside another command */ /* COMMAND = TODO */ -static int tsl_parser_parse_command(TslParser *self) { - if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LPAREN)) - return -1; - +static TslParseResult tsl_parser_parse_command(TslParser *self) { + return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LPAREN)); for(;;) { TslStringView command_arg; TslCommandToken command_token = tsl_tokenizer_next_command_arg(&self->tokenizer, &command_arg); if(command_token == TSL_COMMAND_TOKEN_ARG) { printf("command arg: |%.*s|\n", (int)command_arg.size, command_arg.data); } else if(command_token == TSL_COMMAND_TOKEN_END) { - return 0; + return TSL_PARSE_RESULT_OK; } else { fprintf(stderr, "Error: Expected command argument or ')', got TODO\n"); - return -1; + return TSL_PARSE_RESULT_ERR; } } } /* RHS_SUB = (VAR_INDEX|FUNC_CALL RHS_SUB?)|(TOKEN_ARITHMETIC RHS) */ -static int tsl_parser_parse_rhs_sub(TslParser *self) { +static TslParseResult tsl_parser_parse_rhs_sub(TslParser *self) { TslToken token = tsl_tokenizer_peek(&self->tokenizer); if(token == TSL_TOKEN_LBRACKET) { - if(tsl_parser_parse_var_indexing(self) != 0) - return -1; + return_if_error(tsl_parser_parse_var_indexing(self)); return tsl_parser_parse_rhs_sub(self); } else if(token == TSL_TOKEN_LPAREN) { - if(tsl_parser_parse_func_call(self) != 0) - return -1; + return_if_error(tsl_parser_parse_func_call(self)); return tsl_parser_parse_rhs_sub(self); } else if(token == TSL_TOKEN_ARITHMETIC) { + TslRegister src_reg; tsl_tokenizer_consume_peek(&self->tokenizer); /* consume previous TSL_TOKEN_ARITHMETIC */ printf("rhs sub arithmetic symbol: %c\n", self->tokenizer.arithmetic_symbol); /* TODO: Handle arithmetic expression precedence */ - return tsl_parser_parse_rhs(self); + return tsl_parser_parse_rhs(self, &src_reg); } /* No sub expression found, possibly a new expression after this (a new expression on a new line), let that part of the code handle error if there is any instead. */ - return 0; + return TSL_PARSE_RESULT_OK; } /* RHS_SUB_ARITHMETIC = TOKEN_ARITHMETIC RHS */ -static int tsl_parser_parse_rhs_sub_arithmetic(TslParser *self) { +static TslParseResult tsl_parser_parse_rhs_sub_arithmetic(TslParser *self) { TslToken token = tsl_tokenizer_peek(&self->tokenizer); if(token == TSL_TOKEN_ARITHMETIC) { + TslRegister src_reg; tsl_tokenizer_consume_peek(&self->tokenizer); /* consume previous TSL_TOKEN_ARITHMETIC */ printf("rhs sub arithmetic symbol: %c\n", self->tokenizer.arithmetic_symbol); /* TODO: Handle arithmetic expression precedence */ - return tsl_parser_parse_rhs(self); + return tsl_parser_parse_rhs(self, &src_reg); } /* No sub expression found, possibly a new expression after this (a new expression on a new line), let that part of the code handle error if there is any instead. */ - return 0; + return TSL_PARSE_RESULT_OK; } /* RHS = (IDENTIFIER|NUM|BOOL|NULL|STRING|MAP|LIST|('fn' FN)|('$' COMMAND)) RHS_SUB? */ -int tsl_parser_parse_rhs(TslParser *self) { +TslParseResult tsl_parser_parse_rhs(TslParser *self, TslRegister *reg_result) { TslToken token = tsl_tokenizer_next(&self->tokenizer); if(token == TSL_TOKEN_IDENTIFIER) { TslStringView var_name = self->tokenizer.identifier; + assert(0 && "TODO: Implement"); printf("rhs var: %.*s\n", (int)var_name.size, var_name.data); return tsl_parser_parse_rhs_sub(self); } else if(token == TSL_TOKEN_NUM) { - TslRegister dst_reg = tsl_bytecode_writer_get_unique_register(&self->bytecode_writer); - if(dst_reg == -1) { + *reg_result = tsl_bytecode_writer_get_unique_register(&self->bytecode_writer); + if(*reg_result == -1) { fprintf(stderr, "Error: Too many registers used\n"); - return -1; + return TSL_PARSE_RESULT_ERR; } - if(!tsl_bytecode_writer_load_number(&self->bytecode_writer, dst_reg, self->tokenizer.number_value)) - return -1; - + return_if_error(tsl_bytecode_writer_load_number(&self->bytecode_writer, *reg_result, self->tokenizer.number_value)); printf("rhs num: %f\n", self->tokenizer.number_value); return tsl_parser_parse_rhs_sub_arithmetic(self); } else if(token == TSL_TOKEN_BOOL) { + assert(0 && "TODO: Implement"); printf("rhs bool: %s\n", self->tokenizer.bool_value ? "true" : "false"); } else if(token == TSL_TOKEN_NULL) { + assert(0 && "TODO: Implement"); printf("rhs null\n"); } else if(token == TSL_TOKEN_STRING) { - printf("rhs string: |%.*s|\n", self->tokenizer.string.size, self->tokenizer.string.data); + assert(0 && "TODO: Implement"); + printf("rhs string: |%.*s|\n", (int)self->tokenizer.string.size, self->tokenizer.string.data); } else if(token == TSL_TOKEN_LBRACE) { + assert(0 && "TODO: Implement"); return tsl_parser_parse_map(self); } else if(token == TSL_TOKEN_LBRACKET) { + assert(0 && "TODO: Implement"); return tsl_parser_parse_list(self); } else if(token == TSL_TOKEN_FN) { + assert(0 && "TODO: Implement"); return tsl_parser_parse_fn(self); } else if(token == TSL_TOKEN_DOLLAR_SIGN) { + assert(0 && "TODO: Implement"); return tsl_parser_parse_command(self); } else { fprintf(stderr, "Error: Expected variable, number, bool, null, map, list, function or command, got TODO (%d) (line: %d)\n", token, tsl_tokenizer_get_line_by_index(&self->tokenizer, self->tokenizer.prev_code_index)); - return -1; + return TSL_PARSE_RESULT_ERR; } - return 0; + return TSL_PARSE_RESULT_OK; } /* EXPR = IDENTIFIER ('=' RHS)|RHS_SUB EXPRS = EXPR* */ -int tsl_parser_parse_expressions(TslParser *self, TslToken end_token) { +TslParseResult tsl_parser_parse_expressions(TslParser *self, TslToken end_token) { for(;;) { TslToken token = tsl_tokenizer_next(&self->tokenizer); if(token == TSL_TOKEN_IDENTIFIER) { TslStringView identifier = self->tokenizer.identifier; - printf("identifier: %.*s\n", identifier.size, identifier.data); + printf("identifier: %.*s\n", (int)identifier.size, identifier.data); if(tsl_tokenizer_peek(&self->tokenizer) == TSL_TOKEN_EQUAL) { - void *existing_variable = tsl_hash_map_get(&self->variables, &identifier, hash_string_view); - if(!existing_variable) { - fprintf(stderr, "Variable declaration: %.*s\n", identifier.size, identifier.data); - if(!tsl_hash_map_insert(&self->variables, &identifier, "a", 1, hash_string_view)) - return -1; - } + TslRegister dst_reg; + TslRegister src_reg; + tsl_tokenizer_consume_peek(&self->tokenizer); /* consume previous TSL_TOKEN_EQUAL */ - if(tsl_parser_parse_rhs(self) != 0) - return -1; + return_if_error(tsl_parser_parse_rhs(self, &src_reg)); + + dst_reg = tsl_bytecode_writer_get_unique_register(&self->bytecode_writer); + if(dst_reg < 0) + return TSL_PARSE_RESULT_ERR; + return_if_error(tsl_bytecode_writer_mov_reg(&self->bytecode_writer, dst_reg, src_reg)); } else { - if(tsl_parser_parse_rhs_sub(self) != 0) - return -1; + return_if_error(tsl_parser_parse_rhs_sub(self)); } } else if(token == end_token) { break; } else { fprintf(stderr, "Error: Expected identifier, got TODO\n"); - return -1; + return TSL_PARSE_RESULT_ERR; } } - return 0; + return TSL_PARSE_RESULT_OK; } -int tsl_parse(const char *code, size_t code_size) { - int result; +TslParseResult tsl_parse(const char *code, size_t code_size) { + TslParseResult result; TslParser parser; tsl_parser_init(&parser, code, code_size); result = tsl_parser_parse_expressions(&parser, TSL_TOKEN_END_OF_FILE); diff --git a/src/std/hash_map.c b/src/std/hash_map.c index 44d36db..968a5ea 100644 --- a/src/std/hash_map.c +++ b/src/std/hash_map.c @@ -10,11 +10,6 @@ struct TslHashMapNode { TslHashMapNode *next; }; -static void hash_map_node_init(TslHashMapNode *self) { - self->data = NULL; - self->next = NULL; -} - static void hash_map_node_get(TslHashMapNode *self, uint64_t *hash, TslStringView *key, size_t *size, uint8_t **data) { memcpy(hash, (uint8_t*)self->data, sizeof(uint64_t)); memcpy(&key->size, (uint8_t*)self->data + sizeof(uint64_t), sizeof(key->size)); -- cgit v1.2.3