From b36143d7a7b721b346511b108c1afd4df8b35f12 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 23 Feb 2016 09:45:27 -0800 Subject: [PATCH] Add flag for logging dot graphs of the stack while parsing --- src/runtime/array.h | 16 ++++++--------- src/runtime/node.c | 7 +++---- src/runtime/parser.c | 46 ++++++++++++++++++++++++++++++-------------- src/runtime/stack.c | 36 +++++++++++++++++++++------------- 4 files changed, 64 insertions(+), 41 deletions(-) diff --git a/src/runtime/array.h b/src/runtime/array.h index 7390277e..10a5c1a7 100644 --- a/src/runtime/array.h +++ b/src/runtime/array.h @@ -43,13 +43,9 @@ extern "C" { array_grow((self), (self)->capacity * 2)) && \ ((self)->contents[(self)->size++] = (element), true)) -#define array_splice(self, index, old_count, new_count, new_elements) \ - array__splice((VoidArray *)(self), \ - array__elem_size(self), \ - index, \ - old_count, \ - new_count, \ - new_elements) \ +#define array_splice(self, index, old_count, new_count, new_elements) \ + array__splice((VoidArray *)(self), array__elem_size(self), index, old_count, \ + new_count, new_elements) #define array_pop(self) ((self)->contents[--(self)->size]) @@ -118,11 +114,11 @@ static inline bool array__splice(VoidArray *self, size_t element_size, char *contents = (char *)self->contents; if (self->size > old_end) - memmove(contents + new_end * element_size, - contents + old_end * element_size, + memmove(contents + new_end * element_size, contents + old_end * element_size, (self->size - old_end) * element_size); if (new_count > 0) - memcpy((contents + index * element_size), elements, new_count * element_size); + memcpy((contents + index * element_size), elements, + new_count * element_size); self->size += new_count - old_count; return true; } diff --git a/src/runtime/node.c b/src/runtime/node.c index a18c7745..cfe37580 100644 --- a/src/runtime/node.c +++ b/src/runtime/node.c @@ -207,9 +207,7 @@ TSSymbol ts_node_symbol(TSNode self) { TSSymbolIterator ts_node_symbols(TSNode self) { const TSTree *tree = ts_node__tree(self); return (TSSymbolIterator){ - .value = tree->symbol, - .done = false, - .data = (void *)tree, + .value = tree->symbol, .done = false, .data = (void *)tree, }; } @@ -280,7 +278,8 @@ char *ts_node_string(TSNode self, const TSDocument *document) { static char SCRATCH[1]; const TSTree *tree = ts_node__tree(self); const char **symbol_names = document->parser.language->symbol_names; - size_t size = ts_tree__write_to_string(tree, symbol_names, SCRATCH, 0, true, false) + 1; + size_t size = + ts_tree__write_to_string(tree, symbol_names, SCRATCH, 0, true, false) + 1; char *result = ts_malloc(size * sizeof(char)); ts_tree__write_to_string(tree, symbol_names, result, size, true, false); return result; diff --git a/src/runtime/parser.c b/src/runtime/parser.c index 2611f47e..ee8109d5 100644 --- a/src/runtime/parser.c +++ b/src/runtime/parser.c @@ -15,6 +15,8 @@ * Debugging */ +bool TS_PARSER_PRINT_STACKS = false; + #define LOG(...) \ if (self->lexer.debugger.debug_fn) { \ snprintf(self->lexer.debug_buffer, TS_DEBUG_BUFFER_SIZE, __VA_ARGS__); \ @@ -22,6 +24,21 @@ TSDebugTypeParse, self->lexer.debug_buffer); \ } +#define LOG_ACTION(...) \ + LOG(__VA_ARGS__); \ + if (TS_PARSER_PRINT_STACKS) { \ + fprintf(stderr, "graph {\nlabel=\""); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\"\n}\n\n"); \ + } + +#define LOG_STACK() \ + if (TS_PARSER_PRINT_STACKS) { \ + fputs(ts_stack_dot_graph(self->stack, self->language->symbol_names), \ + stderr); \ + fputs("\n\n", stderr); \ + } + #define SYM_NAME(sym) self->language->symbol_names[sym] #define BOOL_STRING(value) (value ? "true" : "false") @@ -345,8 +362,8 @@ static ParseActionResult ts_parser__reduce(TSParser *self, int head, } size_t child_count = pop_result.trees.size - trailing_extra_count; - parent = - ts_tree_make_node(symbol, child_count, pop_result.trees.contents, metadata); + parent = ts_tree_make_node(symbol, child_count, pop_result.trees.contents, + metadata); if (!parent) { for (size_t i = 0; i < pop_result.trees.size; i++) ts_tree_release(pop_result.trees.contents[i]); @@ -637,7 +654,7 @@ static ParseActionResult ts_parser__consume_lookahead(TSParser *self, int head, current_head = head; } else { current_head = ts_parser__split(self, head); - LOG("split_action from_head:%d, new_head:%d", head, current_head); + LOG_ACTION("split_action from_head:%d, new_head:%d", head, current_head); } LookaheadState *lookahead_state = @@ -648,9 +665,11 @@ static ParseActionResult ts_parser__consume_lookahead(TSParser *self, int head, if (lookahead->symbol == ts_builtin_sym_error) action.type = TSParseActionTypeError; + LOG_STACK(); + switch (action.type) { case TSParseActionTypeError: - LOG("error_sym"); + LOG_ACTION("error_sym"); if (lookahead_state->is_verifying) { ts_parser__breakdown_top_of_stack(self, current_head); lookahead_state->is_verifying = false; @@ -667,17 +686,17 @@ static ParseActionResult ts_parser__consume_lookahead(TSParser *self, int head, return ts_parser__accept(self, current_head); } } else { - LOG("bail current_head:%d", current_head); + LOG_ACTION("bail current_head:%d", current_head); ts_parser__remove_head(self, current_head); return RemovedStackHead; } case TSParseActionTypeShift: if (action.extra) { - LOG("shift_extra"); + LOG_ACTION("shift_extra"); return ts_parser__shift_extra(self, current_head, state, lookahead); } else { - LOG("shift state:%u", action.data.to_state); + LOG_ACTION("shift state:%u", action.data.to_state); lookahead_state->is_verifying = (lookahead->child_count > 0); TSStateId state = action.data.to_state; return ts_parser__shift(self, current_head, state, lookahead); @@ -687,13 +706,13 @@ static ParseActionResult ts_parser__consume_lookahead(TSParser *self, int head, lookahead_state->is_verifying = false; if (action.extra) { - LOG("reduce_extra sym:%s", SYM_NAME(action.data.symbol)); + LOG_ACTION("reduce_extra sym:%s", SYM_NAME(action.data.symbol)); ts_parser__reduce(self, current_head, action.data.symbol, 1, true, false, false); } else { - LOG("reduce sym:%s, child_count:%u, fragile:%s", - SYM_NAME(action.data.symbol), action.data.child_count, - BOOL_STRING(action.fragile)); + LOG_ACTION("reduce sym:%s, child_count:%u, fragile:%s", + SYM_NAME(action.data.symbol), action.data.child_count, + BOOL_STRING(action.fragile)); switch (ts_parser__reduce(self, current_head, action.data.symbol, action.data.child_count, false, action.fragile, false)) { @@ -710,7 +729,7 @@ static ParseActionResult ts_parser__consume_lookahead(TSParser *self, int head, break; case TSParseActionTypeAccept: - LOG("accept"); + LOG_ACTION("accept"); return ts_parser__accept(self, current_head); } } @@ -799,8 +818,7 @@ TSTree *ts_parser_parse(TSParser *self, TSInput input, TSTree *previous_tree) { ts_stack_head_count(self->stack), ts_stack_top_state(self->stack, head), position); - if (!lookahead || - (position != last_position) || + if (!lookahead || (position != last_position) || !ts_parser__can_reuse(self, head, lookahead)) { ts_tree_release(lookahead); lookahead = ts_parser__get_next_lookahead(self, head); diff --git a/src/runtime/stack.c b/src/runtime/stack.c index 19cb9639..c98eab34 100644 --- a/src/runtime/stack.c +++ b/src/runtime/stack.c @@ -392,8 +392,7 @@ StackPopResultArray ts_stack_pop(Stack *self, int head_index, int child_count, array_reverse(&path->trees); StackPopResult result = { - .trees = path->trees, - .head_index = -1, + .trees = path->trees, .head_index = -1, }; if (i == 0) { @@ -476,19 +475,27 @@ void ts_stack_delete(Stack *self) { ts_free(self); } +static const char *graph_colors[] = { + "red", "blue", "orange", "green", "purple", +}; + size_t ts_stack__write_dot_graph(Stack *self, char *string, size_t n, const char **symbol_names) { char *cursor = string; char **s = n > 0 ? &cursor : &string; cursor += snprintf(*s, n, "digraph stack {\n"); cursor += snprintf(*s, n, "rankdir=\"RL\";\n"); - cursor += snprintf(*s, n, "node_%p [label=\"0:NULL\"];\n", NULL); array_clear(&self->pop_paths); - for (int i = 0; i < self->heads.size; i++) + for (size_t i = 0; i < self->heads.size; i++) { + StackNode *node = self->heads.contents[i]; + const char *color = + graph_colors[i % (sizeof(graph_colors) / sizeof(graph_colors[0]))]; + cursor += snprintf(*s, n, "node_%p [color=%s];\n", node, color); array_push(&self->pop_paths, ((PopPath){ - .node = self->heads.contents[i], - })); + .node = node, + })); + } bool all_paths_done = false; while (!all_paths_done) { @@ -503,17 +510,19 @@ size_t ts_stack__write_dot_graph(Stack *self, char *string, size_t n, all_paths_done = false; - cursor += snprintf(*s, n, "node_%p [label=\"%d:%s\"];\n", node, - node->entry.state, - symbol_names[node->entry.tree->symbol]); + cursor += + snprintf(*s, n, "node_%p [label=\"%s\\n%d\"];\n", node, + symbol_names[node->entry.tree->symbol], node->entry.state); path->node = node->successors[0]; - cursor += snprintf(*s, n, "node_%p -> node_%p;\n", node, node->successors[0]); + cursor += + snprintf(*s, n, "node_%p -> node_%p;\n", node, node->successors[0]); for (int j = 1; j < node->successor_count; j++) { if (!array_push(&self->pop_paths, *path)) goto error; - cursor += snprintf(*s, n, "node_%p -> node_%p;\n", node, node->successors[j]); + cursor += + snprintf(*s, n, "node_%p -> node_%p;\n", node, node->successors[j]); PopPath *next_path = array_back(&self->pop_paths); next_path->node = node->successors[j]; @@ -522,6 +531,7 @@ size_t ts_stack__write_dot_graph(Stack *self, char *string, size_t n, } } + cursor += snprintf(*s, n, "node_%p [label=\"-\\n0\"];\n", NULL); cursor += snprintf(*s, n, "}\n"); return cursor - string; @@ -534,7 +544,7 @@ char *ts_stack_dot_graph(Stack *self, const char **symbol_names) { static char SCRATCH[1]; char *result = NULL; size_t size = ts_stack__write_dot_graph(self, SCRATCH, 0, symbol_names) + 1; - if (size == -1) + if (size == (size_t)-1) goto error; result = ts_malloc(size * sizeof(char)); @@ -542,7 +552,7 @@ char *ts_stack_dot_graph(Stack *self, const char **symbol_names) { goto error; size = ts_stack__write_dot_graph(self, result, size, symbol_names); - if (size == -1) + if (size == (size_t)-1) goto error; return result;