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
|
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)
|
||||||
|
|
8
enums.c
8
enums.c
|
@ -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
61
main.c
|
@ -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
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