145 lines
3.6 KiB
C
145 lines
3.6 KiB
C
#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();
|
|
}
|
|
}
|
|
}
|