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
|
LD=gcc
|
||||||
LDFLAGS=$(DEBUG_FLAGS)
|
LDFLAGS=$(DEBUG_FLAGS)
|
||||||
|
|
||||||
lambda: main.o token.o lc.o
|
lambda: main.o token.o lc.o util.o
|
||||||
$(LD) $(LDFLAGS) -o $@ $^
|
$(LD) $(LDFLAGS) -o $@ $^
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
@@ -19,4 +19,5 @@ clean:
|
|||||||
# Dependencies
|
# Dependencies
|
||||||
main.o: token.h lc.h
|
main.o: token.h lc.h
|
||||||
token.o: token.h util.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 "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
|
#ifndef INCLUDED_TERM_H
|
||||||
#define INCLUDED_TERM_H
|
#define INCLUDED_TERM_H
|
||||||
|
|
||||||
|
#include "token.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -14,17 +16,22 @@ struct _LambdaTerm {
|
|||||||
LambdaTermType type;
|
LambdaTermType type;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
char name;
|
char *name;
|
||||||
|
size_t name_len;
|
||||||
} v;
|
} v;
|
||||||
struct {
|
struct {
|
||||||
char argument;
|
char *arg;
|
||||||
|
size_t arg_len;
|
||||||
LambdaTerm *body;
|
LambdaTerm *body;
|
||||||
} l;
|
} l;
|
||||||
struct {
|
struct {
|
||||||
char function;
|
LambdaTerm *func;
|
||||||
LambdaTerm *argument;
|
LambdaTerm *arg;
|
||||||
};
|
} a;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
LambdaTerm *read_lambda_term(TokenStream *restrict stream,
|
||||||
|
ParseError *restrict err_out);
|
||||||
|
|
||||||
#endif
|
#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,
|
static bool read_next_reduce(TokenStream *restrict stream, Token *restrict out,
|
||||||
ParseError *restrict error);
|
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,
|
bool token_stream_next(TokenStream *restrict stream, Token *restrict out,
|
||||||
ParseError *restrict error) {
|
ParseError *restrict error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
error->set = false;
|
error->set = false;
|
||||||
}
|
}
|
||||||
|
if (stream->has_buffer) {
|
||||||
|
stream->has_buffer = false;
|
||||||
|
*out = stream->buffer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
restart:
|
restart:
|
||||||
skip_whitespace(stream);
|
skip_whitespace(stream);
|
||||||
int c = peekc(stream);
|
int c = peekc(stream);
|
||||||
@@ -232,3 +253,16 @@ static bool read_next_reduce(TokenStream *restrict stream, Token *restrict out,
|
|||||||
return false;
|
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;
|
SrcPos pos;
|
||||||
const char *src;
|
const char *src;
|
||||||
size_t src_len;
|
size_t src_len;
|
||||||
|
|
||||||
|
bool has_buffer;
|
||||||
|
Token buffer;
|
||||||
} TokenStream;
|
} TokenStream;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -66,6 +69,7 @@ inline static void token_stream_init(TokenStream *stream, const char *src,
|
|||||||
stream->pos.line_offset = 0;
|
stream->pos.line_offset = 0;
|
||||||
stream->src = src;
|
stream->src = src;
|
||||||
stream->src_len = src_len;
|
stream->src_len = src_len;
|
||||||
|
stream->has_buffer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static bool token_stream_is_eof(TokenStream *stream) {
|
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
|
// 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,
|
bool token_stream_next(TokenStream *restrict stream, Token *restrict out,
|
||||||
ParseError *restrict error);
|
ParseError *restrict error);
|
||||||
|
bool token_stream_discard(TokenStream *restrict stream,
|
||||||
|
ParseError *restrict error);
|
||||||
|
|
||||||
static inline void parse_error_clear(ParseError *error) {
|
static inline void parse_error_clear(ParseError *error) {
|
||||||
error->set = false;
|
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