#include "lc.h" #include "util.h" #include #include 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(); } } }