1
0
Fork 0
lesson-lisp/parser.c

101 lines
2.1 KiB
C
Raw Normal View History

2023-05-04 06:20:48 -04:00
#include "parser.h"
#include "enums.h"
#include "object.h"
#include "tokens.h"
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
static void expect(enum TokenType token_type);
static struct Object *expr();
static struct Object *parens();
static struct Object *parens_part();
void expect(const enum TokenType token_type)
{
assert(tokens_expect(token_type));
}
struct Object *parse()
{
return expr();
}
struct Object *expr()
{
assert(tokens_top());
switch (tokens_top()->type) {
2023-05-04 07:05:20 -04:00
case TOKEN_ROUND_OPEN:
case TOKEN_SQUARE_OPEN:
case TOKEN_CURLY_OPEN:
return parens();
2023-05-04 06:29:22 -04:00
case TOKEN_SYMBOL:
2023-05-04 06:20:48 -04:00
{
2023-05-04 06:29:22 -04:00
struct Object *const object = Object_new_symbol(tokens_top()->val);
2023-05-04 06:20:48 -04:00
tokens_pop();
return object;
}
case TOKEN_NUM:
{
struct Object *const object =
Object_new_number(atoll(tokens_top()->val));
tokens_pop();
return object;
}
default:
abort();
return NULL;
}
}
struct Object *parens()
{
2023-05-04 07:05:20 -04:00
assert(tokens_top());
struct Object *object = NULL;
if (tokens_top()->type == TOKEN_ROUND_OPEN) {
expect(TOKEN_ROUND_OPEN);
object = parens_part();
expect(TOKEN_ROUND_CLOSE);
} else if (tokens_top()->type == TOKEN_SQUARE_OPEN) {
expect(TOKEN_SQUARE_OPEN);
object = parens_part();
expect(TOKEN_SQUARE_CLOSE);
} else {
expect(TOKEN_CURLY_OPEN);
object = parens_part();
expect(TOKEN_CURLY_CLOSE);
}
2023-05-04 06:20:48 -04:00
return object;
}
struct Object *parens_part()
{
assert(tokens_top());
2023-05-04 07:05:20 -04:00
if (tokens_top()->type == TOKEN_ROUND_CLOSE ||
tokens_top()->type == TOKEN_SQUARE_CLOSE ||
tokens_top()->type == TOKEN_CURLY_CLOSE)
{
return NULL;
}
2023-05-04 06:20:48 -04:00
struct Object *const a = expr();
assert(tokens_top());
struct Object *b = NULL;
2023-05-04 07:05:20 -04:00
if (tokens_top()->type != TOKEN_ROUND_CLOSE &&
tokens_top()->type != TOKEN_SQUARE_CLOSE &&
tokens_top()->type != TOKEN_CURLY_CLOSE)
{
2023-05-04 06:20:48 -04:00
b = parens_part();
}
struct Object *object = Object_new_pair(a, b);
return object;
}