diff --git a/src/runtime/parser.c b/src/runtime/parser.c index 4617eb18..9442d2c4 100644 --- a/src/runtime/parser.c +++ b/src/runtime/parser.c @@ -129,12 +129,14 @@ static bool ts_parser__can_reuse(TSParser *self, int head, TSTree *subtree) { return false; if (subtree->symbol == ts_builtin_sym_error) return false; - if (ts_tree_is_fragile(subtree)) - return false; + if (ts_tree_is_fragile(subtree)) { + if (subtree->context.parse_state != ts_stack_top_state(self->stack, head)) + return false; + } TSStateId state = ts_stack_top_state(self->stack, head); - if (subtree->context.lex_state != TSTREE_LEX_STATE_INDEPENDENT) { + if (subtree->context.lex_state != TSTREE_STATE_INDEPENDENT) { TSStateId lex_state = self->language->lex_states[state]; if (subtree->context.lex_state != lex_state) return false; @@ -335,6 +337,10 @@ static bool ts_parser__reduce(TSParser *self, int head, TSSymbol symbol, */ TSStateId state; TSStateId top_state = ts_stack_top_state(self->stack, new_head); + + if (parent->context.parse_state != TSTREE_STATE_ERROR) + parent->context.parse_state = top_state; + if (extra) { ts_tree_set_extra(parent); state = top_state; @@ -378,6 +384,7 @@ static bool ts_parser__reduce(TSParser *self, int head, TSSymbol symbol, TSTree **parent = vector_get(&self->reduce_parents, i); (*parent)->options.fragile_left = true; (*parent)->options.fragile_right = true; + (*parent)->context.parse_state = TSTREE_STATE_ERROR; } } diff --git a/src/runtime/tree.c b/src/runtime/tree.c index dc084407..ba4ccc45 100644 --- a/src/runtime/tree.c +++ b/src/runtime/tree.c @@ -20,7 +20,8 @@ TSTree *ts_tree_make_leaf(TSSymbol sym, TSLength padding, TSLength size, .padding = padding, .options.visible = metadata.visible, .options.named = metadata.named, - .context.lex_state = TSTREE_LEX_STATE_INDEPENDENT, + .context.lex_state = TSTREE_STATE_INDEPENDENT, + .context.parse_state = TSTREE_STATE_INDEPENDENT, }; if (sym == ts_builtin_sym_error) { @@ -87,6 +88,7 @@ void ts_tree_set_children(TSTree *self, size_t child_count, TSTree **children) { if (child->symbol == ts_builtin_sym_error) { self->options.fragile_left = self->options.fragile_right = true; + self->context.parse_state = TSTREE_STATE_ERROR; } } diff --git a/src/runtime/tree.h b/src/runtime/tree.h index c2693618..0e6a464e 100644 --- a/src/runtime/tree.h +++ b/src/runtime/tree.h @@ -9,7 +9,8 @@ extern "C" { #include "tree_sitter/parser.h" #include "runtime/length.h" -#define TSTREE_LEX_STATE_INDEPENDENT (unsigned short)(-1) +#define TSTREE_STATE_INDEPENDENT (unsigned short)(-1) +#define TSTREE_STATE_ERROR (TSTREE_STATE_INDEPENDENT - 1) struct TSTree { struct { @@ -17,6 +18,7 @@ struct TSTree { size_t index; TSLength offset; TSStateId lex_state; + TSStateId parse_state; } context; size_t child_count; size_t visible_child_count;