tokens.h
This commit is contained in:
parent
97e2470e6b
commit
01ece4cc9f
5 changed files with 98 additions and 50 deletions
8
Makefile
8
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)
|
||||
|
|
8
enums.c
8
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;
|
||||
}
|
||||
|
||||
|
|
61
main.c
61
main.c
|
@ -1,4 +1,5 @@
|
|||
#include "enums.h"
|
||||
#include "tokens.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
@ -8,12 +9,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
|
|
52
tokens.c
Normal file
52
tokens.c
Normal 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
19
tokens.h
Normal 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
|
Loading…
Reference in a new issue