@@ -949,6 +949,7 @@ static StackVersion ts_parser__reduce(
949949 // children.
950950 StackSliceArray pop = ts_stack_pop_count (self -> stack , version , count );
951951 uint32_t removed_version_count = 0 ;
952+ uint32_t halted_version_count = ts_stack_halted_version_count (self -> stack );
952953 for (uint32_t i = 0 ; i < pop .size ; i ++ ) {
953954 StackSlice slice = pop .contents [i ];
954955 StackVersion slice_version = slice .version - removed_version_count ;
@@ -957,11 +958,12 @@ static StackVersion ts_parser__reduce(
957958 // will all be sorted and truncated at the end of the outer parsing loop.
958959 // Allow the maximum version count to be temporarily exceeded, but only
959960 // by a limited threshold.
960- if (slice_version > MAX_VERSION_COUNT + MAX_VERSION_COUNT_OVERFLOW ) {
961+ if (slice_version > MAX_VERSION_COUNT + MAX_VERSION_COUNT_OVERFLOW + halted_version_count ) {
961962 ts_stack_remove_version (self -> stack , slice_version );
962963 ts_subtree_array_delete (& self -> tree_pool , & slice .subtrees );
963964 removed_version_count ++ ;
964965 while (i + 1 < pop .size ) {
966+ LOG ("aborting reduce with too many versions" )
965967 StackSlice next_slice = pop .contents [i + 1 ];
966968 if (next_slice .version != slice .version ) break ;
967969 ts_subtree_array_delete (& self -> tree_pool , & next_slice .subtrees );
@@ -1318,10 +1320,23 @@ static void ts_parser__recover(
13181320 // and subsequently halted. Remove those versions.
13191321 for (unsigned i = previous_version_count ; i < ts_stack_version_count (self -> stack ); i ++ ) {
13201322 if (!ts_stack_is_active (self -> stack , i )) {
1323+ LOG ("removed paused version:%u" , i );
13211324 ts_stack_remove_version (self -> stack , i -- );
1325+ LOG_STACK ();
13221326 }
13231327 }
13241328
1329+ // If the parser is still in the error state at the end of the file, just wrap everything
1330+ // in an ERROR node and terminate.
1331+ if (ts_subtree_is_eof (lookahead )) {
1332+ LOG ("recover_eof" );
1333+ SubtreeArray children = array_new ();
1334+ Subtree parent = ts_subtree_new_error_node (& children , false, self -> language );
1335+ ts_stack_push (self -> stack , version , parent , false, 1 );
1336+ ts_parser__accept (self , version , lookahead );
1337+ return ;
1338+ }
1339+
13251340 // If strategy 1 succeeded, a new stack version will have been created which is able to handle
13261341 // the current lookahead token. Now, in addition, try strategy 2 described above: skip the
13271342 // current lookahead token by wrapping it in an ERROR node.
@@ -1342,17 +1357,6 @@ static void ts_parser__recover(
13421357 return ;
13431358 }
13441359
1345- // If the parser is still in the error state at the end of the file, just wrap everything
1346- // in an ERROR node and terminate.
1347- if (ts_subtree_is_eof (lookahead )) {
1348- LOG ("recover_eof" );
1349- SubtreeArray children = array_new ();
1350- Subtree parent = ts_subtree_new_error_node (& children , false, self -> language );
1351- ts_stack_push (self -> stack , version , parent , false, 1 );
1352- ts_parser__accept (self , version , lookahead );
1353- return ;
1354- }
1355-
13561360 // Do not recover if the result would clearly be worse than some existing stack version.
13571361 unsigned new_cost =
13581362 current_error_cost + ERROR_COST_PER_SKIPPED_TREE +
@@ -1618,6 +1622,7 @@ static bool ts_parser__advance(
16181622 // an ambiguous state. REDUCE actions always create a new stack
16191623 // version, whereas SHIFT actions update the existing stack version
16201624 // and terminate this loop.
1625+ bool did_reduce = false;
16211626 StackVersion last_reduction_version = STACK_VERSION_NONE ;
16221627 for (uint32_t i = 0 ; i < table_entry .action_count ; i ++ ) {
16231628 TSParseAction action = table_entry .actions [i ];
@@ -1653,6 +1658,7 @@ static bool ts_parser__advance(
16531658 action .reduce .dynamic_precedence , action .reduce .production_id ,
16541659 is_fragile , end_of_non_terminal_extra
16551660 );
1661+ did_reduce = true;
16561662 if (reduction_version != STACK_VERSION_NONE ) {
16571663 last_reduction_version = reduction_version ;
16581664 }
@@ -1704,9 +1710,12 @@ static bool ts_parser__advance(
17041710 continue ;
17051711 }
17061712
1707- // A non-terminal extra rule was reduced and merged into an existing
1708- // stack version. This version can be discarded.
1709- if (!lookahead .ptr ) {
1713+ // A reduction was performed, but was merged into an existing stack version.
1714+ // This version can be discarded.
1715+ if (did_reduce ) {
1716+ if (lookahead .ptr ) {
1717+ ts_subtree_release (& self -> tree_pool , lookahead );
1718+ }
17101719 ts_stack_halt (self -> stack , version );
17111720 return true;
17121721 }
@@ -1755,7 +1764,7 @@ static bool ts_parser__advance(
17551764 // versions that exist. If some other version advances successfully, then
17561765 // this version can simply be removed. But if all versions end up paused,
17571766 // then error recovery is needed.
1758- LOG ("detect_error" );
1767+ LOG ("detect_error lookahead:%s" , TREE_NAME ( lookahead ) );
17591768 ts_stack_pause (self -> stack , version , lookahead );
17601769 return true;
17611770 }
@@ -1844,6 +1853,7 @@ static unsigned ts_parser__condense_stack(TSParser *self) {
18441853 has_unpaused_version = true;
18451854 } else {
18461855 ts_stack_remove_version (self -> stack , i );
1856+ made_changes = true;
18471857 i -- ;
18481858 n -- ;
18491859 }
0 commit comments