diff --git a/.gitignore b/.gitignore index 08e593b..4350d4c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ build/ bin/ +session.nvim + diff --git a/Makefile b/Makefile index 8befa33..27cb698 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ all: compile_flags.txt dirs scirpt UTILS_SRC = stringmap.c UTILS_OBJ = $(patsubst %.c, build/utils/%.o, $(UTILS_SRC)) -SCIRPT_SRC = main.c lexer.c parser.c +SCIRPT_SRC = main.c lexer.c ast.c parser.c SCIRPT_OBJ = $(patsubst %.c, build/scirpt/%.o, $(SCIRPT_SRC)) scirpt: $(SCIRPT_OBJ) $(UTILS_OBJ) diff --git a/include/scirpt/ast.h b/include/scirpt/ast.h new file mode 100644 index 0000000..4f44b6d --- /dev/null +++ b/include/scirpt/ast.h @@ -0,0 +1,28 @@ +#ifndef SCIRPT_AST_H +#define SCIRPT_AST_H + +#include +#include + +typedef enum { + ScirptAstExprTypeEof, + ScirptAstExprTypeError, + ScirptAstExprTypeId, + ScirptAstExprTypeInt, + ScirptAstExprTypeString, + ScirptAstExprTypeBool, +} ScirptAstExprType; + +typedef struct { + ScirptAstExprType type; + union { + char* id_value; + int64_t int_value; + char* string_value; + bool bool_value; + }; +} ScirptAstExpr; + +void scirpt_ast_expr_delete(ScirptAstExpr* expr); + +#endif diff --git a/include/scirpt/parser.h b/include/scirpt/parser.h index 788cbd8..8e2fd60 100644 --- a/include/scirpt/parser.h +++ b/include/scirpt/parser.h @@ -1,4 +1,29 @@ #ifndef SCIRPT_PARSER_H #define SCIRPT_PARSER_H +#include "scirpt/ast.h" +#include "scirpt/lexer.h" +#include "utils/generic_array.h" +#include "utils/string.h" +#include + +typedef struct { + HeapString message; + ScirptPosition pos; +} ScirptParserError; + +GENERIC_ARRAY( + ScirptParserError, ScirptParserErrorArray, scirpt_parser_error_array +) +typedef struct ScirptParserErrorArray ScirptParserErrorArray; + +typedef struct ScirptParser ScirptParser; + +ScirptParser* +scirpt_parser_new(const char* text, size_t text_length, ScirptLexer* lexer); +void scirpt_parser_delete(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_next_expr(ScirptParser* parser); +bool scirpt_parser_ok(const ScirptParser* parser); +const ScirptParserErrorArray* scirpt_parser_errors(const ScirptParser* parser); + #endif diff --git a/include/scirpt/token.h b/include/scirpt/token.h index b4556d7..f2652ce 100644 --- a/include/scirpt/token.h +++ b/include/scirpt/token.h @@ -7,6 +7,8 @@ typedef enum { ScirptTokenTypeEof, ScirptTokenTypeInvalidChar, + ScirptTokenTypeMalformedComment, + ScirptTokenTypeMalformedString, ScirptTokenTypeId, ScirptTokenTypeInt, ScirptTokenTypeString, @@ -21,11 +23,29 @@ typedef enum { ScirptTokenTypeColon, ScirptTokenTypeSemicolon, ScirptTokenTypePlus, + ScirptTokenTypePlusEqual, ScirptTokenTypeMinus, + ScirptTokenTypeMinusEqual, ScirptTokenTypeAsterisk, + ScirptTokenTypeAsteriskEqual, + ScirptTokenTypeSlash, + ScirptTokenTypeSlashEqual, + ScirptTokenTypePercent, + ScirptTokenTypePercentEqual, + ScirptTokenTypeEqual, + ScirptTokenTypeEqualEqual, + ScirptTokenTypeExclamation, + ScirptTokenTypeExclamationEqual, + ScirptTokenTypeLt, + ScirptTokenTypeLtEqual, + ScirptTokenTypeGt, + ScirptTokenTypeGtEqual, ScirptTokenTypeNull, ScirptTokenTypeFalse, ScirptTokenTypeTrue, + ScirptTokenTypeNot, + ScirptTokenTypeAnd, + ScirptTokenTypeOr, ScirptTokenTypeLet, ScirptTokenTypeIf, ScirptTokenTypeElse, diff --git a/include/utils/generic_array.h b/include/utils/generic_array.h new file mode 100644 index 0000000..5441050 --- /dev/null +++ b/include/utils/generic_array.h @@ -0,0 +1,61 @@ +#ifndef UTILS_GENERIC_ARRAY_H +#define UTILS_GENERIC_ARRAY_H + +#include +#include + +#define GENERIC_ARRAY(Type, struct_name, function_prefix) \ + struct struct_name { \ + Type* data; \ + size_t length, capacity; \ + }; \ + \ + static inline void function_prefix##_construct(struct struct_name* array) \ + { \ + *array = (struct struct_name) { \ + .data = NULL, \ + .length = 0, \ + .capacity = 0, \ + }; \ + } \ + \ + static inline void function_prefix##_destroy(struct struct_name* array) \ + { \ + if (array->data) \ + free(array->data); \ + } \ + \ + static inline size_t function_prefix##_length( \ + const struct struct_name* array \ + ) \ + { \ + return array->length; \ + } \ + \ + static inline Type* function_prefix##_get( \ + const struct struct_name* array, size_t index \ + ) \ + { \ + if (index >= array->length) \ + return NULL; \ + else \ + return &array->data[index]; \ + } \ + \ + static inline void function_prefix##_append( \ + struct struct_name* array, Type value \ + ) \ + { \ + if (array->data == NULL) { \ + array->capacity = 8; \ + array->data = malloc(sizeof(Type) * array->capacity); \ + } else if (array->length == array->capacity) { \ + array->capacity *= 2; \ + array->data \ + = realloc(array->data, sizeof(Type) * array->capacity); \ + } \ + array->data[array->length] = value; \ + array->length++; \ + } + +#endif diff --git a/include/utils/math.h b/include/utils/math.h new file mode 100644 index 0000000..4b64812 --- /dev/null +++ b/include/utils/math.h @@ -0,0 +1,21 @@ +#ifndef UTILS_MATH_H +#define UTILS_MATH_H + +#include + +// https://stackoverflow.com/questions/466204/rounding-up-to-next-power-of-2 +// https://stackoverflow.com/questions/1322510/given-an-integer-how-do-i-find-the-next-largest-power-of-two-using-bit-twiddlin/1322548#1322548 +static inline uint64_t utils_nearest_bigger_power_of_2_u64(uint64_t value) +{ + value--; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + value |= value >> 32; + value++; + return value; +} + +#endif diff --git a/include/utils/string.h b/include/utils/string.h new file mode 100644 index 0000000..f2a909e --- /dev/null +++ b/include/utils/string.h @@ -0,0 +1,37 @@ +#ifndef UTILS_STRING_H +#define UTILS_STRING_H + +#include +#include +#include + +typedef struct { + const char* data; + size_t length; +} StringView; + +typedef struct { + char* data; + size_t length; +} HeapString; + +static inline HeapString heapstring_from(const char* text, size_t length) +{ + char* allocated = malloc(sizeof(char) * length + 1); + strncpy(allocated, text, length); + HeapString string = { + .data = allocated, + .length = length, + }; + return string; +} +static inline HeapString heapstring_from_cstring(const char* text) +{ + return heapstring_from(text, strlen(text)); +} +static inline void heapstring_destroy(HeapString* string) +{ + free(string->data); +} + +#endif diff --git a/include/utils/string_array.h b/include/utils/string_array.h new file mode 100644 index 0000000..a5e2393 --- /dev/null +++ b/include/utils/string_array.h @@ -0,0 +1,38 @@ +#ifndef UTILS_STRING_ARRAY_H +#define UTILS_STRING_ARRAY_H + +#include "utils/generic_array.h" +#include "utils/string.h" +#include + +GENERIC_ARRAY(StringView, StringViewArray, stringview_array) +typedef struct StringViewArray StringViewArray; + +static inline StringViewArray* stringview_array_new(void) +{ + StringViewArray* array = malloc(sizeof(StringViewArray)); + stringview_array_construct(array); + return array; +} +static inline void stringview_array_delete(StringViewArray* array) +{ + stringview_array_destroy(array); + free(array); +} + +GENERIC_ARRAY(HeapString, HeapStringArray, heapstring_array) +typedef struct HeapStringArray HeapStringArray; + +static inline HeapStringArray* heapstring_array_new(void) +{ + HeapStringArray* array = malloc(sizeof(HeapStringArray)); + heapstring_array_construct(array); + return array; +} +static inline void heapstring_array_delete(HeapStringArray* array) +{ + heapstring_array_destroy(array); + free(array); +} + +#endif diff --git a/include/utils/stringmap.h b/include/utils/stringmap.h index bac36ff..d2e37dd 100644 --- a/include/utils/stringmap.h +++ b/include/utils/stringmap.h @@ -3,26 +3,11 @@ #include #include -#include - -// https://stackoverflow.com/questions/466204/rounding-up-to-next-power-of-2 -// https://stackoverflow.com/questions/1322510/given-an-integer-how-do-i-find-the-next-largest-power-of-two-using-bit-twiddlin/1322548#1322548 -static inline uint64_t utils_nearest_bigger_power_of_2_u64(uint64_t value) -{ - value--; - value |= value >> 1; - value |= value >> 2; - value |= value >> 4; - value |= value >> 8; - value |= value >> 16; - value |= value >> 32; - value++; - return value; -} // https://stackoverflow.com/questions/7666509/hash-function-for-string // http://www.cse.yorku.ca/~oz/hash.html -static inline size_t string_hash_djb2(const unsigned char* value, size_t length) +static inline size_t +utils_string_hash_djb2(const unsigned char* value, size_t length) { size_t hash = 5381; for (size_t i = 0; i < length && value[i] != '\0'; ++i) @@ -44,5 +29,6 @@ void stringmap_remove(StringMap* map, const char* key, size_t key_length); void stringmap_clean(StringMap* map); void stringmap_shrink(StringMap* map); void stringmap_clean_and_shrink(StringMap* map); +size_t stringmap_length(StringMap* map); #endif diff --git a/parser.c b/parser.c deleted file mode 100644 index c1dfa96..0000000 --- a/parser.c +++ /dev/null @@ -1 +0,0 @@ -#include "parser.h" diff --git a/scirpt/ast.c b/scirpt/ast.c new file mode 100644 index 0000000..c09c2d2 --- /dev/null +++ b/scirpt/ast.c @@ -0,0 +1,22 @@ +#include "scirpt/ast.h" +#include + +void scirpt_ast_expr_delete(ScirptAstExpr* expr) +{ + switch (expr->type) { + case ScirptAstExprTypeEof: + break; + case ScirptAstExprTypeError: + break; + case ScirptAstExprTypeId: + free(expr->id_value); + break; + case ScirptAstExprTypeInt: + break; + case ScirptAstExprTypeString: + free(expr->string_value); + break; + case ScirptAstExprTypeBool: + break; + } +} diff --git a/scirpt/lexer.c b/scirpt/lexer.c index 2c47a22..a2b6146 100644 --- a/scirpt/lexer.c +++ b/scirpt/lexer.c @@ -6,6 +6,8 @@ #include #include +#define TT(type) ScirptTokenType##type + static inline void step(ScirptLexer* lexer) { scirpt_lexer_step(lexer); } static inline ScirptToken token(const ScirptLexer* lexer, ScirptTokenType type, ScirptPosition start) @@ -49,18 +51,21 @@ void scirpt_lexer_create( ) { StringMap* keywords = stringmap_new(); - add_keyword(keywords, "null", ScirptTokenTypeNull); - add_keyword(keywords, "false", ScirptTokenTypeFalse); - add_keyword(keywords, "true", ScirptTokenTypeTrue); - add_keyword(keywords, "let", ScirptTokenTypeLet); - add_keyword(keywords, "if", ScirptTokenTypeIf); - add_keyword(keywords, "else", ScirptTokenTypeElse); - add_keyword(keywords, "while", ScirptTokenTypeWhile); - add_keyword(keywords, "for", ScirptTokenTypeFor); - add_keyword(keywords, "in", ScirptTokenTypeIn); - add_keyword(keywords, "break", ScirptTokenTypeBreak); - add_keyword(keywords, "fn", ScirptTokenTypeFn); - add_keyword(keywords, "return", ScirptTokenTypeReturn); + add_keyword(keywords, "null", TT(Null)); + add_keyword(keywords, "false", TT(False)); + add_keyword(keywords, "true", TT(True)); + add_keyword(keywords, "not", TT(Not)); + add_keyword(keywords, "and", TT(And)); + add_keyword(keywords, "or", TT(Or)); + add_keyword(keywords, "let", TT(Let)); + add_keyword(keywords, "if", TT(If)); + add_keyword(keywords, "else", TT(Else)); + add_keyword(keywords, "while", TT(While)); + add_keyword(keywords, "for", TT(For)); + add_keyword(keywords, "in", TT(In)); + add_keyword(keywords, "break", TT(Break)); + add_keyword(keywords, "fn", TT(Fn)); + add_keyword(keywords, "return", TT(Return)); *lexer = (ScirptLexer) { .text = text, .text_length = text_length, @@ -99,27 +104,196 @@ static inline bool is_id_char(char value) ScirptToken scirpt_lexer_next(ScirptLexer* lexer) { - if (done(lexer)) { - return token(lexer, ScirptTokenTypeEof, pos(lexer)); - } else if (is_whitespace(current(lexer))) { + return scirpt_lexer_level_1(lexer); +} + +ScirptToken scirpt_lexer_level_1(ScirptLexer* lexer) +{ + if (done(lexer)) + return token(lexer, TT(Eof), pos(lexer)); + else if (is_whitespace(current(lexer))) + return scirpt_lexer_skip_whitespace(lexer); + else if (is_id_char_excluding_numbers(current(lexer))) + return scirpt_lexer_id_token(lexer); + else + return scirpt_lexer_level_2(lexer); +} + +static inline ScirptToken single_token(ScirptLexer* lexer, ScirptTokenType type) +{ + ScirptPosition start = pos(lexer); + step(lexer); + return token(lexer, type, start); +} + +static inline ScirptToken single_or_double_token( + ScirptLexer* lexer, + ScirptTokenType first_type, + char second_char, + ScirptTokenType second_type +) +{ + ScirptPosition start = pos(lexer); + step(lexer); + if (current_is(lexer, second_char)) { step(lexer); - while (!done(lexer) && is_whitespace(current(lexer))) + return token(lexer, second_type, start); + } else { + return token(lexer, first_type, start); + } +} + +ScirptToken scirpt_lexer_level_2(ScirptLexer* lexer) +{ + switch (current(lexer)) { + case '0': + return single_token(lexer, TT(Int)); + case '"': + return scirpt_lexer_string_token(lexer); + case '(': + return single_token(lexer, TT(LParen)); + case ')': + return single_token(lexer, TT(RParen)); + case '{': + return single_token(lexer, TT(LBrace)); + case '}': + return single_token(lexer, TT(RBrace)); + case '[': + return single_token(lexer, TT(LBracket)); + case ']': + return single_token(lexer, TT(RBracket)); + case '.': + return single_token(lexer, TT(RBracket)); + case ',': + return single_token(lexer, TT(RBracket)); + case ':': + return single_token(lexer, TT(RBracket)); + case ';': + return single_token(lexer, TT(RBracket)); + case '+': + return single_or_double_token(lexer, TT(Plus), '=', TT(PlusEqual)); + case '-': + return single_or_double_token( + lexer, TT(Minus), '=', TT(MinusEqual) + ); + case '*': + return single_or_double_token( + lexer, TT(Asterisk), '=', TT(AsteriskEqual) + ); + case '/': + return single_token(lexer, TT(RBracket)); + case '%': + return single_or_double_token( + lexer, TT(Percent), '=', TT(PercentEqual) + ); + case '=': + return single_or_double_token( + lexer, TT(Equal), '=', TT(EqualEqual) + ); + case '!': + return single_or_double_token( + lexer, TT(Exclamation), '=', TT(ExclamationEqual) + ); + case '<': + return single_or_double_token(lexer, TT(Lt), '=', TT(LtEqual)); + case '>': + return single_or_double_token(lexer, TT(Gt), '=', TT(GtEqual)); + default: + return scirpt_lexer_level_3(lexer); + } +} + +ScirptToken scirpt_lexer_level_3(ScirptLexer* lexer) +{ + if (is_int_char(current(lexer))) + return scirpt_lexer_int_token(lexer); + else + return single_token(lexer, TT(InvalidChar)); +} + +ScirptToken scirpt_lexer_skip_whitespace(ScirptLexer* lexer) +{ + step(lexer); + while (!done(lexer) && is_whitespace(current(lexer))) + step(lexer); + return scirpt_lexer_next(lexer); +} + +ScirptToken scirpt_lexer_id_token(ScirptLexer* lexer) +{ + ScirptPosition start = pos(lexer); + step(lexer); + while (!done(lexer) && is_id_char(current(lexer))) + step(lexer); + size_t* found_keyword = stringmap_get( + lexer->keywords, &lexer->text[start.index], lexer->index - start.index + ); + if (found_keyword) + return token(lexer, (ScirptTokenType)*found_keyword, start); + else + return token(lexer, TT(Id), start); +} + +ScirptToken scirpt_lexer_int_token(ScirptLexer* lexer) +{ + ScirptPosition start = pos(lexer); + step(lexer); + while (!done(lexer) && is_int_char(current(lexer))) + step(lexer); + return token(lexer, TT(Int), start); +} + +ScirptToken scirpt_lexer_string_token(ScirptLexer* lexer) +{ + ScirptPosition start = pos(lexer); + step(lexer); + while (!done(lexer) && current(lexer) != '\"') { + char first = current(lexer); + step(lexer); + if (!done(lexer) && first == '\\') + step(lexer); + } + if (!current_is(lexer, '"')) + return token(lexer, TT(MalformedString), start); + step(lexer); + return token(lexer, TT(String), start); +} + +ScirptToken scirpt_lexer_slash_token(ScirptLexer* lexer) +{ + + ScirptPosition start = pos(lexer); + step(lexer); + if (current_is(lexer, TT(Slash))) { + step(lexer); + while (!done(lexer) && current(lexer) != '\n') step(lexer); return scirpt_lexer_next(lexer); - } else if (is_id_char_excluding_numbers(current(lexer))) { - ScirptPosition start = pos(lexer); + } else if (current_is(lexer, TT(Asterisk))) { step(lexer); - while (!done(lexer) && is_id_char(current(lexer))) - step(lexer); - return token(lexer, ScirptTokenTypeId, start); - } else { - switch (current(lexer)) { - default: { - ScirptPosition start = pos(lexer); - step(lexer); - return token(lexer, ScirptTokenTypeInvalidChar, start); + int depth = 0; + char last_char = '\0'; + while (!done(lexer)) { + if (last_char == '/' && current(lexer) == '*') { + depth++; + } else if (last_char == '*' && current(lexer) == '/') { + depth--; + if (depth == 0) { + step(lexer); + break; + } } + last_char = current(lexer); + step(lexer); } + if (depth != 0) + return token(lexer, TT(MalformedComment), start); + return scirpt_lexer_next(lexer); + } else if (current_is(lexer, TT(Equal))) { + step(lexer); + return token(lexer, TT(SlashEqual), start); + } else { + return token(lexer, TT(Slash), start); } } diff --git a/scirpt/lexer.h b/scirpt/lexer.h index 3ebbf01..162b5fc 100644 --- a/scirpt/lexer.h +++ b/scirpt/lexer.h @@ -19,6 +19,14 @@ void scirpt_lexer_create( ScirptLexer* lexer, const char* text, size_t text_length ); void scirpt_lexer_destroy(ScirptLexer* lexer); +ScirptToken scirpt_lexer_level_1(ScirptLexer* lexer); +ScirptToken scirpt_lexer_level_2(ScirptLexer* lexer); +ScirptToken scirpt_lexer_level_3(ScirptLexer* lexer); +ScirptToken scirpt_lexer_skip_whitespace(ScirptLexer* lexer); +ScirptToken scirpt_lexer_id_token(ScirptLexer* lexer); +ScirptToken scirpt_lexer_int_token(ScirptLexer* lexer); +ScirptToken scirpt_lexer_string_token(ScirptLexer* lexer); +ScirptToken scirpt_lexer_slash_token(ScirptLexer* lexer); void scirpt_lexer_step(ScirptLexer* lexer); ScirptPosition scirpt_lexer_pos(const ScirptLexer* lexer); ScirptToken scirpt_lexer_token( diff --git a/scirpt/main.c b/scirpt/main.c index 1e2af83..291dcc4 100644 --- a/scirpt/main.c +++ b/scirpt/main.c @@ -1,20 +1,56 @@ +#include "scirpt/ast.h" #include "scirpt/lexer.h" +#include "scirpt/parser.h" #include "scirpt/token.h" #include +#include #include #include int main(void) { - printf("hello world\n"); - const char* text = "123 if +"; + printf("test program = \"\"\"\n%s\n\"\"\"\n", text); - ScirptLexer* lexer = scirpt_lexer_new(text, strlen(text)); - while (true) { - ScirptToken token = scirpt_lexer_next(lexer); - if (token.type == ScirptTokenTypeEof) - break; - printf("%d\n", token.type); + { + printf("\n- test lexer\n"); + ScirptLexer* lexer = scirpt_lexer_new(text, strlen(text)); + while (true) { + ScirptToken token = scirpt_lexer_next(lexer); + if (token.type == ScirptTokenTypeEof) + break; + printf("%d\n", token.type); + } + scirpt_lexer_delete(lexer); + } + + { + printf("\n- test lexer + parser\n"); + ScirptLexer* lexer = scirpt_lexer_new(text, strlen(text)); + ScirptParser* parser = scirpt_parser_new(text, strlen(text), lexer); + while (true) { + ScirptAstExpr* expr = scirpt_parser_next_expr(parser); + if (expr->type == ScirptAstExprTypeEof) { + break; + } else if (!scirpt_parser_ok(parser)) { + const ScirptParserErrorArray* errors + = scirpt_parser_errors(parser); + for (size_t i = 0; i < scirpt_parser_error_array_length(errors); + ++i) { + ScirptParserError* error + = scirpt_parser_error_array_get(errors, i); + printf( + "error: %s at %d:%d\n", + error->message.data, + error->pos.line, + error->pos.col + ); + } + break; + } + printf("%d\n", expr->type); + scirpt_ast_expr_delete(expr); + } + scirpt_parser_delete(parser); } } diff --git a/scirpt/parser.c b/scirpt/parser.c index e69de29..61eefb6 100644 --- a/scirpt/parser.c +++ b/scirpt/parser.c @@ -0,0 +1,160 @@ +#include "scirpt/parser.h" +#include "parser.h" +#include "scirpt/ast.h" +#include "scirpt/lexer.h" +#include "scirpt/position.h" +#include "scirpt/token.h" +#include "utils/string.h" +#include +#include + +#define TT(type) ScirptTokenType##type + +static inline ScirptAstExpr* alloc_expr(ScirptAstExpr data) +{ + ScirptAstExpr* expr = malloc(sizeof(ScirptAstExpr)); + *expr = data; + return expr; +} +static inline void +error(ScirptParser* parser, HeapString message, ScirptPosition pos) +{ + scirpt_parser_error(parser, message, pos); +} +static inline ScirptPosition pos(ScirptParser* parser) +{ + return parser->current.pos; +} +static inline void step(ScirptParser* parser) { scirpt_parser_step(parser); } +static inline bool current_is(const ScirptParser* parser, ScirptTokenType type) +{ + return scirpt_parser_current_is(parser, type); +} +static inline bool done(const ScirptParser* parser) +{ + return scirpt_parser_done(parser); +} + +ScirptParser* +scirpt_parser_new(const char* text, size_t text_length, ScirptLexer* lexer) +{ + ScirptParser* parser = malloc(sizeof(ScirptParser)); + scirpt_parser_construct(parser, text, text_length, lexer); + return parser; +} + +void scirpt_parser_delete(ScirptParser* parser) { free(parser); } + +ScirptAstExpr* scirpt_parser_next_expr(ScirptParser* parser) +{ + if (done(parser)) { + return alloc_expr((ScirptAstExpr) { + .type = ScirptAstExprTypeEof, + }); + } else { + return scirpt_parser_parse_expr(parser); + } +} + +bool scirpt_parser_ok(const ScirptParser* parser) { return parser->ok; } + +const ScirptParserErrorArray* scirpt_parser_errors(const ScirptParser* parser) +{ + return &parser->errors; +} + +void scirpt_parser_construct( + ScirptParser* parser, + const char* text, + size_t text_length, + ScirptLexer* lexer +) +{ + ScirptParserErrorArray errors; + scirpt_parser_error_array_construct(&errors); + + *parser = (ScirptParser) { + .text = text, + .text_length = text_length, + .lexer = lexer, + .current = scirpt_lexer_next(lexer), + .errors = errors, + .ok = true, + }; +} + +void scirpt_parser_destroy(ScirptParser* parser) +{ + scirpt_parser_error_array_construct(&parser->errors); +} + +ScirptAstExpr* scirpt_parser_parse_expr(ScirptParser* parser) +{ + return scirpt_parser_parse_operand(parser); +} + +ScirptAstExpr* scirpt_parser_parse_operand(ScirptParser* parser) +{ + switch (parser->current.type) { + case ScirptTokenTypeInt: { + HeapString value_string = heapstring_from( + &parser->text[pos(parser).index], parser->current.length + ); + int64_t value = atoll(value_string.data); + step(parser); + return alloc_expr((ScirptAstExpr) { + .type = ScirptAstExprTypeInt, + .int_value = value, + }); + } + case ScirptTokenTypeEof: { + error( + parser, + heapstring_from_cstring("expected value, got Eof"), + pos(parser) + ); + return alloc_expr((ScirptAstExpr) { + .type = ScirptAstExprTypeError, + }); + } + default: { + error( + parser, heapstring_from_cstring("expected value"), pos(parser) + ); + step(parser); + return alloc_expr((ScirptAstExpr) { + .type = ScirptAstExprTypeError, + }); + } + } +} + +void scirpt_parser_error( + ScirptParser* parser, HeapString message, ScirptPosition pos +) +{ + if (parser->ok) + parser->ok = false; + scirpt_parser_error_array_append( + &parser->errors, + (ScirptParserError) { + .message = message, + .pos = pos, + } + ); +} + +void scirpt_parser_step(ScirptParser* parser) +{ + parser->current = scirpt_lexer_next(parser->lexer); +} + +bool scirpt_parser_current_is(const ScirptParser* parser, ScirptTokenType type) +{ + return parser->current.type == type; +} + +bool scirpt_parser_done(const ScirptParser* parser) +{ + return parser->current.type == ScirptTokenTypeEof; +} diff --git a/scirpt/parser.h b/scirpt/parser.h index c349953..8d76bf3 100644 --- a/scirpt/parser.h +++ b/scirpt/parser.h @@ -1,6 +1,37 @@ #ifndef PARSER_H #define PARSER_H +#include "scirpt/ast.h" +#include "scirpt/lexer.h" #include "scirpt/parser.h" +#include "scirpt/position.h" +#include "scirpt/token.h" +#include +#include + +struct ScirptParser { + const char* text; + size_t text_length; + ScirptLexer* lexer; + ScirptToken current; + ScirptParserErrorArray errors; + bool ok; +}; + +void scirpt_parser_construct( + ScirptParser* parser, + const char* text, + size_t text_length, + ScirptLexer* lexer +); +void scirpt_parser_destroy(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_expr(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_operand(ScirptParser* parser); +void scirpt_parser_error( + ScirptParser* parser, HeapString message, ScirptPosition pos +); +void scirpt_parser_step(ScirptParser* parser); +bool scirpt_parser_current_is(const ScirptParser* parser, ScirptTokenType type); +bool scirpt_parser_done(const ScirptParser* parser); #endif diff --git a/session.vim b/session.vim new file mode 100644 index 0000000..758b70a --- /dev/null +++ b/session.vim @@ -0,0 +1,464 @@ +let SessionLoad = 1 +let s:so_save = &g:so | let s:siso_save = &g:siso | setg so=0 siso=0 | setl so=-1 siso=-1 +let v:this_session=expand(":p") +silent only +silent tabonly +cd ~/Workspace/codebased +if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' + let s:wipebuf = bufnr('%') +endif +let s:shortmess_save = &shortmess +if &shortmess =~ 'A' + set shortmess=aoOA +else + set shortmess=aoO +endif +badd +258 scirpt/lexer.c +badd +0 include/scirpt/lexer.h +badd +29 scirpt/lexer.h +badd +11 include/scirpt/token.h +badd +18 term://~/Workspace/codebased//21887:/bin/bash +badd +32 include/utils/stringmap.h +badd +3 utils/stringmap.h +badd +39 utils/stringmap.c +badd +13 scirpt/main.c +badd +26 include/scirpt/ast.h +badd +27 include/scirpt/parser.h +badd +30 scirpt/parser.h +badd +61 scirpt/parser.c +badd +17 scirpt/ast.c +badd +19 include/utils/math.h +badd +9 include/utils/string.h +badd +59 include/utils/generic_array.h +badd +9 include/utils/string_array.h +badd +17 Makefile +argglobal +%argdel +set stal=2 +tabnew +setlocal\ bufhidden=wipe +tabnew +setlocal\ bufhidden=wipe +tabnew +setlocal\ bufhidden=wipe +tabrewind +edit scirpt/main.c +let s:save_splitbelow = &splitbelow +let s:save_splitright = &splitright +set splitbelow splitright +wincmd _ | wincmd | +vsplit +1wincmd h +wincmd w +let &splitbelow = s:save_splitbelow +let &splitright = s:save_splitright +wincmd t +let s:save_winminheight = &winminheight +let s:save_winminwidth = &winminwidth +set winminheight=0 +set winheight=1 +set winminwidth=0 +set winwidth=1 +exe 'vert 1resize ' . ((&columns * 127 + 127) / 255) +exe 'vert 2resize ' . ((&columns * 127 + 127) / 255) +argglobal +balt Makefile +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let &fdl = &fdl +let s:l = 30 - ((29 * winheight(0) + 32) / 65) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 30 +normal! 076| +wincmd w +argglobal +if bufexists(fnamemodify("term://~/Workspace/codebased//21887:/bin/bash", ":p")) | buffer term://~/Workspace/codebased//21887:/bin/bash | else | edit term://~/Workspace/codebased//21887:/bin/bash | endif +if &buftype ==# 'terminal' + silent file term://~/Workspace/codebased//21887:/bin/bash +endif +balt scirpt/lexer.c +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +let s:l = 164 - ((28 * winheight(0) + 32) / 65) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 164 +normal! 031| +wincmd w +2wincmd w +exe 'vert 1resize ' . ((&columns * 127 + 127) / 255) +exe 'vert 2resize ' . ((&columns * 127 + 127) / 255) +tabnext +edit include/utils/stringmap.h +let s:save_splitbelow = &splitbelow +let s:save_splitright = &splitright +set splitbelow splitright +wincmd _ | wincmd | +vsplit +1wincmd h +wincmd _ | wincmd | +split +1wincmd k +wincmd w +wincmd w +let &splitbelow = s:save_splitbelow +let &splitright = s:save_splitright +wincmd t +let s:save_winminheight = &winminheight +let s:save_winminwidth = &winminwidth +set winminheight=0 +set winheight=1 +set winminwidth=0 +set winwidth=1 +exe '1resize ' . ((&lines * 32 + 34) / 68) +exe 'vert 1resize ' . ((&columns * 127 + 127) / 255) +exe '2resize ' . ((&lines * 32 + 34) / 68) +exe 'vert 2resize ' . ((&columns * 127 + 127) / 255) +exe 'vert 3resize ' . ((&columns * 127 + 127) / 255) +argglobal +balt term://~/Workspace/codebased//21887:/bin/bash +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let &fdl = &fdl +let s:l = 29 - ((22 * winheight(0) + 16) / 32) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 29 +normal! 037| +wincmd w +argglobal +if bufexists(fnamemodify("utils/stringmap.h", ":p")) | buffer utils/stringmap.h | else | edit utils/stringmap.h | endif +if &buftype ==# 'terminal' + silent file utils/stringmap.h +endif +balt include/utils/stringmap.h +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let &fdl = &fdl +let s:l = 14 - ((13 * winheight(0) + 16) / 32) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 14 +normal! 022| +wincmd w +argglobal +if bufexists(fnamemodify("include/utils/generic_array.h", ":p")) | buffer include/utils/generic_array.h | else | edit include/utils/generic_array.h | endif +if &buftype ==# 'terminal' + silent file include/utils/generic_array.h +endif +balt include/utils/string.h +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let &fdl = &fdl +let s:l = 36 - ((35 * winheight(0) + 32) / 65) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 36 +normal! 014| +wincmd w +exe '1resize ' . ((&lines * 32 + 34) / 68) +exe 'vert 1resize ' . ((&columns * 127 + 127) / 255) +exe '2resize ' . ((&lines * 32 + 34) / 68) +exe 'vert 2resize ' . ((&columns * 127 + 127) / 255) +exe 'vert 3resize ' . ((&columns * 127 + 127) / 255) +tabnext +edit include/scirpt/token.h +let s:save_splitbelow = &splitbelow +let s:save_splitright = &splitright +set splitbelow splitright +wincmd _ | wincmd | +vsplit +wincmd _ | wincmd | +vsplit +2wincmd h +wincmd w +wincmd _ | wincmd | +split +1wincmd k +wincmd w +wincmd w +let &splitbelow = s:save_splitbelow +let &splitright = s:save_splitright +wincmd t +let s:save_winminheight = &winminheight +let s:save_winminwidth = &winminwidth +set winminheight=0 +set winheight=1 +set winminwidth=0 +set winwidth=1 +exe 'vert 1resize ' . ((&columns * 46 + 127) / 255) +exe '2resize ' . ((&lines * 19 + 34) / 68) +exe 'vert 2resize ' . ((&columns * 79 + 127) / 255) +exe '3resize ' . ((&lines * 45 + 34) / 68) +exe 'vert 3resize ' . ((&columns * 79 + 127) / 255) +exe 'vert 4resize ' . ((&columns * 128 + 127) / 255) +argglobal +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let &fdl = &fdl +let s:l = 22 - ((21 * winheight(0) + 32) / 65) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 22 +normal! 025| +wincmd w +argglobal +if bufexists(fnamemodify("include/scirpt/lexer.h", ":p")) | buffer include/scirpt/lexer.h | else | edit include/scirpt/lexer.h | endif +if &buftype ==# 'terminal' + silent file include/scirpt/lexer.h +endif +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let &fdl = &fdl +let s:l = 1 - ((0 * winheight(0) + 9) / 19) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 1 +normal! 09| +wincmd w +argglobal +if bufexists(fnamemodify("scirpt/lexer.h", ":p")) | buffer scirpt/lexer.h | else | edit scirpt/lexer.h | endif +if &buftype ==# 'terminal' + silent file scirpt/lexer.h +endif +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let &fdl = &fdl +let s:l = 39 - ((38 * winheight(0) + 22) / 45) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 39 +normal! 06| +wincmd w +argglobal +if bufexists(fnamemodify("scirpt/lexer.c", ":p")) | buffer scirpt/lexer.c | else | edit scirpt/lexer.c | endif +if &buftype ==# 'terminal' + silent file scirpt/lexer.c +endif +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let &fdl = &fdl +let s:l = 11 - ((10 * winheight(0) + 32) / 65) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 11 +normal! 041| +wincmd w +exe 'vert 1resize ' . ((&columns * 46 + 127) / 255) +exe '2resize ' . ((&lines * 19 + 34) / 68) +exe 'vert 2resize ' . ((&columns * 79 + 127) / 255) +exe '3resize ' . ((&lines * 45 + 34) / 68) +exe 'vert 3resize ' . ((&columns * 79 + 127) / 255) +exe 'vert 4resize ' . ((&columns * 128 + 127) / 255) +tabnext +edit include/scirpt/ast.h +let s:save_splitbelow = &splitbelow +let s:save_splitright = &splitright +set splitbelow splitright +wincmd _ | wincmd | +vsplit +wincmd _ | wincmd | +vsplit +2wincmd h +wincmd w +wincmd _ | wincmd | +split +1wincmd k +wincmd w +wincmd w +let &splitbelow = s:save_splitbelow +let &splitright = s:save_splitright +wincmd t +let s:save_winminheight = &winminheight +let s:save_winminwidth = &winminwidth +set winminheight=0 +set winheight=1 +set winminwidth=0 +set winwidth=1 +exe 'vert 1resize ' . ((&columns * 60 + 127) / 255) +exe '2resize ' . ((&lines * 32 + 34) / 68) +exe 'vert 2resize ' . ((&columns * 88 + 127) / 255) +exe '3resize ' . ((&lines * 32 + 34) / 68) +exe 'vert 3resize ' . ((&columns * 88 + 127) / 255) +exe 'vert 4resize ' . ((&columns * 105 + 127) / 255) +argglobal +balt scirpt/lexer.c +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let &fdl = &fdl +let s:l = 22 - ((21 * winheight(0) + 32) / 65) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 22 +normal! 024| +wincmd w +argglobal +if bufexists(fnamemodify("include/scirpt/parser.h", ":p")) | buffer include/scirpt/parser.h | else | edit include/scirpt/parser.h | endif +if &buftype ==# 'terminal' + silent file include/scirpt/parser.h +endif +balt include/scirpt/ast.h +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let &fdl = &fdl +let s:l = 27 - ((26 * winheight(0) + 16) / 32) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 27 +normal! 06| +wincmd w +argglobal +if bufexists(fnamemodify("scirpt/parser.h", ":p")) | buffer scirpt/parser.h | else | edit scirpt/parser.h | endif +if &buftype ==# 'terminal' + silent file scirpt/parser.h +endif +balt include/scirpt/parser.h +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let &fdl = &fdl +let s:l = 10 - ((9 * winheight(0) + 16) / 32) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 10 +normal! 019| +wincmd w +argglobal +if bufexists(fnamemodify("scirpt/parser.c", ":p")) | buffer scirpt/parser.c | else | edit scirpt/parser.c | endif +if &buftype ==# 'terminal' + silent file scirpt/parser.c +endif +balt include/scirpt/parser.h +setlocal fdm=manual +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=0 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +silent! normal! zE +let &fdl = &fdl +let s:l = 61 - ((45 * winheight(0) + 32) / 65) +if s:l < 1 | let s:l = 1 | endif +keepjumps exe s:l +normal! zt +keepjumps 61 +normal! 06| +wincmd w +exe 'vert 1resize ' . ((&columns * 60 + 127) / 255) +exe '2resize ' . ((&lines * 32 + 34) / 68) +exe 'vert 2resize ' . ((&columns * 88 + 127) / 255) +exe '3resize ' . ((&lines * 32 + 34) / 68) +exe 'vert 3resize ' . ((&columns * 88 + 127) / 255) +exe 'vert 4resize ' . ((&columns * 105 + 127) / 255) +tabnext 1 +set stal=1 +if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' + silent exe 'bwipe ' . s:wipebuf +endif +unlet! s:wipebuf +set winheight=1 winwidth=20 +let &shortmess = s:shortmess_save +let &winminheight = s:save_winminheight +let &winminwidth = s:save_winminwidth +let s:sx = expand(":p:r")."x.vim" +if filereadable(s:sx) + exe "source " . fnameescape(s:sx) +endif +let &g:so = s:so_save | let &g:siso = s:siso_save +doautoall SessionLoadPost +unlet SessionLoad +" vim: set ft=vim : diff --git a/utils/stringmap.c b/utils/stringmap.c index ed70837..37d23e2 100644 --- a/utils/stringmap.c +++ b/utils/stringmap.c @@ -1,4 +1,5 @@ #include "stringmap.h" +#include "utils/math.h" #include "utils/stringmap.h" #include #include @@ -14,18 +15,20 @@ void stringmap_delete(StringMap* map) { free(map); } size_t* stringmap_get(const StringMap* map, const char* key, size_t key_length) { - size_t key_hash = string_hash_djb2((const unsigned char*)key, key_length); - for (size_t i = 0; i < map->size; ++i) - if (map->entries[i].key_hash == key_hash && !map->entries[i].deleted) - return &map->entries[i].value; + size_t key_hash + = utils_string_hash_djb2((const unsigned char*)key, key_length); + for (size_t i = 0; i < map->length; ++i) + if (map->data[i].key_hash == key_hash && !map->data[i].deleted) + return &map->data[i].value; return NULL; } bool stringmap_has(const StringMap* map, const char* key, size_t key_length) { - size_t key_hash = string_hash_djb2((const unsigned char*)key, key_length); - for (size_t i = 0; i < map->size; ++i) - if (map->entries[i].key_hash == key_hash && !map->entries[i].deleted) + size_t key_hash + = utils_string_hash_djb2((const unsigned char*)key, key_length); + for (size_t i = 0; i < map->length; ++i) + if (map->data[i].key_hash == key_hash && !map->data[i].deleted) return true; return false; } @@ -34,27 +37,27 @@ void stringmap_set( StringMap* map, const char* key, size_t key_length, size_t value ) { - size_t key_hash = string_hash_djb2((const unsigned char*)key, key_length); - for (size_t i = 0; i < map->size; ++i) { - if (map->entries[i].key_hash == key_hash && !map->entries[i].deleted) { - map->entries[i].value = value; + size_t key_hash + = utils_string_hash_djb2((const unsigned char*)key, key_length); + for (size_t i = 0; i < map->length; ++i) { + if (map->data[i].key_hash == key_hash && !map->data[i].deleted) { + map->data[i].value = value; return; } } - if (map->entries == NULL) { + if (map->data == NULL) { map->capacity = 8; - map->entries = malloc(sizeof(StringMapEntry) * map->capacity); - } else if (map->size == map->capacity) { + map->data = malloc(sizeof(StringMapEntry) * map->capacity); + } else if (map->length == map->capacity) { map->capacity *= 2; - map->entries - = realloc(map->entries, sizeof(StringMapEntry) * map->capacity); + map->data = realloc(map->data, sizeof(StringMapEntry) * map->capacity); } - map->entries[map->size] = (StringMapEntry) { + map->data[map->length] = (StringMapEntry) { .deleted = false, .key_hash = key_hash, .value = value, }; - map->size++; + map->length++; } void stringmap_reserve(StringMap* map, size_t minimum_size) @@ -62,16 +65,16 @@ void stringmap_reserve(StringMap* map, size_t minimum_size) if (map->capacity >= minimum_size) return; map->capacity = utils_nearest_bigger_power_of_2_u64(minimum_size); - map->entries - = realloc(map->entries, sizeof(StringMapEntry) * map->capacity); + map->data = realloc(map->data, sizeof(StringMapEntry) * map->capacity); } void stringmap_remove(StringMap* map, const char* key, size_t key_length) { - size_t key_hash = string_hash_djb2((const unsigned char*)key, key_length); - for (size_t i = 0; i < map->size; ++i) { - if (map->entries[i].key_hash == key_hash && !map->entries[i].deleted) { - map->entries[i].deleted = true; + size_t key_hash + = utils_string_hash_djb2((const unsigned char*)key, key_length); + for (size_t i = 0; i < map->length; ++i) { + if (map->data[i].key_hash == key_hash && !map->data[i].deleted) { + map->data[i].deleted = true; } } } @@ -79,21 +82,20 @@ void stringmap_remove(StringMap* map, const char* key, size_t key_length) void stringmap_clean(StringMap* map) { size_t shift_amount = 0; - for (size_t i = 0; i < map->size; ++i) { - map->entries[i - shift_amount] = map->entries[i]; - if (map->entries[i].deleted) + for (size_t i = 0; i < map->length; ++i) { + map->data[i - shift_amount] = map->data[i]; + if (map->data[i].deleted) shift_amount++; } } void stringmap_shrink(StringMap* map) { - size_t new_size = utils_nearest_bigger_power_of_2_u64(map->size); + size_t new_size = utils_nearest_bigger_power_of_2_u64(map->length); if (new_size >= map->capacity) return; map->capacity = new_size; - map->entries - = realloc(map->entries, sizeof(StringMapEntry) * map->capacity); + map->data = realloc(map->data, sizeof(StringMapEntry) * map->capacity); } void stringmap_clean_and_shrink(StringMap* map) @@ -102,17 +104,19 @@ void stringmap_clean_and_shrink(StringMap* map) stringmap_shrink(map); } +size_t stringmap_length(StringMap* map) { return map->length; } + void stringmap_create(StringMap* map) { *map = (StringMap) { - .entries = NULL, - .size = 0, + .data = NULL, + .length = 0, .capacity = 0, }; } void stringmap_destroy(StringMap* map) { - if (map->entries) - free(map->entries); + if (map->data) + free(map->data); } diff --git a/utils/stringmap.h b/utils/stringmap.h index d9c3c64..5faf01f 100644 --- a/utils/stringmap.h +++ b/utils/stringmap.h @@ -11,8 +11,8 @@ typedef struct StringMapEntry { } StringMapEntry; struct StringMap { - StringMapEntry* entries; - size_t size, capacity; + StringMapEntry* data; + size_t length, capacity; }; void stringmap_create(StringMap* map);