zig0

my attempts at zig bootstrapping in C
Log | Files | Refs | README | LICENSE

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 }