From 70d3ef508e10d458b89bf1eaac7238fa61376112 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Fri, 8 Oct 2021 16:11:39 +0200 Subject: Add support for strings --- src/bootstrap/main.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c index fad3333..241697a 100755 --- a/src/bootstrap/main.c +++ b/src/bootstrap/main.c @@ -5,6 +5,10 @@ #include "shorthand.h" + +// FIXME: We are not worried right now about freeing memory, but we should in +// the future. + typedef struct StringView { char *start; size_t n; @@ -93,8 +97,44 @@ tokenize(StringView sv) { } continue; } break; + case '"': { + if (token_n != 0) { + fprintf(stderr, "error: string started inside symbol\n"); + return (Tokens){0}; + } + + // Find end delimiter. + size_t string_start = i + 1; + size_t string_end = i + 1; + while (true) { + if (sv.start[string_end] == '"' && sv.start[string_end - 1] != '\\') { + break; + } + if (string_end >= sv.n) { + fprintf(stderr, "error: string delimiter not found\n"); + return (Tokens){0}; + } + string_end++; + } + + // Push string token. + tokens_buf[n++] = (StringView){ + .start = &sv.start[string_start - 1], + .n = 1, + }; + tokens_buf[n++] = (StringView){ + .start = &sv.start[string_start], + .n = string_end - string_start, + }; + tokens_buf[n++] = (StringView){ + .start = &sv.start[string_end], + .n = 1, + }; + token_n = 0; + i += string_end - string_start + 1; + } break; case '(': { - if ((i + 1 < sv.n)) { + if ((i + 1) < sv.n) { char next_c = sv.start[i + 1]; if (isspace(next_c)) { fprintf(stderr, "error: lparen delimiter followed by space\n"); @@ -113,7 +153,7 @@ tokenize(StringView sv) { }; } break; case ')': { - if ((i + 1 < sv.n)) { + if ((i + 1) < sv.n) { char next_c = sv.start[i + 1]; if ((next_c != ')' && !isspace(next_c))) { fprintf(stderr, "error: rparen delimiter within symbol name\n"); @@ -227,15 +267,28 @@ make_boolean(bool b) { } Object * -make_string(const char *str, size_t n) { +make_empty_string(void) { Object *obj = malloc(sizeof(Object)); obj->type = OBJ_TYPE_STRING; - obj->string = malloc(sizeof(char) * n); - memcpy(obj->string, str, n); - obj->string_n = n; + obj->string = NULL; + obj->string_n = 0; return obj; } +void +append_string(Object *string, StringView sv) { + assert(string != NULL); + assert(string->type == OBJ_TYPE_STRING); + + if (sv.n == 0) { + return; + } + + string->string = realloc(string->string, (string->string_n + sv.n) * sizeof(char)); + memcpy(string->string + string->string_n, sv.start, sv.n); + string->string_n += sv.n; +} + Object * make_symbol(const char *str, size_t n) { Object *obj = malloc(sizeof(Object)); @@ -302,6 +355,9 @@ build_ast(Tokens *tokens) { // TODO: Report error if we haven't consumed all the tokens? while (tokens->n > 0) { StringView *token = consume_token(tokens); + if (token == NULL) { + return NULL; + } // OBJ_TYPE_FIXNUM if (token_is_fixnum(*token)) { @@ -344,6 +400,15 @@ build_ast(Tokens *tokens) { return list; } + // OBJ_TYPE_STRING + if (token->start[0] == '"') { + Object *obj = make_empty_string(); + token = consume_token(tokens); + append_string(obj, *token); + consume_token(tokens); + return obj; + } + // OBJ_TYPE_SYMBOL return make_symbol(token->start, token->n); } -- cgit v1.2.1