Some work
This commit is contained in:
5
Makefile
5
Makefile
@@ -5,7 +5,7 @@ CFLAGS=-std=c11 -D_FILE_OFFSET_BITS=64 -D_POSIX_C_SOURCE=200112L -Wall -Wextra $
|
||||
LD=gcc
|
||||
LDFLAGS=$(DEBUG_FLAGS)
|
||||
|
||||
lambda: main.o token.o lc.o
|
||||
lambda: main.o token.o lc.o util.o
|
||||
$(LD) $(LDFLAGS) -o $@ $^
|
||||
|
||||
%.o: %.c
|
||||
@@ -19,4 +19,5 @@ clean:
|
||||
# Dependencies
|
||||
main.o: token.h lc.h
|
||||
token.o: token.h util.h
|
||||
lc.o: lc.h token.h
|
||||
lc.o: lc.h token.h util.h
|
||||
util.o: util.h
|
||||
|
||||
143
lc.c
143
lc.c
@@ -1 +1,144 @@
|
||||
#include "lc.h"
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static LambdaTerm *make_variable(char *name, size_t name_len) {
|
||||
LambdaTerm *term = malloc_safe(sizeof(LambdaTerm));
|
||||
term->type = TYPE_VARIABLE;
|
||||
term->v.name = name;
|
||||
term->v.name_len = name_len;
|
||||
return term;
|
||||
}
|
||||
|
||||
static LambdaTerm *make_lambda(char *arg, size_t arg_len, LambdaTerm *body) {
|
||||
LambdaTerm *term = malloc_safe(sizeof(LambdaTerm));
|
||||
term->type = TYPE_LAMBDA;
|
||||
term->l.arg = arg;
|
||||
term->l.arg_len = arg_len;
|
||||
term->l.body = body;
|
||||
return term;
|
||||
}
|
||||
|
||||
static LambdaTerm *make_apply(LambdaTerm *func, LambdaTerm *arg) {
|
||||
LambdaTerm *term = malloc_safe(sizeof(LambdaTerm));
|
||||
term->type = TYPE_APPLY;
|
||||
term->a.func = func;
|
||||
term->a.arg = arg;
|
||||
return term;
|
||||
}
|
||||
|
||||
static bool is_lambda_term_token(const Token *tok) {
|
||||
switch (tok->type) {
|
||||
case TOKEN_BACKSLASH:
|
||||
case TOKEN_OPEN_PAREN:
|
||||
case TOKEN_CLOSE_PAREN:
|
||||
case TOKEN_IDENT:
|
||||
return true;
|
||||
case TOKEN_LET:
|
||||
case TOKEN_EVAL:
|
||||
case TOKEN_CONF:
|
||||
case TOKEN_EQUALS:
|
||||
case TOKEN_COLON:
|
||||
case TOKEN_DEFINE:
|
||||
case TOKEN_REDUCE:
|
||||
case TOKEN_EOF:
|
||||
return false;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
enum OperatorType {
|
||||
OPER_APPLY,
|
||||
OPER_DEFINE,
|
||||
};
|
||||
|
||||
struct OperatorStack {
|
||||
struct OperatorStack *next;
|
||||
Token src;
|
||||
enum OperatorType type;
|
||||
};
|
||||
|
||||
static struct OperatorStack *push_oper(struct OperatorStack *restrict stack,
|
||||
const Token *restrict src,
|
||||
enum OperatorType type) {
|
||||
struct OperatorStack *new = malloc_safe(sizeof(struct OperatorStack));
|
||||
new->next = stack;
|
||||
new->src = *src;
|
||||
new->type = type;
|
||||
return new;
|
||||
}
|
||||
|
||||
enum OperandType {
|
||||
OPAND_TERM,
|
||||
OPAND_OPEN_PAREN,
|
||||
OPAND_DEF_BEGIN,
|
||||
};
|
||||
|
||||
struct OperandStack {
|
||||
struct OperandStack *next;
|
||||
Token src;
|
||||
enum OperandType type;
|
||||
LambdaTerm *term;
|
||||
};
|
||||
|
||||
static struct OperandStack *push_opand(struct OperandStack *restrict stack,
|
||||
const Token *restrict src,
|
||||
enum OperandType type, ...) {
|
||||
struct OperandStack *new = malloc_safe(sizeof(struct OperandStack));
|
||||
new->next = stack;
|
||||
new->src = *src;
|
||||
new->type = type;
|
||||
if (type == OPAND_TERM) {
|
||||
va_list args;
|
||||
va_start(args, type);
|
||||
new->term = va_arg(args, LambdaTerm *);
|
||||
va_end(args);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
static void apply_one(struct OperatorStack **oper_stack,
|
||||
struct OperandStack **opand_stack,
|
||||
ParseError *restrict err_out) {
|
||||
if (!*oper_stack) {
|
||||
abort();
|
||||
} else if () {
|
||||
}
|
||||
}
|
||||
|
||||
LambdaTerm *read_lambda_term(TokenStream *restrict stream,
|
||||
ParseError *restrict err_out) {
|
||||
ParseError backup_err;
|
||||
if (!err_out) {
|
||||
err_out = &backup_err;
|
||||
}
|
||||
struct OperatorStack *oper_stack = NULL;
|
||||
struct OperandStack *opand_stack = NULL;
|
||||
Token tok;
|
||||
while (true) {
|
||||
if (!token_stream_peek(stream, &tok, err_out)) {
|
||||
return false;
|
||||
} else if (!is_lambda_term_token(&tok)) {
|
||||
break;
|
||||
}
|
||||
token_stream_discard(stream, NULL);
|
||||
switch (tok.type) {
|
||||
case TOKEN_OPEN_PAREN:
|
||||
opand_stack = push_opand(opand_stack, OPAND_OPEN_PAREN);
|
||||
break;
|
||||
case TOKEN_BACKSLASH:
|
||||
opand_stack = push_opand(opand_stack, OPAND_DEF_BEGIN);
|
||||
break;
|
||||
case TOKEN_CLOSE_PAREN:
|
||||
case TOKEN_IDENT:
|
||||
case TOKEN_DEFINE:
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
17
lc.h
17
lc.h
@@ -1,6 +1,8 @@
|
||||
#ifndef INCLUDED_TERM_H
|
||||
#define INCLUDED_TERM_H
|
||||
|
||||
#include "token.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef enum {
|
||||
@@ -14,17 +16,22 @@ struct _LambdaTerm {
|
||||
LambdaTermType type;
|
||||
union {
|
||||
struct {
|
||||
char name;
|
||||
char *name;
|
||||
size_t name_len;
|
||||
} v;
|
||||
struct {
|
||||
char argument;
|
||||
char *arg;
|
||||
size_t arg_len;
|
||||
LambdaTerm *body;
|
||||
} l;
|
||||
struct {
|
||||
char function;
|
||||
LambdaTerm *argument;
|
||||
};
|
||||
LambdaTerm *func;
|
||||
LambdaTerm *arg;
|
||||
} a;
|
||||
};
|
||||
};
|
||||
|
||||
LambdaTerm *read_lambda_term(TokenStream *restrict stream,
|
||||
ParseError *restrict err_out);
|
||||
|
||||
#endif
|
||||
|
||||
34
token.c
34
token.c
@@ -136,11 +136,32 @@ static bool read_next_ident(TokenStream *restrict stream, Token *restrict out);
|
||||
static bool read_next_reduce(TokenStream *restrict stream, Token *restrict out,
|
||||
ParseError *restrict error);
|
||||
|
||||
bool token_stream_peek(TokenStream *restrict stream, Token *restrict out,
|
||||
ParseError *restrict error) {
|
||||
if (error) {
|
||||
error->set = false;
|
||||
}
|
||||
if (!stream->has_buffer) {
|
||||
bool res = token_stream_next(stream, &stream->buffer, error);
|
||||
if (!res) {
|
||||
return false;
|
||||
}
|
||||
stream->has_buffer = true;
|
||||
}
|
||||
*out = stream->buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool token_stream_next(TokenStream *restrict stream, Token *restrict out,
|
||||
ParseError *restrict error) {
|
||||
if (error) {
|
||||
error->set = false;
|
||||
}
|
||||
if (stream->has_buffer) {
|
||||
stream->has_buffer = false;
|
||||
*out = stream->buffer;
|
||||
return true;
|
||||
}
|
||||
restart:
|
||||
skip_whitespace(stream);
|
||||
int c = peekc(stream);
|
||||
@@ -232,3 +253,16 @@ static bool read_next_reduce(TokenStream *restrict stream, Token *restrict out,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool token_stream_discard(TokenStream *restrict stream,
|
||||
ParseError *restrict error) {
|
||||
if (stream->has_buffer) {
|
||||
stream->has_buffer = false;
|
||||
if (error) {
|
||||
error->set = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Token tok;
|
||||
return token_stream_next(stream, &tok, error);
|
||||
}
|
||||
|
||||
9
token.h
9
token.h
@@ -50,6 +50,9 @@ typedef struct {
|
||||
SrcPos pos;
|
||||
const char *src;
|
||||
size_t src_len;
|
||||
|
||||
bool has_buffer;
|
||||
Token buffer;
|
||||
} TokenStream;
|
||||
|
||||
typedef struct {
|
||||
@@ -66,6 +69,7 @@ inline static void token_stream_init(TokenStream *stream, const char *src,
|
||||
stream->pos.line_offset = 0;
|
||||
stream->src = src;
|
||||
stream->src_len = src_len;
|
||||
stream->has_buffer = false;
|
||||
}
|
||||
|
||||
inline static bool token_stream_is_eof(TokenStream *stream) {
|
||||
@@ -73,8 +77,13 @@ inline static bool token_stream_is_eof(TokenStream *stream) {
|
||||
}
|
||||
|
||||
// return true on success, false on error
|
||||
bool token_stream_peek(TokenStream *restrict stream, Token *restrict out,
|
||||
ParseError *restrict error);
|
||||
bool token_stream_next(TokenStream *restrict stream, Token *restrict out,
|
||||
ParseError *restrict error);
|
||||
bool token_stream_discard(TokenStream *restrict stream,
|
||||
ParseError *restrict error);
|
||||
|
||||
static inline void parse_error_clear(ParseError *error) {
|
||||
error->set = false;
|
||||
}
|
||||
|
||||
13
util.c
Normal file
13
util.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "util.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void *malloc_safe(size_t size) {
|
||||
void *ptr = malloc(size);
|
||||
if (!ptr && size) {
|
||||
static char message[] = "out of memory!\n";
|
||||
fwrite(message, 1, sizeof(message) - 1, stdout);
|
||||
abort();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
Reference in New Issue
Block a user