From 3ac36b0cbeac190120cb39ecf9db2c2bf7036069 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Sat, 25 Jun 2022 17:13:11 -0700 Subject: [PATCH] Handle backslashes in token names when printing DOT debug graphs --- lib/src/language.h | 25 +++++++++++++++++++++++++ lib/src/parser.c | 2 +- lib/src/stack.c | 6 +----- lib/src/subtree.c | 14 +------------- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/lib/src/language.h b/lib/src/language.h index 1b65f25f..7234685e 100644 --- a/lib/src/language.h +++ b/lib/src/language.h @@ -283,6 +283,31 @@ static inline void ts_language_aliases_for_symbol( } } +static inline void ts_language_write_symbol_as_dot_string( + const TSLanguage *self, + FILE *f, + TSSymbol symbol +) { + const char *name = ts_language_symbol_name(self, symbol); + for (const char *c = name; *c; c++) { + switch (*c) { + case '"': + case '\\': + fputc('\\', f); + fputc(*c, f); + break; + case '\n': + fputs("\\n", f); + break; + case '\t': + fputs("\\n", f); + break; + default: + fputc(*c, f); + break; + } + } +} #ifdef __cplusplus } diff --git a/lib/src/parser.c b/lib/src/parser.c index 18c91f8e..a45204e1 100644 --- a/lib/src/parser.c +++ b/lib/src/parser.c @@ -160,7 +160,7 @@ static void ts_parser__log(TSParser *self) { if (self->dot_graph_file) { fprintf(self->dot_graph_file, "graph {\nlabel=\""); for (char *c = &self->lexer.debug_buffer[0]; *c != 0; c++) { - if (*c == '"') fputc('\\', self->dot_graph_file); + if (*c == '"' || *c == '\\') fputc('\\', self->dot_graph_file); fputc(*c, self->dot_graph_file); } fprintf(self->dot_graph_file, "\"\n}\n\n"); diff --git a/lib/src/stack.c b/lib/src/stack.c index 2a11abd8..6962a157 100644 --- a/lib/src/stack.c +++ b/lib/src/stack.c @@ -846,11 +846,7 @@ bool ts_stack_print_dot_graph(Stack *self, const TSLanguage *language, FILE *f) fprintf(f, "label=\""); bool quoted = ts_subtree_visible(link.subtree) && !ts_subtree_named(link.subtree); if (quoted) fprintf(f, "'"); - const char *name = ts_language_symbol_name(language, ts_subtree_symbol(link.subtree)); - for (const char *c = name; *c; c++) { - if (*c == '\"' || *c == '\\') fprintf(f, "\\"); - fprintf(f, "%c", *c); - } + ts_language_write_symbol_as_dot_string(language, f, ts_subtree_symbol(link.subtree)); if (quoted) fprintf(f, "'"); fprintf(f, "\""); fprintf( diff --git a/lib/src/subtree.c b/lib/src/subtree.c index 1516c18d..d6cd2d71 100644 --- a/lib/src/subtree.c +++ b/lib/src/subtree.c @@ -834,18 +834,6 @@ static size_t ts_subtree__write_char_to_string(char *s, size_t n, int32_t c) { return snprintf(s, n, "%d", c); } -static void ts_subtree__write_dot_string(FILE *f, const char *string) { - for (const char *c = string; *c; c++) { - if (*c == '"') { - fputs("\\\"", f); - } else if (*c == '\n') { - fputs("\\n", f); - } else { - fputc(*c, f); - } - } -} - static const char *ROOT_FIELD = "__ROOT__"; static size_t ts_subtree__write_to_string( @@ -975,7 +963,7 @@ void ts_subtree__print_dot_graph(const Subtree *self, uint32_t start_offset, TSSymbol symbol = alias_symbol ? alias_symbol : subtree_symbol; uint32_t end_offset = start_offset + ts_subtree_total_bytes(*self); fprintf(f, "tree_%p [label=\"", (void *)self); - ts_subtree__write_dot_string(f, ts_language_symbol_name(language, symbol)); + ts_language_write_symbol_as_dot_string(language, f, symbol); fprintf(f, "\""); if (ts_subtree_child_count(*self) == 0) fprintf(f, ", shape=plaintext");