#include "parse.h" #include #include #include "code.h" #include "mem.h" extern struct fuspel *import(struct fuspel *already_parsed, char *name); struct parsing_list { struct token_list *tokens; unsigned int i; }; bool parse_name(char **name, struct parsing_list *list) { if (list->tokens->elems[list->i].kind != TOKEN_NAME) return false; // TODO error handling *name = my_calloc(1, strlen(list->tokens->elems[list->i].var) + 1); strcpy(*name, list->tokens->elems[list->i].var); list->i++; return true; } bool parse_simple_expression(struct expression *expr, struct parsing_list *list) { struct expression *_expr; switch (list->tokens->elems[list->i].kind) { case TOKEN_INT: expr->kind = EXPR_INT; expr->var1 = my_calloc(1, sizeof(int)); *((int*) expr->var1) = *((int*) list->tokens->elems[list->i].var); list->i++; return true; case TOKEN_NAME: expr->kind = EXPR_NAME; parse_name((char**) &expr->var1, list); return true; case TOKEN_CODE: if (list->i < list->tokens->index && list->tokens->elems[list->i+1].kind == TOKEN_NAME) { char *name; expr->kind = EXPR_CODE; list->i++; parse_name(&name, list); expr->var2 = my_calloc(1, sizeof(unsigned char)); *((unsigned char*) expr->var2) = code_find(name, &expr->var1); my_free(name); return true; } else { return false; // TODO error handling } case TOKEN_OPEN_P: list->i++; if (!parse_simple_expression(expr, list)) { list->i--; return false; } switch (list->tokens->elems[list->i].kind) { case TOKEN_CLOSE_P: list->i++; return true; case TOKEN_COMMA: _expr = my_calloc(1, sizeof(struct expression)); cpy_expression(_expr, expr); free_expression(expr); expr->kind = EXPR_TUPLE; expr->var1 = _expr; expr->var2 = my_calloc(1, sizeof(struct expression)); list->i++; if (!parse_simple_expression(expr->var2, list) || list->tokens->elems[list->i].kind != TOKEN_CLOSE_P) { list->i--; free_expression(_expr); my_free(_expr); return false; } else { list->i++; return true; } default: return false; } break; case TOKEN_OPEN_SQ: expr->kind = EXPR_LIST; list->i++; if (list->tokens->elems[list->i].kind == TOKEN_CLOSE_SQ) { list->i++; return true; } expr->var1 = my_calloc(1, sizeof(struct expression)); expr->var2 = my_calloc(1, sizeof(struct expression)); if (!parse_simple_expression(expr->var1, list) || (list->tokens->elems[list->i].kind != TOKEN_COLON && list->tokens->elems[list->i].kind != TOKEN_COMMA && list->tokens->elems[list->i].kind != TOKEN_CLOSE_SQ)) { free_expression(expr->var1); return false; } else if (list->tokens->elems[list->i].kind == TOKEN_CLOSE_SQ) { ((struct expression *) expr->var2)->kind = EXPR_LIST; ((struct expression *) expr->var2)->var1 = NULL; ((struct expression *) expr->var2)->var2 = NULL; list->i++; return true; } else if (list->tokens->elems[list->i].kind == TOKEN_COMMA) { struct expression *_expr = expr; bool loop = true; while (loop && list->tokens->elems[list->i].kind == TOKEN_COMMA) { _expr = _expr->var2; _expr->kind = EXPR_LIST; _expr->var1 = my_calloc(1, sizeof(struct expression)); _expr->var2 = my_calloc(1, sizeof(struct expression)); list->i++; loop = parse_simple_expression(_expr->var1, list); } if (list->i >= list->tokens->length || (list->tokens->elems[list->i].kind != TOKEN_CLOSE_SQ && list->tokens->elems[list->i].kind != TOKEN_COLON)) { free_expression(expr); return false; } else if (list->tokens->elems[list->i].kind == TOKEN_COLON) { list->i++; if (!parse_simple_expression(((struct expression*) expr->var2)->var2, list) || list->tokens->elems[list->i].kind != TOKEN_CLOSE_SQ) { free_expression(expr); return false; } else { list->i++; return true; } } else if (list->tokens->elems[list->i].kind == TOKEN_CLOSE_SQ) { ((struct expression*) _expr->var2)->kind = EXPR_LIST; ((struct expression*) _expr->var2)->var1 = NULL; ((struct expression*) _expr->var2)->var2 = NULL; list->i++; return true; } } default: return false; } } bool parse_arg_list(struct arg_list **args, struct parsing_list *list) { if (list->tokens->elems[list->i].kind == TOKEN_EQUALS) return true; *args = my_calloc(1, sizeof(struct arg_list)); if (!parse_simple_expression(&(*args)->elem, list)) return false; return parse_arg_list(&(*args)->rest, list); } bool parse_expression(struct expression*, struct parsing_list*); bool parse_expression_no_app(struct expression *expr, struct parsing_list *list) { if (list->tokens->elems[list->i].kind == TOKEN_OPEN_P) { list->i++; if (parse_expression(expr, list)) { if (list->tokens->elems[list->i].kind == TOKEN_CLOSE_P) { list->i++; return true; } else if (list->tokens->elems[list->i].kind == TOKEN_COMMA) { struct expression *_expr = my_calloc(1, sizeof(struct expression)); cpy_expression(_expr, expr); free_expression(expr); expr->kind = EXPR_TUPLE; expr->var1 = _expr; expr->var2 = my_calloc(1, sizeof(struct expression)); list->i++; if (parse_expression(expr->var2, list) && list->tokens->elems[list->i].kind == TOKEN_CLOSE_P) { list->i++; return true; } } free_expression(expr); } } else if (list->tokens->elems[list->i].kind == TOKEN_OPEN_SQ) { expr->kind = EXPR_LIST; if (list->tokens->elems[list->i+1].kind == TOKEN_CLOSE_SQ) { list->i += 2; return true; } expr->var1 = my_calloc(1, sizeof(struct expression)); expr->var2 = my_calloc(1, sizeof(struct expression)); list->i++; if (!parse_expression(expr->var1, list) || (list->tokens->elems[list->i].kind != TOKEN_COLON && list->tokens->elems[list->i].kind != TOKEN_COMMA && list->tokens->elems[list->i].kind != TOKEN_CLOSE_SQ)) { free_expression(expr); } else if (list->tokens->elems[list->i].kind == TOKEN_CLOSE_SQ) { ((struct expression *) expr->var2)->kind = EXPR_LIST; ((struct expression *) expr->var2)->var1 = NULL; ((struct expression *) expr->var2)->var2 = NULL; list->i++; return true; } else if (list->tokens->elems[list->i].kind == TOKEN_COMMA) { struct expression *_expr = expr; bool loop = true; while (loop && list->tokens->elems[list->i].kind == TOKEN_COMMA) { _expr = _expr->var2; _expr->kind = EXPR_LIST; _expr->var1 = my_calloc(1, sizeof(struct expression)); _expr->var2 = my_calloc(1, sizeof(struct expression)); list->i++; loop = parse_expression(_expr->var1, list); } if (list->i >= list->tokens->length || (list->tokens->elems[list->i].kind != TOKEN_CLOSE_SQ && list->tokens->elems[list->i].kind != TOKEN_COLON)) { free_expression(expr); } else if (list->tokens->elems[list->i].kind == TOKEN_COLON) { list->i++; if (!parse_expression(((struct expression*) expr->var2)->var2, list) || list->tokens->elems[list->i].kind != TOKEN_CLOSE_SQ) free_expression(expr); else return list; } else if (list->tokens->elems[list->i].kind == TOKEN_CLOSE_SQ) { ((struct expression*) _expr->var2)->kind = EXPR_LIST; ((struct expression*) _expr->var2)->var1 = NULL; ((struct expression*) _expr->var2)->var2 = NULL; list->i++; return list; } } else if (list->tokens->elems[list->i].kind == TOKEN_COLON) { list->i++; if (!parse_expression(expr->var2, list) || list->tokens->elems[list->i].kind != TOKEN_CLOSE_SQ) { free_expression(expr); } else { list->i++; return list; } } } return parse_simple_expression(expr, list); } bool parse_expression(struct expression *expr, struct parsing_list *list) { if (!parse_expression_no_app(expr, list)) return false; while (list->tokens->elems[list->i].kind != TOKEN_SEMICOLON && list->tokens->elems[list->i].kind != TOKEN_CLOSE_P && list->tokens->elems[list->i].kind != TOKEN_CLOSE_SQ && list->tokens->elems[list->i].kind != TOKEN_COLON && list->tokens->elems[list->i].kind != TOKEN_COMMA) { struct expression *_expr = my_calloc(1, sizeof(struct expression)); cpy_expression(_expr, expr); free_expression(expr); expr->kind = EXPR_APP; expr->var1 = _expr; expr->var2 = my_calloc(1, sizeof(struct expression)); if (!parse_expression_no_app(expr->var2, list)) { free_expression(expr); return false; } } return true; } bool parse_rule(struct rewrite_rule *rule, struct parsing_list *list) { if (!parse_name(&rule->name, list)) return false; if (!parse_arg_list(&rule->args, list)) { my_free(rule->name); return false; } if (list->tokens->elems[list->i].kind != TOKEN_EQUALS) { my_free(rule->name); free_arg_list(rule->args); return false; } list->i++; return parse_expression(&rule->rhs, list); } struct fuspel *parse_intern(struct parsing_list *list) { struct fuspel *rules = NULL; struct fuspel *return_rules; while (list->i < list->tokens->index && list->tokens->elems[list->i].kind == TOKEN_SEMICOLON) list->i++; if (list->i >= list->tokens->index) return NULL; if (list->tokens->elems[list->i].kind == TOKEN_IMPORT) { list->i++; if (!list || list->tokens->elems[list->i].kind != TOKEN_NAME) return NULL; rules = import(rules, list->tokens->elems[list->i].var); if (!rules) return NULL; list->i += 2; return_rules = rules; while (rules->rest) rules = rules->rest; } else { return_rules = rules = my_calloc(1, sizeof(struct fuspel)); if (!parse_rule(&rules->rule, list)) { my_free(rules); return NULL; } } rules->rest = parse_intern(list); return return_rules; } struct fuspel *parse(struct token_list *tk_list) { struct fuspel *pgm; struct parsing_list *list = my_calloc(1, sizeof(struct parsing_list)); list->i = 0; list->tokens = tk_list; pgm = parse_intern(list); my_free(list); return pgm; }