#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)
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);
}
}
-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) {
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;
}