1
0
Fork 0
This commit is contained in:
Alex Kotov 2023-05-04 02:05:11 +04:00
parent 97e2470e6b
commit 01ece4cc9f
Signed by: kotovalexarian
GPG key ID: 553C0EBBEB5D5F08
5 changed files with 98 additions and 50 deletions

View file

@ -3,7 +3,13 @@ all: lisp
CC = gcc CC = gcc
CFLAGS = -Wall -Wextra 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) lisp: $(OBJS)
$(CC) -o $@ $^ $(CFLAGS) $(CC) -o $@ $^ $(CFLAGS)

View file

@ -42,10 +42,10 @@ bool
State_to_token_type(const enum State state, enum TokenType *const token_type) State_to_token_type(const enum State state, enum TokenType *const token_type)
{ {
switch (state) { switch (state) {
case STATE_OPEN: *token_type = STATE_OPEN; break; case STATE_OPEN: *token_type = TOKEN_OPEN; break;
case STATE_CLOSE: *token_type = STATE_CLOSE; break; case STATE_CLOSE: *token_type = TOKEN_CLOSE; break;
case STATE_ID: *token_type = STATE_ID; break; case STATE_ID: *token_type = TOKEN_ID; break;
case STATE_NUM: *token_type = STATE_NUM; break; case STATE_NUM: *token_type = TOKEN_NUM; break;
default: return false; default: return false;
} }

61
main.c
View file

@ -1,4 +1,5 @@
#include "enums.h" #include "enums.h"
#include "tokens.h"
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
@ -8,12 +9,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
struct Token {
struct Token *next;
enum TokenType type;
char *val;
};
struct Object { struct Object {
enum Type type; enum Type type;
union { union {
@ -30,7 +25,6 @@ static char buffer[1024];
static size_t buffer_index = 0; static size_t buffer_index = 0;
static enum State state = STATE_INIT; static enum State state = STATE_INIT;
static struct Token *tokens = NULL;
static void error(const char *msg); static void error(const char *msg);
@ -47,7 +41,6 @@ static void lex(char chr);
* Parser * * Parser *
**********/ **********/
static void shift_token();
static struct Object *prepare_object(enum Type type); static struct Object *prepare_object(enum Type type);
static void expect(enum TokenType token_type); static void expect(enum TokenType token_type);
@ -77,7 +70,11 @@ int main()
printf("Tokens:\n"); 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); 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; enum TokenType token_type;
if (!State_to_token_type(state, &token_type)) error("invalid state"); if (!State_to_token_type(state, &token_type)) error("invalid state");
struct Token *token = malloc(sizeof(struct Token)); tokens_push(token_type, val);
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;
}
}
}
} }
void lex(char chr) void lex(char chr)
@ -297,13 +277,6 @@ void lex(char chr)
* Parser * * 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 *prepare_object(const enum Type type)
{ {
struct Object *const object = malloc(sizeof(struct Object)); 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) void expect(const enum TokenType token_type)
{ {
if (!tokens) error("no tokens in expect"); if (!tokens_expect(token_type)) error("expect");
if (tokens->type != token_type) error("no expected");
shift_token();
} }
struct Object *parse() struct Object *parse()
@ -327,22 +298,22 @@ struct Object *parse()
struct Object *expr() 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_OPEN: return parens();
case TOKEN_ID: case TOKEN_ID:
{ {
struct Object *const object = prepare_object(TYPE_ATOM); struct Object *const object = prepare_object(TYPE_ATOM);
object->s = tokens->val; object->s = tokens_top()->val;
shift_token(); tokens_pop();
return object; return object;
} }
case TOKEN_NUM: case TOKEN_NUM:
{ {
struct Object *const object = prepare_object(TYPE_NUMBER); struct Object *const object = prepare_object(TYPE_NUMBER);
object->i = atoll(tokens->val); object->i = atoll(tokens_top()->val);
shift_token(); tokens_pop();
return object; return object;
} }
default: default:
@ -363,11 +334,11 @@ struct Object *parens_part()
{ {
struct Object *const object = prepare_object(TYPE_PAIR); 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(); object->a = expr();
} }
if (tokens && tokens->type != TOKEN_CLOSE) { if (tokens_top() && tokens_top()->type != TOKEN_CLOSE) {
object->b = parens_part(); object->b = parens_part();
} else { } else {
object->b = NULL; object->b = NULL;

52
tokens.c Normal file
View file

@ -0,0 +1,52 @@
#include "tokens.h"
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
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;
}
}
}
}

19
tokens.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef __TOKENS_H__
#define __TOKENS_H__
#include "enums.h"
#include <stdbool.h>
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