From 094182ca4197f568880ce15fc94c19a796118a7f Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Mon, 11 May 2020 17:29:00 -0500 Subject: [PATCH] Split project up and working on bh_arr --- Makefile | 3 +- bh.h | 80 ++++++++++++++- onyx | Bin 35904 -> 37160 bytes onyx.c | 288 ++++-------------------------------------------------- onyxlex.c | 225 ++++++++++++++++++++++++++++++++++++++++++ onyxlex.h | 71 ++++++++++++++ 6 files changed, 394 insertions(+), 273 deletions(-) create mode 100644 onyxlex.c create mode 100644 onyxlex.h diff --git a/Makefile b/Makefile index 2f544b46..187b707f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ OBJ_FILES=\ + onyxlex.o \ onyx.o CC=gcc @@ -10,7 +11,7 @@ FLAGS=-g $(CC) $(FLAGS) -c $< -o $@ $(INCLUDES) onyx: $(OBJ_FILES) - $(CC) $(FLAGS) $< -o $@ $(LIBS) + $(CC) $(FLAGS) $? -o $@ $(LIBS) clean: rm $(OBJ_FILES) 2>&1 >/dev/null diff --git a/bh.h b/bh.h index 40dd979f..16a51c87 100644 --- a/bh.h +++ b/bh.h @@ -1,3 +1,6 @@ +#ifndef BH_H +#define BH_H + #include #include #include @@ -32,6 +35,7 @@ b32 char_is_alphanum(const char a); b32 char_is_whitespace(const char a); b32 char_in_range(const char lo, const char hi, const char a); char charset_contains(const char* charset, char ch); +i64 chars_match(char* ptr1, char* ptr2); //------------------------------------------------------------------------------------- // Better strings @@ -150,15 +154,39 @@ bh_file_contents bh_file_read_contents_bh_file(bh_file* file); bh_file_contents bh_file_read_contents_direct(const char* filename); i32 bh_file_contents_delete(bh_file_contents* contents); +//------------------------------------------------------------------------------------- +// Better arrays +//------------------------------------------------------------------------------------- +typedef struct bh__arr { + i32 length, capacity; +} bh__arr; +#define bh_arr(T) T* +#define bh__arrhead(arr) (((bh__arr *)(arr)) - 1) +#define bh_arr_length(arr) (arr ? bh__arrhead(arr)->length : 0) +#define bh_arr_capacity(arr) (arr ? bh__arrhead(arr)->capacity : 0) +#define bh_arr_valid(arr, i) (arr ? (int)(i) < bh__arrhead(arr)->length : 0) +#define bh_arr_set_length(arr, n) (bh__arr_ensure_capacity((void **) &arr, sizeof(arr[0]), n), bh__arrhead(arr)->length = n) +#define bh_arr_pop(arr) ((arr)[--bh__arrhead(arr)->length]) +#define bh_arr_last(arr) ((arr)[bh__arrhead(arr)->length - 1]) +#define bh_arr_end(arr, i) ((i) >= &(arr)[bh_arr_length(arr)]) +#define bh_arr_new(arr, cap) (bh__arr_ensure_capacity((void**) &arr, sizeof(arr[0]), cap)) +#define bh_arr_free(arr) (bh__arr_free((void**) &arr)) +#define bh_arr_copy(arr) (bh__arr_copy(arr, sizeof(arr[0]))) +#define bh_arr_insert_end(arr, n) ( \ + bh__arr_ensure_capacity((void**) &arr, sizeof(arr[0]), bh_arr_length(arr) + n), \ + bh__arrhead(arr)->length += n) +b32 bh__arr_ensure_capacity(void** arr, int elemsize, int cap); +b32 bh__arr_free(void **arr); +void* bh__arr_copy(void *arr, int elemsize); - - +#ifdef BH_DEFINE +#undef BH_DEFINE //------------------------------------------------------------------------------------- @@ -509,3 +537,51 @@ b32 bh_file_contents_delete(bh_file_contents* contents) { contents->length = 0; return 1; } + +//------------------------------------------------------------------------------------- +// ARRAY IMPLEMENTATION +//------------------------------------------------------------------------------------- + +b32 bh__arr_ensure_capacity(void** arr, int elemsize, int cap) { + bh__arr* arrptr; + + if (*arr == NULL) { + if (cap == 0 && elemsize == 0) return 1; + + arrptr = (bh__arr *) malloc(sizeof(*arrptr) + elemsize * cap); + arrptr->capacity = cap; + arrptr->length = 0; + + } else { + arrptr = bh__arrhead(*arr); + if (arrptr->length > cap) return 1; + + if (arrptr->capacity < cap) { + void* p; + int newcap = arrptr->capacity ? arrptr->capacity : 4; + while (newcap < cap) newcap <<= 1; + + p = realloc(arrptr, sizeof(*arrptr) + elemsize * newcap); + + if (p) { + arrptr = (bh__arr *) p; + arrptr->capacity = newcap; + } else { + return 0; + } + } + } + + *arr = arrptr + 1; + return 1; +} + +b32 bh__arr_free(void **arr) { + bh__arr* arrptr = bh__arrhead(*arr); + free(arrptr); +} + + +#endif // ifdef BH_DEFINE + +#endif // ifndef BH_H diff --git a/onyx b/onyx index b0a2ad6f86daadfc6c9215135d1e8514ea63ec3b..6ea581cce3958f127854e5c867d1f2b65076bbfa 100755 GIT binary patch literal 37160 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 literal 35904 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 // TODO: Replace with custom lib +#define BH_DEFINE #include "bh.h" -typedef struct Tokenizer { - char *start, *curr, *end; - - // TODO: Fix the line number and column count - u64 line_number; - u64 line_column; -} Tokenizer; - -typedef enum TokenType { - TOKEN_TYPE_UNKNOWN, - TOKEN_TYPE_END_STREAM, - - TOKEN_TYPE_COMMENT, - - TOKEN_TYPE_KEYWORD_STRUCT, - TOKEN_TYPE_KEYWORD_USE, - TOKEN_TYPE_KEYWORD_EXPORT, - TOKEN_TYPE_KEYWORD_IF, - TOKEN_TYPE_KEYWORD_ELSE, - TOKEN_TYPE_KEYWORD_FOR, - TOKEN_TYPE_KEYWORD_RETURN, - - TOKEN_TYPE_RIGHT_ARROW, - TOKEN_TYPE_LEFT_ARROW, - TOKEN_TYPE_OPEN_PAREN, - TOKEN_TYPE_CLOSE_PAREN, - TOKEN_TYPE_OPEN_BRACE, - TOKEN_TYPE_CLOSE_BRACE, - TOKEN_TYPE_OPEN_BRACKET, - TOKEN_TYPE_CLOSE_BRACKET, - TOKEN_TYPE_OPEN_ANGLE, - TOKEN_TYPE_CLOSE_ANGLE, - - TOKEN_TYPE_SYM_PLUS, - TOKEN_TYPE_SYM_MINUS, - TOKEN_TYPE_SYM_STAR, - TOKEN_TYPE_SYM_PERCENT, - TOKEN_TYPE_SYM_FSLASH, - TOKEN_TYPE_SYM_BSLASH, - TOKEN_TYPE_SYM_COLON, - TOKEN_TYPE_SYM_SEMICOLON, - TOKEN_TYPE_SYM_COMMA, - TOKEN_TYPE_SYM_EQUALS, - TOKEN_TYPE_SYM_GRAVE, - TOKEN_TYPE_SYM_TILDE, - TOKEN_TYPE_SYM_BANG, - - TOKEN_TYPE_SYMBOL, - TOKEN_TYPE_LITERAL_STRING, - TOKEN_TYPE_LITERAL_NUMERIC, - - TOKEN_TYPE_COUNT -} TokenType; - -static const char* TokenTypeNames[] = { - "TOKEN_TYPE_UNKNOWN", - "TOKEN_TYPE_END_STREAM", - - "TOKEN_TYPE_COMMENT", - - "TOKEN_TYPE_KEYWORD_STRUCT", - "TOKEN_TYPE_KEYWORD_USE", - "TOKEN_TYPE_KEYWORD_EXPORT", - "TOKEN_TYPE_KEYWORD_IF", - "TOKEN_TYPE_KEYWORD_ELSE", - "TOKEN_TYPE_KEYWORD_FOR", - "TOKEN_TYPE_KEYWORD_RETURN", - - "TOKEN_TYPE_RIGHT_ARROW", - "TOKEN_TYPE_LEFT_ARROW", - "TOKEN_TYPE_OPEN_PAREN", - "TOKEN_TYPE_CLOSE_PAREN", - "TOKEN_TYPE_OPEN_BRACE", - "TOKEN_TYPE_CLOSE_BRACE", - "TOKEN_TYPE_OPEN_BRACKET", - "TOKEN_TYPE_CLOSE_BRACKET", - "TOKEN_TYPE_OPEN_ANGLE", - "TOKEN_TYPE_CLOSE_ANGLE", - - "TOKEN_TYPE_SYM_PLUS", - "TOKEN_TYPE_SYM_MINUS", - "TOKEN_TYPE_SYM_STAR", - "TOKEN_TYPE_SYM_PERCENT", - "TOKEN_TYPE_SYM_FSLASH", - "TOKEN_TYPE_SYM_BSLASH", - "TOKEN_TYPE_SYM_COLON", - "TOKEN_TYPE_SYM_SEMICOLON", - "TOKEN_TYPE_SYM_COMMA", - "TOKEN_TYPE_SYM_EQUALS", - "TOKEN_TYPE_SYM_GRAVE", - "TOKEN_TYPE_SYM_TILDE", - "TOKEN_TYPE_SYM_BANG", - - "TOKEN_TYPE_SYMBOL", - "TOKEN_TYPE_LITERAL_STRING", - "TOKEN_TYPE_LITERAL_NUMERIC", - - "TOKEN_TYPE_COUNT" -}; - -typedef struct Token { - TokenType type; - char* token; - isize length; - u64 line_number, line_column; -} Token; - -#ifndef LITERAL_TOKEN -#define LITERAL_TOKEN(token, token_type) \ - if (token_lit(tokenizer, &tk, token, token_type)) goto token_parsed; -#endif - -#ifndef INCREMENT_CURR_TOKEN -#define INCREMENT_CURR_TOKEN(tkn) { \ - tkn->curr++; \ - tkn->line_column++; \ - if (*tkn->curr == '\n') { \ - tkn->line_number++; \ - tkn->line_column = 1; \ - } \ -} -#endif - -b32 token_lit(Tokenizer* tokenizer, Token* tk, char* lit, TokenType type) { - i64 len = chars_match(tokenizer->curr, lit); - if (len > 0) { - tk->type = type; - tk->token = tokenizer->curr; - tk->length = len; - - tokenizer->curr += len; - tokenizer->line_column += len; - - return 1; - } - return 0; -} - -Token get_token(Tokenizer* tokenizer) { - Token tk; - - // Skip whitespace - while (char_is_whitespace(*tokenizer->curr) && tokenizer->curr != tokenizer->end) - INCREMENT_CURR_TOKEN(tokenizer) - - tk.type = TOKEN_TYPE_UNKNOWN; - tk.token = tokenizer->curr; - tk.length = 1; - tk.line_number = tokenizer->line_number; - tk.line_column = tokenizer->line_column; - - if (tokenizer->curr == tokenizer->end) { - tk.type = TOKEN_TYPE_END_STREAM; - goto token_parsed; - } - - // Comments - if (*tokenizer->curr == '/' && *(tokenizer->curr + 1) == '*') { - tokenizer->curr += 2; - tk.type = TOKEN_TYPE_COMMENT; - tk.token = tokenizer->curr; - u16 layers = 1; - - while (layers >= 1) { - INCREMENT_CURR_TOKEN(tokenizer); - - if (tokenizer->curr == tokenizer->end) { - tk.type = TOKEN_TYPE_END_STREAM; - break; - } - - if (*tokenizer->curr == '/' && *(tokenizer->curr + 1) == '*') { - layers++; - INCREMENT_CURR_TOKEN(tokenizer); - } - - if (*tokenizer->curr == '*' && *(tokenizer->curr + 1) == '/') { - layers--; - INCREMENT_CURR_TOKEN(tokenizer); - } - } - - INCREMENT_CURR_TOKEN(tokenizer); - - tk.length = tokenizer->curr - tk.token - 2; - goto token_parsed; - } - - LITERAL_TOKEN("struct", TOKEN_TYPE_KEYWORD_STRUCT); - LITERAL_TOKEN("export", TOKEN_TYPE_KEYWORD_EXPORT); - LITERAL_TOKEN("use", TOKEN_TYPE_KEYWORD_USE); - LITERAL_TOKEN("if", TOKEN_TYPE_KEYWORD_IF); - LITERAL_TOKEN("else", TOKEN_TYPE_KEYWORD_ELSE); - LITERAL_TOKEN("for", TOKEN_TYPE_KEYWORD_FOR); - LITERAL_TOKEN("return", TOKEN_TYPE_KEYWORD_RETURN); - LITERAL_TOKEN("->", TOKEN_TYPE_RIGHT_ARROW); - LITERAL_TOKEN("<-", TOKEN_TYPE_RIGHT_ARROW); - LITERAL_TOKEN("(", TOKEN_TYPE_OPEN_PAREN); - LITERAL_TOKEN(")", TOKEN_TYPE_CLOSE_PAREN); - LITERAL_TOKEN("{", TOKEN_TYPE_OPEN_BRACE); - LITERAL_TOKEN("}", TOKEN_TYPE_CLOSE_BRACE); - LITERAL_TOKEN("[", TOKEN_TYPE_OPEN_BRACKET); - LITERAL_TOKEN("]", TOKEN_TYPE_CLOSE_BRACKET); - LITERAL_TOKEN("<", TOKEN_TYPE_OPEN_ANGLE); - LITERAL_TOKEN(">", TOKEN_TYPE_CLOSE_ANGLE); - LITERAL_TOKEN("+", TOKEN_TYPE_SYM_PLUS); - LITERAL_TOKEN("-", TOKEN_TYPE_SYM_MINUS); - LITERAL_TOKEN("*", TOKEN_TYPE_SYM_STAR); - LITERAL_TOKEN("/", TOKEN_TYPE_SYM_FSLASH); - LITERAL_TOKEN("%", TOKEN_TYPE_SYM_PERCENT); - LITERAL_TOKEN("\\", TOKEN_TYPE_SYM_BSLASH); - LITERAL_TOKEN(":", TOKEN_TYPE_SYM_COLON); - LITERAL_TOKEN(";", TOKEN_TYPE_SYM_SEMICOLON); - LITERAL_TOKEN(",", TOKEN_TYPE_SYM_COMMA); - LITERAL_TOKEN("=", TOKEN_TYPE_SYM_EQUALS); - LITERAL_TOKEN("`", TOKEN_TYPE_SYM_GRAVE); - LITERAL_TOKEN("~", TOKEN_TYPE_SYM_TILDE); - LITERAL_TOKEN("!", TOKEN_TYPE_SYM_BANG); - - // Symbols - if (char_is_alpha(*tk.token)) { - u64 len = 0; - while (char_is_alphanum(*tokenizer->curr) || charset_contains("_$", *tokenizer->curr)) { - len++; - INCREMENT_CURR_TOKEN(tokenizer); - } - - tk.length = len; - tk.type = TOKEN_TYPE_SYMBOL; - goto token_parsed; - } - - // String literal - if (*tk.token == '"') { - u64 len = 0; - u64 slash_count = 0; - - INCREMENT_CURR_TOKEN(tokenizer); - - while (!(*tokenizer->curr == '"' && slash_count == 0)) { - len++; +#include // TODO: Replace with custom lib - if (*tokenizer->curr == '\\') { - slash_count += 1; - slash_count %= 2; - } else { - slash_count = 0; - } +#include "onyxlex.h" - INCREMENT_CURR_TOKEN(tokenizer); - } +int main(int argc, char const *argv[]) { + bh_arr(int) arr = NULL; // Must initialize to NULL + bh_arr_new(arr, 0); - INCREMENT_CURR_TOKEN(tokenizer); + bh_arr_set_length(arr, 10); + for (int i = 0; i < 10; i++) + arr[i] = i; + printf("Length: %d\nCapacity: %d\n", bh_arr_length(arr), bh_arr_capacity(arr)); - tk.token++; - tk.type = TOKEN_TYPE_LITERAL_STRING; - tk.length = len; - goto token_parsed; - } + bh_arr_set_length(arr, 0); - // Number literal - if (char_is_num(*tokenizer->curr)) { - u64 len = 0; - while (char_is_num(*tokenizer->curr) || *tokenizer->curr == '.') { - len++; - INCREMENT_CURR_TOKEN(tokenizer); - } + printf("Length: %d\nCapacity: %d\n", bh_arr_length(arr), bh_arr_capacity(arr)); - tk.type = TOKEN_TYPE_LITERAL_NUMERIC; - tk.length = len; + for (int* it = arr; !bh_arr_end(arr, it); it++) { + printf("%d ", *it); } - INCREMENT_CURR_TOKEN(tokenizer); + bh_arr_free(arr); -token_parsed: - return tk; + return 0; } -int main(int argc, char *argv[]) { +int main2(int argc, char *argv[]) { bh_file source_file; bh_file_error err = bh_file_open(&source_file, argv[1]); if (err != BH_FILE_ERROR_NONE) { @@ -303,7 +51,7 @@ int main(int argc, char *argv[]) { tk = get_token(&tknizer); char c = *(tk.token + tk.length); *(tk.token + tk.length) = '\0'; - printf("Line %ld, Column %ld: \n%s: %s\n", tk.line_number, tk.line_column, TokenTypeNames[tk.type], tk.token); + printf("Line %ld, Column %ld: \n%s: %s\n", tk.line_number, tk.line_column, get_token_type_name(tk), tk.token); *(tk.token + tk.length) = c; } while (tk.type != TOKEN_TYPE_END_STREAM); diff --git a/onyxlex.c b/onyxlex.c new file mode 100644 index 00000000..a5945683 --- /dev/null +++ b/onyxlex.c @@ -0,0 +1,225 @@ +#include "bh.h" +#include "onyxlex.h" + +static const char* TokenTypeNames[] = { + "TOKEN_TYPE_UNKNOWN", + "TOKEN_TYPE_END_STREAM", + + "TOKEN_TYPE_COMMENT", + + "TOKEN_TYPE_KEYWORD_STRUCT", + "TOKEN_TYPE_KEYWORD_USE", + "TOKEN_TYPE_KEYWORD_EXPORT", + "TOKEN_TYPE_KEYWORD_IF", + "TOKEN_TYPE_KEYWORD_ELSE", + "TOKEN_TYPE_KEYWORD_FOR", + "TOKEN_TYPE_KEYWORD_RETURN", + "TOKEN_TYPE_KEYWORD_FOREIGN", + + "TOKEN_TYPE_RIGHT_ARROW", + "TOKEN_TYPE_LEFT_ARROW", + "TOKEN_TYPE_OPEN_PAREN", + "TOKEN_TYPE_CLOSE_PAREN", + "TOKEN_TYPE_OPEN_BRACE", + "TOKEN_TYPE_CLOSE_BRACE", + "TOKEN_TYPE_OPEN_BRACKET", + "TOKEN_TYPE_CLOSE_BRACKET", + "TOKEN_TYPE_OPEN_ANGLE", + "TOKEN_TYPE_CLOSE_ANGLE", + + "TOKEN_TYPE_SYM_PLUS", + "TOKEN_TYPE_SYM_MINUS", + "TOKEN_TYPE_SYM_STAR", + "TOKEN_TYPE_SYM_PERCENT", + "TOKEN_TYPE_SYM_FSLASH", + "TOKEN_TYPE_SYM_BSLASH", + "TOKEN_TYPE_SYM_COLON", + "TOKEN_TYPE_SYM_SEMICOLON", + "TOKEN_TYPE_SYM_COMMA", + "TOKEN_TYPE_SYM_EQUALS", + "TOKEN_TYPE_SYM_GRAVE", + "TOKEN_TYPE_SYM_TILDE", + "TOKEN_TYPE_SYM_BANG", + + "TOKEN_TYPE_SYMBOL", + "TOKEN_TYPE_LITERAL_STRING", + "TOKEN_TYPE_LITERAL_NUMERIC", + + "TOKEN_TYPE_COUNT" +}; + +#ifndef LITERAL_TOKEN +#define LITERAL_TOKEN(token, token_type) \ + if (token_lit(tokenizer, &tk, token, token_type)) goto token_parsed; +#endif + +#ifndef INCREMENT_CURR_TOKEN +#define INCREMENT_CURR_TOKEN(tkn) { \ + tkn->curr++; \ + tkn->line_column++; \ + if (*tkn->curr == '\n') { \ + tkn->line_number++; \ + tkn->line_column = 1; \ + } \ +} +#endif + +static b32 token_lit(Tokenizer* tokenizer, Token* tk, char* lit, TokenType type) { + i64 len = chars_match(tokenizer->curr, lit); + if (len > 0) { + tk->type = type; + tk->token = tokenizer->curr; + tk->length = len; + + tokenizer->curr += len; + tokenizer->line_column += len; + + return 1; + } + return 0; +} + +const char* get_token_type_name(Token tkn) { + return TokenTypeNames[tkn.type]; +} + +Token get_token(Tokenizer* tokenizer) { + Token tk; + + // Skip whitespace + while (char_is_whitespace(*tokenizer->curr) && tokenizer->curr != tokenizer->end) + INCREMENT_CURR_TOKEN(tokenizer) + + tk.type = TOKEN_TYPE_UNKNOWN; + tk.token = tokenizer->curr; + tk.length = 1; + tk.line_number = tokenizer->line_number; + tk.line_column = tokenizer->line_column; + + if (tokenizer->curr == tokenizer->end) { + tk.type = TOKEN_TYPE_END_STREAM; + goto token_parsed; + } + + // Comments + if (*tokenizer->curr == '/' && *(tokenizer->curr + 1) == '*') { + tokenizer->curr += 2; + tk.type = TOKEN_TYPE_COMMENT; + tk.token = tokenizer->curr; + u16 layers = 1; + + while (layers >= 1) { + INCREMENT_CURR_TOKEN(tokenizer); + + if (tokenizer->curr == tokenizer->end) { + tk.type = TOKEN_TYPE_END_STREAM; + break; + } + + if (*tokenizer->curr == '/' && *(tokenizer->curr + 1) == '*') { + layers++; + INCREMENT_CURR_TOKEN(tokenizer); + } + + if (*tokenizer->curr == '*' && *(tokenizer->curr + 1) == '/') { + layers--; + INCREMENT_CURR_TOKEN(tokenizer); + } + } + + INCREMENT_CURR_TOKEN(tokenizer); + + tk.length = tokenizer->curr - tk.token - 2; + goto token_parsed; + } + + LITERAL_TOKEN("struct", TOKEN_TYPE_KEYWORD_STRUCT); + LITERAL_TOKEN("export", TOKEN_TYPE_KEYWORD_EXPORT); + LITERAL_TOKEN("use", TOKEN_TYPE_KEYWORD_USE); + LITERAL_TOKEN("if", TOKEN_TYPE_KEYWORD_IF); + LITERAL_TOKEN("else", TOKEN_TYPE_KEYWORD_ELSE); + LITERAL_TOKEN("foreign", TOKEN_TYPE_KEYWORD_FOREIGN); + LITERAL_TOKEN("for", TOKEN_TYPE_KEYWORD_FOR); + LITERAL_TOKEN("return", TOKEN_TYPE_KEYWORD_RETURN); + LITERAL_TOKEN("->", TOKEN_TYPE_RIGHT_ARROW); + LITERAL_TOKEN("<-", TOKEN_TYPE_RIGHT_ARROW); + LITERAL_TOKEN("(", TOKEN_TYPE_OPEN_PAREN); + LITERAL_TOKEN(")", TOKEN_TYPE_CLOSE_PAREN); + LITERAL_TOKEN("{", TOKEN_TYPE_OPEN_BRACE); + LITERAL_TOKEN("}", TOKEN_TYPE_CLOSE_BRACE); + LITERAL_TOKEN("[", TOKEN_TYPE_OPEN_BRACKET); + LITERAL_TOKEN("]", TOKEN_TYPE_CLOSE_BRACKET); + LITERAL_TOKEN("<", TOKEN_TYPE_OPEN_ANGLE); + LITERAL_TOKEN(">", TOKEN_TYPE_CLOSE_ANGLE); + LITERAL_TOKEN("+", TOKEN_TYPE_SYM_PLUS); + LITERAL_TOKEN("-", TOKEN_TYPE_SYM_MINUS); + LITERAL_TOKEN("*", TOKEN_TYPE_SYM_STAR); + LITERAL_TOKEN("/", TOKEN_TYPE_SYM_FSLASH); + LITERAL_TOKEN("%", TOKEN_TYPE_SYM_PERCENT); + LITERAL_TOKEN("\\", TOKEN_TYPE_SYM_BSLASH); + LITERAL_TOKEN(":", TOKEN_TYPE_SYM_COLON); + LITERAL_TOKEN(";", TOKEN_TYPE_SYM_SEMICOLON); + LITERAL_TOKEN(",", TOKEN_TYPE_SYM_COMMA); + LITERAL_TOKEN("=", TOKEN_TYPE_SYM_EQUALS); + LITERAL_TOKEN("`", TOKEN_TYPE_SYM_GRAVE); + LITERAL_TOKEN("~", TOKEN_TYPE_SYM_TILDE); + LITERAL_TOKEN("!", TOKEN_TYPE_SYM_BANG); + + // Symbols + if (char_is_alpha(*tk.token)) { + u64 len = 0; + while (char_is_alphanum(*tokenizer->curr) || charset_contains("_$", *tokenizer->curr)) { + len++; + INCREMENT_CURR_TOKEN(tokenizer); + } + + tk.length = len; + tk.type = TOKEN_TYPE_SYMBOL; + goto token_parsed; + } + + // String literal + if (*tk.token == '"') { + u64 len = 0; + u64 slash_count = 0; + + INCREMENT_CURR_TOKEN(tokenizer); + + while (!(*tokenizer->curr == '"' && slash_count == 0)) { + len++; + + if (*tokenizer->curr == '\\') { + slash_count += 1; + slash_count %= 2; + } else { + slash_count = 0; + } + + INCREMENT_CURR_TOKEN(tokenizer); + } + + INCREMENT_CURR_TOKEN(tokenizer); + + tk.token++; + tk.type = TOKEN_TYPE_LITERAL_STRING; + tk.length = len; + goto token_parsed; + } + + // Number literal + if (char_is_num(*tokenizer->curr)) { + u64 len = 0; + while (char_is_num(*tokenizer->curr) || *tokenizer->curr == '.') { + len++; + INCREMENT_CURR_TOKEN(tokenizer); + } + + tk.type = TOKEN_TYPE_LITERAL_NUMERIC; + tk.length = len; + } + + INCREMENT_CURR_TOKEN(tokenizer); + +token_parsed: + return tk; +} diff --git a/onyxlex.h b/onyxlex.h new file mode 100644 index 00000000..01dc7fd6 --- /dev/null +++ b/onyxlex.h @@ -0,0 +1,71 @@ +#ifndef ONYXLEX_H +#define ONYXLEX_H + +#include "bh.h" + +typedef struct Tokenizer { + char *start, *curr, *end; + + // TODO: Fix the line number and column count + u64 line_number; + u64 line_column; +} Tokenizer; + +typedef enum TokenType { + TOKEN_TYPE_UNKNOWN, + TOKEN_TYPE_END_STREAM, + + TOKEN_TYPE_COMMENT, + + TOKEN_TYPE_KEYWORD_STRUCT, + TOKEN_TYPE_KEYWORD_USE, + TOKEN_TYPE_KEYWORD_EXPORT, + TOKEN_TYPE_KEYWORD_IF, + TOKEN_TYPE_KEYWORD_ELSE, + TOKEN_TYPE_KEYWORD_FOR, + TOKEN_TYPE_KEYWORD_RETURN, + TOKEN_TYPE_KEYWORD_FOREIGN, + + TOKEN_TYPE_RIGHT_ARROW, + TOKEN_TYPE_LEFT_ARROW, + TOKEN_TYPE_OPEN_PAREN, + TOKEN_TYPE_CLOSE_PAREN, + TOKEN_TYPE_OPEN_BRACE, + TOKEN_TYPE_CLOSE_BRACE, + TOKEN_TYPE_OPEN_BRACKET, + TOKEN_TYPE_CLOSE_BRACKET, + TOKEN_TYPE_OPEN_ANGLE, + TOKEN_TYPE_CLOSE_ANGLE, + + TOKEN_TYPE_SYM_PLUS, + TOKEN_TYPE_SYM_MINUS, + TOKEN_TYPE_SYM_STAR, + TOKEN_TYPE_SYM_PERCENT, + TOKEN_TYPE_SYM_FSLASH, + TOKEN_TYPE_SYM_BSLASH, + TOKEN_TYPE_SYM_COLON, + TOKEN_TYPE_SYM_SEMICOLON, + TOKEN_TYPE_SYM_COMMA, + TOKEN_TYPE_SYM_EQUALS, + TOKEN_TYPE_SYM_GRAVE, + TOKEN_TYPE_SYM_TILDE, + TOKEN_TYPE_SYM_BANG, + + TOKEN_TYPE_SYMBOL, + TOKEN_TYPE_LITERAL_STRING, + TOKEN_TYPE_LITERAL_NUMERIC, + + TOKEN_TYPE_COUNT +} TokenType; + +typedef struct Token { + TokenType type; + char* token; + isize length; + u64 line_number, line_column; +} Token; + +const char* get_token_type_name(Token tkn); +Token get_token(Tokenizer* tokenizer); + +#endif \ No newline at end of file -- 2.25.1