1
0
Fork 0
lesson-lisp/src/parser.c

137 lines
3.5 KiB
C
Raw Normal View History

2023-05-04 06:20:48 -04:00
#include "parser.h"
#include "object.h"
#include "tokens.h"
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
2023-05-05 06:03:32 -04:00
#include <string.h>
2023-05-04 06:20:48 -04:00
2023-05-05 04:16:50 -04:00
static void expect(Tokens tokens, enum TokenType token_type);
2023-05-04 06:20:48 -04:00
2023-05-05 04:16:50 -04:00
static struct Object *expr(Tokens tokens);
static struct Object *parens(Tokens tokens);
static struct Object *parens_part(Tokens tokens);
2023-05-04 06:20:48 -04:00
2023-05-05 04:16:50 -04:00
void expect(const Tokens tokens, const enum TokenType token_type)
2023-05-04 06:20:48 -04:00
{
2023-05-05 04:16:50 -04:00
assert(Tokens_expect(tokens, token_type));
2023-05-04 06:20:48 -04:00
}
2023-05-05 04:16:50 -04:00
struct Object *parse(const Tokens tokens)
2023-05-04 06:20:48 -04:00
{
2023-05-05 04:16:50 -04:00
return expr(tokens);
2023-05-04 06:20:48 -04:00
}
2023-05-05 04:16:50 -04:00
struct Object *expr(const Tokens tokens)
2023-05-04 06:20:48 -04:00
{
2023-05-05 04:16:50 -04:00
assert(Tokens_top(tokens));
2023-05-04 06:20:48 -04:00
2023-05-05 04:16:50 -04:00
switch (Tokens_top(tokens)->type) {
2023-05-04 07:05:20 -04:00
case TOKEN_ROUND_OPEN:
case TOKEN_SQUARE_OPEN:
case TOKEN_CURLY_OPEN:
2023-05-05 04:16:50 -04:00
return parens(tokens);
2023-05-05 03:44:33 -04:00
case TOKEN_QUOTE:
2023-05-05 04:16:50 -04:00
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));
2023-05-05 06:03:32 -04:00
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;
}
2023-05-04 07:22:11 -04:00
case TOKEN_IDENT:
2023-05-04 06:20:48 -04:00
{
2023-05-05 04:16:50 -04:00
struct Object *const object = Object_new_symbol(Tokens_top(tokens)->val);
Tokens_pop(tokens);
2023-05-04 06:20:48 -04:00
return object;
}
case TOKEN_NUM:
{
struct Object *const object =
2023-05-05 04:16:50 -04:00
Object_new_number(atoll(Tokens_top(tokens)->val));
Tokens_pop(tokens);
2023-05-04 06:20:48 -04:00
return object;
}
2023-05-05 16:06:04 -04:00
case TOKEN_STRING:
{
struct Object *const object =
Object_new_string(Tokens_top(tokens)->val);
Tokens_pop(tokens);
return object;
}
2023-05-04 06:20:48 -04:00
default:
abort();
return NULL;
}
}
2023-05-05 04:16:50 -04:00
struct Object *parens(const Tokens tokens)
2023-05-04 06:20:48 -04:00
{
2023-05-05 04:16:50 -04:00
assert(Tokens_top(tokens));
2023-05-04 07:05:20 -04:00
struct Object *object = NULL;
2023-05-05 04:16:50 -04:00
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);
2023-05-04 07:05:20 -04:00
} else {
2023-05-05 04:16:50 -04:00
expect(tokens, TOKEN_CURLY_OPEN);
object = parens_part(tokens);
expect(tokens, TOKEN_CURLY_CLOSE);
2023-05-04 07:05:20 -04:00
}
2023-05-04 06:20:48 -04:00
return object;
}
2023-05-05 04:16:50 -04:00
struct Object *parens_part(const Tokens tokens)
2023-05-04 06:20:48 -04:00
{
2023-05-05 04:16:50 -04:00
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)
2023-05-04 07:05:20 -04:00
{
return NULL;
}
2023-05-04 06:20:48 -04:00
2023-05-05 04:16:50 -04:00
struct Object *const a = expr(tokens);
assert(Tokens_top(tokens));
2023-05-04 06:20:48 -04:00
struct Object *b = NULL;
2023-05-05 04:16:50 -04:00
if (Tokens_top(tokens)->type != TOKEN_ROUND_CLOSE &&
Tokens_top(tokens)->type != TOKEN_SQUARE_CLOSE &&
Tokens_top(tokens)->type != TOKEN_CURLY_CLOSE)
2023-05-04 07:05:20 -04:00
{
2023-05-05 04:16:50 -04:00
b = parens_part(tokens);
2023-05-04 06:20:48 -04:00
}
struct Object *object = Object_new_pair(a, b);
return object;
}