diff --git a/Makefile b/Makefile index c146684..23357ed 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,13 @@ all: lisp CC = gcc CFLAGS = -Wall -Wextra -OBJS = main.c.o enums.c.o +OBJS = enums.c.o main.c.o tokens.c.o + +run: lisp + ./lisp + +clean: + rm -f lisp $(OBJS) lisp: $(OBJS) $(CC) -o $@ $^ $(CFLAGS) diff --git a/enums.c b/enums.c index 1203d2f..e7ddb19 100644 --- a/enums.c +++ b/enums.c @@ -42,10 +42,10 @@ bool State_to_token_type(const enum State state, enum TokenType *const token_type) { switch (state) { - case STATE_OPEN: *token_type = STATE_OPEN; break; - case STATE_CLOSE: *token_type = STATE_CLOSE; break; - case STATE_ID: *token_type = STATE_ID; break; - case STATE_NUM: *token_type = STATE_NUM; break; + case STATE_OPEN: *token_type = TOKEN_OPEN; break; + case STATE_CLOSE: *token_type = TOKEN_CLOSE; break; + case STATE_ID: *token_type = TOKEN_ID; break; + case STATE_NUM: *token_type = TOKEN_NUM; break; default: return false; } diff --git a/main.c b/main.c index 12ef32b..d058dba 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,5 @@ #include "enums.h" +#include "tokens.h" #include #include @@ -8,12 +9,6 @@ #include #include -struct Token { - struct Token *next; - enum TokenType type; - char *val; -}; - struct Object { enum Type type; union { @@ -30,7 +25,6 @@ static char buffer[1024]; static size_t buffer_index = 0; static enum State state = STATE_INIT; -static struct Token *tokens = NULL; static void error(const char *msg); @@ -47,7 +41,6 @@ static void lex(char chr); * Parser * **********/ -static void shift_token(); static struct Object *prepare_object(enum Type type); static void expect(enum TokenType token_type); @@ -77,7 +70,11 @@ int main() printf("Tokens:\n"); - for (const struct Token *token = tokens; token; token = token->next) { + for ( + const struct Tokens *token = tokens_top(); + token; + token = token->next + ) { printf("%s:%s;\n", TokenType_to_str(token->type), token->val); } @@ -116,24 +113,7 @@ void token_add(enum State state, char *val) enum TokenType token_type; if (!State_to_token_type(state, &token_type)) error("invalid state"); - struct Token *token = malloc(sizeof(struct Token)); - assert(token); - token->next = NULL; - token->type = token_type; - token->val = malloc(strlen(val) + 1); - assert(token->val); - strcpy(token->val, val); - - if (!tokens) { - tokens = token; - } else { - for (struct Token *curr = tokens; curr; curr = curr->next) { - if (!curr->next) { - curr->next = token; - break; - } - } - } + tokens_push(token_type, val); } void lex(char chr) @@ -297,13 +277,6 @@ void lex(char chr) * Parser * **********/ -void shift_token() -{ - struct Token *const cur_token = tokens; - tokens = tokens->next; - free(cur_token); -} - struct Object *prepare_object(const enum Type type) { struct Object *const object = malloc(sizeof(struct Object)); @@ -315,9 +288,7 @@ struct Object *prepare_object(const enum Type type) void expect(const enum TokenType token_type) { - if (!tokens) error("no tokens in expect"); - if (tokens->type != token_type) error("no expected"); - shift_token(); + if (!tokens_expect(token_type)) error("expect"); } struct Object *parse() @@ -327,22 +298,22 @@ struct Object *parse() struct Object *expr() { - if (!tokens) error("no tokens"); + if (!tokens_top()) error("no tokens"); - switch (tokens->type) { + switch (tokens_top()->type) { case TOKEN_OPEN: return parens(); case TOKEN_ID: { struct Object *const object = prepare_object(TYPE_ATOM); - object->s = tokens->val; - shift_token(); + object->s = tokens_top()->val; + tokens_pop(); return object; } case TOKEN_NUM: { struct Object *const object = prepare_object(TYPE_NUMBER); - object->i = atoll(tokens->val); - shift_token(); + object->i = atoll(tokens_top()->val); + tokens_pop(); return object; } default: @@ -363,11 +334,11 @@ struct Object *parens_part() { struct Object *const object = prepare_object(TYPE_PAIR); - if (tokens && tokens->type != TOKEN_CLOSE) { + if (tokens_top() && tokens_top()->type != TOKEN_CLOSE) { object->a = expr(); } - if (tokens && tokens->type != TOKEN_CLOSE) { + if (tokens_top() && tokens_top()->type != TOKEN_CLOSE) { object->b = parens_part(); } else { object->b = NULL; diff --git a/tokens.c b/tokens.c new file mode 100644 index 0000000..a4be6c6 --- /dev/null +++ b/tokens.c @@ -0,0 +1,52 @@ +#include "tokens.h" + +#include +#include +#include +#include +#include + +static struct Tokens *tokens = NULL; + +const struct Tokens *tokens_top() +{ + return tokens; +} + +bool tokens_expect(const enum TokenType token_type) +{ + if (!tokens && tokens->type != token_type) return false; + tokens_pop(); + return true; +} + +void tokens_pop() +{ + struct Tokens *const token = tokens; + if (token) { + tokens = token->next; + free(token); + } +} + +void tokens_push(const enum TokenType token_type, const char *const val) +{ + struct Tokens *token = malloc(sizeof(struct Tokens)); + assert(token); + token->next = NULL; + token->type = token_type; + token->val = malloc(strlen(val) + 1); + assert(token->val); + strcpy(token->val, val); + + if (!tokens) { + tokens = token; + } else { + for (struct Tokens *curr = tokens; curr; curr = curr->next) { + if (!curr->next) { + curr->next = token; + break; + } + } + } +} diff --git a/tokens.h b/tokens.h new file mode 100644 index 0000000..2e11549 --- /dev/null +++ b/tokens.h @@ -0,0 +1,19 @@ +#ifndef __TOKENS_H__ +#define __TOKENS_H__ + +#include "enums.h" + +#include + +struct Tokens { + struct Tokens *next; + enum TokenType type; + char *val; +}; + +void tokens_push(enum TokenType token_type, const char *val); +void tokens_pop(); +bool tokens_expect(enum TokenType token_type); +const struct Tokens *tokens_top(); + +#endif