#include "all.h" #include static inline char peek(const char **p) { return **p; } static inline char advance(const char **p) { return *(*p)++; } static ast_node_t *new_node(ast_type_e type, int val) { ast_node_t *n = malloc(sizeof(ast_node_t)); n->type = type; n->val = val; n->next = NULL; n->children = (node_vec){0}; return n; } static ast_node_t *parse_block(const char **p); static ast_node_t *parse_single(const char **p) { char c = peek(p); switch (c) { case '+': { int count = 0; while (peek(p) == '+') { advance(p); count++; } return new_node(AST_INC, count); } case '-': { int count = 0; while (peek(p) == '-') { advance(p); count++; } return new_node(AST_DEC, count); } case '>': { int count = 0; while (peek(p) == '>') { advance(p); count++; } return new_node(AST_PTR_INC, count); } case '<': { int count = 0; while (peek(p) == '<') { advance(p); count++; } return new_node(AST_PTR_DEC, count); } case '.': advance(p); return new_node(AST_OUT, 1); case ',': advance(p); return new_node(AST_IN, 1); case '[': advance(p); return parse_block(p); case ']': case '\0': return NULL; default: advance(p); // ignore garbage return NULL; } } static ast_node_t *parse_block(const char **p) { ast_node_t *loop = new_node(AST_LOOP, 1); while (**p) { if (**p == ']') { advance(p); break; } ast_node_t *child = parse_single(p); if (child) node_vec_push(&loop->children, child); } return loop; } ast_node_t *parse(const char *src) { const char *p = src; ast_node_t *head = NULL; ast_node_t *tail = NULL; while (*p) { ast_node_t *node = parse_single(&p); if (!node) continue; if (!head) { head = tail = node; } else { tail->next = node; tail = node; } } return head; } void ast_free(ast_node_t *node) { if (!node) return; if (node->next) ast_free(node->next); for (size_t i = 0; i < node->children.len; i++) { ast_free(node->children._data[i]); } node_vec_free(&node->children); free(node); }