#include "../libs/tree-sitter-ruby/bindings/c/tree-sitter-ruby.h" #include "../libs/tree-sitter/lib/include/tree_sitter/api.h" #include #include #include #include static void die(const char *msg) { fprintf(stderr, "error: %s\n", msg); exit(1); } static char *read_stdin(size_t *out_len) { size_t cap = 4096, len = 0; char *buf = (char *)malloc(cap); if (!buf) die("malloc failed"); size_t n; while (!feof(stdin)) { if (cap - len < 2048) { cap *= 2; char *tmp = (char *)realloc(buf, cap); if (!tmp) { free(buf); die("realloc failed"); } buf = tmp; } n = fread(buf + len, 1, cap - len, stdin); len += n; } // ensure NUL-terminated for convenience if (len == cap) { char *tmp = (char *)realloc(buf, cap + 1); if (!tmp) { free(buf); die("realloc term failed"); } buf = tmp; } buf[len] = '\0'; if (out_len) *out_len = len; return buf; } static void walk(TSNode node, int depth) { uint16_t sym = ts_node_symbol(node); const char *type = ts_node_type(node); for (int i = 0; i < depth; i++) putchar(' '); uint32_t n = ts_node_child_count(node); printf("#define SYM_%s %u\n", type, sym); for (uint32_t i = 0; i < n; i++) { TSNode child = ts_node_child(node, i); walk(child, depth + 2); } } int main(void) { size_t len = 0; char *src = read_stdin(&len); if (len == 0) { fprintf(stderr, "No input on stdin. Paste some Ruby code and press Ctrl-D.\n"); free(src); return 1; } TSParser *parser = ts_parser_new(); if (!parser) { free(src); die("ts_parser_new failed"); } if (!ts_parser_set_language(parser, tree_sitter_ruby())) { ts_parser_delete(parser); free(src); die("ts_parser_set_language failed (is tree-sitter-ruby linked?)"); } TSTree *tree = ts_parser_parse_string(parser, NULL, src, (uint32_t)len); if (!tree) { ts_parser_delete(parser); free(src); die("parse failed"); } TSNode root = ts_tree_root_node(tree); walk(root, 0); ts_tree_delete(tree); ts_parser_delete(parser); free(src); return 0; }