#include #include #include #include "common.h" #include "parser.h" // TODO: Do all the todos // adds another child of type type to the sexp sexp // returns the index of the added type and < 0 on fail static size_t sexp_add(struct sexp *sexp, enum ast_type type); // self-explanatory static void sexp_init(struct sexp *sexp); static void sexp_print(struct sexp *sexp, int indent); static void sexp_free(struct sexp *sexp); static void ast_free(struct ast *ast); static void quote_stack_push(struct quote_node **head, struct sexp *cur_sexp); static struct sexp *quote_stack_pop(struct quote_node **head, int peek); // returns 0 on success enum paren_type { P_OPEN, P_CLOSE }; static int on_paren(parser_t parser, enum paren_type type); // 0 is open, 1 is close static int on_quote(parser_t parent); static int on_value(parser_t parent, value_t value); #define TOKEN_CALLBACK_TBL(X, parser, token) \ /* X(test, execute on succes) */ \ X(TOKEN_PARENTHS_OPEN, on_paren(parser, P_OPEN)) \ X(TOKEN_PARENTHS_CLOSE, on_paren(parser, P_CLOSE)) \ X(TOKEN_SPECIAL_QUOTE, on_quote(parser)) \ X(TOKEN_VALUE, on_value(parser, token->value)) #define FN(fn, arg) "%s", fn(arg, buf, buf_sz) #define MANAGE_AST_TBL(X, ast) \ X(AST_SEXP, sexp_free(&ast->sexp), "|") \ X(AST_VALUE, value_destroy(ast->value), FN(value_string, ast->value)) \ // ---------- Exported Functions ---------- // #define CASE_TYPE(type, callback) \ case type: \ if(callback) { \ err(#callback ": failed"); \ return -1; \ } break; int parser_parse_toklist(parser_t parser, toklist_t *toklist, ast_t *ast) { if(parser->cur_sexp == NULL) { size_t index = sexp_add(&ast->sexp, AST_VALUE); ast->sexp.children[index].value = value_copy(parser->begin_symbol_value); parser->cur_sexp = &ast->sexp; } for(size_t i = 0; i < toklist->ntokens; i++) { struct token *token = &toklist->tokens[i]; switch(token->type) { TOKEN_CALLBACK_TBL(CASE_TYPE, parser, token); default: err("parser_parse_lexer: Unknown token type given"); break; } if(token->type != TOKEN_SPECIAL_QUOTE) while(parser->cur_sexp == quote_stack_pop(&parser->quote_head, 1)) { on_paren(parser, P_CLOSE); quote_stack_pop(&parser->quote_head, 0); } } if(&ast->sexp == parser->cur_sexp) { return 0; } else { return 1; } } parser_t parser_create() { parser_t parser = xmalloc(sizeof(struct parser)); #define VALUE_CREATE(str) \ value_create(VALUE_SYMBOL, str, &ret); \ if(ret) { \ err("value_create: failed"); \ return NULL; \ } int ret = 0; parser->begin_symbol_value = VALUE_CREATE("begin"); parser->quote_symbol_value = VALUE_CREATE("quote"); parser->quote_head = NULL; parser_reset(parser); return parser; } void parser_destroy(parser_t parser) { if(!parser) return; value_destroy(parser->begin_symbol_value); value_destroy(parser->quote_symbol_value); parser_reset(parser); free(parser); } void parser_reset(parser_t parser) { parser->cur_sexp = NULL; while(quote_stack_pop(&parser->quote_head, 0) != NULL); } void ast_reset(ast_t *ast) { sexp_free(&ast->sexp); sexp_init(&ast->sexp); } void ast_print(ast_t *ast) { sexp_print(&ast->sexp, 0); } // ---------- Callback Functions ---------- // static int on_paren(parser_t parser, enum paren_type type) { if(type == P_CLOSE) { parser->cur_sexp = parser->cur_sexp->prev; } else if(type == P_OPEN) { size_t index = sexp_add(parser->cur_sexp, AST_SEXP); struct sexp *prev = parser->cur_sexp; struct sexp *new = &prev->children[index].sexp; sexp_init(new); parser->cur_sexp = new; parser->cur_sexp->prev = prev; } return 0; } static int on_quote(parser_t parser) { // new sexp on_paren(parser, P_OPEN); // add symbol to the sexp on_value(parser, parser->quote_symbol_value); // save the current quote sexp quote_stack_push(&parser->quote_head, parser->cur_sexp); return 0; } static int on_value(parser_t parser, value_t value) { size_t index = sexp_add(parser->cur_sexp, AST_VALUE); value_t copied = value_copy(value); parser->cur_sexp->children[index].value = copied; return 0; } // ---------- Parser Functions ---------- // static size_t sexp_add(struct sexp *sexp, enum ast_type type) { sexp->children = xrealloc(sexp->children, sizeof(struct ast) * (sexp->nchildren+1)); sexp->children[sexp->nchildren].type = type; return sexp->nchildren++; } static void sexp_init(struct sexp *sexp) { sexp->children = NULL; sexp->nchildren = 0; sexp->prev = NULL; } static void sexp_print(struct sexp *sexp, int indent) { // (void)indent; // printf("( "); for(size_t i = 0; i < sexp->nchildren; i++) { struct ast *child = &sexp->children[i]; if(child->type == AST_SEXP) { sexp_print(&child->sexp, indent + 2); continue; } char buf[LEXER_IDEN_CAP]; size_t buf_sz = LEXER_IDEN_CAP; for(int i = 0; i < indent; i++) printf(" "); printf("%s\n", value_string(child->value, buf, buf_sz)); } // printf(")"); } static void sexp_free(struct sexp *sexp) { for(size_t i = 0; i < sexp->nchildren; i++){ ast_free(&sexp->children[i]); } if(sexp->children) free(sexp->children); } #define CASE_FREE(type, free_func, print_func) \ case type: free_func; return; static void ast_free(struct ast *ast) { if(!ast) return; switch(ast->type) { MANAGE_AST_TBL(CASE_FREE, ast) default: err("ast_free: Unknown ast type given"); break; } } static void quote_stack_push(struct quote_node **head, struct sexp *cur_sexp) { struct quote_node *node = xmalloc(sizeof(struct quote_node)); node->prev = *head; node->cur_sexp = cur_sexp; *head = node; } static struct sexp *quote_stack_pop(struct quote_node **head, int peek) { if(*head == NULL) { return NULL; } struct sexp *sexp = (*head)->cur_sexp; if(!peek) { struct quote_node *prev = (*head)->prev; free(*head); *head = prev; } return sexp; }