]> git.lizzy.rs Git - nothing.git/blobdiff - src/script/expr.c
TODO(#296)
[nothing.git] / src / script / expr.c
index 1920655547b51ce3f26e23022823f2bbd2cfc4ab..39fd84cc7f8081a295b87b5a58bd2e4406a5e328 100644 (file)
@@ -7,9 +7,21 @@
 
 #include "script/expr.h"
 
-static struct Expr create_nil(void)
+static char *string_duplicate(const char *str,
+                              const char *str_end)
 {
-    return atom_as_expr(create_atom(ATOM_SYMBOL, "nil"));
+    if (str_end != NULL && str > str_end) {
+        return NULL;
+    }
+
+    const size_t n = str_end == NULL ? strlen(str) : (size_t) (str_end - str);
+    char *dup_str = malloc(sizeof(char) * (n + 1));
+    if (dup_str == NULL) {
+        return NULL;
+    }
+
+    memcpy(dup_str, str, n);
+    return dup_str;
 }
 
 struct Expr atom_as_expr(struct Atom *atom)
@@ -64,6 +76,7 @@ void print_cons_as_sexpr(struct Cons *cons)
 
 void print_expr_as_sexpr(struct Expr expr)
 {
+    /* TODO(#296): print_expr_as_sexpr doesn't support lists */
     switch (expr.type) {
     case EXPR_ATOM:
         print_atom_as_sexpr(expr.atom);
@@ -75,110 +88,6 @@ void print_expr_as_sexpr(struct Expr expr)
     }
 }
 
-struct ParseResult parse_success(struct Expr expr)
-{
-    struct ParseResult result = {
-        .is_error = false,
-        .expr = expr
-    };
-
-    return result;
-}
-
-struct ParseResult parse_failure(const char *error)
-{
-    struct ParseResult result = {
-        .is_error = true,
-        .error = error
-    };
-
-    return result;
-}
-
-static void skip_whitespaces(const char *str, size_t *cursor, size_t n)
-{
-    assert(str);
-    assert(cursor);
-    (void) n;
-
-    /* TODO: skip_whitespaces is not implemented */
-}
-
-struct ParseResult create_expr_from_str(const char *str,
-                                        size_t *cursor,
-                                        size_t n)
-{
-    assert(str);
-    assert(cursor);
-
-    skip_whitespaces(str, cursor, n);
-    if (*cursor >= n) {
-        return parse_failure("EOF");
-    }
-
-    switch (str[*cursor]) {
-    case '(': {
-        (*cursor)++;
-        struct ParseResult car = create_expr_from_str(str, cursor, n);
-        if (car.is_error) {
-            return car;
-        }
-
-        skip_whitespaces(str, cursor, n);
-        if (*cursor >= n) {
-            return parse_failure("EOF");
-        }
-
-        if (str[*cursor] != '.') {
-            return parse_failure("Expected .");
-        }
-        (*cursor)++;
-
-        skip_whitespaces(str, cursor, n);
-        if (*cursor >= n) {
-            return parse_failure("EOF");
-        }
-
-        struct ParseResult cdr = create_expr_from_str(str, cursor, n);
-        if (cdr.is_error) {
-            return cdr;
-        }
-
-        skip_whitespaces(str, cursor, n);
-        if (*cursor >= n) {
-            return parse_failure("EOF");
-        }
-
-        if (str[*cursor] != ')') {
-            return parse_failure("Expected )");
-        }
-
-        (*cursor)++;
-
-        return parse_success(cons_as_expr(create_cons(car.expr, cdr.expr)));
-    }
-
-    case '"': {
-        /* TODO: create_expr_from_str does not support strings */
-        return parse_failure("Strings are not supported");
-    }
-
-    default: {
-        if (isdigit(str[*cursor])) {
-            /* TODO: create_expr_from_str does not support numbers */
-            return parse_failure("Numbers are not supported");
-        } else if (isalpha(str[*cursor])) {
-            /* TODO: create_expr_from_str does not support symbols */
-            return parse_failure("Symbols are not supported");
-        } else {
-            return parse_failure("Unexpected sequence of characters");
-        }
-    }
-    }
-
-    return parse_success(create_nil());
-}
-
 void destroy_expr(struct Expr expr)
 {
     switch (expr.type) {
@@ -212,40 +121,45 @@ void destroy_cons(struct Cons *cons)
     free(cons);
 }
 
-struct Atom *create_atom(enum AtomType type, ...)
+struct Atom *create_number_atom(float num)
 {
     struct Atom *atom = malloc(sizeof(struct Atom));
     if (atom == NULL) {
         return NULL;
     }
+    atom->type = ATOM_NUMBER;
+    atom->num = num;
+    return atom;
+}
 
-    va_list args;
-    va_start(args, type);
-
-    atom->type = type;
-
-    switch (type) {
-    case ATOM_SYMBOL:
-    case ATOM_STRING: {
-        const char *arg_str = va_arg(args, const char *);
-        const size_t n = strlen(arg_str);
-        char *str = malloc(sizeof(char) * (n + 1));
-
-        if (str == NULL) {
-            free(atom);
-            return NULL;
-        }
+struct Atom *create_string_atom(const char *str, const char *str_end)
+{
+    struct Atom *atom = malloc(sizeof(struct Atom));
+    if (atom == NULL) {
+        return NULL;
+    }
+    atom->type = ATOM_STRING;
+    atom->str = string_duplicate(str, str_end);
+    if (atom->str == NULL) {
+        free(atom);
+        return NULL;
+    }
 
-        memcpy(str, arg_str, n + 1);
-        atom->str = str;
-    } break;
+    return atom;
+}
 
-    case ATOM_NUMBER: {
-        atom->num = (float) va_arg(args, double);
-    } break;
+struct Atom *create_symbol_atom(const char *sym, const char *sym_end)
+{
+    struct Atom *atom = malloc(sizeof(struct Atom));
+    if (atom == NULL) {
+        return NULL;
+    }
+    atom->type = ATOM_SYMBOL;
+    atom->sym = string_duplicate(sym, sym_end);
+    if (atom->sym == NULL) {
+        free(atom);
+        return NULL;
     }
-
-    va_end(args);
 
     return atom;
 }