Implement enum-strs

This commit is contained in:
soup 2024-12-14 18:34:14 -05:00
parent 18103df342
commit 043cfd687c
Signed by: soup
SSH key fingerprint: SHA256:GYxje8eQkJ6HZKzVWDdyOUF1TyDiprruGhE0Ym8qYDY
5 changed files with 126 additions and 18 deletions

View file

@ -1,7 +1,7 @@
CC := gcc -g -Og -std=c23 -Wall -Wextra -Wpedantic -Isrc -ltree-sitter
CC := gcc -g -Og -std=c23 -Wall -Wextra -Wpedantic -Isrc -ltree-sitter -Ibuild
build/bin/cgen: src/main.c | build/.build-dirs
$(CC) deps/tree-sitter-c/src/parser.c $^ -o build/bin/cgen
build/bin/cgen: src/main.c build/gen/.queries | build/.build-dirs
$(CC) deps/tree-sitter-c/src/parser.c $< -o build/bin/cgen
.PHONY: run
run: build/bin/cgen
@ -9,8 +9,13 @@ run: build/bin/cgen
build/.build-dirs: Makefile
mkdir -p build/bin
mkdir -p build/gen
touch build/.build-dirs
build/gen/.queries: src/gen_enum.tsq | build/.build-dirs
xxd -i src/gen_enum.tsq > build/gen/gen_enum_tsq.h
touch build/gen/.queries
.PHONY: clean
clean:
rm -rf build

View file

@ -10,6 +10,27 @@
"-Wextra",
"-Wpedantic",
"-Isrc",
"-Ibuild",
"-o",
"build/bin/cgen",
"deps/tree-sitter-c/src/parser.c"
],
"directory": "/home/n/src/cgen",
"file": "/home/n/src/cgen/deps/tree-sitter-c/src/parser.c",
"output": "/home/n/src/cgen/build/bin/cgen"
},
{
"arguments": [
"/nix/store/1ciadcliylyyi9vx21id9vi1p1mayjn8-gcc-wrapper-14.2.0/bin/gcc",
"-c",
"-g",
"-Og",
"-std=c23",
"-Wall",
"-Wextra",
"-Wpedantic",
"-Isrc",
"-Ibuild",
"-o",
"build/bin/cgen",
"src/main.c"

View file

@ -11,12 +11,13 @@
pkgs.mkShell {
packages = with pkgs; [
gdb
gcc15
gcc14
valgrind
strace
llvmPackages_17.clang-tools
bear
tree-sitter
tinyxxd
];
};
}

View file

@ -1,5 +1,18 @@
(enum_specifier
name: (type_identifier)? @enum_name
body: (enumerator_list
(enumerator
name: (identifier) @enum_variant)?))
[
(translation_unit
(type_definition
(enum_specifier
name: (type_identifier)? @enum_name
body: (enumerator_list
((enumerator name: (identifier) @enum_variant) ","?)*
)) @enum_spec
declarator: (type_identifier) @enum_declarator_name
))
(translation_unit
(enum_specifier
name: (type_identifier)? @enum_name
body: (enumerator_list
((enumerator name: (identifier) @enum_variant) ","?)*
)) @enum_spec)
]

View file

@ -5,6 +5,8 @@
#include <tree_sitter/api.h>
#include "gen/gen_enum_tsq.h"
TSLanguage const *tree_sitter_c(void);
char const *USAGE = "\
@ -25,9 +27,6 @@ size_t read_stdin(char *buf, size_t buf_cap) {
return at - buf;
}
char const gen_enum_query_str[] = {
#embed "./gen_enum.tsq", '\0'
};
void gen_enum_strs() {
size_t buf_cap = 2 << 16;
char *buf = calloc(buf_cap, sizeof(*buf));
@ -40,22 +39,91 @@ void gen_enum_strs() {
TSTree *tree = ts_parser_parse_string(parser, nullptr, buf, buf_len);
TSNode root_node = ts_tree_root_node(tree);
char *string = ts_node_string(root_node);
printf("%s\n", string);
uint32_t err_offset = 0;
TSQueryError err = {};
TSQuery *query = ts_query_new(
lang_c,
gen_enum_query_str,
strlen(gen_enum_query_str),
(char*)src_gen_enum_tsq,
src_gen_enum_tsq_len,
&err_offset,
&err
);
if (err != TSQueryErrorNone) {
printf("query error %d near: %s\n", err, gen_enum_query_str + err_offset);
printf("query error %d near: %s\n", err, src_gen_enum_tsq + err_offset);
assert(false);
}
uint32_t cap_id_poison = 2 << 16;
uint32_t cap_id_enum_name = cap_id_poison;
uint32_t cap_id_enum_variant = cap_id_poison;
uint32_t cap_id_enum_declarator_name = cap_id_poison;
uint32_t cap_count = ts_query_capture_count(query);
for (uint32_t i = 0; i < cap_count; ++i) {
uint32_t len = 0;
char const *name = ts_query_capture_name_for_id(query, i, &len);
if (!strncmp(name, "enum_name", len)) {
cap_id_enum_name = i;
}
if (!strncmp(name, "enum_variant", len)) {
cap_id_enum_variant = i;
}
if (!strncmp(name, "enum_declarator_name", len)) {
cap_id_enum_declarator_name = i;
}
}
TSQueryCursor *qc = ts_query_cursor_new();
ts_query_cursor_exec(qc, query, root_node);
TSQueryMatch match = {};
while (ts_query_cursor_next_match(qc, &match)) {
char const *poison = "POISON";
char const *enum_name = poison;
size_t enum_name_len = strlen(poison);
size_t enum_variants_cap = 512;
struct {
char const *start;
size_t len;
} enum_variants[enum_variants_cap] = {};
size_t enum_variants_len = 0;
for (uint32_t i = 0; i < match.capture_count; ++i) {
TSQueryCapture cap = match.captures[i];
uint32_t start = ts_node_start_byte(cap.node);
uint32_t end = ts_node_end_byte(cap.node);
uint32_t len = end - start;
char const *at = buf + start;
if (
cap.index == cap_id_enum_name
|| cap.index == cap_id_enum_declarator_name
) {
enum_name = at;
enum_name_len = len;
}
if (
cap.index == cap_id_enum_variant
&& enum_variants_len < enum_variants_cap
) {
enum_variants[enum_variants_len].len = len;
enum_variants[enum_variants_len].start = at;
enum_variants_len++;
}
}
printf("char const *%.*s_strs[] = {\n", (int)enum_name_len, enum_name);
for (size_t i = 0; i < enum_variants_len; ++i) {
typeof(enum_variants[0]) evar = enum_variants[i];
printf("\t[%.*s] = \"%.*s\",\n", (int)evar.len, evar.start, (int)evar.len, evar.start);
}
printf("};\n");
}
}
int main(int argc, char **argv) {