Some work
This commit is contained in:
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user