#include "parse.h" #include #include #include token_list* parse_name(char** name, token_list* list) { if (list->elem.kind != TOKEN_NAME) return NULL; *name = calloc(1, strlen(list->elem.var) + 1); if (!*name) error_no_mem(); strcpy(*name, list->elem.var); return list->rest; } token_list* parse_simple_expression(expression* expr, token_list* list) { switch (list->elem.kind) { case TOKEN_INT: expr->kind = EXPR_INT; expr->var1 = calloc(1, sizeof(int)); if(!expr->var1) error_no_mem(); *((int*) expr->var1) = *((int*) list->elem.var); return list->rest; case TOKEN_NAME: expr->kind = EXPR_NAME; list = parse_name((char**) &expr->var1, list); return list; case TOKEN_OPEN_P: list = parse_simple_expression(expr, list->rest); if (!list) return NULL; expression* _expr; switch (list->elem.kind) { case TOKEN_CLOSE_P: return list->rest; break; case TOKEN_COMMA: _expr = calloc(1, sizeof(expression)); if (!_expr) error_no_mem(); cpy_expression(_expr, expr); expr->kind = EXPR_TUPLE; expr->var1 = _expr; expr->var2 = calloc(1, sizeof(expression)); if (!expr->var2) error_no_mem(); list = parse_simple_expression(expr->var2, list->rest); if (!list || list->elem.kind != TOKEN_CLOSE_P) { free_expression(_expr); free(_expr); return NULL; } else { return list->rest; } break; default: return NULL; } break; case TOKEN_OPEN_SQ: expr->kind = EXPR_LIST; list = list->rest; if (!list) return NULL; if (list->elem.kind == TOKEN_CLOSE_SQ) return list->rest; expr->var1 = calloc(1, sizeof(expression)); expr->var2 = calloc(1, sizeof(expression)); if (!expr->var1 || !expr->var2) error_no_mem(); list = parse_simple_expression(expr->var1, list); if (!list || list->elem.kind != TOKEN_COLON) { free_expression(expr->var1); free(expr->var1); return NULL; } list = parse_simple_expression(expr->var2, list->rest); if (!list || list->elem.kind != TOKEN_CLOSE_SQ) { free_expression(expr->var1); free(expr->var1); free_expression(expr->var2); free(expr->var2); return NULL; } return list->rest; break; default: return NULL; } } token_list* parse_arg_list(arg_list** args, token_list* list) { if (list->elem.kind == TOKEN_EQUALS) return list; *args = calloc(1, sizeof(arg_list)); if (!*args) error_no_mem(); list = parse_simple_expression(&(*args)->elem, list); if (!list) return NULL; list = parse_arg_list(&(*args)->rest, list); return list; } token_list* parse_expression(expression*, token_list*); token_list* parse_expression_no_app(expression* expr, token_list* list) { if (list->elem.kind == TOKEN_OPEN_P) { token_list* _list = parse_expression(expr, list->rest); if (_list) { if (_list->elem.kind == TOKEN_CLOSE_P) { return _list->rest; } else if (_list->elem.kind == TOKEN_COMMA) { expression* _expr = calloc(1, sizeof(expression)); if (!_expr) error_no_mem(); cpy_expression(_expr, expr); expr->kind = EXPR_TUPLE; expr->var1 = _expr; expr->var2 = calloc(1, sizeof(expression)); if (!expr->var2) error_no_mem(); _list = parse_expression(expr->var2, _list->rest); if (_list && _list->elem.kind == TOKEN_CLOSE_P) { return _list->rest; } } free_expression(expr); } } else if (list->elem.kind == TOKEN_OPEN_SQ) { expr->kind = EXPR_LIST; if (list->rest->elem.kind == TOKEN_CLOSE_SQ) { return list->rest->rest; } expression* expr1 = calloc(1, sizeof(expression)); expression* expr2 = calloc(1, sizeof(expression)); if (!expr1 || !expr2) error_no_mem(); token_list* _list = parse_expression(expr1, list->rest); if (!_list || _list->elem.kind != TOKEN_COLON) { free(expr1); } else { _list = parse_expression(expr2, _list->rest); if (!_list || _list->elem.kind != TOKEN_CLOSE_SQ) { free_expression(expr1); free(expr2); } else { expr->var1 = expr1; expr->var2 = expr2; return _list->rest; } } } list = parse_simple_expression(expr, list); if (!list) free_expression(expr); return list; } token_list* parse_expression(expression* expr, token_list* list) { list = parse_expression_no_app(expr, list); if (!list) return NULL; while (list->elem.kind != TOKEN_SEMICOLON && list->elem.kind != TOKEN_CLOSE_P && list->elem.kind != TOKEN_CLOSE_SQ && list->elem.kind != TOKEN_COLON && list->elem.kind != TOKEN_COMMA) { expression* _expr = calloc(1, sizeof(expression)); if (!_expr) error_no_mem(); cpy_expression(_expr, expr); expr->kind = EXPR_APP; expr->var1 = _expr; expr->var2 = calloc(1, sizeof(expression)); if (!expr->var2) error_no_mem(); list = parse_expression_no_app(expr->var2, list); if (!list) { free_expression(expr); return NULL; } } return list; } token_list* parse_rule(rewrite_rule* rule, token_list* list) { list = parse_name(&rule->name, list); if (!list) return NULL; list = parse_arg_list(&rule->args, list); if (!list) { log_debug("parse_rule: error in arg_list"); free(rule->name); return NULL; } if (list->elem.kind != TOKEN_EQUALS) { log_debug("parse_rule: no ="); free(rule->name); free_arg_list(rule->args); return NULL; } list = parse_expression(&rule->rhs, list->rest); return list; } fuspel* parse(token_list* list) { while (list && list->elem.kind == TOKEN_SEMICOLON) list = list->rest; if (!list) return NULL; fuspel* rules = calloc(1, sizeof(fuspel)); list = parse_rule(&rules->rule, list); if (!list) return NULL; rules->rest = parse(list); return rules; }