ast.c (3235B) - Raw
1 #include "common.h" 2 3 #include <setjmp.h> 4 #include <stdbool.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include "ast.h" 9 #include "parser.h" 10 11 #define N 1024 12 13 static void astTokenListEnsureCapacity( 14 AstTokenList* list, uint32_t additional) { 15 const uint32_t new_len = list->len + additional; 16 if (new_len <= list->cap) { 17 return; 18 } 19 20 const uint32_t new_cap = new_len > list->cap * 2 ? new_len : list->cap * 2; 21 list->tags = realloc(list->tags, new_cap * sizeof(TokenizerTag)); 22 list->starts = realloc(list->starts, new_cap * sizeof(AstIndex)); 23 if (!list->tags || !list->starts) 24 exit(1); 25 list->cap = new_cap; 26 } 27 28 Ast astParse(const char* source, const uint32_t len) { 29 uint32_t estimated_token_count = len / 8; 30 31 AstTokenList tokens = { 32 .len = 0, 33 .cap = estimated_token_count, 34 .tags = ARR_INIT(TokenizerTag, estimated_token_count), 35 .starts = ARR_INIT(AstIndex, estimated_token_count), 36 }; 37 38 Tokenizer tok = tokenizerInit(source, len); 39 while (true) { 40 astTokenListEnsureCapacity(&tokens, 1); 41 TokenizerToken token = tokenizerNext(&tok); 42 tokens.tags[tokens.len] = token.tag; 43 tokens.starts[tokens.len++] = token.loc.start; 44 if (token.tag == TOKEN_EOF) 45 break; 46 } 47 48 uint32_t estimated_node_count = (tokens.len + 2) / 2; 49 50 char err_buf[PARSE_ERR_BUF_SIZE]; 51 err_buf[0] = '\0'; 52 53 Parser p = { 54 .source = source, 55 .source_len = len, 56 .token_tags = tokens.tags, 57 .token_starts = tokens.starts, 58 .tokens_len = tokens.len, 59 .tok_i = 0, 60 .nodes = { 61 .len = 0, 62 .cap = estimated_node_count, 63 .tags = ARR_INIT(AstNodeTag, estimated_node_count), 64 .main_tokens = ARR_INIT(AstTokenIndex, estimated_node_count), 65 .datas = ARR_INIT(AstData, estimated_node_count), 66 }, 67 .extra_data = SLICE_INIT(AstNodeIndex, N), 68 .scratch = SLICE_INIT(AstNodeIndex, N), 69 .err_buf = err_buf, 70 }; 71 72 bool has_error = false; 73 if (setjmp(p.error_jmp) != 0) { 74 has_error = true; 75 } 76 if (!has_error) 77 parseRoot(&p); 78 79 p.scratch.cap = p.scratch.len = 0; 80 free(p.scratch.arr); 81 82 char* err_msg = NULL; 83 if (has_error && err_buf[0] != '\0') { 84 const size_t len2 = strlen(err_buf); 85 err_msg = malloc(len2 + 1); 86 if (!err_msg) 87 exit(1); 88 memcpy(err_msg, err_buf, len2 + 1); 89 } 90 91 return (Ast) { 92 .source = source, 93 .source_len = len, 94 .tokens = tokens, 95 .nodes = p.nodes, 96 .extra_data = { 97 .len = p.extra_data.len, 98 .cap = p.extra_data.cap, 99 .arr = p.extra_data.arr, 100 }, 101 .has_error = has_error, 102 .err_msg = err_msg, 103 }; 104 } 105 106 void astDeinit(Ast* tree) { 107 free(tree->err_msg); 108 109 tree->tokens.cap = tree->tokens.len = 0; 110 free(tree->tokens.tags); 111 free(tree->tokens.starts); 112 113 tree->nodes.cap = 0; 114 tree->nodes.len = 0; 115 free(tree->nodes.tags); 116 free(tree->nodes.main_tokens); 117 free(tree->nodes.datas); 118 119 tree->extra_data.cap = 0; 120 tree->extra_data.len = 0; 121 free(tree->extra_data.arr); 122 }