diff --git a/.gitignore b/.gitignore index 5b03d0a..16b9a79 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.o *.so +tags *.out .cache compile_commands.json diff --git a/Makefile b/Makefile index 598be07..2878383 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ TEST_OBJ_DIR = $(TEST_BUILD_DIR)/obj CC = clang LINK = clang -CFLAGS = -Wall +CFLAGS = -Wall -DDBG -ggdb LDFLAGS = SRC_FILES = $(wildcard $(SRC_DIR)/*.c) @@ -28,6 +28,10 @@ WHITE_BOLD = $(RESETCOLOR)\x1b[37;1m all: $(TARGET) +release: clean +release: CFLAGS = -Wall -O2 +release: $(TARGET) + # Link to final binary. $(TARGET): $(OBJ_FILES) @ echo -e "$(WHITE_BOLD)Linking $(WHITE)$(TARGET)$(WHITE_BOLD)...$(RESETCOLOR) $(CC) -o $(TARGET) $(OBJ_FILES) $(LDFLAGS)" @@ -56,5 +60,8 @@ clean: @ echo -e "$(WHITE_BOLD)Cleaning up...$(WHITE) $(OBJ_DIR)/*.o $(TEST_OBJ_DIR)/*.o $(TEST_BUILD_DIR)/test.out $(TARGET)$(RESETCOLOR)" @ rm -rf $(OBJ_DIR)/*.o $(TEST_OBJ_DIR)/*.o $(TEST_BUILD_DIR)/test.out $(TARGET) -.PHONY: all clean test nocolor +run: + ./$(TARGET) + +.PHONY: all clean test nocolor release diff --git a/examples/test.scl b/examples/test.scl new file mode 100644 index 0000000..8d2f097 --- /dev/null +++ b/examples/test.scl @@ -0,0 +1 @@ +1 + 1 diff --git a/src/dstr.c b/src/dstr.c new file mode 100644 index 0000000..32c69be --- /dev/null +++ b/src/dstr.c @@ -0,0 +1,27 @@ +#include "include/dstr.h" +#include + +Dstr* dstr_init(void) { + Dstr* dstr = malloc(sizeof(Dstr)); + + dstr->bufsz = DSTR_INITSZ; + dstr->buf = malloc(DSTR_INITSZ); + dstr->ln = 0; + + return dstr; +} + +void dstr_destroy(Dstr* dstr) { + free(dstr->buf); + free(dstr); +} + +void dstr_append(Dstr* dest, size_t ln, char* src) { + if (dest->ln + ln > dest->bufsz) { + // Double the buffer size when overflown. + dest->bufsz *= dest->bufsz; + dest->buf = realloc(dest->buf, dest->bufsz); + } + + strcat(dest->buf + ln, src); +} diff --git a/src/include/dstr.h b/src/include/dstr.h new file mode 100644 index 0000000..cd64c93 --- /dev/null +++ b/src/include/dstr.h @@ -0,0 +1,21 @@ +#ifndef DSTR_H +#define DSTR_H + +#include +#include + +#define DSTR_INITSZ 128 + +typedef struct { + char* buf; // The buffer containing the string. + size_t bufsz; // The size of the buffer. + size_t ln; // The number of characters in the buffer. +} Dstr; + +Dstr* dstr_init(void); +void dstr_destroy(Dstr* dstr); + +// Append ln characters of src to dest. +void dstr_append(Dstr* dest, size_t ln, char* src); + +#endif diff --git a/src/include/lexer.h b/src/include/lexer.h index 47827ae..d0032fa 100644 --- a/src/include/lexer.h +++ b/src/include/lexer.h @@ -4,7 +4,10 @@ #include #include #include +#include +#include +#include "util.h" #include "token.h" #define TOKENS_MAX 32 @@ -52,9 +55,4 @@ void lexer_inc(Lexer* lexer); // Add a token to the lexer. void lexer_add_token(Lexer* lexer, Token* token); -// Print the contents of a lexer. -void lexer_print(Lexer* lexer); - -static char* lexer_state_str(Lexer* lexer); - #endif diff --git a/src/include/token.h b/src/include/token.h index 8f1159f..3108b14 100644 --- a/src/include/token.h +++ b/src/include/token.h @@ -19,7 +19,10 @@ typedef struct { Token* token_init(TokenType type, char* val); void token_destroy(Token* token); -void token_print(Token* token); -static char* token_type_str(Token* token); +// Returns a string representation of the Token. +char* token_to_str(Token* token, unsigned int indent); + +// Returns a string representation of the TokenType. +char* token_type_to_str(TokenType t); #endif diff --git a/src/include/util.h b/src/include/util.h index d2f0eee..051b6ce 100644 --- a/src/include/util.h +++ b/src/include/util.h @@ -1,6 +1,12 @@ #ifndef UTIL_H #define UTIL_H -int is_even(int n); +#ifdef DBG +#define log_dbg(msg) \ + printf("[dbg:%s:%s:%d] %s\n", __FILE__, __func__, __LINE__, msg); \ + fflush(stdout); +#else +#define log_dbg(msg) +#endif #endif diff --git a/src/lexer.c b/src/lexer.c index 3dac4f4..d466364 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -1,9 +1,5 @@ #include "include/lexer.h" -#include "include/token.h" -#include -#include -#include -#include +#include "include/util.h" Lexer* lexer_init(char* src) { Lexer* lexer = malloc(sizeof(Lexer)); @@ -12,7 +8,7 @@ Lexer* lexer_init(char* src) { lexer->srcl = strlen(src); lexer->cchar = lexer->src; - lexer->tokens = calloc(TOKENS_MAX, sizeof(Token)); + lexer->tokens = calloc(TOKENS_MAX, sizeof(Token*)); lexer->ntokens = 0; lexer->state = LEXER_STATE_CONFUSED; @@ -22,7 +18,7 @@ Lexer* lexer_init(char* src) { void lexer_destroy(Lexer* lexer) { free(lexer->src); - for (int i = 0; i < lexer->ntokens; token_destroy(lexer->tokens[i++])); + for (int i = 0; i < lexer->ntokens; i++) token_destroy(lexer->tokens[i]); } void lexer_lex(Lexer* lexer) { @@ -37,11 +33,13 @@ void lexer_lex(Lexer* lexer) { } void lexer_do_confused(Lexer* lexer) { + log_dbg("entered confused mode"); if (isdigit(*lexer->cchar)) lexer_do_number(lexer); else lexer_do_call(lexer); } void lexer_do_number(Lexer* lexer) { + log_dbg("entered number mode"); // Size of the number string. size_t numsz; @@ -59,6 +57,7 @@ void lexer_do_number(Lexer* lexer) { } void lexer_do_call(Lexer* lexer) { + log_dbg("entered call mode"); // Size of the call string. size_t callsz; @@ -71,6 +70,8 @@ void lexer_do_call(Lexer* lexer) { char* call = malloc(callsz + 1); memcpy(call, start, callsz); call[callsz] = '\0'; + + lexer_add_token(lexer, token_init(TOKEN_TYPE_CALL, call)); } void lexer_inc(Lexer* lexer) { @@ -81,29 +82,8 @@ void lexer_add_token(Lexer* lexer, Token* token) { assert(lexer->ntokens < TOKENS_MAX); if (lexer->ntokens < TOKENS_MAX - 1) { - lexer->tokens[lexer->ntokens - 1] = token; + lexer->tokens[lexer->ntokens] = token; lexer->ntokens++; } } -void lexer_print(Lexer* lexer) { - printf("Lexer @%p:\n", lexer); - printf("\tsrc: \"%s\"\n", lexer->src); - printf("\tsrcl: \"%ld\"\n", lexer->srcl); - printf("\tcchar: \"%s\"\n", lexer->cchar); - printf("\tntokens: %ld\n", lexer->ntokens); - printf("\ttokens: [START]\n"); - for (int i = 0; i < lexer->ntokens; i++) token_print(lexer->tokens[i]); - printf("[END]\n"); - printf("\tstate: %s\n", lexer_state_str(lexer)); - -} - -static char* lexer_state_str(Lexer* lexer) { - switch (lexer->state) { - case LEXER_STATE_NUM: return "NUM"; - case LEXER_STATE_CALL: return "CALL"; - case LEXER_STATE_CONFUSED: return "CONFUSED"; - default: return "???"; - } -} diff --git a/src/main.c b/src/main.c index 2bf16be..fda8dd7 100644 --- a/src/main.c +++ b/src/main.c @@ -1,14 +1,17 @@ #include +#include "include/token.h" #include "include/util.h" #include "include/lexer.h" int main(int argc, char** argv) { char* text = malloc(5); - text = "a1b2"; + text = "aa11"; Lexer* lexer = lexer_init(text); - lexer_print(lexer); lexer_lex(lexer); - lexer_print(lexer); + + printf("%s\n", token_to_str(lexer->tokens[0], 0)); + + lexer_destroy(lexer); } diff --git a/src/token.c b/src/token.c index 368c5ed..07251bb 100644 --- a/src/token.c +++ b/src/token.c @@ -1,4 +1,5 @@ #include "include/token.h" +#include Token* token_init(TokenType type, char* val) { Token* t = malloc(sizeof(Token)); @@ -14,17 +15,8 @@ void token_destroy(Token* t) { free(t); } -void token_print(Token* token) { - printf("Token @%p:\n", token); - printf("\ttype: %s\n", token_type_str(token)); - printf("\tval: %s\n", token->val); - printf("\tlen: %ld\n", token->len); -} - -static char* token_type_str(Token* token) { - switch (token->type) { - case TOKEN_TYPE_CALL: return "CALL"; - case TOKEN_TYPE_NUMBER: return "NUMBER"; - default: return "???"; - } +char* token_to_str(Token* token, unsigned int indent) { + char* title = malloc(sizeof("Token @ 0x000000000000\n")); + sprintf(title, "Token @%p\n", token); + return title; } diff --git a/src/util.c b/src/util.c index 9e9e272..2e34b20 100644 --- a/src/util.c +++ b/src/util.c @@ -1,3 +1 @@ #include "include/util.h" - -int is_even(int n) { return !(n % 2); } diff --git a/test/dstr.c b/test/dstr.c new file mode 100644 index 0000000..1630415 --- /dev/null +++ b/test/dstr.c @@ -0,0 +1,37 @@ +#include "../src/include/dstr.h" +#include "unity/unity.h" +#include "registry.h" + +void test_dstr_init() { + Dstr* dstr = dstr_init(); + + TEST_ASSERT_EQUAL_INT(DSTR_INITSZ, dstr->bufsz); + TEST_ASSERT_EQUAL_STRING(malloc(DSTR_INITSZ), dstr->buf); + TEST_ASSERT_EQUAL_size_t(0, dstr->ln); +} + +void test_dstr_append() { + char* str1 = malloc(2); + str1 = "h"; + + char* str2 = malloc(DSTR_INITSZ); + str2 = "h"; + + + Dstr* dstr = dstr_init(); + dstr_append(dstr, 1, str1); + + TEST_ASSERT_EQUAL_STRING(str2, dstr->buf); +} + +int test_dstr() { + UNITY_BEGIN(); + RUN_TEST(test_dstr_init); + RUN_TEST(test_dstr_append); + UNITY_END(); + return 0; +} + +__attribute__((constructor)) void register_dstr() { + register_test(test_dstr); +} diff --git a/test/lexer.c b/test/lexer.c new file mode 100644 index 0000000..c3edc58 --- /dev/null +++ b/test/lexer.c @@ -0,0 +1,52 @@ +#include "../src/include/lexer.h" +#include "unity/unity.h" +#include "registry.h" + +void test_lexer_init() { + char* src = malloc(sizeof("a1b2")); + src = "a1b2"; + Lexer* lexer = lexer_init(src); + + TEST_ASSERT_EQUAL_STRING(src, lexer->src); + TEST_ASSERT_EQUAL_INT(4, lexer->srcl); + TEST_ASSERT_EQUAL_CHAR(src[0], *lexer->cchar); + TEST_ASSERT_EQUAL_INT(LEXER_STATE_CONFUSED, lexer->state); + // Hope that token arr. is right size :). + TEST_ASSERT_EQUAL_INT(0, lexer->ntokens); +} + +void test_lexer_lex_callnum() { + char* src = malloc(sizeof("a1b2")); + src = "a1b2"; + Lexer* lexer = lexer_init(src); + + Token* tokens[4] = { + token_init(TOKEN_TYPE_CALL, "a"), + token_init(TOKEN_TYPE_NUMBER, "1"), + token_init(TOKEN_TYPE_CALL, "b"), + token_init(TOKEN_TYPE_NUMBER, "2"), + }; + + lexer_lex(lexer); + + TEST_ASSERT_EQUAL_INT(4, lexer->ntokens); + + for (int i = 0; i < 4; i++) { + printf("h"); + fflush(stdout); + TEST_ASSERT_EQUAL_INT(tokens[i]->type, lexer->tokens[i]->type); + TEST_ASSERT_EQUAL_STRING(tokens[i]->val, lexer->tokens[i]->val); + } +} + +int test_lexer() { + UNITY_BEGIN(); + RUN_TEST(test_lexer_init); + RUN_TEST(test_lexer_lex_callnum); + UNITY_END(); + return 0; +} + +__attribute__((constructor)) void register_lexer() { + register_test(test_lexer); +} diff --git a/test/util.c b/test/util.c deleted file mode 100644 index 0268bee..0000000 --- a/test/util.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "../src/include/util.h" -#include "registry.h" -#include "unity/unity.h" - -void test_is_even() { - TEST_ASSERT_EQUAL(0, is_even(1));; - TEST_ASSERT_EQUAL(1, is_even(2)); -} - -int test_util() { - UNITY_BEGIN(); - RUN_TEST(test_is_even); - return UNITY_END(); -} - -__attribute__((constructor)) void register_tests_util() { - register_test(test_util); -}