Implement enum-strs
This commit is contained in:
parent
18103df342
commit
043cfd687c
11
Makefile
11
Makefile
|
|
@ -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
|
build/bin/cgen: src/main.c build/gen/.queries | build/.build-dirs
|
||||||
$(CC) deps/tree-sitter-c/src/parser.c $^ -o build/bin/cgen
|
$(CC) deps/tree-sitter-c/src/parser.c $< -o build/bin/cgen
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: build/bin/cgen
|
run: build/bin/cgen
|
||||||
|
|
@ -9,8 +9,13 @@ run: build/bin/cgen
|
||||||
|
|
||||||
build/.build-dirs: Makefile
|
build/.build-dirs: Makefile
|
||||||
mkdir -p build/bin
|
mkdir -p build/bin
|
||||||
|
mkdir -p build/gen
|
||||||
touch build/.build-dirs
|
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
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -rf build
|
rm -rf build
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,27 @@
|
||||||
"-Wextra",
|
"-Wextra",
|
||||||
"-Wpedantic",
|
"-Wpedantic",
|
||||||
"-Isrc",
|
"-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",
|
"-o",
|
||||||
"build/bin/cgen",
|
"build/bin/cgen",
|
||||||
"src/main.c"
|
"src/main.c"
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,13 @@
|
||||||
pkgs.mkShell {
|
pkgs.mkShell {
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
gdb
|
gdb
|
||||||
gcc15
|
gcc14
|
||||||
valgrind
|
valgrind
|
||||||
strace
|
strace
|
||||||
llvmPackages_17.clang-tools
|
llvmPackages_17.clang-tools
|
||||||
bear
|
bear
|
||||||
tree-sitter
|
tree-sitter
|
||||||
|
tinyxxd
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,18 @@
|
||||||
(enum_specifier
|
[
|
||||||
name: (type_identifier)? @enum_name
|
(translation_unit
|
||||||
body: (enumerator_list
|
(type_definition
|
||||||
(enumerator
|
(enum_specifier
|
||||||
name: (identifier) @enum_variant)?))
|
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)
|
||||||
|
]
|
||||||
|
|
|
||||||
86
src/main.c
86
src/main.c
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
#include <tree_sitter/api.h>
|
#include <tree_sitter/api.h>
|
||||||
|
|
||||||
|
#include "gen/gen_enum_tsq.h"
|
||||||
|
|
||||||
TSLanguage const *tree_sitter_c(void);
|
TSLanguage const *tree_sitter_c(void);
|
||||||
|
|
||||||
char const *USAGE = "\
|
char const *USAGE = "\
|
||||||
|
|
@ -25,9 +27,6 @@ size_t read_stdin(char *buf, size_t buf_cap) {
|
||||||
return at - buf;
|
return at - buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const gen_enum_query_str[] = {
|
|
||||||
#embed "./gen_enum.tsq", '\0'
|
|
||||||
};
|
|
||||||
void gen_enum_strs() {
|
void gen_enum_strs() {
|
||||||
size_t buf_cap = 2 << 16;
|
size_t buf_cap = 2 << 16;
|
||||||
char *buf = calloc(buf_cap, sizeof(*buf));
|
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);
|
TSTree *tree = ts_parser_parse_string(parser, nullptr, buf, buf_len);
|
||||||
TSNode root_node = ts_tree_root_node(tree);
|
TSNode root_node = ts_tree_root_node(tree);
|
||||||
|
|
||||||
char *string = ts_node_string(root_node);
|
|
||||||
printf("%s\n", string);
|
|
||||||
|
|
||||||
uint32_t err_offset = 0;
|
uint32_t err_offset = 0;
|
||||||
TSQueryError err = {};
|
TSQueryError err = {};
|
||||||
TSQuery *query = ts_query_new(
|
TSQuery *query = ts_query_new(
|
||||||
lang_c,
|
lang_c,
|
||||||
gen_enum_query_str,
|
(char*)src_gen_enum_tsq,
|
||||||
strlen(gen_enum_query_str),
|
src_gen_enum_tsq_len,
|
||||||
&err_offset,
|
&err_offset,
|
||||||
&err
|
&err
|
||||||
);
|
);
|
||||||
if (err != TSQueryErrorNone) {
|
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);
|
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) {
|
int main(int argc, char **argv) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue