#include "parser.h" #include "object.h" #include "tokens.h" #include #include #include #include static void expect(Tokens tokens, enum TokenType token_type); static struct Object *expr(Tokens tokens); static struct Object *parens(Tokens tokens); static struct Object *parens_part(Tokens tokens); void expect(const Tokens tokens, const enum TokenType token_type) { assert(Tokens_expect(tokens, token_type)); } struct Object *parse(const Tokens tokens) { return expr(tokens); } struct Object *expr(const Tokens tokens) { assert(Tokens_top(tokens)); switch (Tokens_top(tokens)->type) { case TOKEN_ROUND_OPEN: case TOKEN_SQUARE_OPEN: case TOKEN_CURLY_OPEN: return parens(tokens); case TOKEN_QUOTE: Tokens_pop(tokens); return \ Object_build_list(2, Object_new_symbol("quote"), expr(tokens)); case TOKEN_QUASI_QUOTE: Tokens_pop(tokens); return \ Object_build_list(2, Object_new_symbol("quasiquote"), expr(tokens)); case TOKEN_QUASI_UNQUOTE: Tokens_pop(tokens); return \ Object_build_list(2, Object_new_symbol("unquote"), expr(tokens)); case TOKEN_TAG: { struct Object *object = NULL; const char *const val = Tokens_top(tokens)->val; assert(val); if (strcmp(val, "f") == 0 || strcmp(val, "false") == 0) { object = Object_new_boolean(false); } else if (strcmp(val, "t") == 0 || strcmp(val, "true") == 0) { object = Object_new_boolean(true); } else { assert(0); } Tokens_pop(tokens); return object; } case TOKEN_IDENT: { struct Object *const object = Object_new_symbol(Tokens_top(tokens)->val); Tokens_pop(tokens); return object; } case TOKEN_NUM: { struct Object *const object = Object_new_number(atoll(Tokens_top(tokens)->val)); Tokens_pop(tokens); return object; } case TOKEN_STRING: { struct Object *const object = Object_new_string(Tokens_top(tokens)->val); Tokens_pop(tokens); return object; } default: abort(); return NULL; } } struct Object *parens(const Tokens tokens) { assert(Tokens_top(tokens)); struct Object *object = NULL; if (Tokens_top(tokens)->type == TOKEN_ROUND_OPEN) { expect(tokens, TOKEN_ROUND_OPEN); object = parens_part(tokens); expect(tokens, TOKEN_ROUND_CLOSE); } else if (Tokens_top(tokens)->type == TOKEN_SQUARE_OPEN) { expect(tokens, TOKEN_SQUARE_OPEN); object = parens_part(tokens); expect(tokens, TOKEN_SQUARE_CLOSE); } else { expect(tokens, TOKEN_CURLY_OPEN); object = parens_part(tokens); expect(tokens, TOKEN_CURLY_CLOSE); } return object; } struct Object *parens_part(const Tokens tokens) { assert(Tokens_top(tokens)); if (Tokens_top(tokens)->type == TOKEN_ROUND_CLOSE || Tokens_top(tokens)->type == TOKEN_SQUARE_CLOSE || Tokens_top(tokens)->type == TOKEN_CURLY_CLOSE) { return NULL; } struct Object *const a = expr(tokens); assert(Tokens_top(tokens)); struct Object *b = NULL; if (Tokens_top(tokens)->type != TOKEN_ROUND_CLOSE && Tokens_top(tokens)->type != TOKEN_SQUARE_CLOSE && Tokens_top(tokens)->type != TOKEN_CURLY_CLOSE) { b = parens_part(tokens); } struct Object *object = Object_new_pair(a, b); return object; }